diff --git a/bench/.gitignore b/bench/.gitignore new file mode 100644 index 0000000..074a1ba --- /dev/null +++ b/bench/.gitignore @@ -0,0 +1,2 @@ +elm-stuff +node_modules \ No newline at end of file diff --git a/bench/LICENCE b/bench/LICENCE new file mode 100644 index 0000000..4b9de32 --- /dev/null +++ b/bench/LICENCE @@ -0,0 +1,27 @@ +Copyright (c) 2016, Evan Czaplicki +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the {organization} nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/bench/elm-package.json b/bench/elm-package.json new file mode 100644 index 0000000..34b77a8 --- /dev/null +++ b/bench/elm-package.json @@ -0,0 +1,15 @@ +{ + "version": "1.0.0", + "summary": "helpful summary of your project, less than 80 characters", + "repository": "https://github.com/user/project.git", + "license": "BSD3", + "source-directories": [ + "." + ], + "exposed-modules": [], + "dependencies": { + "elm-lang/core": "4.0.5 <= v < 5.0.0", + "elm-lang/html": "1.1.0 <= v < 2.0.0" + }, + "elm-version": "0.17.1 <= v < 0.18.0" +} diff --git a/bench/implementations/angular-1.5.8-optimized/build.min.js b/bench/implementations/angular-1.5.8-optimized/build.min.js new file mode 100755 index 0000000..e94ad0f --- /dev/null +++ b/bench/implementations/angular-1.5.8-optimized/build.min.js @@ -0,0 +1 @@ +(function(){"use strict";angular.module("todoCtrl",[]).controller("TodoCtrl",function TodoCtrl($scope,$location){var TC=this;var todos=TC.todos=[];TC.ESCAPE_KEY=27;TC.editedTodo={};TC.updateRemainingCount=function(){TC.remainingCount=todos.filter(function(todo){return!todo.completed}).length;TC.allChecked=TC.remainingCount===0};function resetTodo(){TC.newTodo={title:"",completed:false}}resetTodo();if($location.path()===""){$location.path("/")}TC.location=$location;$scope.$watch("TC.location.path()",function(path){TC.statusFilter={"/active":{completed:false},"/completed":{completed:true}}[path]});TC.addTodo=function(){var newTitle=TC.newTodo.title=TC.newTodo.title.trim();if(newTitle.length===0){return}todos.push(TC.newTodo);resetTodo();TC.updateRemainingCount()};TC.editTodo=function(todo){TC.editedTodo=todo;TC.originalTodo=angular.copy(todo)};TC.doneEditing=function(todo,index){TC.editedTodo={};todo.title=todo.title.trim();if(!todo.title){TC.removeTodo(index)}TC.updateRemainingCount()};TC.revertEditing=function(index){TC.editedTodo={};todos[index]=TC.originalTodo;TC.updateRemainingCount()};TC.removeTodo=function(index){todos.splice(index,1);TC.updateRemainingCount()};TC.clearCompletedTodos=function(){TC.todos=todos=todos.filter(function(val){return!val.completed});TC.updateRemainingCount()};TC.markAll=function(completed){todos.forEach(function(todo){todo.completed=completed});TC.updateRemainingCount()}});angular.module("todoFocus",[]).directive("todoFocus",function($timeout){return function(scope,elem,attrs){scope.$watch(attrs.todoFocus,function(newVal){if(newVal){$timeout(function(){elem[0].focus()},0,false)}})}});angular.module("todomvc",["todoCtrl","todoFocus"])})(); \ No newline at end of file diff --git a/bench/implementations/angular-1.5.8-optimized/index.html b/bench/implementations/angular-1.5.8-optimized/index.html new file mode 100755 index 0000000..de0c93f --- /dev/null +++ b/bench/implementations/angular-1.5.8-optimized/index.html @@ -0,0 +1,77 @@ + + + + + + AngularJS • TodoMVC + + + + + + +
+
+

todos

+
+ +
+
+
+ + + +
+ +
+ + + + + + + diff --git a/bench/implementations/angular-1.5.8-optimized/js/app.js b/bench/implementations/angular-1.5.8-optimized/js/app.js new file mode 100755 index 0000000..6c93010 --- /dev/null +++ b/bench/implementations/angular-1.5.8-optimized/js/app.js @@ -0,0 +1,118 @@ +/* jshint undef: true, unused: true */ +/*global angular */ +(function () { + 'use strict'; + + angular.module('todoCtrl', []) + + /** + * The main controller for the app. The controller: + * - retrieves and persists the model via the todoStorage service + * - exposes the model to the template and provides event handlers + */ + .controller('TodoCtrl', function TodoCtrl($scope, $location) { + var TC = this; + var todos = TC.todos = []; + + TC.ESCAPE_KEY = 27; + TC.editedTodo = {}; + + TC.updateRemainingCount = function () { + TC.remainingCount = todos.filter(function (todo) { return !todo.completed; }).length; + TC.allChecked = (TC.remainingCount === 0); + } + + function resetTodo() { + TC.newTodo = {title: '', completed: false}; + } + + resetTodo(); + + if ($location.path() === '') { + $location.path('/'); + } + + TC.location = $location; + + $scope.$watch('TC.location.path()', function (path) { + TC.statusFilter = { '/active': {completed: false}, '/completed': {completed: true} }[path]; + }); + + TC.addTodo = function () { + var newTitle = TC.newTodo.title = TC.newTodo.title.trim(); + if (newTitle.length === 0) { + return; + } + + todos.push(TC.newTodo); + resetTodo(); + TC.updateRemainingCount(); + }; + + TC.editTodo = function (todo) { + TC.editedTodo = todo; + + // Clone the original todo to restore it on demand. + TC.originalTodo = angular.copy(todo); + }; + + TC.doneEditing = function (todo, index) { + TC.editedTodo = {}; + todo.title = todo.title.trim(); + + if (!todo.title) { + TC.removeTodo(index); + } + TC.updateRemainingCount(); + }; + + TC.revertEditing = function (index) { + TC.editedTodo = {}; + todos[index] = TC.originalTodo; + TC.updateRemainingCount(); + }; + + TC.removeTodo = function (index) { + todos.splice(index, 1); + TC.updateRemainingCount(); + }; + + TC.clearCompletedTodos = function () { + TC.todos = todos = todos.filter(function (val) { + return !val.completed; + }); + TC.updateRemainingCount(); + }; + + TC.markAll = function (completed) { + todos.forEach(function (todo) { + todo.completed = completed; + }); + TC.updateRemainingCount(); + }; + }); + + + angular.module('todoFocus', []) + + /** + * Directive that places focus on the element it is applied to when the expression it binds to evaluates to true + */ + .directive('todoFocus', function ($timeout) { + return function (scope, elem, attrs) { + scope.$watch(attrs.todoFocus, function (newVal) { + if (newVal) { + $timeout(function () { + elem[0].focus(); + }, 0, false); + } + }); + }; + }); + /** + * The main TodoMVC app module that pulls all dependency modules declared in same named files + * + * @type {angular.Module} + */ + angular.module('todomvc', ['todoCtrl', 'todoFocus']); +})(); diff --git a/bench/implementations/angular-1.5.8-optimized/package.json b/bench/implementations/angular-1.5.8-optimized/package.json new file mode 100644 index 0000000..f23e1dc --- /dev/null +++ b/bench/implementations/angular-1.5.8-optimized/package.json @@ -0,0 +1,14 @@ +{ + "private": true, + "scripts": { + "make": "uglifyjs js/app.js -o build.min.js" + }, + "dependencies": { + "angular": "^1.5.8", + "todomvc-app-css": "^2.0.6", + "todomvc-common": "^1.0.2" + }, + "devDependencies": { + "uglify-js": "^2.6.4" + } +} diff --git a/bench/implementations/angular-1.5.8-optimized/readme.md b/bench/implementations/angular-1.5.8-optimized/readme.md new file mode 100755 index 0000000..14e4142 --- /dev/null +++ b/bench/implementations/angular-1.5.8-optimized/readme.md @@ -0,0 +1,25 @@ +# Angular TodoMVC for Benchmarking + +This is an update of the +_[Angular TodoMVC example](https://github.com/tastejs/todomvc/tree/gh-pages/examples/angularjs-perf)_ +with the following changes: + +* Upgrade to Angular 1.5.7 +* Update todomvc-app-css to 2.0.6 to match other examples in this benchmark +* Remove localStorage functionality - not relevant to measuring render performance +* Concat JS into one file +* Minify with uglify + +and additional performance optimizations: + +#### Removed the deep $watch in favor of direct function calls +The original example uses $scope.$watch with object equality enabled to track changes to the array of todos and perform actions when changes are detected. This is not a good practice as it causes a deep array comparison to happen every digest cycle, which can significantly degrade performance when working with large collections. Instead we can perform the required actions directly whenever todos are modified, since we control all points of possible modification. + +#### Removed "track by $index" from the ng-repeat directive +The original example uses the ng-repeat directive with a "track by $index" clause to display the list of todos. _[Refer to section "Tracking and Duplicates" here for information on using "track by".](https://code.angularjs.org/1.5.7/docs/api/ng/directive/ngRepeat)_ In this particular case it is not necessary to use it, as long as care is taken not to persist the "$$hashKey" property added by Angular to local storage, which would cause duplicates to appear when the collection is loaded and new items are added, triggering an exception. The version without the "track by" clause could reasonably be written by someone implementing this from scratch and demonstrates better performance. + +# Building + +1. `npm install` +2. `npm run make` +3. Open a local server (e.g. with `npm install -g http-server`) and open index.html diff --git a/bench/implementations/angular-1.5.8/build.min.js b/bench/implementations/angular-1.5.8/build.min.js new file mode 100644 index 0000000..d0d056c --- /dev/null +++ b/bench/implementations/angular-1.5.8/build.min.js @@ -0,0 +1 @@ +(function(){"use strict";angular.module("todoCtrl",[]).controller("TodoCtrl",function TodoCtrl($scope,$location){var TC=this;var todos=TC.todos=[];TC.ESCAPE_KEY=27;TC.editedTodo={};function resetTodo(){TC.newTodo={title:"",completed:false}}resetTodo();if($location.path()===""){$location.path("/")}TC.location=$location;$scope.$watch("TC.location.path()",function(path){TC.statusFilter={"/active":{completed:false},"/completed":{completed:true}}[path]});$scope.$watch("TC.todos",function(){TC.remainingCount=todos.filter(function(todo){return!todo.completed}).length;TC.allChecked=TC.remainingCount===0},true);TC.addTodo=function(){var newTitle=TC.newTodo.title=TC.newTodo.title.trim();if(newTitle.length===0){return}todos.push(TC.newTodo);resetTodo()};TC.editTodo=function(todo){TC.editedTodo=todo;TC.originalTodo=angular.copy(todo)};TC.doneEditing=function(todo,index){TC.editedTodo={};todo.title=todo.title.trim();if(!todo.title){TC.removeTodo(index)}};TC.revertEditing=function(index){TC.editedTodo={};todos[index]=TC.originalTodo};TC.removeTodo=function(index){todos.splice(index,1)};TC.clearCompletedTodos=function(){TC.todos=todos=todos.filter(function(val){return!val.completed})};TC.markAll=function(completed){todos.forEach(function(todo){todo.completed=completed})}});angular.module("todoFocus",[]).directive("todoFocus",function($timeout){return function(scope,elem,attrs){scope.$watch(attrs.todoFocus,function(newVal){if(newVal){$timeout(function(){elem[0].focus()},0,false)}})}});angular.module("todomvc",["todoCtrl","todoFocus"])})(); \ No newline at end of file diff --git a/bench/implementations/angular-1.5.8/index.html b/bench/implementations/angular-1.5.8/index.html new file mode 100644 index 0000000..327d016 --- /dev/null +++ b/bench/implementations/angular-1.5.8/index.html @@ -0,0 +1,77 @@ + + + + + + AngularJS • TodoMVC + + + + + + +
+
+

todos

+
+ +
+
+
+ + + +
+ +
+ + + + + + + diff --git a/bench/implementations/angular-1.5.8/js/app.js b/bench/implementations/angular-1.5.8/js/app.js new file mode 100644 index 0000000..3e4a810 --- /dev/null +++ b/bench/implementations/angular-1.5.8/js/app.js @@ -0,0 +1,113 @@ +/* jshint undef: true, unused: true */ +/*global angular */ +(function () { + 'use strict'; + + + angular.module('todoCtrl', []) + + /** + * The main controller for the app. The controller: + * - retrieves and persists the model via the todoStorage service + * - exposes the model to the template and provides event handlers + */ + .controller('TodoCtrl', function TodoCtrl($scope, $location) { + var TC = this; + var todos = TC.todos = []; + + TC.ESCAPE_KEY = 27; + TC.editedTodo = {}; + + function resetTodo() { + TC.newTodo = {title: '', completed: false}; + } + + resetTodo(); + + if ($location.path() === '') { + $location.path('/'); + } + + TC.location = $location; + + $scope.$watch('TC.location.path()', function (path) { + TC.statusFilter = { '/active': {completed: false}, '/completed': {completed: true} }[path]; + }); + + // 3rd argument `true` for deep object watching + $scope.$watch('TC.todos', function () { + TC.remainingCount = todos.filter(function (todo) { return !todo.completed; }).length; + TC.allChecked = (TC.remainingCount === 0); + }, true); + + TC.addTodo = function () { + var newTitle = TC.newTodo.title = TC.newTodo.title.trim(); + if (newTitle.length === 0) { + return; + } + + todos.push(TC.newTodo); + resetTodo(); + }; + + TC.editTodo = function (todo) { + TC.editedTodo = todo; + + // Clone the original todo to restore it on demand. + TC.originalTodo = angular.copy(todo); + }; + + TC.doneEditing = function (todo, index) { + TC.editedTodo = {}; + todo.title = todo.title.trim(); + + if (!todo.title) { + TC.removeTodo(index); + } + }; + + TC.revertEditing = function (index) { + TC.editedTodo = {}; + todos[index] = TC.originalTodo; + }; + + TC.removeTodo = function (index) { + todos.splice(index, 1); + }; + + TC.clearCompletedTodos = function () { + TC.todos = todos = todos.filter(function (val) { + return !val.completed; + }); + }; + + TC.markAll = function (completed) { + todos.forEach(function (todo) { + todo.completed = completed; + }); + }; + }); + + angular.module('todoFocus', []) + + /** + * Directive that places focus on the element it is applied to when the expression it binds to evaluates to true + */ + .directive('todoFocus', function ($timeout) { + return function (scope, elem, attrs) { + scope.$watch(attrs.todoFocus, function (newVal) { + if (newVal) { + $timeout(function () { + elem[0].focus(); + }, 0, false); + } + }); + }; + }); + /** + * The main TodoMVC app module that pulls all dependency modules declared in same named files + * + * @type {angular.Module} + */ + angular.module('todomvc', ['todoCtrl', 'todoFocus']); +})(); diff --git a/bench/implementations/angular-1.5.8/package.json b/bench/implementations/angular-1.5.8/package.json new file mode 100644 index 0000000..f23e1dc --- /dev/null +++ b/bench/implementations/angular-1.5.8/package.json @@ -0,0 +1,14 @@ +{ + "private": true, + "scripts": { + "make": "uglifyjs js/app.js -o build.min.js" + }, + "dependencies": { + "angular": "^1.5.8", + "todomvc-app-css": "^2.0.6", + "todomvc-common": "^1.0.2" + }, + "devDependencies": { + "uglify-js": "^2.6.4" + } +} diff --git a/bench/implementations/angular-1.5.8/readme.md b/bench/implementations/angular-1.5.8/readme.md new file mode 100644 index 0000000..0b688c9 --- /dev/null +++ b/bench/implementations/angular-1.5.8/readme.md @@ -0,0 +1,19 @@ +# Angular TodoMVC for Benchmarking + +This is an update of the +_[Angular TodoMVC example](https://github.com/tastejs/todomvc/tree/gh-pages/examples/angularjs-perf)_ +with the following changes: + +* Upgrade to Angular 1.5.7 +* Update todomvc-app-css to 2.0.6 to match other examples in this benchmark +* Remove localStorage functionality - not relevant to measuring render performance +* Concat JS into one file +* Minify with uglify + +This example is listed as "performance optimized" in the TodoMVC repository, but doesn't appear to make any performance improvements to the basic example other than excluding all features not mentioned in the app specification. Therefore, it should count as having no optimizations for the purposes of this benchmark. + +# Building + +1. `npm install` +2. `npm run make` +3. Open a local server (e.g. with `npm install -g http-server`) and open index.html diff --git a/bench/implementations/angular-2-optimized/.gitignore b/bench/implementations/angular-2-optimized/.gitignore new file mode 100644 index 0000000..64ee7d5 --- /dev/null +++ b/bench/implementations/angular-2-optimized/.gitignore @@ -0,0 +1,28 @@ +node_modules/.bin + +# ignore the source / documentation of each node module, but retain the +# distribution builds + +node_modules/systemjs +!node_modules/systemjs/dist/system.src.js + +node_modules/todomvc-app-css +!node_modules/todomvc-app-css/index.css + +node_modules/todomvc-common +!node_modules/todomvc-common/base.css + +node_modules/angular2 +!node_modules/angular2/bundles/angular2-polyfills.js +!node_modules/angular2/bundles/angular2.dev.js + +node_modules/rxjs +!node_modules/rxjs/bundles/Rx.js + +# Ignore development dependencies +node_modules/tsd +node_modules/typescript + +*.js +*.js.map +typings diff --git a/bench/implementations/angular-2-optimized/app/app.html b/bench/implementations/angular-2-optimized/app/app.html new file mode 100644 index 0000000..3caa060 --- /dev/null +++ b/bench/implementations/angular-2-optimized/app/app.html @@ -0,0 +1,23 @@ +
+
+

todos

+ +
+
+ + +
+ +
diff --git a/bench/implementations/angular-2-optimized/app/app.ts b/bench/implementations/angular-2-optimized/app/app.ts new file mode 100644 index 0000000..a59feca --- /dev/null +++ b/bench/implementations/angular-2-optimized/app/app.ts @@ -0,0 +1,62 @@ +import {Component} from 'angular2/core'; +import {TodoStore, Todo} from './services/store'; + +@Component({ + selector: 'todo-app', + templateUrl: 'app/app.html' +}) +export default class TodoApp { + todoStore: TodoStore; + newTodoText = ''; + + constructor(todoStore: TodoStore) { + this.todoStore = todoStore; + } + + identify(index: number) { + return index; + } + + stopEditing(todo: Todo, editedTitle: string) { + todo.title = editedTitle; + todo.editing = false; + } + + cancelEditingTodo(todo: Todo) { + todo.editing = false; + } + + updateEditingTodo(todo: Todo, editedTitle: string) { + editedTitle = editedTitle.trim(); + todo.editing = false; + + if (editedTitle.length === 0) { + return this.todoStore.remove(todo); + } + + todo.title = editedTitle; + } + + editTodo(todo: Todo) { + todo.editing = true; + } + + removeCompleted() { + this.todoStore.removeCompleted(); + } + + toggleCompletion(todo: Todo) { + this.todoStore.toggleCompletion(todo); + } + + remove(todo: Todo){ + this.todoStore.remove(todo); + } + + addTodo() { + if (this.newTodoText.trim().length) { + this.todoStore.add(this.newTodoText); + this.newTodoText = ''; + } + } +} diff --git a/bench/implementations/angular-2-optimized/app/bootstrap.ts b/bench/implementations/angular-2-optimized/app/bootstrap.ts new file mode 100644 index 0000000..fd300af --- /dev/null +++ b/bench/implementations/angular-2-optimized/app/bootstrap.ts @@ -0,0 +1,9 @@ +/// + +import {bootstrap} from 'angular2/platform/browser'; +import TodoApp from './app' +import {TodoStore} from './services/store'; +import {enableProdMode} from 'angular2/core'; + +enableProdMode(); +bootstrap(TodoApp, [TodoStore]); diff --git a/bench/implementations/angular-2-optimized/app/services/store.ts b/bench/implementations/angular-2-optimized/app/services/store.ts new file mode 100644 index 0000000..ca4e3b6 --- /dev/null +++ b/bench/implementations/angular-2-optimized/app/services/store.ts @@ -0,0 +1,62 @@ +export class Todo { + completed: Boolean; + editing: Boolean; + + private _title: String; + get title() { + return this._title; + } + set title(value: String) { + this._title = value.trim(); + } + + constructor(title: String) { + this.completed = false; + this.editing = false; + this.title = title.trim(); + } +} + +export class TodoStore { + todos: Array; + + constructor() { + this.todos = []; + } + + private getWithCompleted(completed: Boolean) { + return this.todos.filter((todo: Todo) => todo.completed === completed); + } + + allCompleted() { + return this.todos.length === this.getCompleted().length; + } + + setAllTo(completed: Boolean) { + this.todos.forEach((t: Todo) => t.completed = completed); + } + + removeCompleted() { + this.todos = this.getWithCompleted(false); + } + + getRemaining() { + return this.getWithCompleted(false); + } + + getCompleted() { + return this.getWithCompleted(true); + } + + toggleCompletion(todo: Todo) { + todo.completed = !todo.completed; + } + + remove(todo: Todo) { + this.todos.splice(this.todos.indexOf(todo), 1); + } + + add(title: String) { + this.todos.push(new Todo(title)); + } +} diff --git a/bench/implementations/angular-2-optimized/index.html b/bench/implementations/angular-2-optimized/index.html new file mode 100644 index 0000000..563d5af --- /dev/null +++ b/bench/implementations/angular-2-optimized/index.html @@ -0,0 +1,35 @@ + + + + + Angular2 • TodoMVC + + + + + + + + + + + + + diff --git a/bench/implementations/angular-2-optimized/package.json b/bench/implementations/angular-2-optimized/package.json new file mode 100644 index 0000000..a12d63e --- /dev/null +++ b/bench/implementations/angular-2-optimized/package.json @@ -0,0 +1,19 @@ +{ + "private": true, + "scripts": { + "dev": "tsc" + }, + "devDependencies": { + "typescript": "^1.8.10" + }, + "dependencies": { + "angular2": "^2.0.0-beta.17", + "es6-shim": "^0.35.1", + "reflect-metadata": "0.1.2", + "rxjs": "5.0.0-beta.6", + "systemjs": "0.19.6", + "todomvc-app-css": "^2.0.0", + "todomvc-common": "^1.0.1", + "zone.js": "^0.6.17" + } +} diff --git a/bench/implementations/angular-2-optimized/readme.md b/bench/implementations/angular-2-optimized/readme.md new file mode 100644 index 0000000..aace877 --- /dev/null +++ b/bench/implementations/angular-2-optimized/readme.md @@ -0,0 +1,32 @@ +# Angular 2 • [TodoMVC](http://todomvc.com) + +> Angular is a development platform for creating applications using modern web standards. Angular includes a wealth of essential features such as mobile gestures, animations, filtering, routing, data binding, security, internationalization, and beautiful UI components. It's extremely modular, lightweight, and easy to learn. + +## Resources + +- [Website](https://angular.io/) +- [Documentation](https://angular.io/docs/ts/latest/) + +### Articles + +- [Angular 2 Beta Announcement](http://angularjs.blogspot.co.uk/2015/12/angular-2-beta.html) + +### Support + +- [StackOverflow](http://stackoverflow.com/questions/tagged/angular2) +- [Google Groups](https://groups.google.com/forum/#!forum/angular) +- [Twitter](http://twitter.com/angularjs) +- [Google+](https://plus.sandbox.google.com/+AngularJS/posts) + +*Let us [know](https://github.com/tastejs/todomvc/issues) if you discover anything worth sharing.* + +## Implementation + +This app was built using TypeScript and Angular 2 beta. To make changes simply + +* `npm i` +* `npm run dev` + +## Credit + +Created by [Sam Saccone](http://github.com/samccone) diff --git a/bench/implementations/angular-2-optimized/tsconfig.json b/bench/implementations/angular-2-optimized/tsconfig.json new file mode 100644 index 0000000..8b3de5f --- /dev/null +++ b/bench/implementations/angular-2-optimized/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "target": "ES5", + "module": "commonjs", + "moduleResolution": "node", + "sourceMap": false, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "removeComments": false, + "noImplicitAny": true + }, + "files": [ + "app/bootstrap.ts" + ] +} diff --git a/bench/implementations/angular-2/.gitignore b/bench/implementations/angular-2/.gitignore new file mode 100755 index 0000000..64ee7d5 --- /dev/null +++ b/bench/implementations/angular-2/.gitignore @@ -0,0 +1,28 @@ +node_modules/.bin + +# ignore the source / documentation of each node module, but retain the +# distribution builds + +node_modules/systemjs +!node_modules/systemjs/dist/system.src.js + +node_modules/todomvc-app-css +!node_modules/todomvc-app-css/index.css + +node_modules/todomvc-common +!node_modules/todomvc-common/base.css + +node_modules/angular2 +!node_modules/angular2/bundles/angular2-polyfills.js +!node_modules/angular2/bundles/angular2.dev.js + +node_modules/rxjs +!node_modules/rxjs/bundles/Rx.js + +# Ignore development dependencies +node_modules/tsd +node_modules/typescript + +*.js +*.js.map +typings diff --git a/bench/implementations/angular-2/app/app.html b/bench/implementations/angular-2/app/app.html new file mode 100755 index 0000000..9718565 --- /dev/null +++ b/bench/implementations/angular-2/app/app.html @@ -0,0 +1,23 @@ +
+
+

todos

+ +
+
+ +
    +
  • +
    + + + +
    + +
  • +
+
+
+ {{todoStore.getRemaining().length}} {{todoStore.getRemaining().length == 1 ? 'item' : 'items'}} left + +
+
diff --git a/bench/implementations/angular-2/app/app.ts b/bench/implementations/angular-2/app/app.ts new file mode 100755 index 0000000..74b8391 --- /dev/null +++ b/bench/implementations/angular-2/app/app.ts @@ -0,0 +1,58 @@ +import {Component} from 'angular2/core'; +import {TodoStore, Todo} from './services/store'; + +@Component({ + selector: 'todo-app', + templateUrl: 'app/app.html' +}) +export default class TodoApp { + todoStore: TodoStore; + newTodoText = ''; + + constructor(todoStore: TodoStore) { + this.todoStore = todoStore; + } + + stopEditing(todo: Todo, editedTitle: string) { + todo.title = editedTitle; + todo.editing = false; + } + + cancelEditingTodo(todo: Todo) { + todo.editing = false; + } + + updateEditingTodo(todo: Todo, editedTitle: string) { + editedTitle = editedTitle.trim(); + todo.editing = false; + + if (editedTitle.length === 0) { + return this.todoStore.remove(todo); + } + + todo.title = editedTitle; + } + + editTodo(todo: Todo) { + todo.editing = true; + } + + removeCompleted() { + this.todoStore.removeCompleted(); + } + + toggleCompletion(todo: Todo) { + this.todoStore.toggleCompletion(todo); + } + + remove(todo: Todo){ + this.todoStore.remove(todo); + } + + addTodo() { + if (this.newTodoText.trim().length) { + this.todoStore.add(this.newTodoText); + this.newTodoText = ''; + } + } +} diff --git a/bench/implementations/angular-2/app/bootstrap.ts b/bench/implementations/angular-2/app/bootstrap.ts new file mode 100755 index 0000000..fd300af --- /dev/null +++ b/bench/implementations/angular-2/app/bootstrap.ts @@ -0,0 +1,9 @@ +/// + +import {bootstrap} from 'angular2/platform/browser'; +import TodoApp from './app' +import {TodoStore} from './services/store'; +import {enableProdMode} from 'angular2/core'; + +enableProdMode(); +bootstrap(TodoApp, [TodoStore]); diff --git a/bench/implementations/angular-2/app/services/store.ts b/bench/implementations/angular-2/app/services/store.ts new file mode 100755 index 0000000..ca4e3b6 --- /dev/null +++ b/bench/implementations/angular-2/app/services/store.ts @@ -0,0 +1,62 @@ +export class Todo { + completed: Boolean; + editing: Boolean; + + private _title: String; + get title() { + return this._title; + } + set title(value: String) { + this._title = value.trim(); + } + + constructor(title: String) { + this.completed = false; + this.editing = false; + this.title = title.trim(); + } +} + +export class TodoStore { + todos: Array; + + constructor() { + this.todos = []; + } + + private getWithCompleted(completed: Boolean) { + return this.todos.filter((todo: Todo) => todo.completed === completed); + } + + allCompleted() { + return this.todos.length === this.getCompleted().length; + } + + setAllTo(completed: Boolean) { + this.todos.forEach((t: Todo) => t.completed = completed); + } + + removeCompleted() { + this.todos = this.getWithCompleted(false); + } + + getRemaining() { + return this.getWithCompleted(false); + } + + getCompleted() { + return this.getWithCompleted(true); + } + + toggleCompletion(todo: Todo) { + todo.completed = !todo.completed; + } + + remove(todo: Todo) { + this.todos.splice(this.todos.indexOf(todo), 1); + } + + add(title: String) { + this.todos.push(new Todo(title)); + } +} diff --git a/bench/implementations/angular-2/index.html b/bench/implementations/angular-2/index.html new file mode 100755 index 0000000..563d5af --- /dev/null +++ b/bench/implementations/angular-2/index.html @@ -0,0 +1,35 @@ + + + + + Angular2 • TodoMVC + + + + + + + + + + + + + diff --git a/bench/implementations/angular-2/package.json b/bench/implementations/angular-2/package.json new file mode 100755 index 0000000..a12d63e --- /dev/null +++ b/bench/implementations/angular-2/package.json @@ -0,0 +1,19 @@ +{ + "private": true, + "scripts": { + "dev": "tsc" + }, + "devDependencies": { + "typescript": "^1.8.10" + }, + "dependencies": { + "angular2": "^2.0.0-beta.17", + "es6-shim": "^0.35.1", + "reflect-metadata": "0.1.2", + "rxjs": "5.0.0-beta.6", + "systemjs": "0.19.6", + "todomvc-app-css": "^2.0.0", + "todomvc-common": "^1.0.1", + "zone.js": "^0.6.17" + } +} diff --git a/bench/implementations/angular-2/readme.md b/bench/implementations/angular-2/readme.md new file mode 100755 index 0000000..aace877 --- /dev/null +++ b/bench/implementations/angular-2/readme.md @@ -0,0 +1,32 @@ +# Angular 2 • [TodoMVC](http://todomvc.com) + +> Angular is a development platform for creating applications using modern web standards. Angular includes a wealth of essential features such as mobile gestures, animations, filtering, routing, data binding, security, internationalization, and beautiful UI components. It's extremely modular, lightweight, and easy to learn. + +## Resources + +- [Website](https://angular.io/) +- [Documentation](https://angular.io/docs/ts/latest/) + +### Articles + +- [Angular 2 Beta Announcement](http://angularjs.blogspot.co.uk/2015/12/angular-2-beta.html) + +### Support + +- [StackOverflow](http://stackoverflow.com/questions/tagged/angular2) +- [Google Groups](https://groups.google.com/forum/#!forum/angular) +- [Twitter](http://twitter.com/angularjs) +- [Google+](https://plus.sandbox.google.com/+AngularJS/posts) + +*Let us [know](https://github.com/tastejs/todomvc/issues) if you discover anything worth sharing.* + +## Implementation + +This app was built using TypeScript and Angular 2 beta. To make changes simply + +* `npm i` +* `npm run dev` + +## Credit + +Created by [Sam Saccone](http://github.com/samccone) diff --git a/bench/implementations/angular-2/tsconfig.json b/bench/implementations/angular-2/tsconfig.json new file mode 100755 index 0000000..8b3de5f --- /dev/null +++ b/bench/implementations/angular-2/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "target": "ES5", + "module": "commonjs", + "moduleResolution": "node", + "sourceMap": false, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "removeComments": false, + "noImplicitAny": true + }, + "files": [ + "app/bootstrap.ts" + ] +} diff --git a/bench/implementations/elm-0.16-optimized/Todo.elm b/bench/implementations/elm-0.16-optimized/Todo.elm new file mode 100755 index 0000000..4b6c07a --- /dev/null +++ b/bench/implementations/elm-0.16-optimized/Todo.elm @@ -0,0 +1,339 @@ +module Todo where +{-| TodoMVC implemented in Elm, using plain HTML and CSS for rendering. + +This application is broken up into four distinct parts: + + 1. Model - a full definition of the application's state + 2. Update - a way to step the application state forward + 3. View - a way to visualize our application state with HTML + 4. Inputs - the signals necessary to manage events + +This clean division of concerns is a core part of Elm. You can read more about +this in the Pong tutorial: http://elm-lang.org/blog/making-pong + +This program is not particularly large, so definitely see the following +for notes on structuring more complex GUIs with Elm: +https://github.com/evancz/elm-architecture-tutorial/ +-} + +import Html exposing (..) +import Html.Attributes exposing (..) +import Html.Events exposing (..) +import Html.Lazy exposing (lazy2, lazy3) +import Json.Decode as Json +import Signal exposing (Signal, Address) +import String +import Window + + +---- MODEL ---- + +-- The full application state of our todo app. +type alias Model = + { tasks : List Task + , field : String + , uid : Int + , visibility : String + } + + +type alias Task = + { description : String + , completed : Bool + , editing : Bool + , id : Int + } + + +newTask : String -> Int -> Task +newTask desc id = + { description = desc + , completed = False + , editing = False + , id = id + } + + +emptyModel : Model +emptyModel = + { tasks = [] + , visibility = "All" + , field = "" + , uid = 0 + } + + +---- UPDATE ---- + +-- A description of the kinds of actions that can be performed on the model of +-- our application. See the following for more info on this pattern and +-- some alternatives: https://github.com/evancz/elm-architecture-tutorial/ +type Action + = NoOp + | UpdateField String + | EditingTask Int Bool + | UpdateTask Int String + | Add + | Delete Int + | DeleteComplete + | Check Int Bool + | CheckAll Bool + | ChangeVisibility String + + +-- How we update our Model on a given Action? +update : Action -> Model -> Model +update action model = + case action of + NoOp -> model + + Add -> + { model | + uid = model.uid + 1, + field = "", + tasks = + if String.isEmpty model.field + then model.tasks + else model.tasks ++ [newTask model.field model.uid] + } + + UpdateField str -> + { model | field = str } + + EditingTask id isEditing -> + let updateTask t = if t.id == id then { t | editing = isEditing } else t + in + { model | tasks = List.map updateTask model.tasks } + + UpdateTask id task -> + let updateTask t = if t.id == id then { t | description = task } else t + in + { model | tasks = List.map updateTask model.tasks } + + Delete id -> + { model | tasks = List.filter (\t -> t.id /= id) model.tasks } + + DeleteComplete -> + { model | tasks = List.filter (not << .completed) model.tasks } + + Check id isCompleted -> + let updateTask t = if t.id == id then { t | completed = isCompleted } else t + in + { model | tasks = List.map updateTask model.tasks } + + CheckAll isCompleted -> + let updateTask t = { t | completed = isCompleted } + in + { model | tasks = List.map updateTask model.tasks } + + ChangeVisibility visibility -> + { model | visibility = visibility } + + +---- VIEW ---- + +view : Address Action -> Model -> Html +view address model = + div + [ class "todomvc-wrapper" + , style [ ("visibility", "hidden") ] + ] + [ section + [ class "todoapp" ] + [ lazy2 taskEntry address model.field + , lazy3 taskList address model.visibility model.tasks + , lazy3 controls address model.visibility model.tasks + ] + , infoFooter + ] + + +onEnter : Address a -> a -> Attribute +onEnter address value = + on "keydown" + (Json.customDecoder keyCode is13) + (\_ -> Signal.message address value) + + +is13 : Int -> Result String () +is13 code = + if code == 13 then Ok () else Err "not the right key code" + + +taskEntry : Address Action -> String -> Html +taskEntry address task = + header + [ class "header" ] + [ h1 [] [ text "todos" ] + , input + [ class "new-todo" + , placeholder "What needs to be done?" + , autofocus True + , value task + , name "newTodo" + , on "input" targetValue (Signal.message address << UpdateField) + , onEnter address Add + ] + [] + ] + + +taskList : Address Action -> String -> List Task -> Html +taskList address visibility tasks = + let isVisible todo = + case visibility of + "Completed" -> todo.completed + "Active" -> not todo.completed + _ -> True + + allCompleted = List.all .completed tasks + + cssVisibility = if List.isEmpty tasks then "hidden" else "visible" + in + section + [ class "main" + , style [ ("visibility", cssVisibility) ] + ] + [ input + [ class "toggle-all" + , type' "checkbox" + , name "toggle" + , checked allCompleted + , onClick address (CheckAll (not allCompleted)) + ] + [] + , label + [ for "toggle-all" ] + [ text "Mark all as complete" ] + , ul + [ class "todo-list" ] + (List.map (todoItem address) (List.filter isVisible tasks)) + ] + + +todoItem : Address Action -> Task -> Html +todoItem address todo = + li + [ classList [ ("completed", todo.completed), ("editing", todo.editing) ] + , key (toString todo.id) + ] + [ div + [ class "view" ] + [ input + [ class "toggle" + , type' "checkbox" + , checked todo.completed + , onClick address (Check todo.id (not todo.completed)) + ] + [] + , label + [ onDoubleClick address (EditingTask todo.id True) ] + [ text todo.description ] + , button + [ class "destroy" + , onClick address (Delete todo.id) + ] + [] + ] + , input + [ class "edit" + , value todo.description + , name "title" + , id ("todo-" ++ toString todo.id) + , on "input" targetValue (Signal.message address << UpdateTask todo.id) + , onBlur address (EditingTask todo.id False) + , onEnter address (EditingTask todo.id False) + ] + [] + ] + + +controls : Address Action -> String -> List Task -> Html +controls address visibility tasks = + let tasksCompleted = List.length (List.filter .completed tasks) + tasksLeft = List.length tasks - tasksCompleted + item_ = if tasksLeft == 1 then " item" else " items" + in + footer + [ class "footer" + , hidden (List.isEmpty tasks) + ] + [ span + [ class "todo-count" ] + [ strong [] [ text (toString tasksLeft) ] + , text (item_ ++ " left") + ] + , ul + [ class "filters" ] + [ visibilitySwap address "#/" "All" visibility + , text " " + , visibilitySwap address "#/active" "Active" visibility + , text " " + , visibilitySwap address "#/completed" "Completed" visibility + ] + , button + [ class "clear-completed" + , hidden (tasksCompleted == 0) + , onClick address DeleteComplete + ] + [ text ("Clear completed (" ++ toString tasksCompleted ++ ")") ] + ] + + +visibilitySwap : Address Action -> String -> String -> String -> Html +visibilitySwap address uri visibility actualVisibility = + li + [ onClick address (ChangeVisibility visibility) ] + [ a [ href uri, classList [("selected", visibility == actualVisibility)] ] [ text visibility ] ] + + +infoFooter : Html +infoFooter = + footer [ class "info" ] + [ p [] [ text "Double-click to edit a todo" ] + , p [] + [ text "Written by " + , a [ href "https://github.com/evancz" ] [ text "Evan Czaplicki" ] + ] + , p [] + [ text "Part of " + , a [ href "http://todomvc.com" ] [ text "TodoMVC" ] + ] + ] + + +---- INPUTS ---- + +-- wire the entire application together +main : Signal Html +main = + Signal.map (view actions.address) model + + +-- manage the model of our application over time +model : Signal Model +model = + Signal.foldp update emptyModel actions.signal + + +-- actions from user input +actions : Signal.Mailbox Action +actions = + Signal.mailbox NoOp + + +port focus : Signal String +port focus = + let needsFocus act = + case act of + EditingTask id bool -> bool + _ -> False + + toSelector act = + case act of + EditingTask id _ -> "#todo-" ++ toString id + _ -> "" + in + actions.signal + |> Signal.filter needsFocus (EditingTask 0 True) + |> Signal.map toSelector diff --git a/bench/implementations/elm-0.16-optimized/elm-package.json b/bench/implementations/elm-0.16-optimized/elm-package.json new file mode 100644 index 0000000..0c8a4c4 --- /dev/null +++ b/bench/implementations/elm-0.16-optimized/elm-package.json @@ -0,0 +1,15 @@ +{ + "version": "1.0.0", + "summary": "TodoMVC created with Elm and elm-html", + "repository": "https://github.com/evancz/elm-todomvc.git", + "license": "BSD3", + "source-directories": [ + "." + ], + "exposed-modules": [], + "dependencies": { + "elm-lang/core": "3.0.0 <= v < 4.0.0", + "evancz/elm-html": "4.0.2 <= v < 5.0.0" + }, + "elm-version": "0.16.0 <= v < 0.17.0" +} diff --git a/bench/implementations/elm-0.16-optimized/elm.js b/bench/implementations/elm-0.16-optimized/elm.js new file mode 100755 index 0000000..416e212 --- /dev/null +++ b/bench/implementations/elm-0.16-optimized/elm.js @@ -0,0 +1,10560 @@ +var Elm = Elm || { Native: {} }; +Elm.Native.Array = {}; +Elm.Native.Array.make = function(localRuntime) { + + localRuntime.Native = localRuntime.Native || {}; + localRuntime.Native.Array = localRuntime.Native.Array || {}; + if (localRuntime.Native.Array.values) + { + return localRuntime.Native.Array.values; + } + if ('values' in Elm.Native.Array) + { + return localRuntime.Native.Array.values = Elm.Native.Array.values; + } + + var List = Elm.Native.List.make(localRuntime); + + // A RRB-Tree has two distinct data types. + // Leaf -> "height" is always 0 + // "table" is an array of elements + // Node -> "height" is always greater than 0 + // "table" is an array of child nodes + // "lengths" is an array of accumulated lengths of the child nodes + + // M is the maximal table size. 32 seems fast. E is the allowed increase + // of search steps when concatting to find an index. Lower values will + // decrease balancing, but will increase search steps. + var M = 32; + var E = 2; + + // An empty array. + var empty = { + ctor: '_Array', + height: 0, + table: [] + }; + + + function get(i, array) + { + if (i < 0 || i >= length(array)) + { + throw new Error( + 'Index ' + i + ' is out of range. Check the length of ' + + 'your array first or use getMaybe or getWithDefault.'); + } + return unsafeGet(i, array); + } + + + function unsafeGet(i, array) + { + for (var x = array.height; x > 0; x--) + { + var slot = i >> (x * 5); + while (array.lengths[slot] <= i) + { + slot++; + } + if (slot > 0) + { + i -= array.lengths[slot - 1]; + } + array = array.table[slot]; + } + return array.table[i]; + } + + + // Sets the value at the index i. Only the nodes leading to i will get + // copied and updated. + function set(i, item, array) + { + if (i < 0 || length(array) <= i) + { + return array; + } + return unsafeSet(i, item, array); + } + + + function unsafeSet(i, item, array) + { + array = nodeCopy(array); + + if (array.height === 0) + { + array.table[i] = item; + } + else + { + var slot = getSlot(i, array); + if (slot > 0) + { + i -= array.lengths[slot - 1]; + } + array.table[slot] = unsafeSet(i, item, array.table[slot]); + } + return array; + } + + + function initialize(len, f) + { + if (len <= 0) + { + return empty; + } + var h = Math.floor( Math.log(len) / Math.log(M) ); + return initialize_(f, h, 0, len); + } + + function initialize_(f, h, from, to) + { + if (h === 0) + { + var table = new Array((to - from) % (M + 1)); + for (var i = 0; i < table.length; i++) + { + table[i] = f(from + i); + } + return { + ctor: '_Array', + height: 0, + table: table + }; + } + + var step = Math.pow(M, h); + var table = new Array(Math.ceil((to - from) / step)); + var lengths = new Array(table.length); + for (var i = 0; i < table.length; i++) + { + table[i] = initialize_(f, h - 1, from + (i * step), Math.min(from + ((i + 1) * step), to)); + lengths[i] = length(table[i]) + (i > 0 ? lengths[i-1] : 0); + } + return { + ctor: '_Array', + height: h, + table: table, + lengths: lengths + }; + } + + function fromList(list) + { + if (list === List.Nil) + { + return empty; + } + + // Allocate M sized blocks (table) and write list elements to it. + var table = new Array(M); + var nodes = []; + var i = 0; + + while (list.ctor !== '[]') + { + table[i] = list._0; + list = list._1; + i++; + + // table is full, so we can push a leaf containing it into the + // next node. + if (i === M) + { + var leaf = { + ctor: '_Array', + height: 0, + table: table + }; + fromListPush(leaf, nodes); + table = new Array(M); + i = 0; + } + } + + // Maybe there is something left on the table. + if (i > 0) + { + var leaf = { + ctor: '_Array', + height: 0, + table: table.splice(0, i) + }; + fromListPush(leaf, nodes); + } + + // Go through all of the nodes and eventually push them into higher nodes. + for (var h = 0; h < nodes.length - 1; h++) + { + if (nodes[h].table.length > 0) + { + fromListPush(nodes[h], nodes); + } + } + + var head = nodes[nodes.length - 1]; + if (head.height > 0 && head.table.length === 1) + { + return head.table[0]; + } + else + { + return head; + } + } + + // Push a node into a higher node as a child. + function fromListPush(toPush, nodes) + { + var h = toPush.height; + + // Maybe the node on this height does not exist. + if (nodes.length === h) + { + var node = { + ctor: '_Array', + height: h + 1, + table: [], + lengths: [] + }; + nodes.push(node); + } + + nodes[h].table.push(toPush); + var len = length(toPush); + if (nodes[h].lengths.length > 0) + { + len += nodes[h].lengths[nodes[h].lengths.length - 1]; + } + nodes[h].lengths.push(len); + + if (nodes[h].table.length === M) + { + fromListPush(nodes[h], nodes); + nodes[h] = { + ctor: '_Array', + height: h + 1, + table: [], + lengths: [] + }; + } + } + + // Pushes an item via push_ to the bottom right of a tree. + function push(item, a) + { + var pushed = push_(item, a); + if (pushed !== null) + { + return pushed; + } + + var newTree = create(item, a.height); + return siblise(a, newTree); + } + + // Recursively tries to push an item to the bottom-right most + // tree possible. If there is no space left for the item, + // null will be returned. + function push_(item, a) + { + // Handle resursion stop at leaf level. + if (a.height === 0) + { + if (a.table.length < M) + { + var newA = { + ctor: '_Array', + height: 0, + table: a.table.slice() + }; + newA.table.push(item); + return newA; + } + else + { + return null; + } + } + + // Recursively push + var pushed = push_(item, botRight(a)); + + // There was space in the bottom right tree, so the slot will + // be updated. + if (pushed !== null) + { + var newA = nodeCopy(a); + newA.table[newA.table.length - 1] = pushed; + newA.lengths[newA.lengths.length - 1]++; + return newA; + } + + // When there was no space left, check if there is space left + // for a new slot with a tree which contains only the item + // at the bottom. + if (a.table.length < M) + { + var newSlot = create(item, a.height - 1); + var newA = nodeCopy(a); + newA.table.push(newSlot); + newA.lengths.push(newA.lengths[newA.lengths.length - 1] + length(newSlot)); + return newA; + } + else + { + return null; + } + } + + // Converts an array into a list of elements. + function toList(a) + { + return toList_(List.Nil, a); + } + + function toList_(list, a) + { + for (var i = a.table.length - 1; i >= 0; i--) + { + list = + a.height === 0 + ? List.Cons(a.table[i], list) + : toList_(list, a.table[i]); + } + return list; + } + + // Maps a function over the elements of an array. + function map(f, a) + { + var newA = { + ctor: '_Array', + height: a.height, + table: new Array(a.table.length) + }; + if (a.height > 0) + { + newA.lengths = a.lengths; + } + for (var i = 0; i < a.table.length; i++) + { + newA.table[i] = + a.height === 0 + ? f(a.table[i]) + : map(f, a.table[i]); + } + return newA; + } + + // Maps a function over the elements with their index as first argument. + function indexedMap(f, a) + { + return indexedMap_(f, a, 0); + } + + function indexedMap_(f, a, from) + { + var newA = { + ctor: '_Array', + height: a.height, + table: new Array(a.table.length) + }; + if (a.height > 0) + { + newA.lengths = a.lengths; + } + for (var i = 0; i < a.table.length; i++) + { + newA.table[i] = + a.height === 0 + ? A2(f, from + i, a.table[i]) + : indexedMap_(f, a.table[i], i == 0 ? from : from + a.lengths[i - 1]); + } + return newA; + } + + function foldl(f, b, a) + { + if (a.height === 0) + { + for (var i = 0; i < a.table.length; i++) + { + b = A2(f, a.table[i], b); + } + } + else + { + for (var i = 0; i < a.table.length; i++) + { + b = foldl(f, b, a.table[i]); + } + } + return b; + } + + function foldr(f, b, a) + { + if (a.height === 0) + { + for (var i = a.table.length; i--; ) + { + b = A2(f, a.table[i], b); + } + } + else + { + for (var i = a.table.length; i--; ) + { + b = foldr(f, b, a.table[i]); + } + } + return b; + } + + // TODO: currently, it slices the right, then the left. This can be + // optimized. + function slice(from, to, a) + { + if (from < 0) + { + from += length(a); + } + if (to < 0) + { + to += length(a); + } + return sliceLeft(from, sliceRight(to, a)); + } + + function sliceRight(to, a) + { + if (to === length(a)) + { + return a; + } + + // Handle leaf level. + if (a.height === 0) + { + var newA = { ctor:'_Array', height:0 }; + newA.table = a.table.slice(0, to); + return newA; + } + + // Slice the right recursively. + var right = getSlot(to, a); + var sliced = sliceRight(to - (right > 0 ? a.lengths[right - 1] : 0), a.table[right]); + + // Maybe the a node is not even needed, as sliced contains the whole slice. + if (right === 0) + { + return sliced; + } + + // Create new node. + var newA = { + ctor: '_Array', + height: a.height, + table: a.table.slice(0, right), + lengths: a.lengths.slice(0, right) + }; + if (sliced.table.length > 0) + { + newA.table[right] = sliced; + newA.lengths[right] = length(sliced) + (right > 0 ? newA.lengths[right - 1] : 0); + } + return newA; + } + + function sliceLeft(from, a) + { + if (from === 0) + { + return a; + } + + // Handle leaf level. + if (a.height === 0) + { + var newA = { ctor:'_Array', height:0 }; + newA.table = a.table.slice(from, a.table.length + 1); + return newA; + } + + // Slice the left recursively. + var left = getSlot(from, a); + var sliced = sliceLeft(from - (left > 0 ? a.lengths[left - 1] : 0), a.table[left]); + + // Maybe the a node is not even needed, as sliced contains the whole slice. + if (left === a.table.length - 1) + { + return sliced; + } + + // Create new node. + var newA = { + ctor: '_Array', + height: a.height, + table: a.table.slice(left, a.table.length + 1), + lengths: new Array(a.table.length - left) + }; + newA.table[0] = sliced; + var len = 0; + for (var i = 0; i < newA.table.length; i++) + { + len += length(newA.table[i]); + newA.lengths[i] = len; + } + + return newA; + } + + // Appends two trees. + function append(a,b) + { + if (a.table.length === 0) + { + return b; + } + if (b.table.length === 0) + { + return a; + } + + var c = append_(a, b); + + // Check if both nodes can be crunshed together. + if (c[0].table.length + c[1].table.length <= M) + { + if (c[0].table.length === 0) + { + return c[1]; + } + if (c[1].table.length === 0) + { + return c[0]; + } + + // Adjust .table and .lengths + c[0].table = c[0].table.concat(c[1].table); + if (c[0].height > 0) + { + var len = length(c[0]); + for (var i = 0; i < c[1].lengths.length; i++) + { + c[1].lengths[i] += len; + } + c[0].lengths = c[0].lengths.concat(c[1].lengths); + } + + return c[0]; + } + + if (c[0].height > 0) + { + var toRemove = calcToRemove(a, b); + if (toRemove > E) + { + c = shuffle(c[0], c[1], toRemove); + } + } + + return siblise(c[0], c[1]); + } + + // Returns an array of two nodes; right and left. One node _may_ be empty. + function append_(a, b) + { + if (a.height === 0 && b.height === 0) + { + return [a, b]; + } + + if (a.height !== 1 || b.height !== 1) + { + if (a.height === b.height) + { + a = nodeCopy(a); + b = nodeCopy(b); + var appended = append_(botRight(a), botLeft(b)); + + insertRight(a, appended[1]); + insertLeft(b, appended[0]); + } + else if (a.height > b.height) + { + a = nodeCopy(a); + var appended = append_(botRight(a), b); + + insertRight(a, appended[0]); + b = parentise(appended[1], appended[1].height + 1); + } + else + { + b = nodeCopy(b); + var appended = append_(a, botLeft(b)); + + var left = appended[0].table.length === 0 ? 0 : 1; + var right = left === 0 ? 1 : 0; + insertLeft(b, appended[left]); + a = parentise(appended[right], appended[right].height + 1); + } + } + + // Check if balancing is needed and return based on that. + if (a.table.length === 0 || b.table.length === 0) + { + return [a, b]; + } + + var toRemove = calcToRemove(a, b); + if (toRemove <= E) + { + return [a, b]; + } + return shuffle(a, b, toRemove); + } + + // Helperfunctions for append_. Replaces a child node at the side of the parent. + function insertRight(parent, node) + { + var index = parent.table.length - 1; + parent.table[index] = node; + parent.lengths[index] = length(node); + parent.lengths[index] += index > 0 ? parent.lengths[index - 1] : 0; + } + + function insertLeft(parent, node) + { + if (node.table.length > 0) + { + parent.table[0] = node; + parent.lengths[0] = length(node); + + var len = length(parent.table[0]); + for (var i = 1; i < parent.lengths.length; i++) + { + len += length(parent.table[i]); + parent.lengths[i] = len; + } + } + else + { + parent.table.shift(); + for (var i = 1; i < parent.lengths.length; i++) + { + parent.lengths[i] = parent.lengths[i] - parent.lengths[0]; + } + parent.lengths.shift(); + } + } + + // Returns the extra search steps for E. Refer to the paper. + function calcToRemove(a, b) + { + var subLengths = 0; + for (var i = 0; i < a.table.length; i++) + { + subLengths += a.table[i].table.length; + } + for (var i = 0; i < b.table.length; i++) + { + subLengths += b.table[i].table.length; + } + + var toRemove = a.table.length + b.table.length; + return toRemove - (Math.floor((subLengths - 1) / M) + 1); + } + + // get2, set2 and saveSlot are helpers for accessing elements over two arrays. + function get2(a, b, index) + { + return index < a.length + ? a[index] + : b[index - a.length]; + } + + function set2(a, b, index, value) + { + if (index < a.length) + { + a[index] = value; + } + else + { + b[index - a.length] = value; + } + } + + function saveSlot(a, b, index, slot) + { + set2(a.table, b.table, index, slot); + + var l = (index === 0 || index === a.lengths.length) + ? 0 + : get2(a.lengths, a.lengths, index - 1); + + set2(a.lengths, b.lengths, index, l + length(slot)); + } + + // Creates a node or leaf with a given length at their arrays for perfomance. + // Is only used by shuffle. + function createNode(h, length) + { + if (length < 0) + { + length = 0; + } + var a = { + ctor: '_Array', + height: h, + table: new Array(length) + }; + if (h > 0) + { + a.lengths = new Array(length); + } + return a; + } + + // Returns an array of two balanced nodes. + function shuffle(a, b, toRemove) + { + var newA = createNode(a.height, Math.min(M, a.table.length + b.table.length - toRemove)); + var newB = createNode(a.height, newA.table.length - (a.table.length + b.table.length - toRemove)); + + // Skip the slots with size M. More precise: copy the slot references + // to the new node + var read = 0; + while (get2(a.table, b.table, read).table.length % M === 0) + { + set2(newA.table, newB.table, read, get2(a.table, b.table, read)); + set2(newA.lengths, newB.lengths, read, get2(a.lengths, b.lengths, read)); + read++; + } + + // Pulling items from left to right, caching in a slot before writing + // it into the new nodes. + var write = read; + var slot = new createNode(a.height - 1, 0); + var from = 0; + + // If the current slot is still containing data, then there will be at + // least one more write, so we do not break this loop yet. + while (read - write - (slot.table.length > 0 ? 1 : 0) < toRemove) + { + // Find out the max possible items for copying. + var source = get2(a.table, b.table, read); + var to = Math.min(M - slot.table.length, source.table.length); + + // Copy and adjust size table. + slot.table = slot.table.concat(source.table.slice(from, to)); + if (slot.height > 0) + { + var len = slot.lengths.length; + for (var i = len; i < len + to - from; i++) + { + slot.lengths[i] = length(slot.table[i]); + slot.lengths[i] += (i > 0 ? slot.lengths[i - 1] : 0); + } + } + + from += to; + + // Only proceed to next slots[i] if the current one was + // fully copied. + if (source.table.length <= to) + { + read++; from = 0; + } + + // Only create a new slot if the current one is filled up. + if (slot.table.length === M) + { + saveSlot(newA, newB, write, slot); + slot = createNode(a.height - 1, 0); + write++; + } + } + + // Cleanup after the loop. Copy the last slot into the new nodes. + if (slot.table.length > 0) + { + saveSlot(newA, newB, write, slot); + write++; + } + + // Shift the untouched slots to the left + while (read < a.table.length + b.table.length ) + { + saveSlot(newA, newB, write, get2(a.table, b.table, read)); + read++; + write++; + } + + return [newA, newB]; + } + + // Navigation functions + function botRight(a) + { + return a.table[a.table.length - 1]; + } + function botLeft(a) + { + return a.table[0]; + } + + // Copies a node for updating. Note that you should not use this if + // only updating only one of "table" or "lengths" for performance reasons. + function nodeCopy(a) + { + var newA = { + ctor: '_Array', + height: a.height, + table: a.table.slice() + }; + if (a.height > 0) + { + newA.lengths = a.lengths.slice(); + } + return newA; + } + + // Returns how many items are in the tree. + function length(array) + { + if (array.height === 0) + { + return array.table.length; + } + else + { + return array.lengths[array.lengths.length - 1]; + } + } + + // Calculates in which slot of "table" the item probably is, then + // find the exact slot via forward searching in "lengths". Returns the index. + function getSlot(i, a) + { + var slot = i >> (5 * a.height); + while (a.lengths[slot] <= i) + { + slot++; + } + return slot; + } + + // Recursively creates a tree with a given height containing + // only the given item. + function create(item, h) + { + if (h === 0) + { + return { + ctor: '_Array', + height: 0, + table: [item] + }; + } + return { + ctor: '_Array', + height: h, + table: [create(item, h - 1)], + lengths: [1] + }; + } + + // Recursively creates a tree that contains the given tree. + function parentise(tree, h) + { + if (h === tree.height) + { + return tree; + } + + return { + ctor: '_Array', + height: h, + table: [parentise(tree, h - 1)], + lengths: [length(tree)] + }; + } + + // Emphasizes blood brotherhood beneath two trees. + function siblise(a, b) + { + return { + ctor: '_Array', + height: a.height + 1, + table: [a, b], + lengths: [length(a), length(a) + length(b)] + }; + } + + function toJSArray(a) + { + var jsArray = new Array(length(a)); + toJSArray_(jsArray, 0, a); + return jsArray; + } + + function toJSArray_(jsArray, i, a) + { + for (var t = 0; t < a.table.length; t++) + { + if (a.height === 0) + { + jsArray[i + t] = a.table[t]; + } + else + { + var inc = t === 0 ? 0 : a.lengths[t - 1]; + toJSArray_(jsArray, i + inc, a.table[t]); + } + } + } + + function fromJSArray(jsArray) + { + if (jsArray.length === 0) + { + return empty; + } + var h = Math.floor(Math.log(jsArray.length) / Math.log(M)); + return fromJSArray_(jsArray, h, 0, jsArray.length); + } + + function fromJSArray_(jsArray, h, from, to) + { + if (h === 0) + { + return { + ctor: '_Array', + height: 0, + table: jsArray.slice(from, to) + }; + } + + var step = Math.pow(M, h); + var table = new Array(Math.ceil((to - from) / step)); + var lengths = new Array(table.length); + for (var i = 0; i < table.length; i++) + { + table[i] = fromJSArray_(jsArray, h - 1, from + (i * step), Math.min(from + ((i + 1) * step), to)); + lengths[i] = length(table[i]) + (i > 0 ? lengths[i - 1] : 0); + } + return { + ctor: '_Array', + height: h, + table: table, + lengths: lengths + }; + } + + Elm.Native.Array.values = { + empty: empty, + fromList: fromList, + toList: toList, + initialize: F2(initialize), + append: F2(append), + push: F2(push), + slice: F3(slice), + get: F2(get), + set: F3(set), + map: F2(map), + indexedMap: F2(indexedMap), + foldl: F3(foldl), + foldr: F3(foldr), + length: length, + + toJSArray: toJSArray, + fromJSArray: fromJSArray + }; + + return localRuntime.Native.Array.values = Elm.Native.Array.values; +}; + +Elm.Native.Basics = {}; +Elm.Native.Basics.make = function(localRuntime) { + localRuntime.Native = localRuntime.Native || {}; + localRuntime.Native.Basics = localRuntime.Native.Basics || {}; + if (localRuntime.Native.Basics.values) + { + return localRuntime.Native.Basics.values; + } + + var Utils = Elm.Native.Utils.make(localRuntime); + + function div(a, b) + { + return (a / b) | 0; + } + function rem(a, b) + { + return a % b; + } + function mod(a, b) + { + if (b === 0) + { + throw new Error('Cannot perform mod 0. Division by zero error.'); + } + var r = a % b; + var m = a === 0 ? 0 : (b > 0 ? (a >= 0 ? r : r + b) : -mod(-a, -b)); + + return m === b ? 0 : m; + } + function logBase(base, n) + { + return Math.log(n) / Math.log(base); + } + function negate(n) + { + return -n; + } + function abs(n) + { + return n < 0 ? -n : n; + } + + function min(a, b) + { + return Utils.cmp(a, b) < 0 ? a : b; + } + function max(a, b) + { + return Utils.cmp(a, b) > 0 ? a : b; + } + function clamp(lo, hi, n) + { + return Utils.cmp(n, lo) < 0 ? lo : Utils.cmp(n, hi) > 0 ? hi : n; + } + + function xor(a, b) + { + return a !== b; + } + function not(b) + { + return !b; + } + function isInfinite(n) + { + return n === Infinity || n === -Infinity; + } + + function truncate(n) + { + return n | 0; + } + + function degrees(d) + { + return d * Math.PI / 180; + } + function turns(t) + { + return 2 * Math.PI * t; + } + function fromPolar(point) + { + var r = point._0; + var t = point._1; + return Utils.Tuple2(r * Math.cos(t), r * Math.sin(t)); + } + function toPolar(point) + { + var x = point._0; + var y = point._1; + return Utils.Tuple2(Math.sqrt(x * x + y * y), Math.atan2(y, x)); + } + + return localRuntime.Native.Basics.values = { + div: F2(div), + rem: F2(rem), + mod: F2(mod), + + pi: Math.PI, + e: Math.E, + cos: Math.cos, + sin: Math.sin, + tan: Math.tan, + acos: Math.acos, + asin: Math.asin, + atan: Math.atan, + atan2: F2(Math.atan2), + + degrees: degrees, + turns: turns, + fromPolar: fromPolar, + toPolar: toPolar, + + sqrt: Math.sqrt, + logBase: F2(logBase), + negate: negate, + abs: abs, + min: F2(min), + max: F2(max), + clamp: F3(clamp), + compare: Utils.compare, + + xor: F2(xor), + not: not, + + truncate: truncate, + ceiling: Math.ceil, + floor: Math.floor, + round: Math.round, + toFloat: function(x) { return x; }, + isNaN: isNaN, + isInfinite: isInfinite + }; +}; + +Elm.Native.Port = {}; + +Elm.Native.Port.make = function(localRuntime) { + localRuntime.Native = localRuntime.Native || {}; + localRuntime.Native.Port = localRuntime.Native.Port || {}; + if (localRuntime.Native.Port.values) + { + return localRuntime.Native.Port.values; + } + + var NS; + + // INBOUND + + function inbound(name, type, converter) + { + if (!localRuntime.argsTracker[name]) + { + throw new Error( + 'Port Error:\n' + + 'No argument was given for the port named \'' + name + '\' with type:\n\n' + + ' ' + type.split('\n').join('\n ') + '\n\n' + + 'You need to provide an initial value!\n\n' + + 'Find out more about ports here ' + ); + } + var arg = localRuntime.argsTracker[name]; + arg.used = true; + + return jsToElm(name, type, converter, arg.value); + } + + + function inboundSignal(name, type, converter) + { + var initialValue = inbound(name, type, converter); + + if (!NS) + { + NS = Elm.Native.Signal.make(localRuntime); + } + var signal = NS.input('inbound-port-' + name, initialValue); + + function send(jsValue) + { + var elmValue = jsToElm(name, type, converter, jsValue); + setTimeout(function() { + localRuntime.notify(signal.id, elmValue); + }, 0); + } + + localRuntime.ports[name] = { send: send }; + + return signal; + } + + + function jsToElm(name, type, converter, value) + { + try + { + return converter(value); + } + catch(e) + { + throw new Error( + 'Port Error:\n' + + 'Regarding the port named \'' + name + '\' with type:\n\n' + + ' ' + type.split('\n').join('\n ') + '\n\n' + + 'You just sent the value:\n\n' + + ' ' + JSON.stringify(value) + '\n\n' + + 'but it cannot be converted to the necessary type.\n' + + e.message + ); + } + } + + + // OUTBOUND + + function outbound(name, converter, elmValue) + { + localRuntime.ports[name] = converter(elmValue); + } + + + function outboundSignal(name, converter, signal) + { + var subscribers = []; + + function subscribe(handler) + { + subscribers.push(handler); + } + function unsubscribe(handler) + { + subscribers.pop(subscribers.indexOf(handler)); + } + + function notify(elmValue) + { + var jsValue = converter(elmValue); + var len = subscribers.length; + for (var i = 0; i < len; ++i) + { + subscribers[i](jsValue); + } + } + + if (!NS) + { + NS = Elm.Native.Signal.make(localRuntime); + } + NS.output('outbound-port-' + name, notify, signal); + + localRuntime.ports[name] = { + subscribe: subscribe, + unsubscribe: unsubscribe + }; + + return signal; + } + + + return localRuntime.Native.Port.values = { + inbound: inbound, + outbound: outbound, + inboundSignal: inboundSignal, + outboundSignal: outboundSignal + }; +}; + +if (!Elm.fullscreen) { + (function() { + 'use strict'; + + var Display = { + FULLSCREEN: 0, + COMPONENT: 1, + NONE: 2 + }; + + Elm.fullscreen = function(module, args) + { + var container = document.createElement('div'); + document.body.appendChild(container); + return init(Display.FULLSCREEN, container, module, args || {}); + }; + + Elm.embed = function(module, container, args) + { + var tag = container.tagName; + if (tag !== 'DIV') + { + throw new Error('Elm.node must be given a DIV, not a ' + tag + '.'); + } + return init(Display.COMPONENT, container, module, args || {}); + }; + + Elm.worker = function(module, args) + { + return init(Display.NONE, {}, module, args || {}); + }; + + function init(display, container, module, args, moduleToReplace) + { + // defining state needed for an instance of the Elm RTS + var inputs = []; + + /* OFFSET + * Elm's time traveling debugger lets you pause time. This means + * "now" may be shifted a bit into the past. By wrapping Date.now() + * we can manage this. + */ + var timer = { + programStart: Date.now(), + now: function() + { + return Date.now(); + } + }; + + var updateInProgress = false; + function notify(id, v) + { + if (updateInProgress) + { + throw new Error( + 'The notify function has been called synchronously!\n' + + 'This can lead to frames being dropped.\n' + + 'Definitely report this to \n'); + } + updateInProgress = true; + var timestep = timer.now(); + for (var i = inputs.length; i--; ) + { + inputs[i].notify(timestep, id, v); + } + updateInProgress = false; + } + function setTimeout(func, delay) + { + return window.setTimeout(func, delay); + } + + var listeners = []; + function addListener(relevantInputs, domNode, eventName, func) + { + domNode.addEventListener(eventName, func); + var listener = { + relevantInputs: relevantInputs, + domNode: domNode, + eventName: eventName, + func: func + }; + listeners.push(listener); + } + + var argsTracker = {}; + for (var name in args) + { + argsTracker[name] = { + value: args[name], + used: false + }; + } + + // create the actual RTS. Any impure modules will attach themselves to this + // object. This permits many Elm programs to be embedded per document. + var elm = { + notify: notify, + setTimeout: setTimeout, + node: container, + addListener: addListener, + inputs: inputs, + timer: timer, + argsTracker: argsTracker, + ports: {}, + + isFullscreen: function() { return display === Display.FULLSCREEN; }, + isEmbed: function() { return display === Display.COMPONENT; }, + isWorker: function() { return display === Display.NONE; } + }; + + function swap(newModule) + { + removeListeners(listeners); + var div = document.createElement('div'); + var newElm = init(display, div, newModule, args, elm); + inputs = []; + + return newElm; + } + + function dispose() + { + removeListeners(listeners); + inputs = []; + } + + var Module = {}; + try + { + Module = module.make(elm); + checkInputs(elm); + } + catch (error) + { + if (typeof container.appendChild === "function") + { + container.appendChild(errorNode(error.message)); + } + else + { + console.error(error.message); + } + throw error; + } + + if (display !== Display.NONE) + { + var graphicsNode = initGraphics(elm, Module); + } + + var rootNode = { kids: inputs }; + trimDeadNodes(rootNode); + inputs = rootNode.kids; + filterListeners(inputs, listeners); + + addReceivers(elm.ports); + + if (typeof moduleToReplace !== 'undefined') + { + hotSwap(moduleToReplace, elm); + + // rerender scene if graphics are enabled. + if (typeof graphicsNode !== 'undefined') + { + graphicsNode.notify(0, true, 0); + } + } + + return { + swap: swap, + ports: elm.ports, + dispose: dispose + }; + } + + function checkInputs(elm) + { + var argsTracker = elm.argsTracker; + for (var name in argsTracker) + { + if (!argsTracker[name].used) + { + throw new Error( + "Port Error:\nYou provided an argument named '" + name + + "' but there is no corresponding port!\n\n" + + "Maybe add a port '" + name + "' to your Elm module?\n" + + "Maybe remove the '" + name + "' argument from your initialization code in JS?" + ); + } + } + } + + function errorNode(message) + { + var code = document.createElement('code'); + + var lines = message.split('\n'); + code.appendChild(document.createTextNode(lines[0])); + code.appendChild(document.createElement('br')); + code.appendChild(document.createElement('br')); + for (var i = 1; i < lines.length; ++i) + { + code.appendChild(document.createTextNode('\u00A0 \u00A0 ' + lines[i].replace(/ /g, '\u00A0 '))); + code.appendChild(document.createElement('br')); + } + code.appendChild(document.createElement('br')); + code.appendChild(document.createTextNode('Open the developer console for more details.')); + return code; + } + + + //// FILTER SIGNALS //// + + // TODO: move this code into the signal module and create a function + // Signal.initializeGraph that actually instantiates everything. + + function filterListeners(inputs, listeners) + { + loop: + for (var i = listeners.length; i--; ) + { + var listener = listeners[i]; + for (var j = inputs.length; j--; ) + { + if (listener.relevantInputs.indexOf(inputs[j].id) >= 0) + { + continue loop; + } + } + listener.domNode.removeEventListener(listener.eventName, listener.func); + } + } + + function removeListeners(listeners) + { + for (var i = listeners.length; i--; ) + { + var listener = listeners[i]; + listener.domNode.removeEventListener(listener.eventName, listener.func); + } + } + + // add receivers for built-in ports if they are defined + function addReceivers(ports) + { + if ('title' in ports) + { + if (typeof ports.title === 'string') + { + document.title = ports.title; + } + else + { + ports.title.subscribe(function(v) { document.title = v; }); + } + } + if ('redirect' in ports) + { + ports.redirect.subscribe(function(v) { + if (v.length > 0) + { + window.location = v; + } + }); + } + } + + + // returns a boolean representing whether the node is alive or not. + function trimDeadNodes(node) + { + if (node.isOutput) + { + return true; + } + + var liveKids = []; + for (var i = node.kids.length; i--; ) + { + var kid = node.kids[i]; + if (trimDeadNodes(kid)) + { + liveKids.push(kid); + } + } + node.kids = liveKids; + + return liveKids.length > 0; + } + + + //// RENDERING //// + + function initGraphics(elm, Module) + { + if (!('main' in Module)) + { + throw new Error("'main' is missing! What do I display?!"); + } + + var signalGraph = Module.main; + + // make sure the signal graph is actually a signal & extract the visual model + if (!('notify' in signalGraph)) + { + signalGraph = Elm.Signal.make(elm).constant(signalGraph); + } + var initialScene = signalGraph.value; + + // Figure out what the render functions should be + var render; + var update; + if (initialScene.ctor === 'Element_elm_builtin') + { + var Element = Elm.Native.Graphics.Element.make(elm); + render = Element.render; + update = Element.updateAndReplace; + } + else + { + var VirtualDom = Elm.Native.VirtualDom.make(elm); + render = VirtualDom.render; + update = VirtualDom.updateAndReplace; + } + + // Add the initialScene to the DOM + var container = elm.node; + var node = render(initialScene); + while (container.firstChild) + { + container.removeChild(container.firstChild); + } + container.appendChild(node); + + var _requestAnimationFrame = + typeof requestAnimationFrame !== 'undefined' + ? requestAnimationFrame + : function(cb) { setTimeout(cb, 1000 / 60); } + ; + + // domUpdate is called whenever the main Signal changes. + // + // domUpdate and drawCallback implement a small state machine in order + // to schedule only 1 draw per animation frame. This enforces that + // once draw has been called, it will not be called again until the + // next frame. + // + // drawCallback is scheduled whenever + // 1. The state transitions from PENDING_REQUEST to EXTRA_REQUEST, or + // 2. The state transitions from NO_REQUEST to PENDING_REQUEST + // + // Invariants: + // 1. In the NO_REQUEST state, there is never a scheduled drawCallback. + // 2. In the PENDING_REQUEST and EXTRA_REQUEST states, there is always exactly 1 + // scheduled drawCallback. + var NO_REQUEST = 0; + var PENDING_REQUEST = 1; + var EXTRA_REQUEST = 2; + var state = NO_REQUEST; + var savedScene = initialScene; + var scheduledScene = initialScene; + + function domUpdate(newScene) + { + scheduledScene = newScene; + + update(elm.node.firstChild, savedScene, scheduledScene); + if (elm.Native.Window) + { + elm.Native.Window.values.resizeIfNeeded(); + } + savedScene = scheduledScene; + } + + var renderer = Elm.Native.Signal.make(elm).output('main', domUpdate, signalGraph); + + // must check for resize after 'renderer' is created so + // that changes show up. + if (elm.Native.Window) + { + elm.Native.Window.values.resizeIfNeeded(); + } + + return renderer; + } + + //// HOT SWAPPING //// + + // Returns boolean indicating if the swap was successful. + // Requires that the two signal graphs have exactly the same + // structure. + function hotSwap(from, to) + { + function similar(nodeOld, nodeNew) + { + if (nodeOld.id !== nodeNew.id) + { + return false; + } + if (nodeOld.isOutput) + { + return nodeNew.isOutput; + } + return nodeOld.kids.length === nodeNew.kids.length; + } + function swap(nodeOld, nodeNew) + { + nodeNew.value = nodeOld.value; + return true; + } + var canSwap = depthFirstTraversals(similar, from.inputs, to.inputs); + if (canSwap) + { + depthFirstTraversals(swap, from.inputs, to.inputs); + } + from.node.parentNode.replaceChild(to.node, from.node); + + return canSwap; + } + + // Returns false if the node operation f ever fails. + function depthFirstTraversals(f, queueOld, queueNew) + { + if (queueOld.length !== queueNew.length) + { + return false; + } + queueOld = queueOld.slice(0); + queueNew = queueNew.slice(0); + + var seen = []; + while (queueOld.length > 0 && queueNew.length > 0) + { + var nodeOld = queueOld.pop(); + var nodeNew = queueNew.pop(); + if (seen.indexOf(nodeOld.id) < 0) + { + if (!f(nodeOld, nodeNew)) + { + return false; + } + queueOld = queueOld.concat(nodeOld.kids || []); + queueNew = queueNew.concat(nodeNew.kids || []); + seen.push(nodeOld.id); + } + } + return true; + } + }()); + + function F2(fun) + { + function wrapper(a) { return function(b) { return fun(a,b); }; } + wrapper.arity = 2; + wrapper.func = fun; + return wrapper; + } + + function F3(fun) + { + function wrapper(a) { + return function(b) { return function(c) { return fun(a, b, c); }; }; + } + wrapper.arity = 3; + wrapper.func = fun; + return wrapper; + } + + function F4(fun) + { + function wrapper(a) { return function(b) { return function(c) { + return function(d) { return fun(a, b, c, d); }; }; }; + } + wrapper.arity = 4; + wrapper.func = fun; + return wrapper; + } + + function F5(fun) + { + function wrapper(a) { return function(b) { return function(c) { + return function(d) { return function(e) { return fun(a, b, c, d, e); }; }; }; }; + } + wrapper.arity = 5; + wrapper.func = fun; + return wrapper; + } + + function F6(fun) + { + function wrapper(a) { return function(b) { return function(c) { + return function(d) { return function(e) { return function(f) { + return fun(a, b, c, d, e, f); }; }; }; }; }; + } + wrapper.arity = 6; + wrapper.func = fun; + return wrapper; + } + + function F7(fun) + { + function wrapper(a) { return function(b) { return function(c) { + return function(d) { return function(e) { return function(f) { + return function(g) { return fun(a, b, c, d, e, f, g); }; }; }; }; }; }; + } + wrapper.arity = 7; + wrapper.func = fun; + return wrapper; + } + + function F8(fun) + { + function wrapper(a) { return function(b) { return function(c) { + return function(d) { return function(e) { return function(f) { + return function(g) { return function(h) { + return fun(a, b, c, d, e, f, g, h); }; }; }; }; }; }; }; + } + wrapper.arity = 8; + wrapper.func = fun; + return wrapper; + } + + function F9(fun) + { + function wrapper(a) { return function(b) { return function(c) { + return function(d) { return function(e) { return function(f) { + return function(g) { return function(h) { return function(i) { + return fun(a, b, c, d, e, f, g, h, i); }; }; }; }; }; }; }; }; + } + wrapper.arity = 9; + wrapper.func = fun; + return wrapper; + } + + function A2(fun, a, b) + { + return fun.arity === 2 + ? fun.func(a, b) + : fun(a)(b); + } + function A3(fun, a, b, c) + { + return fun.arity === 3 + ? fun.func(a, b, c) + : fun(a)(b)(c); + } + function A4(fun, a, b, c, d) + { + return fun.arity === 4 + ? fun.func(a, b, c, d) + : fun(a)(b)(c)(d); + } + function A5(fun, a, b, c, d, e) + { + return fun.arity === 5 + ? fun.func(a, b, c, d, e) + : fun(a)(b)(c)(d)(e); + } + function A6(fun, a, b, c, d, e, f) + { + return fun.arity === 6 + ? fun.func(a, b, c, d, e, f) + : fun(a)(b)(c)(d)(e)(f); + } + function A7(fun, a, b, c, d, e, f, g) + { + return fun.arity === 7 + ? fun.func(a, b, c, d, e, f, g) + : fun(a)(b)(c)(d)(e)(f)(g); + } + function A8(fun, a, b, c, d, e, f, g, h) + { + return fun.arity === 8 + ? fun.func(a, b, c, d, e, f, g, h) + : fun(a)(b)(c)(d)(e)(f)(g)(h); + } + function A9(fun, a, b, c, d, e, f, g, h, i) + { + return fun.arity === 9 + ? fun.func(a, b, c, d, e, f, g, h, i) + : fun(a)(b)(c)(d)(e)(f)(g)(h)(i); + } +} + +Elm.Native = Elm.Native || {}; +Elm.Native.Utils = {}; +Elm.Native.Utils.make = function(localRuntime) { + localRuntime.Native = localRuntime.Native || {}; + localRuntime.Native.Utils = localRuntime.Native.Utils || {}; + if (localRuntime.Native.Utils.values) + { + return localRuntime.Native.Utils.values; + } + + + // COMPARISONS + + function eq(l, r) + { + var stack = [{'x': l, 'y': r}]; + while (stack.length > 0) + { + var front = stack.pop(); + var x = front.x; + var y = front.y; + if (x === y) + { + continue; + } + if (typeof x === 'object') + { + var c = 0; + for (var i in x) + { + ++c; + if (i in y) + { + if (i !== 'ctor') + { + stack.push({ 'x': x[i], 'y': y[i] }); + } + } + else + { + return false; + } + } + if ('ctor' in x) + { + stack.push({'x': x.ctor, 'y': y.ctor}); + } + if (c !== Object.keys(y).length) + { + return false; + } + } + else if (typeof x === 'function') + { + throw new Error('Equality error: general function equality is ' + + 'undecidable, and therefore, unsupported'); + } + else + { + return false; + } + } + return true; + } + + // code in Generate/JavaScript.hs depends on the particular + // integer values assigned to LT, EQ, and GT + var LT = -1, EQ = 0, GT = 1, ord = ['LT', 'EQ', 'GT']; + + function compare(x, y) + { + return { + ctor: ord[cmp(x, y) + 1] + }; + } + + function cmp(x, y) { + var ord; + if (typeof x !== 'object') + { + return x === y ? EQ : x < y ? LT : GT; + } + else if (x.isChar) + { + var a = x.toString(); + var b = y.toString(); + return a === b + ? EQ + : a < b + ? LT + : GT; + } + else if (x.ctor === '::' || x.ctor === '[]') + { + while (true) + { + if (x.ctor === '[]' && y.ctor === '[]') + { + return EQ; + } + if (x.ctor !== y.ctor) + { + return x.ctor === '[]' ? LT : GT; + } + ord = cmp(x._0, y._0); + if (ord !== EQ) + { + return ord; + } + x = x._1; + y = y._1; + } + } + else if (x.ctor.slice(0, 6) === '_Tuple') + { + var n = x.ctor.slice(6) - 0; + var err = 'cannot compare tuples with more than 6 elements.'; + if (n === 0) return EQ; + if (n >= 1) { ord = cmp(x._0, y._0); if (ord !== EQ) return ord; + if (n >= 2) { ord = cmp(x._1, y._1); if (ord !== EQ) return ord; + if (n >= 3) { ord = cmp(x._2, y._2); if (ord !== EQ) return ord; + if (n >= 4) { ord = cmp(x._3, y._3); if (ord !== EQ) return ord; + if (n >= 5) { ord = cmp(x._4, y._4); if (ord !== EQ) return ord; + if (n >= 6) { ord = cmp(x._5, y._5); if (ord !== EQ) return ord; + if (n >= 7) throw new Error('Comparison error: ' + err); } } } } } } + return EQ; + } + else + { + throw new Error('Comparison error: comparison is only defined on ints, ' + + 'floats, times, chars, strings, lists of comparable values, ' + + 'and tuples of comparable values.'); + } + } + + + // TUPLES + + var Tuple0 = { + ctor: '_Tuple0' + }; + + function Tuple2(x, y) + { + return { + ctor: '_Tuple2', + _0: x, + _1: y + }; + } + + + // LITERALS + + function chr(c) + { + var x = new String(c); + x.isChar = true; + return x; + } + + function txt(str) + { + var t = new String(str); + t.text = true; + return t; + } + + + // GUID + + var count = 0; + function guid(_) + { + return count++; + } + + + // RECORDS + + function update(oldRecord, updatedFields) + { + var newRecord = {}; + for (var key in oldRecord) + { + var value = (key in updatedFields) ? updatedFields[key] : oldRecord[key]; + newRecord[key] = value; + } + return newRecord; + } + + + // MOUSE COORDINATES + + function getXY(e) + { + var posx = 0; + var posy = 0; + if (e.pageX || e.pageY) + { + posx = e.pageX; + posy = e.pageY; + } + else if (e.clientX || e.clientY) + { + posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft; + posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop; + } + + if (localRuntime.isEmbed()) + { + var rect = localRuntime.node.getBoundingClientRect(); + var relx = rect.left + document.body.scrollLeft + document.documentElement.scrollLeft; + var rely = rect.top + document.body.scrollTop + document.documentElement.scrollTop; + // TODO: figure out if there is a way to avoid rounding here + posx = posx - Math.round(relx) - localRuntime.node.clientLeft; + posy = posy - Math.round(rely) - localRuntime.node.clientTop; + } + return Tuple2(posx, posy); + } + + + //// LIST STUFF //// + + var Nil = { ctor: '[]' }; + + function Cons(hd, tl) + { + return { + ctor: '::', + _0: hd, + _1: tl + }; + } + + function list(arr) + { + var out = Nil; + for (var i = arr.length; i--; ) + { + out = Cons(arr[i], out); + } + return out; + } + + function range(lo, hi) + { + var list = Nil; + if (lo <= hi) + { + do + { + list = Cons(hi, list); + } + while (hi-- > lo); + } + return list; + } + + function append(xs, ys) + { + // append Strings + if (typeof xs === 'string') + { + return xs + ys; + } + + // append Text + if (xs.ctor.slice(0, 5) === 'Text:') + { + return { + ctor: 'Text:Append', + _0: xs, + _1: ys + }; + } + + + // append Lists + if (xs.ctor === '[]') + { + return ys; + } + var root = Cons(xs._0, Nil); + var curr = root; + xs = xs._1; + while (xs.ctor !== '[]') + { + curr._1 = Cons(xs._0, Nil); + xs = xs._1; + curr = curr._1; + } + curr._1 = ys; + return root; + } + + + // CRASHES + + function crash(moduleName, region) + { + return function(message) { + throw new Error( + 'Ran into a `Debug.crash` in module `' + moduleName + '` ' + regionToString(region) + '\n' + + 'The message provided by the code author is:\n\n ' + + message + ); + }; + } + + function crashCase(moduleName, region, value) + { + return function(message) { + throw new Error( + 'Ran into a `Debug.crash` in module `' + moduleName + '`\n\n' + + 'This was caused by the `case` expression ' + regionToString(region) + '.\n' + + 'One of the branches ended with a crash and the following value got through:\n\n ' + toString(value) + '\n\n' + + 'The message provided by the code author is:\n\n ' + + message + ); + }; + } + + function regionToString(region) + { + if (region.start.line == region.end.line) + { + return 'on line ' + region.start.line; + } + return 'between lines ' + region.start.line + ' and ' + region.end.line; + } + + + // BAD PORTS + + function badPort(expected, received) + { + throw new Error( + 'Runtime error when sending values through a port.\n\n' + + 'Expecting ' + expected + ' but was given ' + formatValue(received) + ); + } + + function formatValue(value) + { + // Explicity format undefined values as "undefined" + // because JSON.stringify(undefined) unhelpfully returns "" + return (value === undefined) ? "undefined" : JSON.stringify(value); + } + + + // TO STRING + + var _Array; + var Dict; + var List; + + var toString = function(v) + { + var type = typeof v; + if (type === 'function') + { + var name = v.func ? v.func.name : v.name; + return ''; + } + else if (type === 'boolean') + { + return v ? 'True' : 'False'; + } + else if (type === 'number') + { + return v + ''; + } + else if ((v instanceof String) && v.isChar) + { + return '\'' + addSlashes(v, true) + '\''; + } + else if (type === 'string') + { + return '"' + addSlashes(v, false) + '"'; + } + else if (type === 'object' && 'ctor' in v) + { + if (v.ctor.substring(0, 6) === '_Tuple') + { + var output = []; + for (var k in v) + { + if (k === 'ctor') continue; + output.push(toString(v[k])); + } + return '(' + output.join(',') + ')'; + } + else if (v.ctor === '_Array') + { + if (!_Array) + { + _Array = Elm.Array.make(localRuntime); + } + var list = _Array.toList(v); + return 'Array.fromList ' + toString(list); + } + else if (v.ctor === '::') + { + var output = '[' + toString(v._0); + v = v._1; + while (v.ctor === '::') + { + output += ',' + toString(v._0); + v = v._1; + } + return output + ']'; + } + else if (v.ctor === '[]') + { + return '[]'; + } + else if (v.ctor === 'RBNode_elm_builtin' || v.ctor === 'RBEmpty_elm_builtin' || v.ctor === 'Set_elm_builtin') + { + if (!Dict) + { + Dict = Elm.Dict.make(localRuntime); + } + var list; + var name; + if (v.ctor === 'Set_elm_builtin') + { + if (!List) + { + List = Elm.List.make(localRuntime); + } + name = 'Set'; + list = A2(List.map, function(x) {return x._0; }, Dict.toList(v._0)); + } + else + { + name = 'Dict'; + list = Dict.toList(v); + } + return name + '.fromList ' + toString(list); + } + else if (v.ctor.slice(0, 5) === 'Text:') + { + return ''; + } + else if (v.ctor === 'Element_elm_builtin') + { + return '' + } + else if (v.ctor === 'Form_elm_builtin') + { + return '
' + } + else + { + var output = ''; + for (var i in v) + { + if (i === 'ctor') continue; + var str = toString(v[i]); + var parenless = str[0] === '{' || str[0] === '<' || str.indexOf(' ') < 0; + output += ' ' + (parenless ? str : '(' + str + ')'); + } + return v.ctor + output; + } + } + else if (type === 'object' && 'notify' in v && 'id' in v) + { + return ''; + } + else if (type === 'object') + { + var output = []; + for (var k in v) + { + output.push(k + ' = ' + toString(v[k])); + } + if (output.length === 0) + { + return '{}'; + } + return '{ ' + output.join(', ') + ' }'; + } + return ''; + }; + + function addSlashes(str, isChar) + { + var s = str.replace(/\\/g, '\\\\') + .replace(/\n/g, '\\n') + .replace(/\t/g, '\\t') + .replace(/\r/g, '\\r') + .replace(/\v/g, '\\v') + .replace(/\0/g, '\\0'); + if (isChar) + { + return s.replace(/\'/g, '\\\''); + } + else + { + return s.replace(/\"/g, '\\"'); + } + } + + + return localRuntime.Native.Utils.values = { + eq: eq, + cmp: cmp, + compare: F2(compare), + Tuple0: Tuple0, + Tuple2: Tuple2, + chr: chr, + txt: txt, + update: update, + guid: guid, + getXY: getXY, + + Nil: Nil, + Cons: Cons, + list: list, + range: range, + append: F2(append), + + crash: crash, + crashCase: crashCase, + badPort: badPort, + + toString: toString + }; +}; + +Elm.Basics = Elm.Basics || {}; +Elm.Basics.make = function (_elm) { + "use strict"; + _elm.Basics = _elm.Basics || {}; + if (_elm.Basics.values) return _elm.Basics.values; + var _U = Elm.Native.Utils.make(_elm),$Native$Basics = Elm.Native.Basics.make(_elm),$Native$Utils = Elm.Native.Utils.make(_elm); + var _op = {}; + var uncurry = F2(function (f,_p0) { var _p1 = _p0;return A2(f,_p1._0,_p1._1);}); + var curry = F3(function (f,a,b) { return f({ctor: "_Tuple2",_0: a,_1: b});}); + var flip = F3(function (f,b,a) { return A2(f,a,b);}); + var snd = function (_p2) { var _p3 = _p2;return _p3._1;}; + var fst = function (_p4) { var _p5 = _p4;return _p5._0;}; + var always = F2(function (a,_p6) { return a;}); + var identity = function (x) { return x;}; + _op["<|"] = F2(function (f,x) { return f(x);}); + _op["|>"] = F2(function (x,f) { return f(x);}); + _op[">>"] = F3(function (f,g,x) { return g(f(x));}); + _op["<<"] = F3(function (g,f,x) { return g(f(x));}); + _op["++"] = $Native$Utils.append; + var toString = $Native$Utils.toString; + var isInfinite = $Native$Basics.isInfinite; + var isNaN = $Native$Basics.isNaN; + var toFloat = $Native$Basics.toFloat; + var ceiling = $Native$Basics.ceiling; + var floor = $Native$Basics.floor; + var truncate = $Native$Basics.truncate; + var round = $Native$Basics.round; + var not = $Native$Basics.not; + var xor = $Native$Basics.xor; + _op["||"] = $Native$Basics.or; + _op["&&"] = $Native$Basics.and; + var max = $Native$Basics.max; + var min = $Native$Basics.min; + var GT = {ctor: "GT"}; + var EQ = {ctor: "EQ"}; + var LT = {ctor: "LT"}; + var compare = $Native$Basics.compare; + _op[">="] = $Native$Basics.ge; + _op["<="] = $Native$Basics.le; + _op[">"] = $Native$Basics.gt; + _op["<"] = $Native$Basics.lt; + _op["/="] = $Native$Basics.neq; + _op["=="] = $Native$Basics.eq; + var e = $Native$Basics.e; + var pi = $Native$Basics.pi; + var clamp = $Native$Basics.clamp; + var logBase = $Native$Basics.logBase; + var abs = $Native$Basics.abs; + var negate = $Native$Basics.negate; + var sqrt = $Native$Basics.sqrt; + var atan2 = $Native$Basics.atan2; + var atan = $Native$Basics.atan; + var asin = $Native$Basics.asin; + var acos = $Native$Basics.acos; + var tan = $Native$Basics.tan; + var sin = $Native$Basics.sin; + var cos = $Native$Basics.cos; + _op["^"] = $Native$Basics.exp; + _op["%"] = $Native$Basics.mod; + var rem = $Native$Basics.rem; + _op["//"] = $Native$Basics.div; + _op["/"] = $Native$Basics.floatDiv; + _op["*"] = $Native$Basics.mul; + _op["-"] = $Native$Basics.sub; + _op["+"] = $Native$Basics.add; + var toPolar = $Native$Basics.toPolar; + var fromPolar = $Native$Basics.fromPolar; + var turns = $Native$Basics.turns; + var degrees = $Native$Basics.degrees; + var radians = function (t) { return t;}; + return _elm.Basics.values = {_op: _op + ,max: max + ,min: min + ,compare: compare + ,not: not + ,xor: xor + ,rem: rem + ,negate: negate + ,abs: abs + ,sqrt: sqrt + ,clamp: clamp + ,logBase: logBase + ,e: e + ,pi: pi + ,cos: cos + ,sin: sin + ,tan: tan + ,acos: acos + ,asin: asin + ,atan: atan + ,atan2: atan2 + ,round: round + ,floor: floor + ,ceiling: ceiling + ,truncate: truncate + ,toFloat: toFloat + ,degrees: degrees + ,radians: radians + ,turns: turns + ,toPolar: toPolar + ,fromPolar: fromPolar + ,isNaN: isNaN + ,isInfinite: isInfinite + ,toString: toString + ,fst: fst + ,snd: snd + ,identity: identity + ,always: always + ,flip: flip + ,curry: curry + ,uncurry: uncurry + ,LT: LT + ,EQ: EQ + ,GT: GT}; +}; +Elm.Maybe = Elm.Maybe || {}; +Elm.Maybe.make = function (_elm) { + "use strict"; + _elm.Maybe = _elm.Maybe || {}; + if (_elm.Maybe.values) return _elm.Maybe.values; + var _U = Elm.Native.Utils.make(_elm); + var _op = {}; + var withDefault = F2(function ($default,maybe) { var _p0 = maybe;if (_p0.ctor === "Just") { return _p0._0;} else { return $default;}}); + var Nothing = {ctor: "Nothing"}; + var oneOf = function (maybes) { + oneOf: while (true) { + var _p1 = maybes; + if (_p1.ctor === "[]") { + return Nothing; + } else { + var _p3 = _p1._0; + var _p2 = _p3; + if (_p2.ctor === "Nothing") { + var _v3 = _p1._1; + maybes = _v3; + continue oneOf; + } else { + return _p3; + } + } + } + }; + var andThen = F2(function (maybeValue,callback) { + var _p4 = maybeValue; + if (_p4.ctor === "Just") { + return callback(_p4._0); + } else { + return Nothing; + } + }); + var Just = function (a) { return {ctor: "Just",_0: a};}; + var map = F2(function (f,maybe) { var _p5 = maybe;if (_p5.ctor === "Just") { return Just(f(_p5._0));} else { return Nothing;}}); + var map2 = F3(function (func,ma,mb) { + var _p6 = {ctor: "_Tuple2",_0: ma,_1: mb}; + if (_p6.ctor === "_Tuple2" && _p6._0.ctor === "Just" && _p6._1.ctor === "Just") { + return Just(A2(func,_p6._0._0,_p6._1._0)); + } else { + return Nothing; + } + }); + var map3 = F4(function (func,ma,mb,mc) { + var _p7 = {ctor: "_Tuple3",_0: ma,_1: mb,_2: mc}; + if (_p7.ctor === "_Tuple3" && _p7._0.ctor === "Just" && _p7._1.ctor === "Just" && _p7._2.ctor === "Just") { + return Just(A3(func,_p7._0._0,_p7._1._0,_p7._2._0)); + } else { + return Nothing; + } + }); + var map4 = F5(function (func,ma,mb,mc,md) { + var _p8 = {ctor: "_Tuple4",_0: ma,_1: mb,_2: mc,_3: md}; + if (_p8.ctor === "_Tuple4" && _p8._0.ctor === "Just" && _p8._1.ctor === "Just" && _p8._2.ctor === "Just" && _p8._3.ctor === "Just") { + return Just(A4(func,_p8._0._0,_p8._1._0,_p8._2._0,_p8._3._0)); + } else { + return Nothing; + } + }); + var map5 = F6(function (func,ma,mb,mc,md,me) { + var _p9 = {ctor: "_Tuple5",_0: ma,_1: mb,_2: mc,_3: md,_4: me}; + if (_p9.ctor === "_Tuple5" && _p9._0.ctor === "Just" && _p9._1.ctor === "Just" && _p9._2.ctor === "Just" && _p9._3.ctor === "Just" && _p9._4.ctor === "Just") + { + return Just(A5(func,_p9._0._0,_p9._1._0,_p9._2._0,_p9._3._0,_p9._4._0)); + } else { + return Nothing; + } + }); + return _elm.Maybe.values = {_op: _op + ,andThen: andThen + ,map: map + ,map2: map2 + ,map3: map3 + ,map4: map4 + ,map5: map5 + ,withDefault: withDefault + ,oneOf: oneOf + ,Just: Just + ,Nothing: Nothing}; +}; +Elm.Native.List = {}; +Elm.Native.List.make = function(localRuntime) { + localRuntime.Native = localRuntime.Native || {}; + localRuntime.Native.List = localRuntime.Native.List || {}; + if (localRuntime.Native.List.values) + { + return localRuntime.Native.List.values; + } + if ('values' in Elm.Native.List) + { + return localRuntime.Native.List.values = Elm.Native.List.values; + } + + var Utils = Elm.Native.Utils.make(localRuntime); + + var Nil = Utils.Nil; + var Cons = Utils.Cons; + + var fromArray = Utils.list; + + function toArray(xs) + { + var out = []; + while (xs.ctor !== '[]') + { + out.push(xs._0); + xs = xs._1; + } + return out; + } + + // f defined similarly for both foldl and foldr (NB: different from Haskell) + // ie, foldl : (a -> b -> b) -> b -> [a] -> b + function foldl(f, b, xs) + { + var acc = b; + while (xs.ctor !== '[]') + { + acc = A2(f, xs._0, acc); + xs = xs._1; + } + return acc; + } + + function foldr(f, b, xs) + { + var arr = toArray(xs); + var acc = b; + for (var i = arr.length; i--; ) + { + acc = A2(f, arr[i], acc); + } + return acc; + } + + function map2(f, xs, ys) + { + var arr = []; + while (xs.ctor !== '[]' && ys.ctor !== '[]') + { + arr.push(A2(f, xs._0, ys._0)); + xs = xs._1; + ys = ys._1; + } + return fromArray(arr); + } + + function map3(f, xs, ys, zs) + { + var arr = []; + while (xs.ctor !== '[]' && ys.ctor !== '[]' && zs.ctor !== '[]') + { + arr.push(A3(f, xs._0, ys._0, zs._0)); + xs = xs._1; + ys = ys._1; + zs = zs._1; + } + return fromArray(arr); + } + + function map4(f, ws, xs, ys, zs) + { + var arr = []; + while ( ws.ctor !== '[]' + && xs.ctor !== '[]' + && ys.ctor !== '[]' + && zs.ctor !== '[]') + { + arr.push(A4(f, ws._0, xs._0, ys._0, zs._0)); + ws = ws._1; + xs = xs._1; + ys = ys._1; + zs = zs._1; + } + return fromArray(arr); + } + + function map5(f, vs, ws, xs, ys, zs) + { + var arr = []; + while ( vs.ctor !== '[]' + && ws.ctor !== '[]' + && xs.ctor !== '[]' + && ys.ctor !== '[]' + && zs.ctor !== '[]') + { + arr.push(A5(f, vs._0, ws._0, xs._0, ys._0, zs._0)); + vs = vs._1; + ws = ws._1; + xs = xs._1; + ys = ys._1; + zs = zs._1; + } + return fromArray(arr); + } + + function sortBy(f, xs) + { + return fromArray(toArray(xs).sort(function(a, b) { + return Utils.cmp(f(a), f(b)); + })); + } + + function sortWith(f, xs) + { + return fromArray(toArray(xs).sort(function(a, b) { + var ord = f(a)(b).ctor; + return ord === 'EQ' ? 0 : ord === 'LT' ? -1 : 1; + })); + } + + function take(n, xs) + { + var arr = []; + while (xs.ctor !== '[]' && n > 0) + { + arr.push(xs._0); + xs = xs._1; + --n; + } + return fromArray(arr); + } + + + Elm.Native.List.values = { + Nil: Nil, + Cons: Cons, + cons: F2(Cons), + toArray: toArray, + fromArray: fromArray, + + foldl: F3(foldl), + foldr: F3(foldr), + + map2: F3(map2), + map3: F4(map3), + map4: F5(map4), + map5: F6(map5), + sortBy: F2(sortBy), + sortWith: F2(sortWith), + take: F2(take) + }; + return localRuntime.Native.List.values = Elm.Native.List.values; +}; + +Elm.List = Elm.List || {}; +Elm.List.make = function (_elm) { + "use strict"; + _elm.List = _elm.List || {}; + if (_elm.List.values) return _elm.List.values; + var _U = Elm.Native.Utils.make(_elm),$Basics = Elm.Basics.make(_elm),$Maybe = Elm.Maybe.make(_elm),$Native$List = Elm.Native.List.make(_elm); + var _op = {}; + var sortWith = $Native$List.sortWith; + var sortBy = $Native$List.sortBy; + var sort = function (xs) { return A2(sortBy,$Basics.identity,xs);}; + var drop = F2(function (n,list) { + drop: while (true) if (_U.cmp(n,0) < 1) return list; else { + var _p0 = list; + if (_p0.ctor === "[]") { + return list; + } else { + var _v1 = n - 1,_v2 = _p0._1; + n = _v1; + list = _v2; + continue drop; + } + } + }); + var take = $Native$List.take; + var map5 = $Native$List.map5; + var map4 = $Native$List.map4; + var map3 = $Native$List.map3; + var map2 = $Native$List.map2; + var any = F2(function (isOkay,list) { + any: while (true) { + var _p1 = list; + if (_p1.ctor === "[]") { + return false; + } else { + if (isOkay(_p1._0)) return true; else { + var _v4 = isOkay,_v5 = _p1._1; + isOkay = _v4; + list = _v5; + continue any; + } + } + } + }); + var all = F2(function (isOkay,list) { return $Basics.not(A2(any,function (_p2) { return $Basics.not(isOkay(_p2));},list));}); + var foldr = $Native$List.foldr; + var foldl = $Native$List.foldl; + var length = function (xs) { return A3(foldl,F2(function (_p3,i) { return i + 1;}),0,xs);}; + var sum = function (numbers) { return A3(foldl,F2(function (x,y) { return x + y;}),0,numbers);}; + var product = function (numbers) { return A3(foldl,F2(function (x,y) { return x * y;}),1,numbers);}; + var maximum = function (list) { + var _p4 = list; + if (_p4.ctor === "::") { + return $Maybe.Just(A3(foldl,$Basics.max,_p4._0,_p4._1)); + } else { + return $Maybe.Nothing; + } + }; + var minimum = function (list) { + var _p5 = list; + if (_p5.ctor === "::") { + return $Maybe.Just(A3(foldl,$Basics.min,_p5._0,_p5._1)); + } else { + return $Maybe.Nothing; + } + }; + var indexedMap = F2(function (f,xs) { return A3(map2,f,_U.range(0,length(xs) - 1),xs);}); + var member = F2(function (x,xs) { return A2(any,function (a) { return _U.eq(a,x);},xs);}); + var isEmpty = function (xs) { var _p6 = xs;if (_p6.ctor === "[]") { return true;} else { return false;}}; + var tail = function (list) { var _p7 = list;if (_p7.ctor === "::") { return $Maybe.Just(_p7._1);} else { return $Maybe.Nothing;}}; + var head = function (list) { var _p8 = list;if (_p8.ctor === "::") { return $Maybe.Just(_p8._0);} else { return $Maybe.Nothing;}}; + _op["::"] = $Native$List.cons; + var map = F2(function (f,xs) { return A3(foldr,F2(function (x,acc) { return A2(_op["::"],f(x),acc);}),_U.list([]),xs);}); + var filter = F2(function (pred,xs) { + var conditionalCons = F2(function (x,xs$) { return pred(x) ? A2(_op["::"],x,xs$) : xs$;}); + return A3(foldr,conditionalCons,_U.list([]),xs); + }); + var maybeCons = F3(function (f,mx,xs) { var _p9 = f(mx);if (_p9.ctor === "Just") { return A2(_op["::"],_p9._0,xs);} else { return xs;}}); + var filterMap = F2(function (f,xs) { return A3(foldr,maybeCons(f),_U.list([]),xs);}); + var reverse = function (list) { return A3(foldl,F2(function (x,y) { return A2(_op["::"],x,y);}),_U.list([]),list);}; + var scanl = F3(function (f,b,xs) { + var scan1 = F2(function (x,accAcc) { + var _p10 = accAcc; + if (_p10.ctor === "::") { + return A2(_op["::"],A2(f,x,_p10._0),accAcc); + } else { + return _U.list([]); + } + }); + return reverse(A3(foldl,scan1,_U.list([b]),xs)); + }); + var append = F2(function (xs,ys) { + var _p11 = ys; + if (_p11.ctor === "[]") { + return xs; + } else { + return A3(foldr,F2(function (x,y) { return A2(_op["::"],x,y);}),ys,xs); + } + }); + var concat = function (lists) { return A3(foldr,append,_U.list([]),lists);}; + var concatMap = F2(function (f,list) { return concat(A2(map,f,list));}); + var partition = F2(function (pred,list) { + var step = F2(function (x,_p12) { + var _p13 = _p12; + var _p15 = _p13._0; + var _p14 = _p13._1; + return pred(x) ? {ctor: "_Tuple2",_0: A2(_op["::"],x,_p15),_1: _p14} : {ctor: "_Tuple2",_0: _p15,_1: A2(_op["::"],x,_p14)}; + }); + return A3(foldr,step,{ctor: "_Tuple2",_0: _U.list([]),_1: _U.list([])},list); + }); + var unzip = function (pairs) { + var step = F2(function (_p17,_p16) { + var _p18 = _p17; + var _p19 = _p16; + return {ctor: "_Tuple2",_0: A2(_op["::"],_p18._0,_p19._0),_1: A2(_op["::"],_p18._1,_p19._1)}; + }); + return A3(foldr,step,{ctor: "_Tuple2",_0: _U.list([]),_1: _U.list([])},pairs); + }; + var intersperse = F2(function (sep,xs) { + var _p20 = xs; + if (_p20.ctor === "[]") { + return _U.list([]); + } else { + var step = F2(function (x,rest) { return A2(_op["::"],sep,A2(_op["::"],x,rest));}); + var spersed = A3(foldr,step,_U.list([]),_p20._1); + return A2(_op["::"],_p20._0,spersed); + } + }); + var repeatHelp = F3(function (result,n,value) { + repeatHelp: while (true) if (_U.cmp(n,0) < 1) return result; else { + var _v18 = A2(_op["::"],value,result),_v19 = n - 1,_v20 = value; + result = _v18; + n = _v19; + value = _v20; + continue repeatHelp; + } + }); + var repeat = F2(function (n,value) { return A3(repeatHelp,_U.list([]),n,value);}); + return _elm.List.values = {_op: _op + ,isEmpty: isEmpty + ,length: length + ,reverse: reverse + ,member: member + ,head: head + ,tail: tail + ,filter: filter + ,take: take + ,drop: drop + ,repeat: repeat + ,append: append + ,concat: concat + ,intersperse: intersperse + ,partition: partition + ,unzip: unzip + ,map: map + ,map2: map2 + ,map3: map3 + ,map4: map4 + ,map5: map5 + ,filterMap: filterMap + ,concatMap: concatMap + ,indexedMap: indexedMap + ,foldr: foldr + ,foldl: foldl + ,sum: sum + ,product: product + ,maximum: maximum + ,minimum: minimum + ,all: all + ,any: any + ,scanl: scanl + ,sort: sort + ,sortBy: sortBy + ,sortWith: sortWith}; +}; +Elm.Array = Elm.Array || {}; +Elm.Array.make = function (_elm) { + "use strict"; + _elm.Array = _elm.Array || {}; + if (_elm.Array.values) return _elm.Array.values; + var _U = Elm.Native.Utils.make(_elm), + $Basics = Elm.Basics.make(_elm), + $List = Elm.List.make(_elm), + $Maybe = Elm.Maybe.make(_elm), + $Native$Array = Elm.Native.Array.make(_elm); + var _op = {}; + var append = $Native$Array.append; + var length = $Native$Array.length; + var isEmpty = function (array) { return _U.eq(length(array),0);}; + var slice = $Native$Array.slice; + var set = $Native$Array.set; + var get = F2(function (i,array) { + return _U.cmp(0,i) < 1 && _U.cmp(i,$Native$Array.length(array)) < 0 ? $Maybe.Just(A2($Native$Array.get,i,array)) : $Maybe.Nothing; + }); + var push = $Native$Array.push; + var empty = $Native$Array.empty; + var filter = F2(function (isOkay,arr) { + var update = F2(function (x,xs) { return isOkay(x) ? A2($Native$Array.push,x,xs) : xs;}); + return A3($Native$Array.foldl,update,$Native$Array.empty,arr); + }); + var foldr = $Native$Array.foldr; + var foldl = $Native$Array.foldl; + var indexedMap = $Native$Array.indexedMap; + var map = $Native$Array.map; + var toIndexedList = function (array) { + return A3($List.map2, + F2(function (v0,v1) { return {ctor: "_Tuple2",_0: v0,_1: v1};}), + _U.range(0,$Native$Array.length(array) - 1), + $Native$Array.toList(array)); + }; + var toList = $Native$Array.toList; + var fromList = $Native$Array.fromList; + var initialize = $Native$Array.initialize; + var repeat = F2(function (n,e) { return A2(initialize,n,$Basics.always(e));}); + var Array = {ctor: "Array"}; + return _elm.Array.values = {_op: _op + ,empty: empty + ,repeat: repeat + ,initialize: initialize + ,fromList: fromList + ,isEmpty: isEmpty + ,length: length + ,push: push + ,append: append + ,get: get + ,set: set + ,slice: slice + ,toList: toList + ,toIndexedList: toIndexedList + ,map: map + ,indexedMap: indexedMap + ,filter: filter + ,foldl: foldl + ,foldr: foldr}; +}; +Elm.Native.Char = {}; +Elm.Native.Char.make = function(localRuntime) { + localRuntime.Native = localRuntime.Native || {}; + localRuntime.Native.Char = localRuntime.Native.Char || {}; + if (localRuntime.Native.Char.values) + { + return localRuntime.Native.Char.values; + } + + var Utils = Elm.Native.Utils.make(localRuntime); + + return localRuntime.Native.Char.values = { + fromCode: function(c) { return Utils.chr(String.fromCharCode(c)); }, + toCode: function(c) { return c.charCodeAt(0); }, + toUpper: function(c) { return Utils.chr(c.toUpperCase()); }, + toLower: function(c) { return Utils.chr(c.toLowerCase()); }, + toLocaleUpper: function(c) { return Utils.chr(c.toLocaleUpperCase()); }, + toLocaleLower: function(c) { return Utils.chr(c.toLocaleLowerCase()); } + }; +}; + +Elm.Char = Elm.Char || {}; +Elm.Char.make = function (_elm) { + "use strict"; + _elm.Char = _elm.Char || {}; + if (_elm.Char.values) return _elm.Char.values; + var _U = Elm.Native.Utils.make(_elm),$Basics = Elm.Basics.make(_elm),$Native$Char = Elm.Native.Char.make(_elm); + var _op = {}; + var fromCode = $Native$Char.fromCode; + var toCode = $Native$Char.toCode; + var toLocaleLower = $Native$Char.toLocaleLower; + var toLocaleUpper = $Native$Char.toLocaleUpper; + var toLower = $Native$Char.toLower; + var toUpper = $Native$Char.toUpper; + var isBetween = F3(function (low,high,$char) { var code = toCode($char);return _U.cmp(code,toCode(low)) > -1 && _U.cmp(code,toCode(high)) < 1;}); + var isUpper = A2(isBetween,_U.chr("A"),_U.chr("Z")); + var isLower = A2(isBetween,_U.chr("a"),_U.chr("z")); + var isDigit = A2(isBetween,_U.chr("0"),_U.chr("9")); + var isOctDigit = A2(isBetween,_U.chr("0"),_U.chr("7")); + var isHexDigit = function ($char) { + return isDigit($char) || (A3(isBetween,_U.chr("a"),_U.chr("f"),$char) || A3(isBetween,_U.chr("A"),_U.chr("F"),$char)); + }; + return _elm.Char.values = {_op: _op + ,isUpper: isUpper + ,isLower: isLower + ,isDigit: isDigit + ,isOctDigit: isOctDigit + ,isHexDigit: isHexDigit + ,toUpper: toUpper + ,toLower: toLower + ,toLocaleUpper: toLocaleUpper + ,toLocaleLower: toLocaleLower + ,toCode: toCode + ,fromCode: fromCode}; +}; +Elm.Native.Color = {}; +Elm.Native.Color.make = function(localRuntime) { + localRuntime.Native = localRuntime.Native || {}; + localRuntime.Native.Color = localRuntime.Native.Color || {}; + if (localRuntime.Native.Color.values) + { + return localRuntime.Native.Color.values; + } + + function toCss(c) + { + var format = ''; + var colors = ''; + if (c.ctor === 'RGBA') + { + format = 'rgb'; + colors = c._0 + ', ' + c._1 + ', ' + c._2; + } + else + { + format = 'hsl'; + colors = (c._0 * 180 / Math.PI) + ', ' + + (c._1 * 100) + '%, ' + + (c._2 * 100) + '%'; + } + if (c._3 === 1) + { + return format + '(' + colors + ')'; + } + else + { + return format + 'a(' + colors + ', ' + c._3 + ')'; + } + } + + return localRuntime.Native.Color.values = { + toCss: toCss + }; +}; + +Elm.Color = Elm.Color || {}; +Elm.Color.make = function (_elm) { + "use strict"; + _elm.Color = _elm.Color || {}; + if (_elm.Color.values) return _elm.Color.values; + var _U = Elm.Native.Utils.make(_elm),$Basics = Elm.Basics.make(_elm); + var _op = {}; + var Radial = F5(function (a,b,c,d,e) { return {ctor: "Radial",_0: a,_1: b,_2: c,_3: d,_4: e};}); + var radial = Radial; + var Linear = F3(function (a,b,c) { return {ctor: "Linear",_0: a,_1: b,_2: c};}); + var linear = Linear; + var fmod = F2(function (f,n) { var integer = $Basics.floor(f);return $Basics.toFloat(A2($Basics._op["%"],integer,n)) + f - $Basics.toFloat(integer);}); + var rgbToHsl = F3(function (red,green,blue) { + var b = $Basics.toFloat(blue) / 255; + var g = $Basics.toFloat(green) / 255; + var r = $Basics.toFloat(red) / 255; + var cMax = A2($Basics.max,A2($Basics.max,r,g),b); + var cMin = A2($Basics.min,A2($Basics.min,r,g),b); + var c = cMax - cMin; + var lightness = (cMax + cMin) / 2; + var saturation = _U.eq(lightness,0) ? 0 : c / (1 - $Basics.abs(2 * lightness - 1)); + var hue = $Basics.degrees(60) * (_U.eq(cMax,r) ? A2(fmod,(g - b) / c,6) : _U.eq(cMax,g) ? (b - r) / c + 2 : (r - g) / c + 4); + return {ctor: "_Tuple3",_0: hue,_1: saturation,_2: lightness}; + }); + var hslToRgb = F3(function (hue,saturation,lightness) { + var hue$ = hue / $Basics.degrees(60); + var chroma = (1 - $Basics.abs(2 * lightness - 1)) * saturation; + var x = chroma * (1 - $Basics.abs(A2(fmod,hue$,2) - 1)); + var _p0 = _U.cmp(hue$,0) < 0 ? {ctor: "_Tuple3",_0: 0,_1: 0,_2: 0} : _U.cmp(hue$,1) < 0 ? {ctor: "_Tuple3",_0: chroma,_1: x,_2: 0} : _U.cmp(hue$, + 2) < 0 ? {ctor: "_Tuple3",_0: x,_1: chroma,_2: 0} : _U.cmp(hue$,3) < 0 ? {ctor: "_Tuple3",_0: 0,_1: chroma,_2: x} : _U.cmp(hue$,4) < 0 ? {ctor: "_Tuple3" + ,_0: 0 + ,_1: x + ,_2: chroma} : _U.cmp(hue$, + 5) < 0 ? {ctor: "_Tuple3",_0: x,_1: 0,_2: chroma} : _U.cmp(hue$,6) < 0 ? {ctor: "_Tuple3",_0: chroma,_1: 0,_2: x} : {ctor: "_Tuple3",_0: 0,_1: 0,_2: 0}; + var r = _p0._0; + var g = _p0._1; + var b = _p0._2; + var m = lightness - chroma / 2; + return {ctor: "_Tuple3",_0: r + m,_1: g + m,_2: b + m}; + }); + var toRgb = function (color) { + var _p1 = color; + if (_p1.ctor === "RGBA") { + return {red: _p1._0,green: _p1._1,blue: _p1._2,alpha: _p1._3}; + } else { + var _p2 = A3(hslToRgb,_p1._0,_p1._1,_p1._2); + var r = _p2._0; + var g = _p2._1; + var b = _p2._2; + return {red: $Basics.round(255 * r),green: $Basics.round(255 * g),blue: $Basics.round(255 * b),alpha: _p1._3}; + } + }; + var toHsl = function (color) { + var _p3 = color; + if (_p3.ctor === "HSLA") { + return {hue: _p3._0,saturation: _p3._1,lightness: _p3._2,alpha: _p3._3}; + } else { + var _p4 = A3(rgbToHsl,_p3._0,_p3._1,_p3._2); + var h = _p4._0; + var s = _p4._1; + var l = _p4._2; + return {hue: h,saturation: s,lightness: l,alpha: _p3._3}; + } + }; + var HSLA = F4(function (a,b,c,d) { return {ctor: "HSLA",_0: a,_1: b,_2: c,_3: d};}); + var hsla = F4(function (hue,saturation,lightness,alpha) { + return A4(HSLA,hue - $Basics.turns($Basics.toFloat($Basics.floor(hue / (2 * $Basics.pi)))),saturation,lightness,alpha); + }); + var hsl = F3(function (hue,saturation,lightness) { return A4(hsla,hue,saturation,lightness,1);}); + var complement = function (color) { + var _p5 = color; + if (_p5.ctor === "HSLA") { + return A4(hsla,_p5._0 + $Basics.degrees(180),_p5._1,_p5._2,_p5._3); + } else { + var _p6 = A3(rgbToHsl,_p5._0,_p5._1,_p5._2); + var h = _p6._0; + var s = _p6._1; + var l = _p6._2; + return A4(hsla,h + $Basics.degrees(180),s,l,_p5._3); + } + }; + var grayscale = function (p) { return A4(HSLA,0,0,1 - p,1);}; + var greyscale = function (p) { return A4(HSLA,0,0,1 - p,1);}; + var RGBA = F4(function (a,b,c,d) { return {ctor: "RGBA",_0: a,_1: b,_2: c,_3: d};}); + var rgba = RGBA; + var rgb = F3(function (r,g,b) { return A4(RGBA,r,g,b,1);}); + var lightRed = A4(RGBA,239,41,41,1); + var red = A4(RGBA,204,0,0,1); + var darkRed = A4(RGBA,164,0,0,1); + var lightOrange = A4(RGBA,252,175,62,1); + var orange = A4(RGBA,245,121,0,1); + var darkOrange = A4(RGBA,206,92,0,1); + var lightYellow = A4(RGBA,255,233,79,1); + var yellow = A4(RGBA,237,212,0,1); + var darkYellow = A4(RGBA,196,160,0,1); + var lightGreen = A4(RGBA,138,226,52,1); + var green = A4(RGBA,115,210,22,1); + var darkGreen = A4(RGBA,78,154,6,1); + var lightBlue = A4(RGBA,114,159,207,1); + var blue = A4(RGBA,52,101,164,1); + var darkBlue = A4(RGBA,32,74,135,1); + var lightPurple = A4(RGBA,173,127,168,1); + var purple = A4(RGBA,117,80,123,1); + var darkPurple = A4(RGBA,92,53,102,1); + var lightBrown = A4(RGBA,233,185,110,1); + var brown = A4(RGBA,193,125,17,1); + var darkBrown = A4(RGBA,143,89,2,1); + var black = A4(RGBA,0,0,0,1); + var white = A4(RGBA,255,255,255,1); + var lightGrey = A4(RGBA,238,238,236,1); + var grey = A4(RGBA,211,215,207,1); + var darkGrey = A4(RGBA,186,189,182,1); + var lightGray = A4(RGBA,238,238,236,1); + var gray = A4(RGBA,211,215,207,1); + var darkGray = A4(RGBA,186,189,182,1); + var lightCharcoal = A4(RGBA,136,138,133,1); + var charcoal = A4(RGBA,85,87,83,1); + var darkCharcoal = A4(RGBA,46,52,54,1); + return _elm.Color.values = {_op: _op + ,rgb: rgb + ,rgba: rgba + ,hsl: hsl + ,hsla: hsla + ,greyscale: greyscale + ,grayscale: grayscale + ,complement: complement + ,linear: linear + ,radial: radial + ,toRgb: toRgb + ,toHsl: toHsl + ,red: red + ,orange: orange + ,yellow: yellow + ,green: green + ,blue: blue + ,purple: purple + ,brown: brown + ,lightRed: lightRed + ,lightOrange: lightOrange + ,lightYellow: lightYellow + ,lightGreen: lightGreen + ,lightBlue: lightBlue + ,lightPurple: lightPurple + ,lightBrown: lightBrown + ,darkRed: darkRed + ,darkOrange: darkOrange + ,darkYellow: darkYellow + ,darkGreen: darkGreen + ,darkBlue: darkBlue + ,darkPurple: darkPurple + ,darkBrown: darkBrown + ,white: white + ,lightGrey: lightGrey + ,grey: grey + ,darkGrey: darkGrey + ,lightCharcoal: lightCharcoal + ,charcoal: charcoal + ,darkCharcoal: darkCharcoal + ,black: black + ,lightGray: lightGray + ,gray: gray + ,darkGray: darkGray}; +}; +Elm.Native.Signal = {}; + +Elm.Native.Signal.make = function(localRuntime) { + localRuntime.Native = localRuntime.Native || {}; + localRuntime.Native.Signal = localRuntime.Native.Signal || {}; + if (localRuntime.Native.Signal.values) + { + return localRuntime.Native.Signal.values; + } + + + var Task = Elm.Native.Task.make(localRuntime); + var Utils = Elm.Native.Utils.make(localRuntime); + + + function broadcastToKids(node, timestamp, update) + { + var kids = node.kids; + for (var i = kids.length; i--; ) + { + kids[i].notify(timestamp, update, node.id); + } + } + + + // INPUT + + function input(name, base) + { + var node = { + id: Utils.guid(), + name: 'input-' + name, + value: base, + parents: [], + kids: [] + }; + + node.notify = function(timestamp, targetId, value) { + var update = targetId === node.id; + if (update) + { + node.value = value; + } + broadcastToKids(node, timestamp, update); + return update; + }; + + localRuntime.inputs.push(node); + + return node; + } + + function constant(value) + { + return input('constant', value); + } + + + // MAILBOX + + function mailbox(base) + { + var signal = input('mailbox', base); + + function send(value) { + return Task.asyncFunction(function(callback) { + localRuntime.setTimeout(function() { + localRuntime.notify(signal.id, value); + }, 0); + callback(Task.succeed(Utils.Tuple0)); + }); + } + + return { + signal: signal, + address: { + ctor: 'Address', + _0: send + } + }; + } + + function sendMessage(message) + { + Task.perform(message._0); + } + + + // OUTPUT + + function output(name, handler, parent) + { + var node = { + id: Utils.guid(), + name: 'output-' + name, + parents: [parent], + isOutput: true + }; + + node.notify = function(timestamp, parentUpdate, parentID) + { + if (parentUpdate) + { + handler(parent.value); + } + }; + + parent.kids.push(node); + + return node; + } + + + // MAP + + function mapMany(refreshValue, args) + { + var node = { + id: Utils.guid(), + name: 'map' + args.length, + value: refreshValue(), + parents: args, + kids: [] + }; + + var numberOfParents = args.length; + var count = 0; + var update = false; + + node.notify = function(timestamp, parentUpdate, parentID) + { + ++count; + + update = update || parentUpdate; + + if (count === numberOfParents) + { + if (update) + { + node.value = refreshValue(); + } + broadcastToKids(node, timestamp, update); + update = false; + count = 0; + } + }; + + for (var i = numberOfParents; i--; ) + { + args[i].kids.push(node); + } + + return node; + } + + + function map(func, a) + { + function refreshValue() + { + return func(a.value); + } + return mapMany(refreshValue, [a]); + } + + + function map2(func, a, b) + { + function refreshValue() + { + return A2( func, a.value, b.value ); + } + return mapMany(refreshValue, [a, b]); + } + + + function map3(func, a, b, c) + { + function refreshValue() + { + return A3( func, a.value, b.value, c.value ); + } + return mapMany(refreshValue, [a, b, c]); + } + + + function map4(func, a, b, c, d) + { + function refreshValue() + { + return A4( func, a.value, b.value, c.value, d.value ); + } + return mapMany(refreshValue, [a, b, c, d]); + } + + + function map5(func, a, b, c, d, e) + { + function refreshValue() + { + return A5( func, a.value, b.value, c.value, d.value, e.value ); + } + return mapMany(refreshValue, [a, b, c, d, e]); + } + + + // FOLD + + function foldp(update, state, signal) + { + var node = { + id: Utils.guid(), + name: 'foldp', + parents: [signal], + kids: [], + value: state + }; + + node.notify = function(timestamp, parentUpdate, parentID) + { + if (parentUpdate) + { + node.value = A2( update, signal.value, node.value ); + } + broadcastToKids(node, timestamp, parentUpdate); + }; + + signal.kids.push(node); + + return node; + } + + + // TIME + + function timestamp(signal) + { + var node = { + id: Utils.guid(), + name: 'timestamp', + value: Utils.Tuple2(localRuntime.timer.programStart, signal.value), + parents: [signal], + kids: [] + }; + + node.notify = function(timestamp, parentUpdate, parentID) + { + if (parentUpdate) + { + node.value = Utils.Tuple2(timestamp, signal.value); + } + broadcastToKids(node, timestamp, parentUpdate); + }; + + signal.kids.push(node); + + return node; + } + + + function delay(time, signal) + { + var delayed = input('delay-input-' + time, signal.value); + + function handler(value) + { + setTimeout(function() { + localRuntime.notify(delayed.id, value); + }, time); + } + + output('delay-output-' + time, handler, signal); + + return delayed; + } + + + // MERGING + + function genericMerge(tieBreaker, leftStream, rightStream) + { + var node = { + id: Utils.guid(), + name: 'merge', + value: A2(tieBreaker, leftStream.value, rightStream.value), + parents: [leftStream, rightStream], + kids: [] + }; + + var left = { touched: false, update: false, value: null }; + var right = { touched: false, update: false, value: null }; + + node.notify = function(timestamp, parentUpdate, parentID) + { + if (parentID === leftStream.id) + { + left.touched = true; + left.update = parentUpdate; + left.value = leftStream.value; + } + if (parentID === rightStream.id) + { + right.touched = true; + right.update = parentUpdate; + right.value = rightStream.value; + } + + if (left.touched && right.touched) + { + var update = false; + if (left.update && right.update) + { + node.value = A2(tieBreaker, left.value, right.value); + update = true; + } + else if (left.update) + { + node.value = left.value; + update = true; + } + else if (right.update) + { + node.value = right.value; + update = true; + } + left.touched = false; + right.touched = false; + + broadcastToKids(node, timestamp, update); + } + }; + + leftStream.kids.push(node); + rightStream.kids.push(node); + + return node; + } + + + // FILTERING + + function filterMap(toMaybe, base, signal) + { + var maybe = toMaybe(signal.value); + var node = { + id: Utils.guid(), + name: 'filterMap', + value: maybe.ctor === 'Nothing' ? base : maybe._0, + parents: [signal], + kids: [] + }; + + node.notify = function(timestamp, parentUpdate, parentID) + { + var update = false; + if (parentUpdate) + { + var maybe = toMaybe(signal.value); + if (maybe.ctor === 'Just') + { + update = true; + node.value = maybe._0; + } + } + broadcastToKids(node, timestamp, update); + }; + + signal.kids.push(node); + + return node; + } + + + // SAMPLING + + function sampleOn(ticker, signal) + { + var node = { + id: Utils.guid(), + name: 'sampleOn', + value: signal.value, + parents: [ticker, signal], + kids: [] + }; + + var signalTouch = false; + var tickerTouch = false; + var tickerUpdate = false; + + node.notify = function(timestamp, parentUpdate, parentID) + { + if (parentID === ticker.id) + { + tickerTouch = true; + tickerUpdate = parentUpdate; + } + if (parentID === signal.id) + { + signalTouch = true; + } + + if (tickerTouch && signalTouch) + { + if (tickerUpdate) + { + node.value = signal.value; + } + tickerTouch = false; + signalTouch = false; + + broadcastToKids(node, timestamp, tickerUpdate); + } + }; + + ticker.kids.push(node); + signal.kids.push(node); + + return node; + } + + + // DROP REPEATS + + function dropRepeats(signal) + { + var node = { + id: Utils.guid(), + name: 'dropRepeats', + value: signal.value, + parents: [signal], + kids: [] + }; + + node.notify = function(timestamp, parentUpdate, parentID) + { + var update = false; + if (parentUpdate && !Utils.eq(node.value, signal.value)) + { + node.value = signal.value; + update = true; + } + broadcastToKids(node, timestamp, update); + }; + + signal.kids.push(node); + + return node; + } + + + return localRuntime.Native.Signal.values = { + input: input, + constant: constant, + mailbox: mailbox, + sendMessage: sendMessage, + output: output, + map: F2(map), + map2: F3(map2), + map3: F4(map3), + map4: F5(map4), + map5: F6(map5), + foldp: F3(foldp), + genericMerge: F3(genericMerge), + filterMap: F3(filterMap), + sampleOn: F2(sampleOn), + dropRepeats: dropRepeats, + timestamp: timestamp, + delay: F2(delay) + }; +}; + +Elm.Native.Transform2D = {}; +Elm.Native.Transform2D.make = function(localRuntime) { + localRuntime.Native = localRuntime.Native || {}; + localRuntime.Native.Transform2D = localRuntime.Native.Transform2D || {}; + if (localRuntime.Native.Transform2D.values) + { + return localRuntime.Native.Transform2D.values; + } + + var A; + if (typeof Float32Array === 'undefined') + { + A = function(arr) + { + this.length = arr.length; + this[0] = arr[0]; + this[1] = arr[1]; + this[2] = arr[2]; + this[3] = arr[3]; + this[4] = arr[4]; + this[5] = arr[5]; + }; + } + else + { + A = Float32Array; + } + + // layout of matrix in an array is + // + // | m11 m12 dx | + // | m21 m22 dy | + // | 0 0 1 | + // + // new A([ m11, m12, dx, m21, m22, dy ]) + + var identity = new A([1, 0, 0, 0, 1, 0]); + function matrix(m11, m12, m21, m22, dx, dy) + { + return new A([m11, m12, dx, m21, m22, dy]); + } + + function rotation(t) + { + var c = Math.cos(t); + var s = Math.sin(t); + return new A([c, -s, 0, s, c, 0]); + } + + function rotate(t, m) + { + var c = Math.cos(t); + var s = Math.sin(t); + var m11 = m[0], m12 = m[1], m21 = m[3], m22 = m[4]; + return new A([m11 * c + m12 * s, -m11 * s + m12 * c, m[2], + m21 * c + m22 * s, -m21 * s + m22 * c, m[5]]); + } + /* + function move(xy,m) { + var x = xy._0; + var y = xy._1; + var m11 = m[0], m12 = m[1], m21 = m[3], m22 = m[4]; + return new A([m11, m12, m11*x + m12*y + m[2], + m21, m22, m21*x + m22*y + m[5]]); + } + function scale(s,m) { return new A([m[0]*s, m[1]*s, m[2], m[3]*s, m[4]*s, m[5]]); } + function scaleX(x,m) { return new A([m[0]*x, m[1], m[2], m[3]*x, m[4], m[5]]); } + function scaleY(y,m) { return new A([m[0], m[1]*y, m[2], m[3], m[4]*y, m[5]]); } + function reflectX(m) { return new A([-m[0], m[1], m[2], -m[3], m[4], m[5]]); } + function reflectY(m) { return new A([m[0], -m[1], m[2], m[3], -m[4], m[5]]); } + + function transform(m11, m21, m12, m22, mdx, mdy, n) { + var n11 = n[0], n12 = n[1], n21 = n[3], n22 = n[4], ndx = n[2], ndy = n[5]; + return new A([m11*n11 + m12*n21, + m11*n12 + m12*n22, + m11*ndx + m12*ndy + mdx, + m21*n11 + m22*n21, + m21*n12 + m22*n22, + m21*ndx + m22*ndy + mdy]); + } + */ + function multiply(m, n) + { + var m11 = m[0], m12 = m[1], m21 = m[3], m22 = m[4], mdx = m[2], mdy = m[5]; + var n11 = n[0], n12 = n[1], n21 = n[3], n22 = n[4], ndx = n[2], ndy = n[5]; + return new A([m11 * n11 + m12 * n21, + m11 * n12 + m12 * n22, + m11 * ndx + m12 * ndy + mdx, + m21 * n11 + m22 * n21, + m21 * n12 + m22 * n22, + m21 * ndx + m22 * ndy + mdy]); + } + + return localRuntime.Native.Transform2D.values = { + identity: identity, + matrix: F6(matrix), + rotation: rotation, + multiply: F2(multiply) + /* + transform: F7(transform), + rotate: F2(rotate), + move: F2(move), + scale: F2(scale), + scaleX: F2(scaleX), + scaleY: F2(scaleY), + reflectX: reflectX, + reflectY: reflectY + */ + }; +}; + +Elm.Transform2D = Elm.Transform2D || {}; +Elm.Transform2D.make = function (_elm) { + "use strict"; + _elm.Transform2D = _elm.Transform2D || {}; + if (_elm.Transform2D.values) return _elm.Transform2D.values; + var _U = Elm.Native.Utils.make(_elm),$Native$Transform2D = Elm.Native.Transform2D.make(_elm); + var _op = {}; + var multiply = $Native$Transform2D.multiply; + var rotation = $Native$Transform2D.rotation; + var matrix = $Native$Transform2D.matrix; + var translation = F2(function (x,y) { return A6(matrix,1,0,0,1,x,y);}); + var scale = function (s) { return A6(matrix,s,0,0,s,0,0);}; + var scaleX = function (x) { return A6(matrix,x,0,0,1,0,0);}; + var scaleY = function (y) { return A6(matrix,1,0,0,y,0,0);}; + var identity = $Native$Transform2D.identity; + var Transform2D = {ctor: "Transform2D"}; + return _elm.Transform2D.values = {_op: _op + ,identity: identity + ,matrix: matrix + ,multiply: multiply + ,rotation: rotation + ,translation: translation + ,scale: scale + ,scaleX: scaleX + ,scaleY: scaleY}; +}; + +// setup +Elm.Native = Elm.Native || {}; +Elm.Native.Graphics = Elm.Native.Graphics || {}; +Elm.Native.Graphics.Collage = Elm.Native.Graphics.Collage || {}; + +// definition +Elm.Native.Graphics.Collage.make = function(localRuntime) { + 'use strict'; + + // attempt to short-circuit + localRuntime.Native = localRuntime.Native || {}; + localRuntime.Native.Graphics = localRuntime.Native.Graphics || {}; + localRuntime.Native.Graphics.Collage = localRuntime.Native.Graphics.Collage || {}; + if ('values' in localRuntime.Native.Graphics.Collage) + { + return localRuntime.Native.Graphics.Collage.values; + } + + // okay, we cannot short-ciruit, so now we define everything + var Color = Elm.Native.Color.make(localRuntime); + var List = Elm.Native.List.make(localRuntime); + var NativeElement = Elm.Native.Graphics.Element.make(localRuntime); + var Transform = Elm.Transform2D.make(localRuntime); + var Utils = Elm.Native.Utils.make(localRuntime); + + function setStrokeStyle(ctx, style) + { + ctx.lineWidth = style.width; + + var cap = style.cap.ctor; + ctx.lineCap = cap === 'Flat' + ? 'butt' + : cap === 'Round' + ? 'round' + : 'square'; + + var join = style.join.ctor; + ctx.lineJoin = join === 'Smooth' + ? 'round' + : join === 'Sharp' + ? 'miter' + : 'bevel'; + + ctx.miterLimit = style.join._0 || 10; + ctx.strokeStyle = Color.toCss(style.color); + } + + function setFillStyle(redo, ctx, style) + { + var sty = style.ctor; + ctx.fillStyle = sty === 'Solid' + ? Color.toCss(style._0) + : sty === 'Texture' + ? texture(redo, ctx, style._0) + : gradient(ctx, style._0); + } + + function trace(ctx, path) + { + var points = List.toArray(path); + var i = points.length - 1; + if (i <= 0) + { + return; + } + ctx.moveTo(points[i]._0, points[i]._1); + while (i--) + { + ctx.lineTo(points[i]._0, points[i]._1); + } + if (path.closed) + { + i = points.length - 1; + ctx.lineTo(points[i]._0, points[i]._1); + } + } + + function line(ctx, style, path) + { + if (style.dashing.ctor === '[]') + { + trace(ctx, path); + } + else + { + customLineHelp(ctx, style, path); + } + ctx.scale(1, -1); + ctx.stroke(); + } + + function customLineHelp(ctx, style, path) + { + var points = List.toArray(path); + if (path.closed) + { + points.push(points[0]); + } + var pattern = List.toArray(style.dashing); + var i = points.length - 1; + if (i <= 0) + { + return; + } + var x0 = points[i]._0, y0 = points[i]._1; + var x1 = 0, y1 = 0, dx = 0, dy = 0, remaining = 0; + var pindex = 0, plen = pattern.length; + var draw = true, segmentLength = pattern[0]; + ctx.moveTo(x0, y0); + while (i--) + { + x1 = points[i]._0; + y1 = points[i]._1; + dx = x1 - x0; + dy = y1 - y0; + remaining = Math.sqrt(dx * dx + dy * dy); + while (segmentLength <= remaining) + { + x0 += dx * segmentLength / remaining; + y0 += dy * segmentLength / remaining; + ctx[draw ? 'lineTo' : 'moveTo'](x0, y0); + // update starting position + dx = x1 - x0; + dy = y1 - y0; + remaining = Math.sqrt(dx * dx + dy * dy); + // update pattern + draw = !draw; + pindex = (pindex + 1) % plen; + segmentLength = pattern[pindex]; + } + if (remaining > 0) + { + ctx[draw ? 'lineTo' : 'moveTo'](x1, y1); + segmentLength -= remaining; + } + x0 = x1; + y0 = y1; + } + } + + function drawLine(ctx, style, path) + { + setStrokeStyle(ctx, style); + return line(ctx, style, path); + } + + function texture(redo, ctx, src) + { + var img = new Image(); + img.src = src; + img.onload = redo; + return ctx.createPattern(img, 'repeat'); + } + + function gradient(ctx, grad) + { + var g; + var stops = []; + if (grad.ctor === 'Linear') + { + var p0 = grad._0, p1 = grad._1; + g = ctx.createLinearGradient(p0._0, -p0._1, p1._0, -p1._1); + stops = List.toArray(grad._2); + } + else + { + var p0 = grad._0, p2 = grad._2; + g = ctx.createRadialGradient(p0._0, -p0._1, grad._1, p2._0, -p2._1, grad._3); + stops = List.toArray(grad._4); + } + var len = stops.length; + for (var i = 0; i < len; ++i) + { + var stop = stops[i]; + g.addColorStop(stop._0, Color.toCss(stop._1)); + } + return g; + } + + function drawShape(redo, ctx, style, path) + { + trace(ctx, path); + setFillStyle(redo, ctx, style); + ctx.scale(1, -1); + ctx.fill(); + } + + + // TEXT RENDERING + + function fillText(redo, ctx, text) + { + drawText(ctx, text, ctx.fillText); + } + + function strokeText(redo, ctx, style, text) + { + setStrokeStyle(ctx, style); + // Use native canvas API for dashes only for text for now + // Degrades to non-dashed on IE 9 + 10 + if (style.dashing.ctor !== '[]' && ctx.setLineDash) + { + var pattern = List.toArray(style.dashing); + ctx.setLineDash(pattern); + } + drawText(ctx, text, ctx.strokeText); + } + + function drawText(ctx, text, canvasDrawFn) + { + var textChunks = chunkText(defaultContext, text); + + var totalWidth = 0; + var maxHeight = 0; + var numChunks = textChunks.length; + + ctx.scale(1,-1); + + for (var i = numChunks; i--; ) + { + var chunk = textChunks[i]; + ctx.font = chunk.font; + var metrics = ctx.measureText(chunk.text); + chunk.width = metrics.width; + totalWidth += chunk.width; + if (chunk.height > maxHeight) + { + maxHeight = chunk.height; + } + } + + var x = -totalWidth / 2.0; + for (var i = 0; i < numChunks; ++i) + { + var chunk = textChunks[i]; + ctx.font = chunk.font; + ctx.fillStyle = chunk.color; + canvasDrawFn.call(ctx, chunk.text, x, maxHeight / 2); + x += chunk.width; + } + } + + function toFont(props) + { + return [ + props['font-style'], + props['font-variant'], + props['font-weight'], + props['font-size'], + props['font-family'] + ].join(' '); + } + + + // Convert the object returned by the text module + // into something we can use for styling canvas text + function chunkText(context, text) + { + var tag = text.ctor; + if (tag === 'Text:Append') + { + var leftChunks = chunkText(context, text._0); + var rightChunks = chunkText(context, text._1); + return leftChunks.concat(rightChunks); + } + if (tag === 'Text:Text') + { + return [{ + text: text._0, + color: context.color, + height: context['font-size'].slice(0, -2) | 0, + font: toFont(context) + }]; + } + if (tag === 'Text:Meta') + { + var newContext = freshContext(text._0, context); + return chunkText(newContext, text._1); + } + } + + function freshContext(props, ctx) + { + return { + 'font-style': props['font-style'] || ctx['font-style'], + 'font-variant': props['font-variant'] || ctx['font-variant'], + 'font-weight': props['font-weight'] || ctx['font-weight'], + 'font-size': props['font-size'] || ctx['font-size'], + 'font-family': props['font-family'] || ctx['font-family'], + 'color': props['color'] || ctx['color'] + }; + } + + var defaultContext = { + 'font-style': 'normal', + 'font-variant': 'normal', + 'font-weight': 'normal', + 'font-size': '12px', + 'font-family': 'sans-serif', + 'color': 'black' + }; + + + // IMAGES + + function drawImage(redo, ctx, form) + { + var img = new Image(); + img.onload = redo; + img.src = form._3; + var w = form._0, + h = form._1, + pos = form._2, + srcX = pos._0, + srcY = pos._1, + srcW = w, + srcH = h, + destX = -w / 2, + destY = -h / 2, + destW = w, + destH = h; + + ctx.scale(1, -1); + ctx.drawImage(img, srcX, srcY, srcW, srcH, destX, destY, destW, destH); + } + + function renderForm(redo, ctx, form) + { + ctx.save(); + + var x = form.x, + y = form.y, + theta = form.theta, + scale = form.scale; + + if (x !== 0 || y !== 0) + { + ctx.translate(x, y); + } + if (theta !== 0) + { + ctx.rotate(theta % (Math.PI * 2)); + } + if (scale !== 1) + { + ctx.scale(scale, scale); + } + if (form.alpha !== 1) + { + ctx.globalAlpha = ctx.globalAlpha * form.alpha; + } + + ctx.beginPath(); + var f = form.form; + switch (f.ctor) + { + case 'FPath': + drawLine(ctx, f._0, f._1); + break; + + case 'FImage': + drawImage(redo, ctx, f); + break; + + case 'FShape': + if (f._0.ctor === 'Line') + { + f._1.closed = true; + drawLine(ctx, f._0._0, f._1); + } + else + { + drawShape(redo, ctx, f._0._0, f._1); + } + break; + + case 'FText': + fillText(redo, ctx, f._0); + break; + + case 'FOutlinedText': + strokeText(redo, ctx, f._0, f._1); + break; + } + ctx.restore(); + } + + function formToMatrix(form) + { + var scale = form.scale; + var matrix = A6( Transform.matrix, scale, 0, 0, scale, form.x, form.y ); + + var theta = form.theta; + if (theta !== 0) + { + matrix = A2( Transform.multiply, matrix, Transform.rotation(theta) ); + } + + return matrix; + } + + function str(n) + { + if (n < 0.00001 && n > -0.00001) + { + return 0; + } + return n; + } + + function makeTransform(w, h, form, matrices) + { + var props = form.form._0._0.props; + var m = A6( Transform.matrix, 1, 0, 0, -1, + (w - props.width ) / 2, + (h - props.height) / 2 ); + var len = matrices.length; + for (var i = 0; i < len; ++i) + { + m = A2( Transform.multiply, m, matrices[i] ); + } + m = A2( Transform.multiply, m, formToMatrix(form) ); + + return 'matrix(' + + str( m[0]) + ', ' + str( m[3]) + ', ' + + str(-m[1]) + ', ' + str(-m[4]) + ', ' + + str( m[2]) + ', ' + str( m[5]) + ')'; + } + + function stepperHelp(list) + { + var arr = List.toArray(list); + var i = 0; + function peekNext() + { + return i < arr.length ? arr[i]._0.form.ctor : ''; + } + // assumes that there is a next element + function next() + { + var out = arr[i]._0; + ++i; + return out; + } + return { + peekNext: peekNext, + next: next + }; + } + + function formStepper(forms) + { + var ps = [stepperHelp(forms)]; + var matrices = []; + var alphas = []; + function peekNext() + { + var len = ps.length; + var formType = ''; + for (var i = 0; i < len; ++i ) + { + if (formType = ps[i].peekNext()) return formType; + } + return ''; + } + // assumes that there is a next element + function next(ctx) + { + while (!ps[0].peekNext()) + { + ps.shift(); + matrices.pop(); + alphas.shift(); + if (ctx) + { + ctx.restore(); + } + } + var out = ps[0].next(); + var f = out.form; + if (f.ctor === 'FGroup') + { + ps.unshift(stepperHelp(f._1)); + var m = A2(Transform.multiply, f._0, formToMatrix(out)); + ctx.save(); + ctx.transform(m[0], m[3], m[1], m[4], m[2], m[5]); + matrices.push(m); + + var alpha = (alphas[0] || 1) * out.alpha; + alphas.unshift(alpha); + ctx.globalAlpha = alpha; + } + return out; + } + function transforms() + { + return matrices; + } + function alpha() + { + return alphas[0] || 1; + } + return { + peekNext: peekNext, + next: next, + transforms: transforms, + alpha: alpha + }; + } + + function makeCanvas(w, h) + { + var canvas = NativeElement.createNode('canvas'); + canvas.style.width = w + 'px'; + canvas.style.height = h + 'px'; + canvas.style.display = 'block'; + canvas.style.position = 'absolute'; + var ratio = window.devicePixelRatio || 1; + canvas.width = w * ratio; + canvas.height = h * ratio; + return canvas; + } + + function render(model) + { + var div = NativeElement.createNode('div'); + div.style.overflow = 'hidden'; + div.style.position = 'relative'; + update(div, model, model); + return div; + } + + function nodeStepper(w, h, div) + { + var kids = div.childNodes; + var i = 0; + var ratio = window.devicePixelRatio || 1; + + function transform(transforms, ctx) + { + ctx.translate( w / 2 * ratio, h / 2 * ratio ); + ctx.scale( ratio, -ratio ); + var len = transforms.length; + for (var i = 0; i < len; ++i) + { + var m = transforms[i]; + ctx.save(); + ctx.transform(m[0], m[3], m[1], m[4], m[2], m[5]); + } + return ctx; + } + function nextContext(transforms) + { + while (i < kids.length) + { + var node = kids[i]; + if (node.getContext) + { + node.width = w * ratio; + node.height = h * ratio; + node.style.width = w + 'px'; + node.style.height = h + 'px'; + ++i; + return transform(transforms, node.getContext('2d')); + } + div.removeChild(node); + } + var canvas = makeCanvas(w, h); + div.appendChild(canvas); + // we have added a new node, so we must step our position + ++i; + return transform(transforms, canvas.getContext('2d')); + } + function addElement(matrices, alpha, form) + { + var kid = kids[i]; + var elem = form.form._0; + + var node = (!kid || kid.getContext) + ? NativeElement.render(elem) + : NativeElement.update(kid, kid.oldElement, elem); + + node.style.position = 'absolute'; + node.style.opacity = alpha * form.alpha * elem._0.props.opacity; + NativeElement.addTransform(node.style, makeTransform(w, h, form, matrices)); + node.oldElement = elem; + ++i; + if (!kid) + { + div.appendChild(node); + } + else + { + div.insertBefore(node, kid); + } + } + function clearRest() + { + while (i < kids.length) + { + div.removeChild(kids[i]); + } + } + return { + nextContext: nextContext, + addElement: addElement, + clearRest: clearRest + }; + } + + + function update(div, _, model) + { + var w = model.w; + var h = model.h; + + var forms = formStepper(model.forms); + var nodes = nodeStepper(w, h, div); + var ctx = null; + var formType = ''; + + while (formType = forms.peekNext()) + { + // make sure we have context if we need it + if (ctx === null && formType !== 'FElement') + { + ctx = nodes.nextContext(forms.transforms()); + ctx.globalAlpha = forms.alpha(); + } + + var form = forms.next(ctx); + // if it is FGroup, all updates are made within formStepper when next is called. + if (formType === 'FElement') + { + // update or insert an element, get a new context + nodes.addElement(forms.transforms(), forms.alpha(), form); + ctx = null; + } + else if (formType !== 'FGroup') + { + renderForm(function() { update(div, model, model); }, ctx, form); + } + } + nodes.clearRest(); + return div; + } + + + function collage(w, h, forms) + { + return A3(NativeElement.newElement, w, h, { + ctor: 'Custom', + type: 'Collage', + render: render, + update: update, + model: {w: w, h: h, forms: forms} + }); + } + + return localRuntime.Native.Graphics.Collage.values = { + collage: F3(collage) + }; +}; + + +// setup +Elm.Native = Elm.Native || {}; +Elm.Native.Graphics = Elm.Native.Graphics || {}; +Elm.Native.Graphics.Element = Elm.Native.Graphics.Element || {}; + +// definition +Elm.Native.Graphics.Element.make = function(localRuntime) { + 'use strict'; + + // attempt to short-circuit + localRuntime.Native = localRuntime.Native || {}; + localRuntime.Native.Graphics = localRuntime.Native.Graphics || {}; + localRuntime.Native.Graphics.Element = localRuntime.Native.Graphics.Element || {}; + if ('values' in localRuntime.Native.Graphics.Element) + { + return localRuntime.Native.Graphics.Element.values; + } + + var Color = Elm.Native.Color.make(localRuntime); + var List = Elm.Native.List.make(localRuntime); + var Maybe = Elm.Maybe.make(localRuntime); + var Text = Elm.Native.Text.make(localRuntime); + var Utils = Elm.Native.Utils.make(localRuntime); + + + // CREATION + + var createNode = + typeof document === 'undefined' + ? + function(_) + { + return { + style: {}, + appendChild: function() {} + }; + } + : + function(elementType) + { + var node = document.createElement(elementType); + node.style.padding = '0'; + node.style.margin = '0'; + return node; + } + ; + + + function newElement(width, height, elementPrim) + { + return { + ctor: 'Element_elm_builtin', + _0: { + element: elementPrim, + props: { + id: Utils.guid(), + width: width, + height: height, + opacity: 1, + color: Maybe.Nothing, + href: '', + tag: '', + hover: Utils.Tuple0, + click: Utils.Tuple0 + } + } + }; + } + + + // PROPERTIES + + function setProps(elem, node) + { + var props = elem.props; + + var element = elem.element; + var width = props.width - (element.adjustWidth || 0); + var height = props.height - (element.adjustHeight || 0); + node.style.width = (width | 0) + 'px'; + node.style.height = (height | 0) + 'px'; + + if (props.opacity !== 1) + { + node.style.opacity = props.opacity; + } + + if (props.color.ctor === 'Just') + { + node.style.backgroundColor = Color.toCss(props.color._0); + } + + if (props.tag !== '') + { + node.id = props.tag; + } + + if (props.hover.ctor !== '_Tuple0') + { + addHover(node, props.hover); + } + + if (props.click.ctor !== '_Tuple0') + { + addClick(node, props.click); + } + + if (props.href !== '') + { + var anchor = createNode('a'); + anchor.href = props.href; + anchor.style.display = 'block'; + anchor.style.pointerEvents = 'auto'; + anchor.appendChild(node); + node = anchor; + } + + return node; + } + + function addClick(e, handler) + { + e.style.pointerEvents = 'auto'; + e.elm_click_handler = handler; + function trigger(ev) + { + e.elm_click_handler(Utils.Tuple0); + ev.stopPropagation(); + } + e.elm_click_trigger = trigger; + e.addEventListener('click', trigger); + } + + function removeClick(e, handler) + { + if (e.elm_click_trigger) + { + e.removeEventListener('click', e.elm_click_trigger); + e.elm_click_trigger = null; + e.elm_click_handler = null; + } + } + + function addHover(e, handler) + { + e.style.pointerEvents = 'auto'; + e.elm_hover_handler = handler; + e.elm_hover_count = 0; + + function over(evt) + { + if (e.elm_hover_count++ > 0) return; + e.elm_hover_handler(true); + evt.stopPropagation(); + } + function out(evt) + { + if (e.contains(evt.toElement || evt.relatedTarget)) return; + e.elm_hover_count = 0; + e.elm_hover_handler(false); + evt.stopPropagation(); + } + e.elm_hover_over = over; + e.elm_hover_out = out; + e.addEventListener('mouseover', over); + e.addEventListener('mouseout', out); + } + + function removeHover(e) + { + e.elm_hover_handler = null; + if (e.elm_hover_over) + { + e.removeEventListener('mouseover', e.elm_hover_over); + e.elm_hover_over = null; + } + if (e.elm_hover_out) + { + e.removeEventListener('mouseout', e.elm_hover_out); + e.elm_hover_out = null; + } + } + + + // IMAGES + + function image(props, img) + { + switch (img._0.ctor) + { + case 'Plain': + return plainImage(img._3); + + case 'Fitted': + return fittedImage(props.width, props.height, img._3); + + case 'Cropped': + return croppedImage(img, props.width, props.height, img._3); + + case 'Tiled': + return tiledImage(img._3); + } + } + + function plainImage(src) + { + var img = createNode('img'); + img.src = src; + img.name = src; + img.style.display = 'block'; + return img; + } + + function tiledImage(src) + { + var div = createNode('div'); + div.style.backgroundImage = 'url(' + src + ')'; + return div; + } + + function fittedImage(w, h, src) + { + var div = createNode('div'); + div.style.background = 'url(' + src + ') no-repeat center'; + div.style.webkitBackgroundSize = 'cover'; + div.style.MozBackgroundSize = 'cover'; + div.style.OBackgroundSize = 'cover'; + div.style.backgroundSize = 'cover'; + return div; + } + + function croppedImage(elem, w, h, src) + { + var pos = elem._0._0; + var e = createNode('div'); + e.style.overflow = 'hidden'; + + var img = createNode('img'); + img.onload = function() { + var sw = w / elem._1, sh = h / elem._2; + img.style.width = ((this.width * sw) | 0) + 'px'; + img.style.height = ((this.height * sh) | 0) + 'px'; + img.style.marginLeft = ((- pos._0 * sw) | 0) + 'px'; + img.style.marginTop = ((- pos._1 * sh) | 0) + 'px'; + }; + img.src = src; + img.name = src; + e.appendChild(img); + return e; + } + + + // FLOW + + function goOut(node) + { + node.style.position = 'absolute'; + return node; + } + function goDown(node) + { + return node; + } + function goRight(node) + { + node.style.styleFloat = 'left'; + node.style.cssFloat = 'left'; + return node; + } + + var directionTable = { + DUp: goDown, + DDown: goDown, + DLeft: goRight, + DRight: goRight, + DIn: goOut, + DOut: goOut + }; + function needsReversal(dir) + { + return dir === 'DUp' || dir === 'DLeft' || dir === 'DIn'; + } + + function flow(dir, elist) + { + var array = List.toArray(elist); + var container = createNode('div'); + var goDir = directionTable[dir]; + if (goDir === goOut) + { + container.style.pointerEvents = 'none'; + } + if (needsReversal(dir)) + { + array.reverse(); + } + var len = array.length; + for (var i = 0; i < len; ++i) + { + container.appendChild(goDir(render(array[i]))); + } + return container; + } + + + // CONTAINER + + function toPos(pos) + { + return pos.ctor === 'Absolute' + ? pos._0 + 'px' + : (pos._0 * 100) + '%'; + } + + // must clear right, left, top, bottom, and transform + // before calling this function + function setPos(pos, wrappedElement, e) + { + var elem = wrappedElement._0; + var element = elem.element; + var props = elem.props; + var w = props.width + (element.adjustWidth ? element.adjustWidth : 0); + var h = props.height + (element.adjustHeight ? element.adjustHeight : 0); + + e.style.position = 'absolute'; + e.style.margin = 'auto'; + var transform = ''; + + switch (pos.horizontal.ctor) + { + case 'P': + e.style.right = toPos(pos.x); + e.style.removeProperty('left'); + break; + + case 'Z': + transform = 'translateX(' + ((-w / 2) | 0) + 'px) '; + + case 'N': + e.style.left = toPos(pos.x); + e.style.removeProperty('right'); + break; + } + switch (pos.vertical.ctor) + { + case 'N': + e.style.bottom = toPos(pos.y); + e.style.removeProperty('top'); + break; + + case 'Z': + transform += 'translateY(' + ((-h / 2) | 0) + 'px)'; + + case 'P': + e.style.top = toPos(pos.y); + e.style.removeProperty('bottom'); + break; + } + if (transform !== '') + { + addTransform(e.style, transform); + } + return e; + } + + function addTransform(style, transform) + { + style.transform = transform; + style.msTransform = transform; + style.MozTransform = transform; + style.webkitTransform = transform; + style.OTransform = transform; + } + + function container(pos, elem) + { + var e = render(elem); + setPos(pos, elem, e); + var div = createNode('div'); + div.style.position = 'relative'; + div.style.overflow = 'hidden'; + div.appendChild(e); + return div; + } + + + function rawHtml(elem) + { + var html = elem.html; + var align = elem.align; + + var div = createNode('div'); + div.innerHTML = html; + div.style.visibility = 'hidden'; + if (align) + { + div.style.textAlign = align; + } + div.style.visibility = 'visible'; + div.style.pointerEvents = 'auto'; + return div; + } + + + // RENDER + + function render(wrappedElement) + { + var elem = wrappedElement._0; + return setProps(elem, makeElement(elem)); + } + + function makeElement(e) + { + var elem = e.element; + switch (elem.ctor) + { + case 'Image': + return image(e.props, elem); + + case 'Flow': + return flow(elem._0.ctor, elem._1); + + case 'Container': + return container(elem._0, elem._1); + + case 'Spacer': + return createNode('div'); + + case 'RawHtml': + return rawHtml(elem); + + case 'Custom': + return elem.render(elem.model); + } + } + + function updateAndReplace(node, curr, next) + { + var newNode = update(node, curr, next); + if (newNode !== node) + { + node.parentNode.replaceChild(newNode, node); + } + return newNode; + } + + + // UPDATE + + function update(node, wrappedCurrent, wrappedNext) + { + var curr = wrappedCurrent._0; + var next = wrappedNext._0; + var rootNode = node; + if (node.tagName === 'A') + { + node = node.firstChild; + } + if (curr.props.id === next.props.id) + { + updateProps(node, curr, next); + return rootNode; + } + if (curr.element.ctor !== next.element.ctor) + { + return render(wrappedNext); + } + var nextE = next.element; + var currE = curr.element; + switch (nextE.ctor) + { + case 'Spacer': + updateProps(node, curr, next); + return rootNode; + + case 'RawHtml': + if(currE.html.valueOf() !== nextE.html.valueOf()) + { + node.innerHTML = nextE.html; + } + updateProps(node, curr, next); + return rootNode; + + case 'Image': + if (nextE._0.ctor === 'Plain') + { + if (nextE._3 !== currE._3) + { + node.src = nextE._3; + } + } + else if (!Utils.eq(nextE, currE) + || next.props.width !== curr.props.width + || next.props.height !== curr.props.height) + { + return render(wrappedNext); + } + updateProps(node, curr, next); + return rootNode; + + case 'Flow': + var arr = List.toArray(nextE._1); + for (var i = arr.length; i--; ) + { + arr[i] = arr[i]._0.element.ctor; + } + if (nextE._0.ctor !== currE._0.ctor) + { + return render(wrappedNext); + } + var nexts = List.toArray(nextE._1); + var kids = node.childNodes; + if (nexts.length !== kids.length) + { + return render(wrappedNext); + } + var currs = List.toArray(currE._1); + var dir = nextE._0.ctor; + var goDir = directionTable[dir]; + var toReverse = needsReversal(dir); + var len = kids.length; + for (var i = len; i--; ) + { + var subNode = kids[toReverse ? len - i - 1 : i]; + goDir(updateAndReplace(subNode, currs[i], nexts[i])); + } + updateProps(node, curr, next); + return rootNode; + + case 'Container': + var subNode = node.firstChild; + var newSubNode = updateAndReplace(subNode, currE._1, nextE._1); + setPos(nextE._0, nextE._1, newSubNode); + updateProps(node, curr, next); + return rootNode; + + case 'Custom': + if (currE.type === nextE.type) + { + var updatedNode = nextE.update(node, currE.model, nextE.model); + updateProps(updatedNode, curr, next); + return updatedNode; + } + return render(wrappedNext); + } + } + + function updateProps(node, curr, next) + { + var nextProps = next.props; + var currProps = curr.props; + + var element = next.element; + var width = nextProps.width - (element.adjustWidth || 0); + var height = nextProps.height - (element.adjustHeight || 0); + if (width !== currProps.width) + { + node.style.width = (width | 0) + 'px'; + } + if (height !== currProps.height) + { + node.style.height = (height | 0) + 'px'; + } + + if (nextProps.opacity !== currProps.opacity) + { + node.style.opacity = nextProps.opacity; + } + + var nextColor = nextProps.color.ctor === 'Just' + ? Color.toCss(nextProps.color._0) + : ''; + if (node.style.backgroundColor !== nextColor) + { + node.style.backgroundColor = nextColor; + } + + if (nextProps.tag !== currProps.tag) + { + node.id = nextProps.tag; + } + + if (nextProps.href !== currProps.href) + { + if (currProps.href === '') + { + // add a surrounding href + var anchor = createNode('a'); + anchor.href = nextProps.href; + anchor.style.display = 'block'; + anchor.style.pointerEvents = 'auto'; + + node.parentNode.replaceChild(anchor, node); + anchor.appendChild(node); + } + else if (nextProps.href === '') + { + // remove the surrounding href + var anchor = node.parentNode; + anchor.parentNode.replaceChild(node, anchor); + } + else + { + // just update the link + node.parentNode.href = nextProps.href; + } + } + + // update click and hover handlers + var removed = false; + + // update hover handlers + if (currProps.hover.ctor === '_Tuple0') + { + if (nextProps.hover.ctor !== '_Tuple0') + { + addHover(node, nextProps.hover); + } + } + else + { + if (nextProps.hover.ctor === '_Tuple0') + { + removed = true; + removeHover(node); + } + else + { + node.elm_hover_handler = nextProps.hover; + } + } + + // update click handlers + if (currProps.click.ctor === '_Tuple0') + { + if (nextProps.click.ctor !== '_Tuple0') + { + addClick(node, nextProps.click); + } + } + else + { + if (nextProps.click.ctor === '_Tuple0') + { + removed = true; + removeClick(node); + } + else + { + node.elm_click_handler = nextProps.click; + } + } + + // stop capturing clicks if + if (removed + && nextProps.hover.ctor === '_Tuple0' + && nextProps.click.ctor === '_Tuple0') + { + node.style.pointerEvents = 'none'; + } + } + + + // TEXT + + function block(align) + { + return function(text) + { + var raw = { + ctor: 'RawHtml', + html: Text.renderHtml(text), + align: align + }; + var pos = htmlHeight(0, raw); + return newElement(pos._0, pos._1, raw); + }; + } + + function markdown(text) + { + var raw = { + ctor: 'RawHtml', + html: text, + align: null + }; + var pos = htmlHeight(0, raw); + return newElement(pos._0, pos._1, raw); + } + + var htmlHeight = + typeof document !== 'undefined' + ? realHtmlHeight + : function(a, b) { return Utils.Tuple2(0, 0); }; + + function realHtmlHeight(width, rawHtml) + { + // create dummy node + var temp = document.createElement('div'); + temp.innerHTML = rawHtml.html; + if (width > 0) + { + temp.style.width = width + 'px'; + } + temp.style.visibility = 'hidden'; + temp.style.styleFloat = 'left'; + temp.style.cssFloat = 'left'; + + document.body.appendChild(temp); + + // get dimensions + var style = window.getComputedStyle(temp, null); + var w = Math.ceil(style.getPropertyValue('width').slice(0, -2) - 0); + var h = Math.ceil(style.getPropertyValue('height').slice(0, -2) - 0); + document.body.removeChild(temp); + return Utils.Tuple2(w, h); + } + + + return localRuntime.Native.Graphics.Element.values = { + render: render, + update: update, + updateAndReplace: updateAndReplace, + + createNode: createNode, + newElement: F3(newElement), + addTransform: addTransform, + htmlHeight: F2(htmlHeight), + guid: Utils.guid, + + block: block, + markdown: markdown + }; +}; + +Elm.Native.Text = {}; +Elm.Native.Text.make = function(localRuntime) { + localRuntime.Native = localRuntime.Native || {}; + localRuntime.Native.Text = localRuntime.Native.Text || {}; + if (localRuntime.Native.Text.values) + { + return localRuntime.Native.Text.values; + } + + var toCss = Elm.Native.Color.make(localRuntime).toCss; + var List = Elm.Native.List.make(localRuntime); + + + // CONSTRUCTORS + + function fromString(str) + { + return { + ctor: 'Text:Text', + _0: str + }; + } + + function append(a, b) + { + return { + ctor: 'Text:Append', + _0: a, + _1: b + }; + } + + function addMeta(field, value, text) + { + var newProps = {}; + var newText = { + ctor: 'Text:Meta', + _0: newProps, + _1: text + }; + + if (text.ctor === 'Text:Meta') + { + newText._1 = text._1; + var props = text._0; + for (var i = metaKeys.length; i--; ) + { + var key = metaKeys[i]; + var val = props[key]; + if (val) + { + newProps[key] = val; + } + } + } + newProps[field] = value; + return newText; + } + + var metaKeys = [ + 'font-size', + 'font-family', + 'font-style', + 'font-weight', + 'href', + 'text-decoration', + 'color' + ]; + + + // conversions from Elm values to CSS + + function toTypefaces(list) + { + var typefaces = List.toArray(list); + for (var i = typefaces.length; i--; ) + { + var typeface = typefaces[i]; + if (typeface.indexOf(' ') > -1) + { + typefaces[i] = "'" + typeface + "'"; + } + } + return typefaces.join(','); + } + + function toLine(line) + { + var ctor = line.ctor; + return ctor === 'Under' + ? 'underline' + : ctor === 'Over' + ? 'overline' + : 'line-through'; + } + + // setting styles of Text + + function style(style, text) + { + var newText = addMeta('color', toCss(style.color), text); + var props = newText._0; + + if (style.typeface.ctor !== '[]') + { + props['font-family'] = toTypefaces(style.typeface); + } + if (style.height.ctor !== 'Nothing') + { + props['font-size'] = style.height._0 + 'px'; + } + if (style.bold) + { + props['font-weight'] = 'bold'; + } + if (style.italic) + { + props['font-style'] = 'italic'; + } + if (style.line.ctor !== 'Nothing') + { + props['text-decoration'] = toLine(style.line._0); + } + return newText; + } + + function height(px, text) + { + return addMeta('font-size', px + 'px', text); + } + + function typeface(names, text) + { + return addMeta('font-family', toTypefaces(names), text); + } + + function monospace(text) + { + return addMeta('font-family', 'monospace', text); + } + + function italic(text) + { + return addMeta('font-style', 'italic', text); + } + + function bold(text) + { + return addMeta('font-weight', 'bold', text); + } + + function link(href, text) + { + return addMeta('href', href, text); + } + + function line(line, text) + { + return addMeta('text-decoration', toLine(line), text); + } + + function color(color, text) + { + return addMeta('color', toCss(color), text); + } + + + // RENDER + + function renderHtml(text) + { + var tag = text.ctor; + if (tag === 'Text:Append') + { + return renderHtml(text._0) + renderHtml(text._1); + } + if (tag === 'Text:Text') + { + return properEscape(text._0); + } + if (tag === 'Text:Meta') + { + return renderMeta(text._0, renderHtml(text._1)); + } + } + + function renderMeta(metas, string) + { + var href = metas.href; + if (href) + { + string = '' + string + ''; + } + var styles = ''; + for (var key in metas) + { + if (key === 'href') + { + continue; + } + styles += key + ':' + metas[key] + ';'; + } + if (styles) + { + string = '' + string + ''; + } + return string; + } + + function properEscape(str) + { + if (str.length === 0) + { + return str; + } + str = str //.replace(/&/g, '&') + .replace(/"/g, '"') + .replace(/'/g, ''') + .replace(//g, '>'); + var arr = str.split('\n'); + for (var i = arr.length; i--; ) + { + arr[i] = makeSpaces(arr[i]); + } + return arr.join('
'); + } + + function makeSpaces(s) + { + if (s.length === 0) + { + return s; + } + var arr = s.split(''); + if (arr[0] === ' ') + { + arr[0] = ' '; + } + for (var i = arr.length; --i; ) + { + if (arr[i][0] === ' ' && arr[i - 1] === ' ') + { + arr[i - 1] = arr[i - 1] + arr[i]; + arr[i] = ''; + } + } + for (var i = arr.length; i--; ) + { + if (arr[i].length > 1 && arr[i][0] === ' ') + { + var spaces = arr[i].split(''); + for (var j = spaces.length - 2; j >= 0; j -= 2) + { + spaces[j] = ' '; + } + arr[i] = spaces.join(''); + } + } + arr = arr.join(''); + if (arr[arr.length - 1] === ' ') + { + return arr.slice(0, -1) + ' '; + } + return arr; + } + + + return localRuntime.Native.Text.values = { + fromString: fromString, + append: F2(append), + + height: F2(height), + italic: italic, + bold: bold, + line: F2(line), + monospace: monospace, + typeface: F2(typeface), + color: F2(color), + link: F2(link), + style: F2(style), + + toTypefaces: toTypefaces, + toLine: toLine, + renderHtml: renderHtml + }; +}; + +Elm.Text = Elm.Text || {}; +Elm.Text.make = function (_elm) { + "use strict"; + _elm.Text = _elm.Text || {}; + if (_elm.Text.values) return _elm.Text.values; + var _U = Elm.Native.Utils.make(_elm), + $Color = Elm.Color.make(_elm), + $List = Elm.List.make(_elm), + $Maybe = Elm.Maybe.make(_elm), + $Native$Text = Elm.Native.Text.make(_elm); + var _op = {}; + var line = $Native$Text.line; + var italic = $Native$Text.italic; + var bold = $Native$Text.bold; + var color = $Native$Text.color; + var height = $Native$Text.height; + var link = $Native$Text.link; + var monospace = $Native$Text.monospace; + var typeface = $Native$Text.typeface; + var style = $Native$Text.style; + var append = $Native$Text.append; + var fromString = $Native$Text.fromString; + var empty = fromString(""); + var concat = function (texts) { return A3($List.foldr,append,empty,texts);}; + var join = F2(function (seperator,texts) { return concat(A2($List.intersperse,seperator,texts));}); + var defaultStyle = {typeface: _U.list([]),height: $Maybe.Nothing,color: $Color.black,bold: false,italic: false,line: $Maybe.Nothing}; + var Style = F6(function (a,b,c,d,e,f) { return {typeface: a,height: b,color: c,bold: d,italic: e,line: f};}); + var Through = {ctor: "Through"}; + var Over = {ctor: "Over"}; + var Under = {ctor: "Under"}; + var Text = {ctor: "Text"}; + return _elm.Text.values = {_op: _op + ,fromString: fromString + ,empty: empty + ,append: append + ,concat: concat + ,join: join + ,link: link + ,style: style + ,defaultStyle: defaultStyle + ,typeface: typeface + ,monospace: monospace + ,height: height + ,color: color + ,bold: bold + ,italic: italic + ,line: line + ,Style: Style + ,Under: Under + ,Over: Over + ,Through: Through}; +}; +Elm.Graphics = Elm.Graphics || {}; +Elm.Graphics.Element = Elm.Graphics.Element || {}; +Elm.Graphics.Element.make = function (_elm) { + "use strict"; + _elm.Graphics = _elm.Graphics || {}; + _elm.Graphics.Element = _elm.Graphics.Element || {}; + if (_elm.Graphics.Element.values) return _elm.Graphics.Element.values; + var _U = Elm.Native.Utils.make(_elm), + $Basics = Elm.Basics.make(_elm), + $Color = Elm.Color.make(_elm), + $List = Elm.List.make(_elm), + $Maybe = Elm.Maybe.make(_elm), + $Native$Graphics$Element = Elm.Native.Graphics.Element.make(_elm), + $Text = Elm.Text.make(_elm); + var _op = {}; + var DOut = {ctor: "DOut"}; + var outward = DOut; + var DIn = {ctor: "DIn"}; + var inward = DIn; + var DRight = {ctor: "DRight"}; + var right = DRight; + var DLeft = {ctor: "DLeft"}; + var left = DLeft; + var DDown = {ctor: "DDown"}; + var down = DDown; + var DUp = {ctor: "DUp"}; + var up = DUp; + var RawPosition = F4(function (a,b,c,d) { return {horizontal: a,vertical: b,x: c,y: d};}); + var Position = function (a) { return {ctor: "Position",_0: a};}; + var Relative = function (a) { return {ctor: "Relative",_0: a};}; + var relative = Relative; + var Absolute = function (a) { return {ctor: "Absolute",_0: a};}; + var absolute = Absolute; + var N = {ctor: "N"}; + var bottomLeft = Position({horizontal: N,vertical: N,x: Absolute(0),y: Absolute(0)}); + var bottomLeftAt = F2(function (x,y) { return Position({horizontal: N,vertical: N,x: x,y: y});}); + var Z = {ctor: "Z"}; + var middle = Position({horizontal: Z,vertical: Z,x: Relative(0.5),y: Relative(0.5)}); + var midLeft = Position({horizontal: N,vertical: Z,x: Absolute(0),y: Relative(0.5)}); + var midBottom = Position({horizontal: Z,vertical: N,x: Relative(0.5),y: Absolute(0)}); + var middleAt = F2(function (x,y) { return Position({horizontal: Z,vertical: Z,x: x,y: y});}); + var midLeftAt = F2(function (x,y) { return Position({horizontal: N,vertical: Z,x: x,y: y});}); + var midBottomAt = F2(function (x,y) { return Position({horizontal: Z,vertical: N,x: x,y: y});}); + var P = {ctor: "P"}; + var topLeft = Position({horizontal: N,vertical: P,x: Absolute(0),y: Absolute(0)}); + var topRight = Position({horizontal: P,vertical: P,x: Absolute(0),y: Absolute(0)}); + var bottomRight = Position({horizontal: P,vertical: N,x: Absolute(0),y: Absolute(0)}); + var midRight = Position({horizontal: P,vertical: Z,x: Absolute(0),y: Relative(0.5)}); + var midTop = Position({horizontal: Z,vertical: P,x: Relative(0.5),y: Absolute(0)}); + var topLeftAt = F2(function (x,y) { return Position({horizontal: N,vertical: P,x: x,y: y});}); + var topRightAt = F2(function (x,y) { return Position({horizontal: P,vertical: P,x: x,y: y});}); + var bottomRightAt = F2(function (x,y) { return Position({horizontal: P,vertical: N,x: x,y: y});}); + var midRightAt = F2(function (x,y) { return Position({horizontal: P,vertical: Z,x: x,y: y});}); + var midTopAt = F2(function (x,y) { return Position({horizontal: Z,vertical: P,x: x,y: y});}); + var justified = $Native$Graphics$Element.block("justify"); + var centered = $Native$Graphics$Element.block("center"); + var rightAligned = $Native$Graphics$Element.block("right"); + var leftAligned = $Native$Graphics$Element.block("left"); + var show = function (value) { return leftAligned($Text.monospace($Text.fromString($Basics.toString(value))));}; + var Tiled = {ctor: "Tiled"}; + var Cropped = function (a) { return {ctor: "Cropped",_0: a};}; + var Fitted = {ctor: "Fitted"}; + var Plain = {ctor: "Plain"}; + var Custom = {ctor: "Custom"}; + var RawHtml = {ctor: "RawHtml"}; + var Spacer = {ctor: "Spacer"}; + var Flow = F2(function (a,b) { return {ctor: "Flow",_0: a,_1: b};}); + var Container = F2(function (a,b) { return {ctor: "Container",_0: a,_1: b};}); + var Image = F4(function (a,b,c,d) { return {ctor: "Image",_0: a,_1: b,_2: c,_3: d};}); + var newElement = $Native$Graphics$Element.newElement; + var image = F3(function (w,h,src) { return A3(newElement,w,h,A4(Image,Plain,w,h,src));}); + var fittedImage = F3(function (w,h,src) { return A3(newElement,w,h,A4(Image,Fitted,w,h,src));}); + var croppedImage = F4(function (pos,w,h,src) { return A3(newElement,w,h,A4(Image,Cropped(pos),w,h,src));}); + var tiledImage = F3(function (w,h,src) { return A3(newElement,w,h,A4(Image,Tiled,w,h,src));}); + var container = F4(function (w,h,_p0,e) { var _p1 = _p0;return A3(newElement,w,h,A2(Container,_p1._0,e));}); + var spacer = F2(function (w,h) { return A3(newElement,w,h,Spacer);}); + var sizeOf = function (_p2) { var _p3 = _p2;var _p4 = _p3._0;return {ctor: "_Tuple2",_0: _p4.props.width,_1: _p4.props.height};}; + var heightOf = function (_p5) { var _p6 = _p5;return _p6._0.props.height;}; + var widthOf = function (_p7) { var _p8 = _p7;return _p8._0.props.width;}; + var above = F2(function (hi,lo) { + return A3(newElement,A2($Basics.max,widthOf(hi),widthOf(lo)),heightOf(hi) + heightOf(lo),A2(Flow,DDown,_U.list([hi,lo]))); + }); + var below = F2(function (lo,hi) { + return A3(newElement,A2($Basics.max,widthOf(hi),widthOf(lo)),heightOf(hi) + heightOf(lo),A2(Flow,DDown,_U.list([hi,lo]))); + }); + var beside = F2(function (lft,rht) { + return A3(newElement,widthOf(lft) + widthOf(rht),A2($Basics.max,heightOf(lft),heightOf(rht)),A2(Flow,right,_U.list([lft,rht]))); + }); + var layers = function (es) { + var hs = A2($List.map,heightOf,es); + var ws = A2($List.map,widthOf,es); + return A3(newElement,A2($Maybe.withDefault,0,$List.maximum(ws)),A2($Maybe.withDefault,0,$List.maximum(hs)),A2(Flow,DOut,es)); + }; + var empty = A2(spacer,0,0); + var flow = F2(function (dir,es) { + var newFlow = F2(function (w,h) { return A3(newElement,w,h,A2(Flow,dir,es));}); + var maxOrZero = function (list) { return A2($Maybe.withDefault,0,$List.maximum(list));}; + var hs = A2($List.map,heightOf,es); + var ws = A2($List.map,widthOf,es); + if (_U.eq(es,_U.list([]))) return empty; else { + var _p9 = dir; + switch (_p9.ctor) + {case "DUp": return A2(newFlow,maxOrZero(ws),$List.sum(hs)); + case "DDown": return A2(newFlow,maxOrZero(ws),$List.sum(hs)); + case "DLeft": return A2(newFlow,$List.sum(ws),maxOrZero(hs)); + case "DRight": return A2(newFlow,$List.sum(ws),maxOrZero(hs)); + case "DIn": return A2(newFlow,maxOrZero(ws),maxOrZero(hs)); + default: return A2(newFlow,maxOrZero(ws),maxOrZero(hs));} + } + }); + var Properties = F9(function (a,b,c,d,e,f,g,h,i) { return {id: a,width: b,height: c,opacity: d,color: e,href: f,tag: g,hover: h,click: i};}); + var Element_elm_builtin = function (a) { return {ctor: "Element_elm_builtin",_0: a};}; + var width = F2(function (newWidth,_p10) { + var _p11 = _p10; + var _p14 = _p11._0.props; + var _p13 = _p11._0.element; + var newHeight = function () { + var _p12 = _p13; + switch (_p12.ctor) + {case "Image": return $Basics.round($Basics.toFloat(_p12._2) / $Basics.toFloat(_p12._1) * $Basics.toFloat(newWidth)); + case "RawHtml": return $Basics.snd(A2($Native$Graphics$Element.htmlHeight,newWidth,_p13)); + default: return _p14.height;} + }(); + return Element_elm_builtin({element: _p13,props: _U.update(_p14,{width: newWidth,height: newHeight})}); + }); + var height = F2(function (newHeight,_p15) { + var _p16 = _p15; + return Element_elm_builtin({element: _p16._0.element,props: _U.update(_p16._0.props,{height: newHeight})}); + }); + var size = F3(function (w,h,e) { return A2(height,h,A2(width,w,e));}); + var opacity = F2(function (givenOpacity,_p17) { + var _p18 = _p17; + return Element_elm_builtin({element: _p18._0.element,props: _U.update(_p18._0.props,{opacity: givenOpacity})}); + }); + var color = F2(function (clr,_p19) { + var _p20 = _p19; + return Element_elm_builtin({element: _p20._0.element,props: _U.update(_p20._0.props,{color: $Maybe.Just(clr)})}); + }); + var tag = F2(function (name,_p21) { var _p22 = _p21;return Element_elm_builtin({element: _p22._0.element,props: _U.update(_p22._0.props,{tag: name})});}); + var link = F2(function (href,_p23) { + var _p24 = _p23; + return Element_elm_builtin({element: _p24._0.element,props: _U.update(_p24._0.props,{href: href})}); + }); + return _elm.Graphics.Element.values = {_op: _op + ,image: image + ,fittedImage: fittedImage + ,croppedImage: croppedImage + ,tiledImage: tiledImage + ,leftAligned: leftAligned + ,rightAligned: rightAligned + ,centered: centered + ,justified: justified + ,show: show + ,width: width + ,height: height + ,size: size + ,color: color + ,opacity: opacity + ,link: link + ,tag: tag + ,widthOf: widthOf + ,heightOf: heightOf + ,sizeOf: sizeOf + ,flow: flow + ,up: up + ,down: down + ,left: left + ,right: right + ,inward: inward + ,outward: outward + ,layers: layers + ,above: above + ,below: below + ,beside: beside + ,empty: empty + ,spacer: spacer + ,container: container + ,middle: middle + ,midTop: midTop + ,midBottom: midBottom + ,midLeft: midLeft + ,midRight: midRight + ,topLeft: topLeft + ,topRight: topRight + ,bottomLeft: bottomLeft + ,bottomRight: bottomRight + ,absolute: absolute + ,relative: relative + ,middleAt: middleAt + ,midTopAt: midTopAt + ,midBottomAt: midBottomAt + ,midLeftAt: midLeftAt + ,midRightAt: midRightAt + ,topLeftAt: topLeftAt + ,topRightAt: topRightAt + ,bottomLeftAt: bottomLeftAt + ,bottomRightAt: bottomRightAt}; +}; +Elm.Graphics = Elm.Graphics || {}; +Elm.Graphics.Collage = Elm.Graphics.Collage || {}; +Elm.Graphics.Collage.make = function (_elm) { + "use strict"; + _elm.Graphics = _elm.Graphics || {}; + _elm.Graphics.Collage = _elm.Graphics.Collage || {}; + if (_elm.Graphics.Collage.values) return _elm.Graphics.Collage.values; + var _U = Elm.Native.Utils.make(_elm), + $Basics = Elm.Basics.make(_elm), + $Color = Elm.Color.make(_elm), + $Graphics$Element = Elm.Graphics.Element.make(_elm), + $List = Elm.List.make(_elm), + $Native$Graphics$Collage = Elm.Native.Graphics.Collage.make(_elm), + $Text = Elm.Text.make(_elm), + $Transform2D = Elm.Transform2D.make(_elm); + var _op = {}; + var Shape = function (a) { return {ctor: "Shape",_0: a};}; + var polygon = function (points) { return Shape(points);}; + var rect = F2(function (w,h) { + var hh = h / 2; + var hw = w / 2; + return Shape(_U.list([{ctor: "_Tuple2",_0: 0 - hw,_1: 0 - hh} + ,{ctor: "_Tuple2",_0: 0 - hw,_1: hh} + ,{ctor: "_Tuple2",_0: hw,_1: hh} + ,{ctor: "_Tuple2",_0: hw,_1: 0 - hh}])); + }); + var square = function (n) { return A2(rect,n,n);}; + var oval = F2(function (w,h) { + var hh = h / 2; + var hw = w / 2; + var n = 50; + var t = 2 * $Basics.pi / n; + var f = function (i) { return {ctor: "_Tuple2",_0: hw * $Basics.cos(t * i),_1: hh * $Basics.sin(t * i)};}; + return Shape(A2($List.map,f,_U.range(0,n - 1))); + }); + var circle = function (r) { return A2(oval,2 * r,2 * r);}; + var ngon = F2(function (n,r) { + var m = $Basics.toFloat(n); + var t = 2 * $Basics.pi / m; + var f = function (i) { return {ctor: "_Tuple2",_0: r * $Basics.cos(t * i),_1: r * $Basics.sin(t * i)};}; + return Shape(A2($List.map,f,_U.range(0,m - 1))); + }); + var Path = function (a) { return {ctor: "Path",_0: a};}; + var path = function (ps) { return Path(ps);}; + var segment = F2(function (p1,p2) { return Path(_U.list([p1,p2]));}); + var collage = $Native$Graphics$Collage.collage; + var Fill = function (a) { return {ctor: "Fill",_0: a};}; + var Line = function (a) { return {ctor: "Line",_0: a};}; + var FGroup = F2(function (a,b) { return {ctor: "FGroup",_0: a,_1: b};}); + var FElement = function (a) { return {ctor: "FElement",_0: a};}; + var FImage = F4(function (a,b,c,d) { return {ctor: "FImage",_0: a,_1: b,_2: c,_3: d};}); + var FText = function (a) { return {ctor: "FText",_0: a};}; + var FOutlinedText = F2(function (a,b) { return {ctor: "FOutlinedText",_0: a,_1: b};}); + var FShape = F2(function (a,b) { return {ctor: "FShape",_0: a,_1: b};}); + var FPath = F2(function (a,b) { return {ctor: "FPath",_0: a,_1: b};}); + var LineStyle = F6(function (a,b,c,d,e,f) { return {color: a,width: b,cap: c,join: d,dashing: e,dashOffset: f};}); + var Clipped = {ctor: "Clipped"}; + var Sharp = function (a) { return {ctor: "Sharp",_0: a};}; + var Smooth = {ctor: "Smooth"}; + var Padded = {ctor: "Padded"}; + var Round = {ctor: "Round"}; + var Flat = {ctor: "Flat"}; + var defaultLine = {color: $Color.black,width: 1,cap: Flat,join: Sharp(10),dashing: _U.list([]),dashOffset: 0}; + var solid = function (clr) { return _U.update(defaultLine,{color: clr});}; + var dashed = function (clr) { return _U.update(defaultLine,{color: clr,dashing: _U.list([8,4])});}; + var dotted = function (clr) { return _U.update(defaultLine,{color: clr,dashing: _U.list([3,3])});}; + var Grad = function (a) { return {ctor: "Grad",_0: a};}; + var Texture = function (a) { return {ctor: "Texture",_0: a};}; + var Solid = function (a) { return {ctor: "Solid",_0: a};}; + var Form_elm_builtin = function (a) { return {ctor: "Form_elm_builtin",_0: a};}; + var form = function (f) { return Form_elm_builtin({theta: 0,scale: 1,x: 0,y: 0,alpha: 1,form: f});}; + var fill = F2(function (style,_p0) { var _p1 = _p0;return form(A2(FShape,Fill(style),_p1._0));}); + var filled = F2(function (color,shape) { return A2(fill,Solid(color),shape);}); + var textured = F2(function (src,shape) { return A2(fill,Texture(src),shape);}); + var gradient = F2(function (grad,shape) { return A2(fill,Grad(grad),shape);}); + var outlined = F2(function (style,_p2) { var _p3 = _p2;return form(A2(FShape,Line(style),_p3._0));}); + var traced = F2(function (style,_p4) { var _p5 = _p4;return form(A2(FPath,style,_p5._0));}); + var sprite = F4(function (w,h,pos,src) { return form(A4(FImage,w,h,pos,src));}); + var toForm = function (e) { return form(FElement(e));}; + var group = function (fs) { return form(A2(FGroup,$Transform2D.identity,fs));}; + var groupTransform = F2(function (matrix,fs) { return form(A2(FGroup,matrix,fs));}); + var text = function (t) { return form(FText(t));}; + var outlinedText = F2(function (ls,t) { return form(A2(FOutlinedText,ls,t));}); + var move = F2(function (_p7,_p6) { + var _p8 = _p7; + var _p9 = _p6; + var _p10 = _p9._0; + return Form_elm_builtin(_U.update(_p10,{x: _p10.x + _p8._0,y: _p10.y + _p8._1})); + }); + var moveX = F2(function (x,_p11) { var _p12 = _p11;var _p13 = _p12._0;return Form_elm_builtin(_U.update(_p13,{x: _p13.x + x}));}); + var moveY = F2(function (y,_p14) { var _p15 = _p14;var _p16 = _p15._0;return Form_elm_builtin(_U.update(_p16,{y: _p16.y + y}));}); + var scale = F2(function (s,_p17) { var _p18 = _p17;var _p19 = _p18._0;return Form_elm_builtin(_U.update(_p19,{scale: _p19.scale * s}));}); + var rotate = F2(function (t,_p20) { var _p21 = _p20;var _p22 = _p21._0;return Form_elm_builtin(_U.update(_p22,{theta: _p22.theta + t}));}); + var alpha = F2(function (a,_p23) { var _p24 = _p23;return Form_elm_builtin(_U.update(_p24._0,{alpha: a}));}); + return _elm.Graphics.Collage.values = {_op: _op + ,collage: collage + ,toForm: toForm + ,filled: filled + ,textured: textured + ,gradient: gradient + ,outlined: outlined + ,traced: traced + ,text: text + ,outlinedText: outlinedText + ,move: move + ,moveX: moveX + ,moveY: moveY + ,scale: scale + ,rotate: rotate + ,alpha: alpha + ,group: group + ,groupTransform: groupTransform + ,rect: rect + ,oval: oval + ,square: square + ,circle: circle + ,ngon: ngon + ,polygon: polygon + ,segment: segment + ,path: path + ,solid: solid + ,dashed: dashed + ,dotted: dotted + ,defaultLine: defaultLine + ,LineStyle: LineStyle + ,Flat: Flat + ,Round: Round + ,Padded: Padded + ,Smooth: Smooth + ,Sharp: Sharp + ,Clipped: Clipped}; +}; +Elm.Native.Debug = {}; +Elm.Native.Debug.make = function(localRuntime) { + localRuntime.Native = localRuntime.Native || {}; + localRuntime.Native.Debug = localRuntime.Native.Debug || {}; + if (localRuntime.Native.Debug.values) + { + return localRuntime.Native.Debug.values; + } + + var toString = Elm.Native.Utils.make(localRuntime).toString; + + function log(tag, value) + { + var msg = tag + ': ' + toString(value); + var process = process || {}; + if (process.stdout) + { + process.stdout.write(msg); + } + else + { + console.log(msg); + } + return value; + } + + function crash(message) + { + throw new Error(message); + } + + function tracePath(tag, form) + { + if (localRuntime.debug) + { + return localRuntime.debug.trace(tag, form); + } + return form; + } + + function watch(tag, value) + { + if (localRuntime.debug) + { + localRuntime.debug.watch(tag, value); + } + return value; + } + + function watchSummary(tag, summarize, value) + { + if (localRuntime.debug) + { + localRuntime.debug.watch(tag, summarize(value)); + } + return value; + } + + return localRuntime.Native.Debug.values = { + crash: crash, + tracePath: F2(tracePath), + log: F2(log), + watch: F2(watch), + watchSummary: F3(watchSummary) + }; +}; + +Elm.Debug = Elm.Debug || {}; +Elm.Debug.make = function (_elm) { + "use strict"; + _elm.Debug = _elm.Debug || {}; + if (_elm.Debug.values) return _elm.Debug.values; + var _U = Elm.Native.Utils.make(_elm),$Graphics$Collage = Elm.Graphics.Collage.make(_elm),$Native$Debug = Elm.Native.Debug.make(_elm); + var _op = {}; + var trace = $Native$Debug.tracePath; + var watchSummary = $Native$Debug.watchSummary; + var watch = $Native$Debug.watch; + var crash = $Native$Debug.crash; + var log = $Native$Debug.log; + return _elm.Debug.values = {_op: _op,log: log,crash: crash,watch: watch,watchSummary: watchSummary,trace: trace}; +}; +Elm.Native.Task = {}; + +Elm.Native.Task.make = function(localRuntime) { + localRuntime.Native = localRuntime.Native || {}; + localRuntime.Native.Task = localRuntime.Native.Task || {}; + if (localRuntime.Native.Task.values) + { + return localRuntime.Native.Task.values; + } + + var Result = Elm.Result.make(localRuntime); + var Signal; + var Utils = Elm.Native.Utils.make(localRuntime); + + + // CONSTRUCTORS + + function succeed(value) + { + return { + tag: 'Succeed', + value: value + }; + } + + function fail(error) + { + return { + tag: 'Fail', + value: error + }; + } + + function asyncFunction(func) + { + return { + tag: 'Async', + asyncFunction: func + }; + } + + function andThen(task, callback) + { + return { + tag: 'AndThen', + task: task, + callback: callback + }; + } + + function catch_(task, callback) + { + return { + tag: 'Catch', + task: task, + callback: callback + }; + } + + + // RUNNER + + function perform(task) { + runTask({ task: task }, function() {}); + } + + function performSignal(name, signal) + { + var workQueue = []; + + function onComplete() + { + workQueue.shift(); + + if (workQueue.length > 0) + { + var task = workQueue[0]; + + setTimeout(function() { + runTask(task, onComplete); + }, 0); + } + } + + function register(task) + { + var root = { task: task }; + workQueue.push(root); + if (workQueue.length === 1) + { + runTask(root, onComplete); + } + } + + if (!Signal) + { + Signal = Elm.Native.Signal.make(localRuntime); + } + Signal.output('perform-tasks-' + name, register, signal); + + register(signal.value); + + return signal; + } + + function mark(status, task) + { + return { status: status, task: task }; + } + + function runTask(root, onComplete) + { + var result = mark('runnable', root.task); + while (result.status === 'runnable') + { + result = stepTask(onComplete, root, result.task); + } + + if (result.status === 'done') + { + root.task = result.task; + onComplete(); + } + + if (result.status === 'blocked') + { + root.task = result.task; + } + } + + function stepTask(onComplete, root, task) + { + var tag = task.tag; + + if (tag === 'Succeed' || tag === 'Fail') + { + return mark('done', task); + } + + if (tag === 'Async') + { + var placeHolder = {}; + var couldBeSync = true; + var wasSync = false; + + task.asyncFunction(function(result) { + placeHolder.tag = result.tag; + placeHolder.value = result.value; + if (couldBeSync) + { + wasSync = true; + } + else + { + runTask(root, onComplete); + } + }); + couldBeSync = false; + return mark(wasSync ? 'done' : 'blocked', placeHolder); + } + + if (tag === 'AndThen' || tag === 'Catch') + { + var result = mark('runnable', task.task); + while (result.status === 'runnable') + { + result = stepTask(onComplete, root, result.task); + } + + if (result.status === 'done') + { + var activeTask = result.task; + var activeTag = activeTask.tag; + + var succeedChain = activeTag === 'Succeed' && tag === 'AndThen'; + var failChain = activeTag === 'Fail' && tag === 'Catch'; + + return (succeedChain || failChain) + ? mark('runnable', task.callback(activeTask.value)) + : mark('runnable', activeTask); + } + if (result.status === 'blocked') + { + return mark('blocked', { + tag: tag, + task: result.task, + callback: task.callback + }); + } + } + } + + + // THREADS + + function sleep(time) { + return asyncFunction(function(callback) { + setTimeout(function() { + callback(succeed(Utils.Tuple0)); + }, time); + }); + } + + function spawn(task) { + return asyncFunction(function(callback) { + var id = setTimeout(function() { + perform(task); + }, 0); + callback(succeed(id)); + }); + } + + + return localRuntime.Native.Task.values = { + succeed: succeed, + fail: fail, + asyncFunction: asyncFunction, + andThen: F2(andThen), + catch_: F2(catch_), + perform: perform, + performSignal: performSignal, + spawn: spawn, + sleep: sleep + }; +}; + +Elm.Result = Elm.Result || {}; +Elm.Result.make = function (_elm) { + "use strict"; + _elm.Result = _elm.Result || {}; + if (_elm.Result.values) return _elm.Result.values; + var _U = Elm.Native.Utils.make(_elm),$Maybe = Elm.Maybe.make(_elm); + var _op = {}; + var toMaybe = function (result) { var _p0 = result;if (_p0.ctor === "Ok") { return $Maybe.Just(_p0._0);} else { return $Maybe.Nothing;}}; + var withDefault = F2(function (def,result) { var _p1 = result;if (_p1.ctor === "Ok") { return _p1._0;} else { return def;}}); + var Err = function (a) { return {ctor: "Err",_0: a};}; + var andThen = F2(function (result,callback) { var _p2 = result;if (_p2.ctor === "Ok") { return callback(_p2._0);} else { return Err(_p2._0);}}); + var Ok = function (a) { return {ctor: "Ok",_0: a};}; + var map = F2(function (func,ra) { var _p3 = ra;if (_p3.ctor === "Ok") { return Ok(func(_p3._0));} else { return Err(_p3._0);}}); + var map2 = F3(function (func,ra,rb) { + var _p4 = {ctor: "_Tuple2",_0: ra,_1: rb}; + if (_p4._0.ctor === "Ok") { + if (_p4._1.ctor === "Ok") { + return Ok(A2(func,_p4._0._0,_p4._1._0)); + } else { + return Err(_p4._1._0); + } + } else { + return Err(_p4._0._0); + } + }); + var map3 = F4(function (func,ra,rb,rc) { + var _p5 = {ctor: "_Tuple3",_0: ra,_1: rb,_2: rc}; + if (_p5._0.ctor === "Ok") { + if (_p5._1.ctor === "Ok") { + if (_p5._2.ctor === "Ok") { + return Ok(A3(func,_p5._0._0,_p5._1._0,_p5._2._0)); + } else { + return Err(_p5._2._0); + } + } else { + return Err(_p5._1._0); + } + } else { + return Err(_p5._0._0); + } + }); + var map4 = F5(function (func,ra,rb,rc,rd) { + var _p6 = {ctor: "_Tuple4",_0: ra,_1: rb,_2: rc,_3: rd}; + if (_p6._0.ctor === "Ok") { + if (_p6._1.ctor === "Ok") { + if (_p6._2.ctor === "Ok") { + if (_p6._3.ctor === "Ok") { + return Ok(A4(func,_p6._0._0,_p6._1._0,_p6._2._0,_p6._3._0)); + } else { + return Err(_p6._3._0); + } + } else { + return Err(_p6._2._0); + } + } else { + return Err(_p6._1._0); + } + } else { + return Err(_p6._0._0); + } + }); + var map5 = F6(function (func,ra,rb,rc,rd,re) { + var _p7 = {ctor: "_Tuple5",_0: ra,_1: rb,_2: rc,_3: rd,_4: re}; + if (_p7._0.ctor === "Ok") { + if (_p7._1.ctor === "Ok") { + if (_p7._2.ctor === "Ok") { + if (_p7._3.ctor === "Ok") { + if (_p7._4.ctor === "Ok") { + return Ok(A5(func,_p7._0._0,_p7._1._0,_p7._2._0,_p7._3._0,_p7._4._0)); + } else { + return Err(_p7._4._0); + } + } else { + return Err(_p7._3._0); + } + } else { + return Err(_p7._2._0); + } + } else { + return Err(_p7._1._0); + } + } else { + return Err(_p7._0._0); + } + }); + var formatError = F2(function (f,result) { var _p8 = result;if (_p8.ctor === "Ok") { return Ok(_p8._0);} else { return Err(f(_p8._0));}}); + var fromMaybe = F2(function (err,maybe) { var _p9 = maybe;if (_p9.ctor === "Just") { return Ok(_p9._0);} else { return Err(err);}}); + return _elm.Result.values = {_op: _op + ,withDefault: withDefault + ,map: map + ,map2: map2 + ,map3: map3 + ,map4: map4 + ,map5: map5 + ,andThen: andThen + ,toMaybe: toMaybe + ,fromMaybe: fromMaybe + ,formatError: formatError + ,Ok: Ok + ,Err: Err}; +}; +Elm.Task = Elm.Task || {}; +Elm.Task.make = function (_elm) { + "use strict"; + _elm.Task = _elm.Task || {}; + if (_elm.Task.values) return _elm.Task.values; + var _U = Elm.Native.Utils.make(_elm), + $List = Elm.List.make(_elm), + $Maybe = Elm.Maybe.make(_elm), + $Native$Task = Elm.Native.Task.make(_elm), + $Result = Elm.Result.make(_elm); + var _op = {}; + var sleep = $Native$Task.sleep; + var spawn = $Native$Task.spawn; + var ThreadID = function (a) { return {ctor: "ThreadID",_0: a};}; + var onError = $Native$Task.catch_; + var andThen = $Native$Task.andThen; + var fail = $Native$Task.fail; + var mapError = F2(function (f,task) { return A2(onError,task,function (err) { return fail(f(err));});}); + var succeed = $Native$Task.succeed; + var map = F2(function (func,taskA) { return A2(andThen,taskA,function (a) { return succeed(func(a));});}); + var map2 = F3(function (func,taskA,taskB) { + return A2(andThen,taskA,function (a) { return A2(andThen,taskB,function (b) { return succeed(A2(func,a,b));});}); + }); + var map3 = F4(function (func,taskA,taskB,taskC) { + return A2(andThen, + taskA, + function (a) { + return A2(andThen,taskB,function (b) { return A2(andThen,taskC,function (c) { return succeed(A3(func,a,b,c));});}); + }); + }); + var map4 = F5(function (func,taskA,taskB,taskC,taskD) { + return A2(andThen, + taskA, + function (a) { + return A2(andThen, + taskB, + function (b) { + return A2(andThen,taskC,function (c) { return A2(andThen,taskD,function (d) { return succeed(A4(func,a,b,c,d));});}); + }); + }); + }); + var map5 = F6(function (func,taskA,taskB,taskC,taskD,taskE) { + return A2(andThen, + taskA, + function (a) { + return A2(andThen, + taskB, + function (b) { + return A2(andThen, + taskC, + function (c) { + return A2(andThen,taskD,function (d) { return A2(andThen,taskE,function (e) { return succeed(A5(func,a,b,c,d,e));});}); + }); + }); + }); + }); + var andMap = F2(function (taskFunc,taskValue) { + return A2(andThen,taskFunc,function (func) { return A2(andThen,taskValue,function (value) { return succeed(func(value));});}); + }); + var sequence = function (tasks) { + var _p0 = tasks; + if (_p0.ctor === "[]") { + return succeed(_U.list([])); + } else { + return A3(map2,F2(function (x,y) { return A2($List._op["::"],x,y);}),_p0._0,sequence(_p0._1)); + } + }; + var toMaybe = function (task) { return A2(onError,A2(map,$Maybe.Just,task),function (_p1) { return succeed($Maybe.Nothing);});}; + var fromMaybe = F2(function ($default,maybe) { var _p2 = maybe;if (_p2.ctor === "Just") { return succeed(_p2._0);} else { return fail($default);}}); + var toResult = function (task) { return A2(onError,A2(map,$Result.Ok,task),function (msg) { return succeed($Result.Err(msg));});}; + var fromResult = function (result) { var _p3 = result;if (_p3.ctor === "Ok") { return succeed(_p3._0);} else { return fail(_p3._0);}}; + var Task = {ctor: "Task"}; + return _elm.Task.values = {_op: _op + ,succeed: succeed + ,fail: fail + ,map: map + ,map2: map2 + ,map3: map3 + ,map4: map4 + ,map5: map5 + ,andMap: andMap + ,sequence: sequence + ,andThen: andThen + ,onError: onError + ,mapError: mapError + ,toMaybe: toMaybe + ,fromMaybe: fromMaybe + ,toResult: toResult + ,fromResult: fromResult + ,spawn: spawn + ,sleep: sleep}; +}; +Elm.Signal = Elm.Signal || {}; +Elm.Signal.make = function (_elm) { + "use strict"; + _elm.Signal = _elm.Signal || {}; + if (_elm.Signal.values) return _elm.Signal.values; + var _U = Elm.Native.Utils.make(_elm), + $Basics = Elm.Basics.make(_elm), + $Debug = Elm.Debug.make(_elm), + $List = Elm.List.make(_elm), + $Maybe = Elm.Maybe.make(_elm), + $Native$Signal = Elm.Native.Signal.make(_elm), + $Task = Elm.Task.make(_elm); + var _op = {}; + var send = F2(function (_p0,value) { + var _p1 = _p0; + return A2($Task.onError,_p1._0(value),function (_p2) { return $Task.succeed({ctor: "_Tuple0"});}); + }); + var Message = function (a) { return {ctor: "Message",_0: a};}; + var message = F2(function (_p3,value) { var _p4 = _p3;return Message(_p4._0(value));}); + var mailbox = $Native$Signal.mailbox; + var Address = function (a) { return {ctor: "Address",_0: a};}; + var forwardTo = F2(function (_p5,f) { var _p6 = _p5;return Address(function (x) { return _p6._0(f(x));});}); + var Mailbox = F2(function (a,b) { return {address: a,signal: b};}); + var sampleOn = $Native$Signal.sampleOn; + var dropRepeats = $Native$Signal.dropRepeats; + var filterMap = $Native$Signal.filterMap; + var filter = F3(function (isOk,base,signal) { + return A3(filterMap,function (value) { return isOk(value) ? $Maybe.Just(value) : $Maybe.Nothing;},base,signal); + }); + var merge = F2(function (left,right) { return A3($Native$Signal.genericMerge,$Basics.always,left,right);}); + var mergeMany = function (signalList) { + var _p7 = $List.reverse(signalList); + if (_p7.ctor === "[]") { + return _U.crashCase("Signal",{start: {line: 184,column: 3},end: {line: 189,column: 40}},_p7)("mergeMany was given an empty list!"); + } else { + return A3($List.foldl,merge,_p7._0,_p7._1); + } + }; + var foldp = $Native$Signal.foldp; + var map5 = $Native$Signal.map5; + var map4 = $Native$Signal.map4; + var map3 = $Native$Signal.map3; + var map2 = $Native$Signal.map2; + var map = $Native$Signal.map; + var constant = $Native$Signal.constant; + var Signal = {ctor: "Signal"}; + return _elm.Signal.values = {_op: _op + ,merge: merge + ,mergeMany: mergeMany + ,map: map + ,map2: map2 + ,map3: map3 + ,map4: map4 + ,map5: map5 + ,constant: constant + ,dropRepeats: dropRepeats + ,filter: filter + ,filterMap: filterMap + ,sampleOn: sampleOn + ,foldp: foldp + ,mailbox: mailbox + ,send: send + ,message: message + ,forwardTo: forwardTo + ,Mailbox: Mailbox}; +}; +Elm.Native.String = {}; + +Elm.Native.String.make = function(localRuntime) { + localRuntime.Native = localRuntime.Native || {}; + localRuntime.Native.String = localRuntime.Native.String || {}; + if (localRuntime.Native.String.values) + { + return localRuntime.Native.String.values; + } + if ('values' in Elm.Native.String) + { + return localRuntime.Native.String.values = Elm.Native.String.values; + } + + + var Char = Elm.Char.make(localRuntime); + var List = Elm.Native.List.make(localRuntime); + var Maybe = Elm.Maybe.make(localRuntime); + var Result = Elm.Result.make(localRuntime); + var Utils = Elm.Native.Utils.make(localRuntime); + + function isEmpty(str) + { + return str.length === 0; + } + function cons(chr, str) + { + return chr + str; + } + function uncons(str) + { + var hd = str[0]; + if (hd) + { + return Maybe.Just(Utils.Tuple2(Utils.chr(hd), str.slice(1))); + } + return Maybe.Nothing; + } + function append(a, b) + { + return a + b; + } + function concat(strs) + { + return List.toArray(strs).join(''); + } + function length(str) + { + return str.length; + } + function map(f, str) + { + var out = str.split(''); + for (var i = out.length; i--; ) + { + out[i] = f(Utils.chr(out[i])); + } + return out.join(''); + } + function filter(pred, str) + { + return str.split('').map(Utils.chr).filter(pred).join(''); + } + function reverse(str) + { + return str.split('').reverse().join(''); + } + function foldl(f, b, str) + { + var len = str.length; + for (var i = 0; i < len; ++i) + { + b = A2(f, Utils.chr(str[i]), b); + } + return b; + } + function foldr(f, b, str) + { + for (var i = str.length; i--; ) + { + b = A2(f, Utils.chr(str[i]), b); + } + return b; + } + function split(sep, str) + { + return List.fromArray(str.split(sep)); + } + function join(sep, strs) + { + return List.toArray(strs).join(sep); + } + function repeat(n, str) + { + var result = ''; + while (n > 0) + { + if (n & 1) + { + result += str; + } + n >>= 1, str += str; + } + return result; + } + function slice(start, end, str) + { + return str.slice(start, end); + } + function left(n, str) + { + return n < 1 ? '' : str.slice(0, n); + } + function right(n, str) + { + return n < 1 ? '' : str.slice(-n); + } + function dropLeft(n, str) + { + return n < 1 ? str : str.slice(n); + } + function dropRight(n, str) + { + return n < 1 ? str : str.slice(0, -n); + } + function pad(n, chr, str) + { + var half = (n - str.length) / 2; + return repeat(Math.ceil(half), chr) + str + repeat(half | 0, chr); + } + function padRight(n, chr, str) + { + return str + repeat(n - str.length, chr); + } + function padLeft(n, chr, str) + { + return repeat(n - str.length, chr) + str; + } + + function trim(str) + { + return str.trim(); + } + function trimLeft(str) + { + return str.replace(/^\s+/, ''); + } + function trimRight(str) + { + return str.replace(/\s+$/, ''); + } + + function words(str) + { + return List.fromArray(str.trim().split(/\s+/g)); + } + function lines(str) + { + return List.fromArray(str.split(/\r\n|\r|\n/g)); + } + + function toUpper(str) + { + return str.toUpperCase(); + } + function toLower(str) + { + return str.toLowerCase(); + } + + function any(pred, str) + { + for (var i = str.length; i--; ) + { + if (pred(Utils.chr(str[i]))) + { + return true; + } + } + return false; + } + function all(pred, str) + { + for (var i = str.length; i--; ) + { + if (!pred(Utils.chr(str[i]))) + { + return false; + } + } + return true; + } + + function contains(sub, str) + { + return str.indexOf(sub) > -1; + } + function startsWith(sub, str) + { + return str.indexOf(sub) === 0; + } + function endsWith(sub, str) + { + return str.length >= sub.length && + str.lastIndexOf(sub) === str.length - sub.length; + } + function indexes(sub, str) + { + var subLen = sub.length; + var i = 0; + var is = []; + while ((i = str.indexOf(sub, i)) > -1) + { + is.push(i); + i = i + subLen; + } + return List.fromArray(is); + } + + function toInt(s) + { + var len = s.length; + if (len === 0) + { + return Result.Err("could not convert string '" + s + "' to an Int" ); + } + var start = 0; + if (s[0] === '-') + { + if (len === 1) + { + return Result.Err("could not convert string '" + s + "' to an Int" ); + } + start = 1; + } + for (var i = start; i < len; ++i) + { + if (!Char.isDigit(s[i])) + { + return Result.Err("could not convert string '" + s + "' to an Int" ); + } + } + return Result.Ok(parseInt(s, 10)); + } + + function toFloat(s) + { + var len = s.length; + if (len === 0) + { + return Result.Err("could not convert string '" + s + "' to a Float" ); + } + var start = 0; + if (s[0] === '-') + { + if (len === 1) + { + return Result.Err("could not convert string '" + s + "' to a Float" ); + } + start = 1; + } + var dotCount = 0; + for (var i = start; i < len; ++i) + { + if (Char.isDigit(s[i])) + { + continue; + } + if (s[i] === '.') + { + dotCount += 1; + if (dotCount <= 1) + { + continue; + } + } + return Result.Err("could not convert string '" + s + "' to a Float" ); + } + return Result.Ok(parseFloat(s)); + } + + function toList(str) + { + return List.fromArray(str.split('').map(Utils.chr)); + } + function fromList(chars) + { + return List.toArray(chars).join(''); + } + + return Elm.Native.String.values = { + isEmpty: isEmpty, + cons: F2(cons), + uncons: uncons, + append: F2(append), + concat: concat, + length: length, + map: F2(map), + filter: F2(filter), + reverse: reverse, + foldl: F3(foldl), + foldr: F3(foldr), + + split: F2(split), + join: F2(join), + repeat: F2(repeat), + + slice: F3(slice), + left: F2(left), + right: F2(right), + dropLeft: F2(dropLeft), + dropRight: F2(dropRight), + + pad: F3(pad), + padLeft: F3(padLeft), + padRight: F3(padRight), + + trim: trim, + trimLeft: trimLeft, + trimRight: trimRight, + + words: words, + lines: lines, + + toUpper: toUpper, + toLower: toLower, + + any: F2(any), + all: F2(all), + + contains: F2(contains), + startsWith: F2(startsWith), + endsWith: F2(endsWith), + indexes: F2(indexes), + + toInt: toInt, + toFloat: toFloat, + toList: toList, + fromList: fromList + }; +}; + +Elm.String = Elm.String || {}; +Elm.String.make = function (_elm) { + "use strict"; + _elm.String = _elm.String || {}; + if (_elm.String.values) return _elm.String.values; + var _U = Elm.Native.Utils.make(_elm),$Maybe = Elm.Maybe.make(_elm),$Native$String = Elm.Native.String.make(_elm),$Result = Elm.Result.make(_elm); + var _op = {}; + var fromList = $Native$String.fromList; + var toList = $Native$String.toList; + var toFloat = $Native$String.toFloat; + var toInt = $Native$String.toInt; + var indices = $Native$String.indexes; + var indexes = $Native$String.indexes; + var endsWith = $Native$String.endsWith; + var startsWith = $Native$String.startsWith; + var contains = $Native$String.contains; + var all = $Native$String.all; + var any = $Native$String.any; + var toLower = $Native$String.toLower; + var toUpper = $Native$String.toUpper; + var lines = $Native$String.lines; + var words = $Native$String.words; + var trimRight = $Native$String.trimRight; + var trimLeft = $Native$String.trimLeft; + var trim = $Native$String.trim; + var padRight = $Native$String.padRight; + var padLeft = $Native$String.padLeft; + var pad = $Native$String.pad; + var dropRight = $Native$String.dropRight; + var dropLeft = $Native$String.dropLeft; + var right = $Native$String.right; + var left = $Native$String.left; + var slice = $Native$String.slice; + var repeat = $Native$String.repeat; + var join = $Native$String.join; + var split = $Native$String.split; + var foldr = $Native$String.foldr; + var foldl = $Native$String.foldl; + var reverse = $Native$String.reverse; + var filter = $Native$String.filter; + var map = $Native$String.map; + var length = $Native$String.length; + var concat = $Native$String.concat; + var append = $Native$String.append; + var uncons = $Native$String.uncons; + var cons = $Native$String.cons; + var fromChar = function ($char) { return A2(cons,$char,"");}; + var isEmpty = $Native$String.isEmpty; + return _elm.String.values = {_op: _op + ,isEmpty: isEmpty + ,length: length + ,reverse: reverse + ,repeat: repeat + ,cons: cons + ,uncons: uncons + ,fromChar: fromChar + ,append: append + ,concat: concat + ,split: split + ,join: join + ,words: words + ,lines: lines + ,slice: slice + ,left: left + ,right: right + ,dropLeft: dropLeft + ,dropRight: dropRight + ,contains: contains + ,startsWith: startsWith + ,endsWith: endsWith + ,indexes: indexes + ,indices: indices + ,toInt: toInt + ,toFloat: toFloat + ,toList: toList + ,fromList: fromList + ,toUpper: toUpper + ,toLower: toLower + ,pad: pad + ,padLeft: padLeft + ,padRight: padRight + ,trim: trim + ,trimLeft: trimLeft + ,trimRight: trimRight + ,map: map + ,filter: filter + ,foldl: foldl + ,foldr: foldr + ,any: any + ,all: all}; +}; +Elm.Dict = Elm.Dict || {}; +Elm.Dict.make = function (_elm) { + "use strict"; + _elm.Dict = _elm.Dict || {}; + if (_elm.Dict.values) return _elm.Dict.values; + var _U = Elm.Native.Utils.make(_elm), + $Basics = Elm.Basics.make(_elm), + $List = Elm.List.make(_elm), + $Maybe = Elm.Maybe.make(_elm), + $Native$Debug = Elm.Native.Debug.make(_elm), + $String = Elm.String.make(_elm); + var _op = {}; + var foldr = F3(function (f,acc,t) { + foldr: while (true) { + var _p0 = t; + if (_p0.ctor === "RBEmpty_elm_builtin") { + return acc; + } else { + var _v1 = f,_v2 = A3(f,_p0._1,_p0._2,A3(foldr,f,acc,_p0._4)),_v3 = _p0._3; + f = _v1; + acc = _v2; + t = _v3; + continue foldr; + } + } + }); + var keys = function (dict) { return A3(foldr,F3(function (key,value,keyList) { return A2($List._op["::"],key,keyList);}),_U.list([]),dict);}; + var values = function (dict) { return A3(foldr,F3(function (key,value,valueList) { return A2($List._op["::"],value,valueList);}),_U.list([]),dict);}; + var toList = function (dict) { + return A3(foldr,F3(function (key,value,list) { return A2($List._op["::"],{ctor: "_Tuple2",_0: key,_1: value},list);}),_U.list([]),dict); + }; + var foldl = F3(function (f,acc,dict) { + foldl: while (true) { + var _p1 = dict; + if (_p1.ctor === "RBEmpty_elm_builtin") { + return acc; + } else { + var _v5 = f,_v6 = A3(f,_p1._1,_p1._2,A3(foldl,f,acc,_p1._3)),_v7 = _p1._4; + f = _v5; + acc = _v6; + dict = _v7; + continue foldl; + } + } + }); + var reportRemBug = F4(function (msg,c,lgot,rgot) { + return $Native$Debug.crash($String.concat(_U.list(["Internal red-black tree invariant violated, expected " + ,msg + ," and got " + ,$Basics.toString(c) + ,"/" + ,lgot + ,"/" + ,rgot + ,"\nPlease report this bug to "]))); + }); + var isBBlack = function (dict) { + var _p2 = dict; + _v8_2: do { + if (_p2.ctor === "RBNode_elm_builtin") { + if (_p2._0.ctor === "BBlack") { + return true; + } else { + break _v8_2; + } + } else { + if (_p2._0.ctor === "LBBlack") { + return true; + } else { + break _v8_2; + } + } + } while (false); + return false; + }; + var Same = {ctor: "Same"}; + var Remove = {ctor: "Remove"}; + var Insert = {ctor: "Insert"}; + var sizeHelp = F2(function (n,dict) { + sizeHelp: while (true) { + var _p3 = dict; + if (_p3.ctor === "RBEmpty_elm_builtin") { + return n; + } else { + var _v10 = A2(sizeHelp,n + 1,_p3._4),_v11 = _p3._3; + n = _v10; + dict = _v11; + continue sizeHelp; + } + } + }); + var size = function (dict) { return A2(sizeHelp,0,dict);}; + var get = F2(function (targetKey,dict) { + get: while (true) { + var _p4 = dict; + if (_p4.ctor === "RBEmpty_elm_builtin") { + return $Maybe.Nothing; + } else { + var _p5 = A2($Basics.compare,targetKey,_p4._1); + switch (_p5.ctor) + {case "LT": var _v14 = targetKey,_v15 = _p4._3; + targetKey = _v14; + dict = _v15; + continue get; + case "EQ": return $Maybe.Just(_p4._2); + default: var _v16 = targetKey,_v17 = _p4._4; + targetKey = _v16; + dict = _v17; + continue get;} + } + } + }); + var member = F2(function (key,dict) { var _p6 = A2(get,key,dict);if (_p6.ctor === "Just") { return true;} else { return false;}}); + var maxWithDefault = F3(function (k,v,r) { + maxWithDefault: while (true) { + var _p7 = r; + if (_p7.ctor === "RBEmpty_elm_builtin") { + return {ctor: "_Tuple2",_0: k,_1: v}; + } else { + var _v20 = _p7._1,_v21 = _p7._2,_v22 = _p7._4; + k = _v20; + v = _v21; + r = _v22; + continue maxWithDefault; + } + } + }); + var RBEmpty_elm_builtin = function (a) { return {ctor: "RBEmpty_elm_builtin",_0: a};}; + var RBNode_elm_builtin = F5(function (a,b,c,d,e) { return {ctor: "RBNode_elm_builtin",_0: a,_1: b,_2: c,_3: d,_4: e};}); + var LBBlack = {ctor: "LBBlack"}; + var LBlack = {ctor: "LBlack"}; + var empty = RBEmpty_elm_builtin(LBlack); + var isEmpty = function (dict) { return _U.eq(dict,empty);}; + var map = F2(function (f,dict) { + var _p8 = dict; + if (_p8.ctor === "RBEmpty_elm_builtin") { + return RBEmpty_elm_builtin(LBlack); + } else { + var _p9 = _p8._1; + return A5(RBNode_elm_builtin,_p8._0,_p9,A2(f,_p9,_p8._2),A2(map,f,_p8._3),A2(map,f,_p8._4)); + } + }); + var NBlack = {ctor: "NBlack"}; + var BBlack = {ctor: "BBlack"}; + var Black = {ctor: "Black"}; + var ensureBlackRoot = function (dict) { + var _p10 = dict; + if (_p10.ctor === "RBNode_elm_builtin" && _p10._0.ctor === "Red") { + return A5(RBNode_elm_builtin,Black,_p10._1,_p10._2,_p10._3,_p10._4); + } else { + return dict; + } + }; + var blackish = function (t) { + var _p11 = t; + if (_p11.ctor === "RBNode_elm_builtin") { + var _p12 = _p11._0; + return _U.eq(_p12,Black) || _U.eq(_p12,BBlack); + } else { + return true; + } + }; + var blacken = function (t) { + var _p13 = t; + if (_p13.ctor === "RBEmpty_elm_builtin") { + return RBEmpty_elm_builtin(LBlack); + } else { + return A5(RBNode_elm_builtin,Black,_p13._1,_p13._2,_p13._3,_p13._4); + } + }; + var Red = {ctor: "Red"}; + var moreBlack = function (color) { + var _p14 = color; + switch (_p14.ctor) + {case "Black": return BBlack; + case "Red": return Black; + case "NBlack": return Red; + default: return $Native$Debug.crash("Can\'t make a double black node more black!");} + }; + var lessBlack = function (color) { + var _p15 = color; + switch (_p15.ctor) + {case "BBlack": return Black; + case "Black": return Red; + case "Red": return NBlack; + default: return $Native$Debug.crash("Can\'t make a negative black node less black!");} + }; + var lessBlackTree = function (dict) { + var _p16 = dict; + if (_p16.ctor === "RBNode_elm_builtin") { + return A5(RBNode_elm_builtin,lessBlack(_p16._0),_p16._1,_p16._2,_p16._3,_p16._4); + } else { + return RBEmpty_elm_builtin(LBlack); + } + }; + var balancedTree = function (col) { + return function (xk) { + return function (xv) { + return function (yk) { + return function (yv) { + return function (zk) { + return function (zv) { + return function (a) { + return function (b) { + return function (c) { + return function (d) { + return A5(RBNode_elm_builtin, + lessBlack(col), + yk, + yv, + A5(RBNode_elm_builtin,Black,xk,xv,a,b), + A5(RBNode_elm_builtin,Black,zk,zv,c,d)); + }; + }; + }; + }; + }; + }; + }; + }; + }; + }; + }; + var redden = function (t) { + var _p17 = t; + if (_p17.ctor === "RBEmpty_elm_builtin") { + return $Native$Debug.crash("can\'t make a Leaf red"); + } else { + return A5(RBNode_elm_builtin,Red,_p17._1,_p17._2,_p17._3,_p17._4); + } + }; + var balanceHelp = function (tree) { + var _p18 = tree; + _v31_6: do { + _v31_5: do { + _v31_4: do { + _v31_3: do { + _v31_2: do { + _v31_1: do { + _v31_0: do { + if (_p18.ctor === "RBNode_elm_builtin") { + if (_p18._3.ctor === "RBNode_elm_builtin") { + if (_p18._4.ctor === "RBNode_elm_builtin") { + switch (_p18._3._0.ctor) + {case "Red": switch (_p18._4._0.ctor) + {case "Red": if (_p18._3._3.ctor === "RBNode_elm_builtin" && _p18._3._3._0.ctor === "Red") { + break _v31_0; + } else { + if (_p18._3._4.ctor === "RBNode_elm_builtin" && _p18._3._4._0.ctor === "Red") { + break _v31_1; + } else { + if (_p18._4._3.ctor === "RBNode_elm_builtin" && _p18._4._3._0.ctor === "Red") { + break _v31_2; + } else { + if (_p18._4._4.ctor === "RBNode_elm_builtin" && _p18._4._4._0.ctor === "Red") { + break _v31_3; + } else { + break _v31_6; + } + } + } + } + case "NBlack": if (_p18._3._3.ctor === "RBNode_elm_builtin" && _p18._3._3._0.ctor === "Red") { + break _v31_0; + } else { + if (_p18._3._4.ctor === "RBNode_elm_builtin" && _p18._3._4._0.ctor === "Red") { + break _v31_1; + } else { + if (_p18._0.ctor === "BBlack" && _p18._4._3.ctor === "RBNode_elm_builtin" && _p18._4._3._0.ctor === "Black" && _p18._4._4.ctor === "RBNode_elm_builtin" && _p18._4._4._0.ctor === "Black") + { + break _v31_4; + } else { + break _v31_6; + } + } + } + default: if (_p18._3._3.ctor === "RBNode_elm_builtin" && _p18._3._3._0.ctor === "Red") { + break _v31_0; + } else { + if (_p18._3._4.ctor === "RBNode_elm_builtin" && _p18._3._4._0.ctor === "Red") { + break _v31_1; + } else { + break _v31_6; + } + }} + case "NBlack": switch (_p18._4._0.ctor) + {case "Red": if (_p18._4._3.ctor === "RBNode_elm_builtin" && _p18._4._3._0.ctor === "Red") { + break _v31_2; + } else { + if (_p18._4._4.ctor === "RBNode_elm_builtin" && _p18._4._4._0.ctor === "Red") { + break _v31_3; + } else { + if (_p18._0.ctor === "BBlack" && _p18._3._3.ctor === "RBNode_elm_builtin" && _p18._3._3._0.ctor === "Black" && _p18._3._4.ctor === "RBNode_elm_builtin" && _p18._3._4._0.ctor === "Black") + { + break _v31_5; + } else { + break _v31_6; + } + } + } + case "NBlack": if (_p18._0.ctor === "BBlack") { + if (_p18._4._3.ctor === "RBNode_elm_builtin" && _p18._4._3._0.ctor === "Black" && _p18._4._4.ctor === "RBNode_elm_builtin" && _p18._4._4._0.ctor === "Black") + { + break _v31_4; + } else { + if (_p18._3._3.ctor === "RBNode_elm_builtin" && _p18._3._3._0.ctor === "Black" && _p18._3._4.ctor === "RBNode_elm_builtin" && _p18._3._4._0.ctor === "Black") + { + break _v31_5; + } else { + break _v31_6; + } + } + } else { + break _v31_6; + } + default: + if (_p18._0.ctor === "BBlack" && _p18._3._3.ctor === "RBNode_elm_builtin" && _p18._3._3._0.ctor === "Black" && _p18._3._4.ctor === "RBNode_elm_builtin" && _p18._3._4._0.ctor === "Black") + { + break _v31_5; + } else { + break _v31_6; + }} + default: switch (_p18._4._0.ctor) + {case "Red": if (_p18._4._3.ctor === "RBNode_elm_builtin" && _p18._4._3._0.ctor === "Red") { + break _v31_2; + } else { + if (_p18._4._4.ctor === "RBNode_elm_builtin" && _p18._4._4._0.ctor === "Red") { + break _v31_3; + } else { + break _v31_6; + } + } + case "NBlack": + if (_p18._0.ctor === "BBlack" && _p18._4._3.ctor === "RBNode_elm_builtin" && _p18._4._3._0.ctor === "Black" && _p18._4._4.ctor === "RBNode_elm_builtin" && _p18._4._4._0.ctor === "Black") + { + break _v31_4; + } else { + break _v31_6; + } + default: break _v31_6;}} + } else { + switch (_p18._3._0.ctor) + {case "Red": if (_p18._3._3.ctor === "RBNode_elm_builtin" && _p18._3._3._0.ctor === "Red") { + break _v31_0; + } else { + if (_p18._3._4.ctor === "RBNode_elm_builtin" && _p18._3._4._0.ctor === "Red") { + break _v31_1; + } else { + break _v31_6; + } + } + case "NBlack": + if (_p18._0.ctor === "BBlack" && _p18._3._3.ctor === "RBNode_elm_builtin" && _p18._3._3._0.ctor === "Black" && _p18._3._4.ctor === "RBNode_elm_builtin" && _p18._3._4._0.ctor === "Black") + { + break _v31_5; + } else { + break _v31_6; + } + default: break _v31_6;} + } + } else { + if (_p18._4.ctor === "RBNode_elm_builtin") { + switch (_p18._4._0.ctor) + {case "Red": if (_p18._4._3.ctor === "RBNode_elm_builtin" && _p18._4._3._0.ctor === "Red") { + break _v31_2; + } else { + if (_p18._4._4.ctor === "RBNode_elm_builtin" && _p18._4._4._0.ctor === "Red") { + break _v31_3; + } else { + break _v31_6; + } + } + case "NBlack": + if (_p18._0.ctor === "BBlack" && _p18._4._3.ctor === "RBNode_elm_builtin" && _p18._4._3._0.ctor === "Black" && _p18._4._4.ctor === "RBNode_elm_builtin" && _p18._4._4._0.ctor === "Black") + { + break _v31_4; + } else { + break _v31_6; + } + default: break _v31_6;} + } else { + break _v31_6; + } + } + } else { + break _v31_6; + } + } while (false); + return balancedTree(_p18._0)(_p18._3._3._1)(_p18._3._3._2)(_p18._3._1)(_p18._3._2)(_p18._1)(_p18._2)(_p18._3._3._3)(_p18._3._3._4)(_p18._3._4)(_p18._4); + } while (false); + return balancedTree(_p18._0)(_p18._3._1)(_p18._3._2)(_p18._3._4._1)(_p18._3._4._2)(_p18._1)(_p18._2)(_p18._3._3)(_p18._3._4._3)(_p18._3._4._4)(_p18._4); + } while (false); + return balancedTree(_p18._0)(_p18._1)(_p18._2)(_p18._4._3._1)(_p18._4._3._2)(_p18._4._1)(_p18._4._2)(_p18._3)(_p18._4._3._3)(_p18._4._3._4)(_p18._4._4); + } while (false); + return balancedTree(_p18._0)(_p18._1)(_p18._2)(_p18._4._1)(_p18._4._2)(_p18._4._4._1)(_p18._4._4._2)(_p18._3)(_p18._4._3)(_p18._4._4._3)(_p18._4._4._4); + } while (false); + return A5(RBNode_elm_builtin, + Black, + _p18._4._3._1, + _p18._4._3._2, + A5(RBNode_elm_builtin,Black,_p18._1,_p18._2,_p18._3,_p18._4._3._3), + A5(balance,Black,_p18._4._1,_p18._4._2,_p18._4._3._4,redden(_p18._4._4))); + } while (false); + return A5(RBNode_elm_builtin, + Black, + _p18._3._4._1, + _p18._3._4._2, + A5(balance,Black,_p18._3._1,_p18._3._2,redden(_p18._3._3),_p18._3._4._3), + A5(RBNode_elm_builtin,Black,_p18._1,_p18._2,_p18._3._4._4,_p18._4)); + } while (false); + return tree; + }; + var balance = F5(function (c,k,v,l,r) { var tree = A5(RBNode_elm_builtin,c,k,v,l,r);return blackish(tree) ? balanceHelp(tree) : tree;}); + var bubble = F5(function (c,k,v,l,r) { + return isBBlack(l) || isBBlack(r) ? A5(balance,moreBlack(c),k,v,lessBlackTree(l),lessBlackTree(r)) : A5(RBNode_elm_builtin,c,k,v,l,r); + }); + var removeMax = F5(function (c,k,v,l,r) { + var _p19 = r; + if (_p19.ctor === "RBEmpty_elm_builtin") { + return A3(rem,c,l,r); + } else { + return A5(bubble,c,k,v,l,A5(removeMax,_p19._0,_p19._1,_p19._2,_p19._3,_p19._4)); + } + }); + var rem = F3(function (c,l,r) { + var _p20 = {ctor: "_Tuple2",_0: l,_1: r}; + if (_p20._0.ctor === "RBEmpty_elm_builtin") { + if (_p20._1.ctor === "RBEmpty_elm_builtin") { + var _p21 = c; + switch (_p21.ctor) + {case "Red": return RBEmpty_elm_builtin(LBlack); + case "Black": return RBEmpty_elm_builtin(LBBlack); + default: return $Native$Debug.crash("cannot have bblack or nblack nodes at this point");} + } else { + var _p24 = _p20._1._0; + var _p23 = _p20._0._0; + var _p22 = {ctor: "_Tuple3",_0: c,_1: _p23,_2: _p24}; + if (_p22.ctor === "_Tuple3" && _p22._0.ctor === "Black" && _p22._1.ctor === "LBlack" && _p22._2.ctor === "Red") { + return A5(RBNode_elm_builtin,Black,_p20._1._1,_p20._1._2,_p20._1._3,_p20._1._4); + } else { + return A4(reportRemBug,"Black/LBlack/Red",c,$Basics.toString(_p23),$Basics.toString(_p24)); + } + } + } else { + if (_p20._1.ctor === "RBEmpty_elm_builtin") { + var _p27 = _p20._1._0; + var _p26 = _p20._0._0; + var _p25 = {ctor: "_Tuple3",_0: c,_1: _p26,_2: _p27}; + if (_p25.ctor === "_Tuple3" && _p25._0.ctor === "Black" && _p25._1.ctor === "Red" && _p25._2.ctor === "LBlack") { + return A5(RBNode_elm_builtin,Black,_p20._0._1,_p20._0._2,_p20._0._3,_p20._0._4); + } else { + return A4(reportRemBug,"Black/Red/LBlack",c,$Basics.toString(_p26),$Basics.toString(_p27)); + } + } else { + var _p31 = _p20._0._2; + var _p30 = _p20._0._4; + var _p29 = _p20._0._1; + var l$ = A5(removeMax,_p20._0._0,_p29,_p31,_p20._0._3,_p30); + var _p28 = A3(maxWithDefault,_p29,_p31,_p30); + var k = _p28._0; + var v = _p28._1; + return A5(bubble,c,k,v,l$,r); + } + } + }); + var update = F3(function (k,alter,dict) { + var up = function (dict) { + var _p32 = dict; + if (_p32.ctor === "RBEmpty_elm_builtin") { + var _p33 = alter($Maybe.Nothing); + if (_p33.ctor === "Nothing") { + return {ctor: "_Tuple2",_0: Same,_1: empty}; + } else { + return {ctor: "_Tuple2",_0: Insert,_1: A5(RBNode_elm_builtin,Red,k,_p33._0,empty,empty)}; + } + } else { + var _p44 = _p32._2; + var _p43 = _p32._4; + var _p42 = _p32._3; + var _p41 = _p32._1; + var _p40 = _p32._0; + var _p34 = A2($Basics.compare,k,_p41); + switch (_p34.ctor) + {case "EQ": var _p35 = alter($Maybe.Just(_p44)); + if (_p35.ctor === "Nothing") { + return {ctor: "_Tuple2",_0: Remove,_1: A3(rem,_p40,_p42,_p43)}; + } else { + return {ctor: "_Tuple2",_0: Same,_1: A5(RBNode_elm_builtin,_p40,_p41,_p35._0,_p42,_p43)}; + } + case "LT": var _p36 = up(_p42); + var flag = _p36._0; + var newLeft = _p36._1; + var _p37 = flag; + switch (_p37.ctor) + {case "Same": return {ctor: "_Tuple2",_0: Same,_1: A5(RBNode_elm_builtin,_p40,_p41,_p44,newLeft,_p43)}; + case "Insert": return {ctor: "_Tuple2",_0: Insert,_1: A5(balance,_p40,_p41,_p44,newLeft,_p43)}; + default: return {ctor: "_Tuple2",_0: Remove,_1: A5(bubble,_p40,_p41,_p44,newLeft,_p43)};} + default: var _p38 = up(_p43); + var flag = _p38._0; + var newRight = _p38._1; + var _p39 = flag; + switch (_p39.ctor) + {case "Same": return {ctor: "_Tuple2",_0: Same,_1: A5(RBNode_elm_builtin,_p40,_p41,_p44,_p42,newRight)}; + case "Insert": return {ctor: "_Tuple2",_0: Insert,_1: A5(balance,_p40,_p41,_p44,_p42,newRight)}; + default: return {ctor: "_Tuple2",_0: Remove,_1: A5(bubble,_p40,_p41,_p44,_p42,newRight)};}} + } + }; + var _p45 = up(dict); + var flag = _p45._0; + var updatedDict = _p45._1; + var _p46 = flag; + switch (_p46.ctor) + {case "Same": return updatedDict; + case "Insert": return ensureBlackRoot(updatedDict); + default: return blacken(updatedDict);} + }); + var insert = F3(function (key,value,dict) { return A3(update,key,$Basics.always($Maybe.Just(value)),dict);}); + var singleton = F2(function (key,value) { return A3(insert,key,value,empty);}); + var union = F2(function (t1,t2) { return A3(foldl,insert,t2,t1);}); + var fromList = function (assocs) { + return A3($List.foldl,F2(function (_p47,dict) { var _p48 = _p47;return A3(insert,_p48._0,_p48._1,dict);}),empty,assocs); + }; + var filter = F2(function (predicate,dictionary) { + var add = F3(function (key,value,dict) { return A2(predicate,key,value) ? A3(insert,key,value,dict) : dict;}); + return A3(foldl,add,empty,dictionary); + }); + var intersect = F2(function (t1,t2) { return A2(filter,F2(function (k,_p49) { return A2(member,k,t2);}),t1);}); + var partition = F2(function (predicate,dict) { + var add = F3(function (key,value,_p50) { + var _p51 = _p50; + var _p53 = _p51._1; + var _p52 = _p51._0; + return A2(predicate,key,value) ? {ctor: "_Tuple2",_0: A3(insert,key,value,_p52),_1: _p53} : {ctor: "_Tuple2",_0: _p52,_1: A3(insert,key,value,_p53)}; + }); + return A3(foldl,add,{ctor: "_Tuple2",_0: empty,_1: empty},dict); + }); + var remove = F2(function (key,dict) { return A3(update,key,$Basics.always($Maybe.Nothing),dict);}); + var diff = F2(function (t1,t2) { return A3(foldl,F3(function (k,v,t) { return A2(remove,k,t);}),t1,t2);}); + return _elm.Dict.values = {_op: _op + ,empty: empty + ,singleton: singleton + ,insert: insert + ,update: update + ,isEmpty: isEmpty + ,get: get + ,remove: remove + ,member: member + ,size: size + ,filter: filter + ,partition: partition + ,foldl: foldl + ,foldr: foldr + ,map: map + ,union: union + ,intersect: intersect + ,diff: diff + ,keys: keys + ,values: values + ,toList: toList + ,fromList: fromList}; +}; +Elm.Native.Json = {}; + +Elm.Native.Json.make = function(localRuntime) { + localRuntime.Native = localRuntime.Native || {}; + localRuntime.Native.Json = localRuntime.Native.Json || {}; + if (localRuntime.Native.Json.values) { + return localRuntime.Native.Json.values; + } + + var ElmArray = Elm.Native.Array.make(localRuntime); + var List = Elm.Native.List.make(localRuntime); + var Maybe = Elm.Maybe.make(localRuntime); + var Result = Elm.Result.make(localRuntime); + var Utils = Elm.Native.Utils.make(localRuntime); + + + function crash(expected, actual) { + throw new Error( + 'expecting ' + expected + ' but got ' + JSON.stringify(actual) + ); + } + + + // PRIMITIVE VALUES + + function decodeNull(successValue) { + return function(value) { + if (value === null) { + return successValue; + } + crash('null', value); + }; + } + + + function decodeString(value) { + if (typeof value === 'string' || value instanceof String) { + return value; + } + crash('a String', value); + } + + + function decodeFloat(value) { + if (typeof value === 'number') { + return value; + } + crash('a Float', value); + } + + + function decodeInt(value) { + if (typeof value !== 'number') { + crash('an Int', value); + } + + if (value < 2147483647 && value > -2147483647 && (value | 0) === value) { + return value; + } + + if (isFinite(value) && !(value % 1)) { + return value; + } + + crash('an Int', value); + } + + + function decodeBool(value) { + if (typeof value === 'boolean') { + return value; + } + crash('a Bool', value); + } + + + // ARRAY + + function decodeArray(decoder) { + return function(value) { + if (value instanceof Array) { + var len = value.length; + var array = new Array(len); + for (var i = len; i--; ) { + array[i] = decoder(value[i]); + } + return ElmArray.fromJSArray(array); + } + crash('an Array', value); + }; + } + + + // LIST + + function decodeList(decoder) { + return function(value) { + if (value instanceof Array) { + var len = value.length; + var list = List.Nil; + for (var i = len; i--; ) { + list = List.Cons( decoder(value[i]), list ); + } + return list; + } + crash('a List', value); + }; + } + + + // MAYBE + + function decodeMaybe(decoder) { + return function(value) { + try { + return Maybe.Just(decoder(value)); + } catch(e) { + return Maybe.Nothing; + } + }; + } + + + // FIELDS + + function decodeField(field, decoder) { + return function(value) { + var subValue = value[field]; + if (subValue !== undefined) { + return decoder(subValue); + } + crash("an object with field '" + field + "'", value); + }; + } + + + // OBJECTS + + function decodeKeyValuePairs(decoder) { + return function(value) { + var isObject = + typeof value === 'object' + && value !== null + && !(value instanceof Array); + + if (isObject) { + var keyValuePairs = List.Nil; + for (var key in value) + { + var elmValue = decoder(value[key]); + var pair = Utils.Tuple2(key, elmValue); + keyValuePairs = List.Cons(pair, keyValuePairs); + } + return keyValuePairs; + } + + crash('an object', value); + }; + } + + function decodeObject1(f, d1) { + return function(value) { + return f(d1(value)); + }; + } + + function decodeObject2(f, d1, d2) { + return function(value) { + return A2( f, d1(value), d2(value) ); + }; + } + + function decodeObject3(f, d1, d2, d3) { + return function(value) { + return A3( f, d1(value), d2(value), d3(value) ); + }; + } + + function decodeObject4(f, d1, d2, d3, d4) { + return function(value) { + return A4( f, d1(value), d2(value), d3(value), d4(value) ); + }; + } + + function decodeObject5(f, d1, d2, d3, d4, d5) { + return function(value) { + return A5( f, d1(value), d2(value), d3(value), d4(value), d5(value) ); + }; + } + + function decodeObject6(f, d1, d2, d3, d4, d5, d6) { + return function(value) { + return A6( f, + d1(value), + d2(value), + d3(value), + d4(value), + d5(value), + d6(value) + ); + }; + } + + function decodeObject7(f, d1, d2, d3, d4, d5, d6, d7) { + return function(value) { + return A7( f, + d1(value), + d2(value), + d3(value), + d4(value), + d5(value), + d6(value), + d7(value) + ); + }; + } + + function decodeObject8(f, d1, d2, d3, d4, d5, d6, d7, d8) { + return function(value) { + return A8( f, + d1(value), + d2(value), + d3(value), + d4(value), + d5(value), + d6(value), + d7(value), + d8(value) + ); + }; + } + + + // TUPLES + + function decodeTuple1(f, d1) { + return function(value) { + if ( !(value instanceof Array) || value.length !== 1 ) { + crash('a Tuple of length 1', value); + } + return f( d1(value[0]) ); + }; + } + + function decodeTuple2(f, d1, d2) { + return function(value) { + if ( !(value instanceof Array) || value.length !== 2 ) { + crash('a Tuple of length 2', value); + } + return A2( f, d1(value[0]), d2(value[1]) ); + }; + } + + function decodeTuple3(f, d1, d2, d3) { + return function(value) { + if ( !(value instanceof Array) || value.length !== 3 ) { + crash('a Tuple of length 3', value); + } + return A3( f, d1(value[0]), d2(value[1]), d3(value[2]) ); + }; + } + + + function decodeTuple4(f, d1, d2, d3, d4) { + return function(value) { + if ( !(value instanceof Array) || value.length !== 4 ) { + crash('a Tuple of length 4', value); + } + return A4( f, d1(value[0]), d2(value[1]), d3(value[2]), d4(value[3]) ); + }; + } + + + function decodeTuple5(f, d1, d2, d3, d4, d5) { + return function(value) { + if ( !(value instanceof Array) || value.length !== 5 ) { + crash('a Tuple of length 5', value); + } + return A5( f, + d1(value[0]), + d2(value[1]), + d3(value[2]), + d4(value[3]), + d5(value[4]) + ); + }; + } + + + function decodeTuple6(f, d1, d2, d3, d4, d5, d6) { + return function(value) { + if ( !(value instanceof Array) || value.length !== 6 ) { + crash('a Tuple of length 6', value); + } + return A6( f, + d1(value[0]), + d2(value[1]), + d3(value[2]), + d4(value[3]), + d5(value[4]), + d6(value[5]) + ); + }; + } + + function decodeTuple7(f, d1, d2, d3, d4, d5, d6, d7) { + return function(value) { + if ( !(value instanceof Array) || value.length !== 7 ) { + crash('a Tuple of length 7', value); + } + return A7( f, + d1(value[0]), + d2(value[1]), + d3(value[2]), + d4(value[3]), + d5(value[4]), + d6(value[5]), + d7(value[6]) + ); + }; + } + + + function decodeTuple8(f, d1, d2, d3, d4, d5, d6, d7, d8) { + return function(value) { + if ( !(value instanceof Array) || value.length !== 8 ) { + crash('a Tuple of length 8', value); + } + return A8( f, + d1(value[0]), + d2(value[1]), + d3(value[2]), + d4(value[3]), + d5(value[4]), + d6(value[5]), + d7(value[6]), + d8(value[7]) + ); + }; + } + + + // CUSTOM DECODERS + + function decodeValue(value) { + return value; + } + + function runDecoderValue(decoder, value) { + try { + return Result.Ok(decoder(value)); + } catch(e) { + return Result.Err(e.message); + } + } + + function customDecoder(decoder, callback) { + return function(value) { + var result = callback(decoder(value)); + if (result.ctor === 'Err') { + throw new Error('custom decoder failed: ' + result._0); + } + return result._0; + }; + } + + function andThen(decode, callback) { + return function(value) { + var result = decode(value); + return callback(result)(value); + }; + } + + function fail(msg) { + return function(value) { + throw new Error(msg); + }; + } + + function succeed(successValue) { + return function(value) { + return successValue; + }; + } + + + // ONE OF MANY + + function oneOf(decoders) { + return function(value) { + var errors = []; + var temp = decoders; + while (temp.ctor !== '[]') { + try { + return temp._0(value); + } catch(e) { + errors.push(e.message); + } + temp = temp._1; + } + throw new Error('expecting one of the following:\n ' + errors.join('\n ')); + }; + } + + function get(decoder, value) { + try { + return Result.Ok(decoder(value)); + } catch(e) { + return Result.Err(e.message); + } + } + + + // ENCODE / DECODE + + function runDecoderString(decoder, string) { + try { + return Result.Ok(decoder(JSON.parse(string))); + } catch(e) { + return Result.Err(e.message); + } + } + + function encode(indentLevel, value) { + return JSON.stringify(value, null, indentLevel); + } + + function identity(value) { + return value; + } + + function encodeObject(keyValuePairs) { + var obj = {}; + while (keyValuePairs.ctor !== '[]') { + var pair = keyValuePairs._0; + obj[pair._0] = pair._1; + keyValuePairs = keyValuePairs._1; + } + return obj; + } + + return localRuntime.Native.Json.values = { + encode: F2(encode), + runDecoderString: F2(runDecoderString), + runDecoderValue: F2(runDecoderValue), + + get: F2(get), + oneOf: oneOf, + + decodeNull: decodeNull, + decodeInt: decodeInt, + decodeFloat: decodeFloat, + decodeString: decodeString, + decodeBool: decodeBool, + + decodeMaybe: decodeMaybe, + + decodeList: decodeList, + decodeArray: decodeArray, + + decodeField: F2(decodeField), + + decodeObject1: F2(decodeObject1), + decodeObject2: F3(decodeObject2), + decodeObject3: F4(decodeObject3), + decodeObject4: F5(decodeObject4), + decodeObject5: F6(decodeObject5), + decodeObject6: F7(decodeObject6), + decodeObject7: F8(decodeObject7), + decodeObject8: F9(decodeObject8), + decodeKeyValuePairs: decodeKeyValuePairs, + + decodeTuple1: F2(decodeTuple1), + decodeTuple2: F3(decodeTuple2), + decodeTuple3: F4(decodeTuple3), + decodeTuple4: F5(decodeTuple4), + decodeTuple5: F6(decodeTuple5), + decodeTuple6: F7(decodeTuple6), + decodeTuple7: F8(decodeTuple7), + decodeTuple8: F9(decodeTuple8), + + andThen: F2(andThen), + decodeValue: decodeValue, + customDecoder: F2(customDecoder), + fail: fail, + succeed: succeed, + + identity: identity, + encodeNull: null, + encodeArray: ElmArray.toJSArray, + encodeList: List.toArray, + encodeObject: encodeObject + + }; +}; + +Elm.Json = Elm.Json || {}; +Elm.Json.Encode = Elm.Json.Encode || {}; +Elm.Json.Encode.make = function (_elm) { + "use strict"; + _elm.Json = _elm.Json || {}; + _elm.Json.Encode = _elm.Json.Encode || {}; + if (_elm.Json.Encode.values) return _elm.Json.Encode.values; + var _U = Elm.Native.Utils.make(_elm),$Array = Elm.Array.make(_elm),$Native$Json = Elm.Native.Json.make(_elm); + var _op = {}; + var list = $Native$Json.encodeList; + var array = $Native$Json.encodeArray; + var object = $Native$Json.encodeObject; + var $null = $Native$Json.encodeNull; + var bool = $Native$Json.identity; + var $float = $Native$Json.identity; + var $int = $Native$Json.identity; + var string = $Native$Json.identity; + var encode = $Native$Json.encode; + var Value = {ctor: "Value"}; + return _elm.Json.Encode.values = {_op: _op + ,encode: encode + ,string: string + ,$int: $int + ,$float: $float + ,bool: bool + ,$null: $null + ,list: list + ,array: array + ,object: object}; +}; +Elm.Json = Elm.Json || {}; +Elm.Json.Decode = Elm.Json.Decode || {}; +Elm.Json.Decode.make = function (_elm) { + "use strict"; + _elm.Json = _elm.Json || {}; + _elm.Json.Decode = _elm.Json.Decode || {}; + if (_elm.Json.Decode.values) return _elm.Json.Decode.values; + var _U = Elm.Native.Utils.make(_elm), + $Array = Elm.Array.make(_elm), + $Dict = Elm.Dict.make(_elm), + $Json$Encode = Elm.Json.Encode.make(_elm), + $List = Elm.List.make(_elm), + $Maybe = Elm.Maybe.make(_elm), + $Native$Json = Elm.Native.Json.make(_elm), + $Result = Elm.Result.make(_elm); + var _op = {}; + var tuple8 = $Native$Json.decodeTuple8; + var tuple7 = $Native$Json.decodeTuple7; + var tuple6 = $Native$Json.decodeTuple6; + var tuple5 = $Native$Json.decodeTuple5; + var tuple4 = $Native$Json.decodeTuple4; + var tuple3 = $Native$Json.decodeTuple3; + var tuple2 = $Native$Json.decodeTuple2; + var tuple1 = $Native$Json.decodeTuple1; + var succeed = $Native$Json.succeed; + var fail = $Native$Json.fail; + var andThen = $Native$Json.andThen; + var customDecoder = $Native$Json.customDecoder; + var decodeValue = $Native$Json.runDecoderValue; + var value = $Native$Json.decodeValue; + var maybe = $Native$Json.decodeMaybe; + var $null = $Native$Json.decodeNull; + var array = $Native$Json.decodeArray; + var list = $Native$Json.decodeList; + var bool = $Native$Json.decodeBool; + var $int = $Native$Json.decodeInt; + var $float = $Native$Json.decodeFloat; + var string = $Native$Json.decodeString; + var oneOf = $Native$Json.oneOf; + var keyValuePairs = $Native$Json.decodeKeyValuePairs; + var object8 = $Native$Json.decodeObject8; + var object7 = $Native$Json.decodeObject7; + var object6 = $Native$Json.decodeObject6; + var object5 = $Native$Json.decodeObject5; + var object4 = $Native$Json.decodeObject4; + var object3 = $Native$Json.decodeObject3; + var object2 = $Native$Json.decodeObject2; + var object1 = $Native$Json.decodeObject1; + _op[":="] = $Native$Json.decodeField; + var at = F2(function (fields,decoder) { return A3($List.foldr,F2(function (x,y) { return A2(_op[":="],x,y);}),decoder,fields);}); + var decodeString = $Native$Json.runDecoderString; + var map = $Native$Json.decodeObject1; + var dict = function (decoder) { return A2(map,$Dict.fromList,keyValuePairs(decoder));}; + var Decoder = {ctor: "Decoder"}; + return _elm.Json.Decode.values = {_op: _op + ,decodeString: decodeString + ,decodeValue: decodeValue + ,string: string + ,$int: $int + ,$float: $float + ,bool: bool + ,$null: $null + ,list: list + ,array: array + ,tuple1: tuple1 + ,tuple2: tuple2 + ,tuple3: tuple3 + ,tuple4: tuple4 + ,tuple5: tuple5 + ,tuple6: tuple6 + ,tuple7: tuple7 + ,tuple8: tuple8 + ,at: at + ,object1: object1 + ,object2: object2 + ,object3: object3 + ,object4: object4 + ,object5: object5 + ,object6: object6 + ,object7: object7 + ,object8: object8 + ,keyValuePairs: keyValuePairs + ,dict: dict + ,maybe: maybe + ,oneOf: oneOf + ,map: map + ,fail: fail + ,succeed: succeed + ,andThen: andThen + ,value: value + ,customDecoder: customDecoder}; +}; +Elm.Native = Elm.Native || {}; +Elm.Native.Window = {}; +Elm.Native.Window.make = function make(localRuntime) { + localRuntime.Native = localRuntime.Native || {}; + localRuntime.Native.Window = localRuntime.Native.Window || {}; + if (localRuntime.Native.Window.values) + { + return localRuntime.Native.Window.values; + } + + var NS = Elm.Native.Signal.make(localRuntime); + var Tuple2 = Elm.Native.Utils.make(localRuntime).Tuple2; + + + function getWidth() + { + return localRuntime.node.clientWidth; + } + + + function getHeight() + { + if (localRuntime.isFullscreen()) + { + return window.innerHeight; + } + return localRuntime.node.clientHeight; + } + + + var dimensions = NS.input('Window.dimensions', Tuple2(getWidth(), getHeight())); + + + function resizeIfNeeded() + { + // Do not trigger event if the dimensions have not changed. + // This should be most of the time. + var w = getWidth(); + var h = getHeight(); + if (dimensions.value._0 === w && dimensions.value._1 === h) + { + return; + } + + setTimeout(function() { + // Check again to see if the dimensions have changed. + // It is conceivable that the dimensions have changed + // again while some other event was being processed. + w = getWidth(); + h = getHeight(); + if (dimensions.value._0 === w && dimensions.value._1 === h) + { + return; + } + localRuntime.notify(dimensions.id, Tuple2(w, h)); + }, 0); + } + + + localRuntime.addListener([dimensions.id], window, 'resize', resizeIfNeeded); + + + return localRuntime.Native.Window.values = { + dimensions: dimensions, + resizeIfNeeded: resizeIfNeeded + }; +}; + +Elm.Window = Elm.Window || {}; +Elm.Window.make = function (_elm) { + "use strict"; + _elm.Window = _elm.Window || {}; + if (_elm.Window.values) return _elm.Window.values; + var _U = Elm.Native.Utils.make(_elm),$Basics = Elm.Basics.make(_elm),$Native$Window = Elm.Native.Window.make(_elm),$Signal = Elm.Signal.make(_elm); + var _op = {}; + var dimensions = $Native$Window.dimensions; + var width = A2($Signal.map,$Basics.fst,dimensions); + var height = A2($Signal.map,$Basics.snd,dimensions); + return _elm.Window.values = {_op: _op,dimensions: dimensions,width: width,height: height}; +}; +(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o> 0 + currentItem = indices[currentIndex] + + if (minIndex === maxIndex) { + return currentItem >= left && currentItem <= right + } else if (currentItem < left) { + minIndex = currentIndex + 1 + } else if (currentItem > right) { + maxIndex = currentIndex - 1 + } else { + return true + } + } + + return false; +} + +function ascending(a, b) { + return a > b ? 1 : -1 +} + +},{}],8:[function(require,module,exports){ +var applyProperties = require("./apply-properties") + +var isWidget = require("../vnode/is-widget.js") +var VPatch = require("../vnode/vpatch.js") + +var render = require("./create-element") +var updateWidget = require("./update-widget") + +module.exports = applyPatch + +function applyPatch(vpatch, domNode, renderOptions) { + var type = vpatch.type + var vNode = vpatch.vNode + var patch = vpatch.patch + + switch (type) { + case VPatch.REMOVE: + return removeNode(domNode, vNode) + case VPatch.INSERT: + return insertNode(domNode, patch, renderOptions) + case VPatch.VTEXT: + return stringPatch(domNode, vNode, patch, renderOptions) + case VPatch.WIDGET: + return widgetPatch(domNode, vNode, patch, renderOptions) + case VPatch.VNODE: + return vNodePatch(domNode, vNode, patch, renderOptions) + case VPatch.ORDER: + reorderChildren(domNode, patch) + return domNode + case VPatch.PROPS: + applyProperties(domNode, patch, vNode.properties) + return domNode + case VPatch.THUNK: + return replaceRoot(domNode, + renderOptions.patch(domNode, patch, renderOptions)) + default: + return domNode + } +} + +function removeNode(domNode, vNode) { + var parentNode = domNode.parentNode + + if (parentNode) { + parentNode.removeChild(domNode) + } + + destroyWidget(domNode, vNode); + + return null +} + +function insertNode(parentNode, vNode, renderOptions) { + var newNode = render(vNode, renderOptions) + + if (parentNode) { + parentNode.appendChild(newNode) + } + + return parentNode +} + +function stringPatch(domNode, leftVNode, vText, renderOptions) { + var newNode + + if (domNode.nodeType === 3) { + domNode.replaceData(0, domNode.length, vText.text) + newNode = domNode + } else { + var parentNode = domNode.parentNode + newNode = render(vText, renderOptions) + + if (parentNode && newNode !== domNode) { + parentNode.replaceChild(newNode, domNode) + } + } + + return newNode +} + +function widgetPatch(domNode, leftVNode, widget, renderOptions) { + var updating = updateWidget(leftVNode, widget) + var newNode + + if (updating) { + newNode = widget.update(leftVNode, domNode) || domNode + } else { + newNode = render(widget, renderOptions) + } + + var parentNode = domNode.parentNode + + if (parentNode && newNode !== domNode) { + parentNode.replaceChild(newNode, domNode) + } + + if (!updating) { + destroyWidget(domNode, leftVNode) + } + + return newNode +} + +function vNodePatch(domNode, leftVNode, vNode, renderOptions) { + var parentNode = domNode.parentNode + var newNode = render(vNode, renderOptions) + + if (parentNode && newNode !== domNode) { + parentNode.replaceChild(newNode, domNode) + } + + return newNode +} + +function destroyWidget(domNode, w) { + if (typeof w.destroy === "function" && isWidget(w)) { + w.destroy(domNode) + } +} + +function reorderChildren(domNode, moves) { + var childNodes = domNode.childNodes + var keyMap = {} + var node + var remove + var insert + + for (var i = 0; i < moves.removes.length; i++) { + remove = moves.removes[i] + node = childNodes[remove.from] + if (remove.key) { + keyMap[remove.key] = node + } + domNode.removeChild(node) + } + + var length = childNodes.length + for (var j = 0; j < moves.inserts.length; j++) { + insert = moves.inserts[j] + node = keyMap[insert.key] + // this is the weirdest bug i've ever seen in webkit + domNode.insertBefore(node, insert.to >= length++ ? null : childNodes[insert.to]) + } +} + +function replaceRoot(oldRoot, newRoot) { + if (oldRoot && newRoot && oldRoot !== newRoot && oldRoot.parentNode) { + oldRoot.parentNode.replaceChild(newRoot, oldRoot) + } + + return newRoot; +} + +},{"../vnode/is-widget.js":16,"../vnode/vpatch.js":19,"./apply-properties":5,"./create-element":6,"./update-widget":10}],9:[function(require,module,exports){ +var document = require("global/document") +var isArray = require("x-is-array") + +var domIndex = require("./dom-index") +var patchOp = require("./patch-op") +module.exports = patch + +function patch(rootNode, patches) { + return patchRecursive(rootNode, patches) +} + +function patchRecursive(rootNode, patches, renderOptions) { + var indices = patchIndices(patches) + + if (indices.length === 0) { + return rootNode + } + + var index = domIndex(rootNode, patches.a, indices) + var ownerDocument = rootNode.ownerDocument + + if (!renderOptions) { + renderOptions = { patch: patchRecursive } + if (ownerDocument !== document) { + renderOptions.document = ownerDocument + } + } + + for (var i = 0; i < indices.length; i++) { + var nodeIndex = indices[i] + rootNode = applyPatch(rootNode, + index[nodeIndex], + patches[nodeIndex], + renderOptions) + } + + return rootNode +} + +function applyPatch(rootNode, domNode, patchList, renderOptions) { + if (!domNode) { + return rootNode + } + + var newNode + + if (isArray(patchList)) { + for (var i = 0; i < patchList.length; i++) { + newNode = patchOp(patchList[i], domNode, renderOptions) + + if (domNode === rootNode) { + rootNode = newNode + } + } + } else { + newNode = patchOp(patchList, domNode, renderOptions) + + if (domNode === rootNode) { + rootNode = newNode + } + } + + return rootNode +} + +function patchIndices(patches) { + var indices = [] + + for (var key in patches) { + if (key !== "a") { + indices.push(Number(key)) + } + } + + return indices +} + +},{"./dom-index":7,"./patch-op":8,"global/document":2,"x-is-array":4}],10:[function(require,module,exports){ +var isWidget = require("../vnode/is-widget.js") + +module.exports = updateWidget + +function updateWidget(a, b) { + if (isWidget(a) && isWidget(b)) { + if ("name" in a && "name" in b) { + return a.id === b.id + } else { + return a.init === b.init + } + } + + return false +} + +},{"../vnode/is-widget.js":16}],11:[function(require,module,exports){ +var isVNode = require("./is-vnode") +var isVText = require("./is-vtext") +var isWidget = require("./is-widget") +var isThunk = require("./is-thunk") + +module.exports = handleThunk + +function handleThunk(a, b) { + var renderedA = a + var renderedB = b + + if (isThunk(b)) { + renderedB = renderThunk(b, a) + } + + if (isThunk(a)) { + renderedA = renderThunk(a, null) + } + + return { + a: renderedA, + b: renderedB + } +} + +function renderThunk(thunk, previous) { + var renderedThunk = thunk.vnode + + if (!renderedThunk) { + renderedThunk = thunk.vnode = thunk.render(previous) + } + + if (!(isVNode(renderedThunk) || + isVText(renderedThunk) || + isWidget(renderedThunk))) { + throw new Error("thunk did not return a valid node"); + } + + return renderedThunk +} + +},{"./is-thunk":12,"./is-vnode":14,"./is-vtext":15,"./is-widget":16}],12:[function(require,module,exports){ +module.exports = isThunk + +function isThunk(t) { + return t && t.type === "Thunk" +} + +},{}],13:[function(require,module,exports){ +module.exports = isHook + +function isHook(hook) { + return hook && + (typeof hook.hook === "function" && !hook.hasOwnProperty("hook") || + typeof hook.unhook === "function" && !hook.hasOwnProperty("unhook")) +} + +},{}],14:[function(require,module,exports){ +var version = require("./version") + +module.exports = isVirtualNode + +function isVirtualNode(x) { + return x && x.type === "VirtualNode" && x.version === version +} + +},{"./version":17}],15:[function(require,module,exports){ +var version = require("./version") + +module.exports = isVirtualText + +function isVirtualText(x) { + return x && x.type === "VirtualText" && x.version === version +} + +},{"./version":17}],16:[function(require,module,exports){ +module.exports = isWidget + +function isWidget(w) { + return w && w.type === "Widget" +} + +},{}],17:[function(require,module,exports){ +module.exports = "2" + +},{}],18:[function(require,module,exports){ +var version = require("./version") +var isVNode = require("./is-vnode") +var isWidget = require("./is-widget") +var isThunk = require("./is-thunk") +var isVHook = require("./is-vhook") + +module.exports = VirtualNode + +var noProperties = {} +var noChildren = [] + +function VirtualNode(tagName, properties, children, key, namespace) { + this.tagName = tagName + this.properties = properties || noProperties + this.children = children || noChildren + this.key = key != null ? String(key) : undefined + this.namespace = (typeof namespace === "string") ? namespace : null + + var count = (children && children.length) || 0 + var descendants = 0 + var hasWidgets = false + var hasThunks = false + var descendantHooks = false + var hooks + + for (var propName in properties) { + if (properties.hasOwnProperty(propName)) { + var property = properties[propName] + if (isVHook(property) && property.unhook) { + if (!hooks) { + hooks = {} + } + + hooks[propName] = property + } + } + } + + for (var i = 0; i < count; i++) { + var child = children[i] + if (isVNode(child)) { + descendants += child.count || 0 + + if (!hasWidgets && child.hasWidgets) { + hasWidgets = true + } + + if (!hasThunks && child.hasThunks) { + hasThunks = true + } + + if (!descendantHooks && (child.hooks || child.descendantHooks)) { + descendantHooks = true + } + } else if (!hasWidgets && isWidget(child)) { + if (typeof child.destroy === "function") { + hasWidgets = true + } + } else if (!hasThunks && isThunk(child)) { + hasThunks = true; + } + } + + this.count = count + descendants + this.hasWidgets = hasWidgets + this.hasThunks = hasThunks + this.hooks = hooks + this.descendantHooks = descendantHooks +} + +VirtualNode.prototype.version = version +VirtualNode.prototype.type = "VirtualNode" + +},{"./is-thunk":12,"./is-vhook":13,"./is-vnode":14,"./is-widget":16,"./version":17}],19:[function(require,module,exports){ +var version = require("./version") + +VirtualPatch.NONE = 0 +VirtualPatch.VTEXT = 1 +VirtualPatch.VNODE = 2 +VirtualPatch.WIDGET = 3 +VirtualPatch.PROPS = 4 +VirtualPatch.ORDER = 5 +VirtualPatch.INSERT = 6 +VirtualPatch.REMOVE = 7 +VirtualPatch.THUNK = 8 + +module.exports = VirtualPatch + +function VirtualPatch(type, vNode, patch) { + this.type = Number(type) + this.vNode = vNode + this.patch = patch +} + +VirtualPatch.prototype.version = version +VirtualPatch.prototype.type = "VirtualPatch" + +},{"./version":17}],20:[function(require,module,exports){ +var version = require("./version") + +module.exports = VirtualText + +function VirtualText(text) { + this.text = String(text) +} + +VirtualText.prototype.version = version +VirtualText.prototype.type = "VirtualText" + +},{"./version":17}],21:[function(require,module,exports){ +var isObject = require("is-object") +var isHook = require("../vnode/is-vhook") + +module.exports = diffProps + +function diffProps(a, b) { + var diff + + for (var aKey in a) { + if (!(aKey in b)) { + diff = diff || {} + diff[aKey] = undefined + } + + var aValue = a[aKey] + var bValue = b[aKey] + + if (aValue === bValue) { + continue + } else if (isObject(aValue) && isObject(bValue)) { + if (getPrototype(bValue) !== getPrototype(aValue)) { + diff = diff || {} + diff[aKey] = bValue + } else if (isHook(bValue)) { + diff = diff || {} + diff[aKey] = bValue + } else { + var objectDiff = diffProps(aValue, bValue) + if (objectDiff) { + diff = diff || {} + diff[aKey] = objectDiff + } + } + } else { + diff = diff || {} + diff[aKey] = bValue + } + } + + for (var bKey in b) { + if (!(bKey in a)) { + diff = diff || {} + diff[bKey] = b[bKey] + } + } + + return diff +} + +function getPrototype(value) { + if (Object.getPrototypeOf) { + return Object.getPrototypeOf(value) + } else if (value.__proto__) { + return value.__proto__ + } else if (value.constructor) { + return value.constructor.prototype + } +} + +},{"../vnode/is-vhook":13,"is-object":3}],22:[function(require,module,exports){ +var isArray = require("x-is-array") + +var VPatch = require("../vnode/vpatch") +var isVNode = require("../vnode/is-vnode") +var isVText = require("../vnode/is-vtext") +var isWidget = require("../vnode/is-widget") +var isThunk = require("../vnode/is-thunk") +var handleThunk = require("../vnode/handle-thunk") + +var diffProps = require("./diff-props") + +module.exports = diff + +function diff(a, b) { + var patch = { a: a } + walk(a, b, patch, 0) + return patch +} + +function walk(a, b, patch, index) { + if (a === b) { + return + } + + var apply = patch[index] + var applyClear = false + + if (isThunk(a) || isThunk(b)) { + thunks(a, b, patch, index) + } else if (b == null) { + + // If a is a widget we will add a remove patch for it + // Otherwise any child widgets/hooks must be destroyed. + // This prevents adding two remove patches for a widget. + if (!isWidget(a)) { + clearState(a, patch, index) + apply = patch[index] + } + + apply = appendPatch(apply, new VPatch(VPatch.REMOVE, a, b)) + } else if (isVNode(b)) { + if (isVNode(a)) { + if (a.tagName === b.tagName && + a.namespace === b.namespace && + a.key === b.key) { + var propsPatch = diffProps(a.properties, b.properties) + if (propsPatch) { + apply = appendPatch(apply, + new VPatch(VPatch.PROPS, a, propsPatch)) + } + apply = diffChildren(a, b, patch, apply, index) + } else { + apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b)) + applyClear = true + } + } else { + apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b)) + applyClear = true + } + } else if (isVText(b)) { + if (!isVText(a)) { + apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b)) + applyClear = true + } else if (a.text !== b.text) { + apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b)) + } + } else if (isWidget(b)) { + if (!isWidget(a)) { + applyClear = true + } + + apply = appendPatch(apply, new VPatch(VPatch.WIDGET, a, b)) + } + + if (apply) { + patch[index] = apply + } + + if (applyClear) { + clearState(a, patch, index) + } +} + +function diffChildren(a, b, patch, apply, index) { + var aChildren = a.children + var orderedSet = reorder(aChildren, b.children) + var bChildren = orderedSet.children + + var aLen = aChildren.length + var bLen = bChildren.length + var len = aLen > bLen ? aLen : bLen + + for (var i = 0; i < len; i++) { + var leftNode = aChildren[i] + var rightNode = bChildren[i] + index += 1 + + if (!leftNode) { + if (rightNode) { + // Excess nodes in b need to be added + apply = appendPatch(apply, + new VPatch(VPatch.INSERT, null, rightNode)) + } + } else { + walk(leftNode, rightNode, patch, index) + } + + if (isVNode(leftNode) && leftNode.count) { + index += leftNode.count + } + } + + if (orderedSet.moves) { + // Reorder nodes last + apply = appendPatch(apply, new VPatch( + VPatch.ORDER, + a, + orderedSet.moves + )) + } + + return apply +} + +function clearState(vNode, patch, index) { + // TODO: Make this a single walk, not two + unhook(vNode, patch, index) + destroyWidgets(vNode, patch, index) +} + +// Patch records for all destroyed widgets must be added because we need +// a DOM node reference for the destroy function +function destroyWidgets(vNode, patch, index) { + if (isWidget(vNode)) { + if (typeof vNode.destroy === "function") { + patch[index] = appendPatch( + patch[index], + new VPatch(VPatch.REMOVE, vNode, null) + ) + } + } else if (isVNode(vNode) && (vNode.hasWidgets || vNode.hasThunks)) { + var children = vNode.children + var len = children.length + for (var i = 0; i < len; i++) { + var child = children[i] + index += 1 + + destroyWidgets(child, patch, index) + + if (isVNode(child) && child.count) { + index += child.count + } + } + } else if (isThunk(vNode)) { + thunks(vNode, null, patch, index) + } +} + +// Create a sub-patch for thunks +function thunks(a, b, patch, index) { + var nodes = handleThunk(a, b) + var thunkPatch = diff(nodes.a, nodes.b) + if (hasPatches(thunkPatch)) { + patch[index] = new VPatch(VPatch.THUNK, null, thunkPatch) + } +} + +function hasPatches(patch) { + for (var index in patch) { + if (index !== "a") { + return true + } + } + + return false +} + +// Execute hooks when two nodes are identical +function unhook(vNode, patch, index) { + if (isVNode(vNode)) { + if (vNode.hooks) { + patch[index] = appendPatch( + patch[index], + new VPatch( + VPatch.PROPS, + vNode, + undefinedKeys(vNode.hooks) + ) + ) + } + + if (vNode.descendantHooks || vNode.hasThunks) { + var children = vNode.children + var len = children.length + for (var i = 0; i < len; i++) { + var child = children[i] + index += 1 + + unhook(child, patch, index) + + if (isVNode(child) && child.count) { + index += child.count + } + } + } + } else if (isThunk(vNode)) { + thunks(vNode, null, patch, index) + } +} + +function undefinedKeys(obj) { + var result = {} + + for (var key in obj) { + result[key] = undefined + } + + return result +} + +// List diff, naive left to right reordering +function reorder(aChildren, bChildren) { + // O(M) time, O(M) memory + var bChildIndex = keyIndex(bChildren) + var bKeys = bChildIndex.keys + var bFree = bChildIndex.free + + if (bFree.length === bChildren.length) { + return { + children: bChildren, + moves: null + } + } + + // O(N) time, O(N) memory + var aChildIndex = keyIndex(aChildren) + var aKeys = aChildIndex.keys + var aFree = aChildIndex.free + + if (aFree.length === aChildren.length) { + return { + children: bChildren, + moves: null + } + } + + // O(MAX(N, M)) memory + var newChildren = [] + + var freeIndex = 0 + var freeCount = bFree.length + var deletedItems = 0 + + // Iterate through a and match a node in b + // O(N) time, + for (var i = 0 ; i < aChildren.length; i++) { + var aItem = aChildren[i] + var itemIndex + + if (aItem.key) { + if (bKeys.hasOwnProperty(aItem.key)) { + // Match up the old keys + itemIndex = bKeys[aItem.key] + newChildren.push(bChildren[itemIndex]) + + } else { + // Remove old keyed items + itemIndex = i - deletedItems++ + newChildren.push(null) + } + } else { + // Match the item in a with the next free item in b + if (freeIndex < freeCount) { + itemIndex = bFree[freeIndex++] + newChildren.push(bChildren[itemIndex]) + } else { + // There are no free items in b to match with + // the free items in a, so the extra free nodes + // are deleted. + itemIndex = i - deletedItems++ + newChildren.push(null) + } + } + } + + var lastFreeIndex = freeIndex >= bFree.length ? + bChildren.length : + bFree[freeIndex] + + // Iterate through b and append any new keys + // O(M) time + for (var j = 0; j < bChildren.length; j++) { + var newItem = bChildren[j] + + if (newItem.key) { + if (!aKeys.hasOwnProperty(newItem.key)) { + // Add any new keyed items + // We are adding new items to the end and then sorting them + // in place. In future we should insert new items in place. + newChildren.push(newItem) + } + } else if (j >= lastFreeIndex) { + // Add any leftover non-keyed items + newChildren.push(newItem) + } + } + + var simulate = newChildren.slice() + var simulateIndex = 0 + var removes = [] + var inserts = [] + var simulateItem + + for (var k = 0; k < bChildren.length;) { + var wantedItem = bChildren[k] + simulateItem = simulate[simulateIndex] + + // remove items + while (simulateItem === null && simulate.length) { + removes.push(remove(simulate, simulateIndex, null)) + simulateItem = simulate[simulateIndex] + } + + if (!simulateItem || simulateItem.key !== wantedItem.key) { + // if we need a key in this position... + if (wantedItem.key) { + if (simulateItem && simulateItem.key) { + // if an insert doesn't put this key in place, it needs to move + if (bKeys[simulateItem.key] !== k + 1) { + removes.push(remove(simulate, simulateIndex, simulateItem.key)) + simulateItem = simulate[simulateIndex] + // if the remove didn't put the wanted item in place, we need to insert it + if (!simulateItem || simulateItem.key !== wantedItem.key) { + inserts.push({key: wantedItem.key, to: k}) + } + // items are matching, so skip ahead + else { + simulateIndex++ + } + } + else { + inserts.push({key: wantedItem.key, to: k}) + } + } + else { + inserts.push({key: wantedItem.key, to: k}) + } + k++ + } + // a key in simulate has no matching wanted key, remove it + else if (simulateItem && simulateItem.key) { + removes.push(remove(simulate, simulateIndex, simulateItem.key)) + } + } + else { + simulateIndex++ + k++ + } + } + + // remove all the remaining nodes from simulate + while(simulateIndex < simulate.length) { + simulateItem = simulate[simulateIndex] + removes.push(remove(simulate, simulateIndex, simulateItem && simulateItem.key)) + } + + // If the only moves we have are deletes then we can just + // let the delete patch remove these items. + if (removes.length === deletedItems && !inserts.length) { + return { + children: newChildren, + moves: null + } + } + + return { + children: newChildren, + moves: { + removes: removes, + inserts: inserts + } + } +} + +function remove(arr, index, key) { + arr.splice(index, 1) + + return { + from: index, + key: key + } +} + +function keyIndex(children) { + var keys = {} + var free = [] + var length = children.length + + for (var i = 0; i < length; i++) { + var child = children[i] + + if (child.key) { + keys[child.key] = i + } else { + free.push(i) + } + } + + return { + keys: keys, // A hash of key name to index + free: free, // An array of unkeyed item indices + } +} + +function appendPatch(apply, patch) { + if (apply) { + if (isArray(apply)) { + apply.push(patch) + } else { + apply = [apply, patch] + } + + return apply + } else { + return patch + } +} + +},{"../vnode/handle-thunk":11,"../vnode/is-thunk":12,"../vnode/is-vnode":14,"../vnode/is-vtext":15,"../vnode/is-widget":16,"../vnode/vpatch":19,"./diff-props":21,"x-is-array":4}],23:[function(require,module,exports){ +var VNode = require('virtual-dom/vnode/vnode'); +var VText = require('virtual-dom/vnode/vtext'); +var diff = require('virtual-dom/vtree/diff'); +var patch = require('virtual-dom/vdom/patch'); +var createElement = require('virtual-dom/vdom/create-element'); +var isHook = require("virtual-dom/vnode/is-vhook"); + + +Elm.Native.VirtualDom = {}; +Elm.Native.VirtualDom.make = function(elm) +{ + elm.Native = elm.Native || {}; + elm.Native.VirtualDom = elm.Native.VirtualDom || {}; + if (elm.Native.VirtualDom.values) + { + return elm.Native.VirtualDom.values; + } + + var Element = Elm.Native.Graphics.Element.make(elm); + var Json = Elm.Native.Json.make(elm); + var List = Elm.Native.List.make(elm); + var Signal = Elm.Native.Signal.make(elm); + var Utils = Elm.Native.Utils.make(elm); + + var ATTRIBUTE_KEY = 'UniqueNameThatOthersAreVeryUnlikelyToUse'; + + + + // VIRTUAL DOM NODES + + + function text(string) + { + return new VText(string); + } + + function node(name) + { + return F2(function(propertyList, contents) { + return makeNode(name, propertyList, contents); + }); + } + + + // BUILD VIRTUAL DOME NODES + + + function makeNode(name, propertyList, contents) + { + var props = listToProperties(propertyList); + + var key, namespace; + // support keys + if (props.key !== undefined) + { + key = props.key; + props.key = undefined; + } + + // support namespace + if (props.namespace !== undefined) + { + namespace = props.namespace; + props.namespace = undefined; + } + + // ensure that setting text of an input does not move the cursor + var useSoftSet = + (name === 'input' || name === 'textarea') + && props.value !== undefined + && !isHook(props.value); + + if (useSoftSet) + { + props.value = SoftSetHook(props.value); + } + + return new VNode(name, props, List.toArray(contents), key, namespace); + } + + function listToProperties(list) + { + var object = {}; + while (list.ctor !== '[]') + { + var entry = list._0; + if (entry.key === ATTRIBUTE_KEY) + { + object.attributes = object.attributes || {}; + object.attributes[entry.value.attrKey] = entry.value.attrValue; + } + else + { + object[entry.key] = entry.value; + } + list = list._1; + } + return object; + } + + + + // PROPERTIES AND ATTRIBUTES + + + function property(key, value) + { + return { + key: key, + value: value + }; + } + + function attribute(key, value) + { + return { + key: ATTRIBUTE_KEY, + value: { + attrKey: key, + attrValue: value + } + }; + } + + + + // NAMESPACED ATTRIBUTES + + + function attributeNS(namespace, key, value) + { + return { + key: key, + value: new AttributeHook(namespace, key, value) + }; + } + + function AttributeHook(namespace, key, value) + { + if (!(this instanceof AttributeHook)) + { + return new AttributeHook(namespace, key, value); + } + + this.namespace = namespace; + this.key = key; + this.value = value; + } + + AttributeHook.prototype.hook = function (node, prop, prev) + { + if (prev + && prev.type === 'AttributeHook' + && prev.value === this.value + && prev.namespace === this.namespace) + { + return; + } + + node.setAttributeNS(this.namespace, prop, this.value); + }; + + AttributeHook.prototype.unhook = function (node, prop, next) + { + if (next + && next.type === 'AttributeHook' + && next.namespace === this.namespace) + { + return; + } + + node.removeAttributeNS(this.namespace, this.key); + }; + + AttributeHook.prototype.type = 'AttributeHook'; + + + + // EVENTS + + + function on(name, options, decoder, createMessage) + { + function eventHandler(event) + { + var value = A2(Json.runDecoderValue, decoder, event); + if (value.ctor === 'Ok') + { + if (options.stopPropagation) + { + event.stopPropagation(); + } + if (options.preventDefault) + { + event.preventDefault(); + } + Signal.sendMessage(createMessage(value._0)); + } + } + return property('on' + name, eventHandler); + } + + function SoftSetHook(value) + { + if (!(this instanceof SoftSetHook)) + { + return new SoftSetHook(value); + } + + this.value = value; + } + + SoftSetHook.prototype.hook = function (node, propertyName) + { + if (node[propertyName] !== this.value) + { + node[propertyName] = this.value; + } + }; + + + + // INTEGRATION WITH ELEMENTS + + + function ElementWidget(element) + { + this.element = element; + } + + ElementWidget.prototype.type = "Widget"; + + ElementWidget.prototype.init = function init() + { + return Element.render(this.element); + }; + + ElementWidget.prototype.update = function update(previous, node) + { + return Element.update(node, previous.element, this.element); + }; + + function fromElement(element) + { + return new ElementWidget(element); + } + + function toElement(width, height, html) + { + return A3(Element.newElement, width, height, { + ctor: 'Custom', + type: 'evancz/elm-html', + render: render, + update: update, + model: html + }); + } + + + + // RENDER AND UPDATE + + + function render(model) + { + var element = Element.createNode('div'); + element.appendChild(createElement(model)); + return element; + } + + function update(node, oldModel, newModel) + { + updateAndReplace(node.firstChild, oldModel, newModel); + return node; + } + + function updateAndReplace(node, oldModel, newModel) + { + var patches = diff(oldModel, newModel); + var newNode = patch(node, patches); + return newNode; + } + + + + // LAZINESS + + + function lazyRef(fn, a) + { + function thunk() + { + return fn(a); + } + return new Thunk(fn, [a], thunk); + } + + function lazyRef2(fn, a, b) + { + function thunk() + { + return A2(fn, a, b); + } + return new Thunk(fn, [a,b], thunk); + } + + function lazyRef3(fn, a, b, c) + { + function thunk() + { + return A3(fn, a, b, c); + } + return new Thunk(fn, [a,b,c], thunk); + } + + function Thunk(fn, args, thunk) + { + /* public (used by VirtualDom.js) */ + this.vnode = null; + this.key = undefined; + + /* private */ + this.fn = fn; + this.args = args; + this.thunk = thunk; + } + + Thunk.prototype.type = "Thunk"; + Thunk.prototype.render = renderThunk; + + function shouldUpdate(current, previous) + { + if (current.fn !== previous.fn) + { + return true; + } + + // if it's the same function, we know the number of args must match + var cargs = current.args; + var pargs = previous.args; + + for (var i = cargs.length; i--; ) + { + if (cargs[i] !== pargs[i]) + { + return true; + } + } + + return false; + } + + function renderThunk(previous) + { + if (previous == null || shouldUpdate(this, previous)) + { + return this.thunk(); + } + else + { + return previous.vnode; + } + } + + + return elm.Native.VirtualDom.values = Elm.Native.VirtualDom.values = { + node: node, + text: text, + on: F4(on), + + property: F2(property), + attribute: F2(attribute), + attributeNS: F3(attributeNS), + + lazy: F2(lazyRef), + lazy2: F3(lazyRef2), + lazy3: F4(lazyRef3), + + toElement: F3(toElement), + fromElement: fromElement, + + render: createElement, + updateAndReplace: updateAndReplace + }; +}; + +},{"virtual-dom/vdom/create-element":6,"virtual-dom/vdom/patch":9,"virtual-dom/vnode/is-vhook":13,"virtual-dom/vnode/vnode":18,"virtual-dom/vnode/vtext":20,"virtual-dom/vtree/diff":22}]},{},[23]); + +Elm.VirtualDom = Elm.VirtualDom || {}; +Elm.VirtualDom.make = function (_elm) { + "use strict"; + _elm.VirtualDom = _elm.VirtualDom || {}; + if (_elm.VirtualDom.values) return _elm.VirtualDom.values; + var _U = Elm.Native.Utils.make(_elm), + $Basics = Elm.Basics.make(_elm), + $Debug = Elm.Debug.make(_elm), + $Graphics$Element = Elm.Graphics.Element.make(_elm), + $Json$Decode = Elm.Json.Decode.make(_elm), + $List = Elm.List.make(_elm), + $Maybe = Elm.Maybe.make(_elm), + $Native$VirtualDom = Elm.Native.VirtualDom.make(_elm), + $Result = Elm.Result.make(_elm), + $Signal = Elm.Signal.make(_elm); + var _op = {}; + var lazy3 = $Native$VirtualDom.lazy3; + var lazy2 = $Native$VirtualDom.lazy2; + var lazy = $Native$VirtualDom.lazy; + var defaultOptions = {stopPropagation: false,preventDefault: false}; + var Options = F2(function (a,b) { return {stopPropagation: a,preventDefault: b};}); + var onWithOptions = $Native$VirtualDom.on; + var on = F3(function (eventName,decoder,toMessage) { return A4($Native$VirtualDom.on,eventName,defaultOptions,decoder,toMessage);}); + var attributeNS = $Native$VirtualDom.attributeNS; + var attribute = $Native$VirtualDom.attribute; + var property = $Native$VirtualDom.property; + var Property = {ctor: "Property"}; + var fromElement = $Native$VirtualDom.fromElement; + var toElement = $Native$VirtualDom.toElement; + var text = $Native$VirtualDom.text; + var node = $Native$VirtualDom.node; + var Node = {ctor: "Node"}; + return _elm.VirtualDom.values = {_op: _op + ,text: text + ,node: node + ,toElement: toElement + ,fromElement: fromElement + ,property: property + ,attribute: attribute + ,attributeNS: attributeNS + ,on: on + ,onWithOptions: onWithOptions + ,defaultOptions: defaultOptions + ,lazy: lazy + ,lazy2: lazy2 + ,lazy3: lazy3 + ,Options: Options}; +}; +Elm.Html = Elm.Html || {}; +Elm.Html.make = function (_elm) { + "use strict"; + _elm.Html = _elm.Html || {}; + if (_elm.Html.values) return _elm.Html.values; + var _U = Elm.Native.Utils.make(_elm), + $Basics = Elm.Basics.make(_elm), + $Debug = Elm.Debug.make(_elm), + $Graphics$Element = Elm.Graphics.Element.make(_elm), + $List = Elm.List.make(_elm), + $Maybe = Elm.Maybe.make(_elm), + $Result = Elm.Result.make(_elm), + $Signal = Elm.Signal.make(_elm), + $VirtualDom = Elm.VirtualDom.make(_elm); + var _op = {}; + var fromElement = $VirtualDom.fromElement; + var toElement = $VirtualDom.toElement; + var text = $VirtualDom.text; + var node = $VirtualDom.node; + var body = node("body"); + var section = node("section"); + var nav = node("nav"); + var article = node("article"); + var aside = node("aside"); + var h1 = node("h1"); + var h2 = node("h2"); + var h3 = node("h3"); + var h4 = node("h4"); + var h5 = node("h5"); + var h6 = node("h6"); + var header = node("header"); + var footer = node("footer"); + var address = node("address"); + var main$ = node("main"); + var p = node("p"); + var hr = node("hr"); + var pre = node("pre"); + var blockquote = node("blockquote"); + var ol = node("ol"); + var ul = node("ul"); + var li = node("li"); + var dl = node("dl"); + var dt = node("dt"); + var dd = node("dd"); + var figure = node("figure"); + var figcaption = node("figcaption"); + var div = node("div"); + var a = node("a"); + var em = node("em"); + var strong = node("strong"); + var small = node("small"); + var s = node("s"); + var cite = node("cite"); + var q = node("q"); + var dfn = node("dfn"); + var abbr = node("abbr"); + var time = node("time"); + var code = node("code"); + var $var = node("var"); + var samp = node("samp"); + var kbd = node("kbd"); + var sub = node("sub"); + var sup = node("sup"); + var i = node("i"); + var b = node("b"); + var u = node("u"); + var mark = node("mark"); + var ruby = node("ruby"); + var rt = node("rt"); + var rp = node("rp"); + var bdi = node("bdi"); + var bdo = node("bdo"); + var span = node("span"); + var br = node("br"); + var wbr = node("wbr"); + var ins = node("ins"); + var del = node("del"); + var img = node("img"); + var iframe = node("iframe"); + var embed = node("embed"); + var object = node("object"); + var param = node("param"); + var video = node("video"); + var audio = node("audio"); + var source = node("source"); + var track = node("track"); + var canvas = node("canvas"); + var svg = node("svg"); + var math = node("math"); + var table = node("table"); + var caption = node("caption"); + var colgroup = node("colgroup"); + var col = node("col"); + var tbody = node("tbody"); + var thead = node("thead"); + var tfoot = node("tfoot"); + var tr = node("tr"); + var td = node("td"); + var th = node("th"); + var form = node("form"); + var fieldset = node("fieldset"); + var legend = node("legend"); + var label = node("label"); + var input = node("input"); + var button = node("button"); + var select = node("select"); + var datalist = node("datalist"); + var optgroup = node("optgroup"); + var option = node("option"); + var textarea = node("textarea"); + var keygen = node("keygen"); + var output = node("output"); + var progress = node("progress"); + var meter = node("meter"); + var details = node("details"); + var summary = node("summary"); + var menuitem = node("menuitem"); + var menu = node("menu"); + return _elm.Html.values = {_op: _op + ,node: node + ,text: text + ,toElement: toElement + ,fromElement: fromElement + ,body: body + ,section: section + ,nav: nav + ,article: article + ,aside: aside + ,h1: h1 + ,h2: h2 + ,h3: h3 + ,h4: h4 + ,h5: h5 + ,h6: h6 + ,header: header + ,footer: footer + ,address: address + ,main$: main$ + ,p: p + ,hr: hr + ,pre: pre + ,blockquote: blockquote + ,ol: ol + ,ul: ul + ,li: li + ,dl: dl + ,dt: dt + ,dd: dd + ,figure: figure + ,figcaption: figcaption + ,div: div + ,a: a + ,em: em + ,strong: strong + ,small: small + ,s: s + ,cite: cite + ,q: q + ,dfn: dfn + ,abbr: abbr + ,time: time + ,code: code + ,$var: $var + ,samp: samp + ,kbd: kbd + ,sub: sub + ,sup: sup + ,i: i + ,b: b + ,u: u + ,mark: mark + ,ruby: ruby + ,rt: rt + ,rp: rp + ,bdi: bdi + ,bdo: bdo + ,span: span + ,br: br + ,wbr: wbr + ,ins: ins + ,del: del + ,img: img + ,iframe: iframe + ,embed: embed + ,object: object + ,param: param + ,video: video + ,audio: audio + ,source: source + ,track: track + ,canvas: canvas + ,svg: svg + ,math: math + ,table: table + ,caption: caption + ,colgroup: colgroup + ,col: col + ,tbody: tbody + ,thead: thead + ,tfoot: tfoot + ,tr: tr + ,td: td + ,th: th + ,form: form + ,fieldset: fieldset + ,legend: legend + ,label: label + ,input: input + ,button: button + ,select: select + ,datalist: datalist + ,optgroup: optgroup + ,option: option + ,textarea: textarea + ,keygen: keygen + ,output: output + ,progress: progress + ,meter: meter + ,details: details + ,summary: summary + ,menuitem: menuitem + ,menu: menu}; +}; +Elm.Html = Elm.Html || {}; +Elm.Html.Attributes = Elm.Html.Attributes || {}; +Elm.Html.Attributes.make = function (_elm) { + "use strict"; + _elm.Html = _elm.Html || {}; + _elm.Html.Attributes = _elm.Html.Attributes || {}; + if (_elm.Html.Attributes.values) return _elm.Html.Attributes.values; + var _U = Elm.Native.Utils.make(_elm), + $Basics = Elm.Basics.make(_elm), + $Debug = Elm.Debug.make(_elm), + $Html = Elm.Html.make(_elm), + $Json$Encode = Elm.Json.Encode.make(_elm), + $List = Elm.List.make(_elm), + $Maybe = Elm.Maybe.make(_elm), + $Result = Elm.Result.make(_elm), + $Signal = Elm.Signal.make(_elm), + $String = Elm.String.make(_elm), + $VirtualDom = Elm.VirtualDom.make(_elm); + var _op = {}; + var attribute = $VirtualDom.attribute; + var contextmenu = function (value) { return A2(attribute,"contextmenu",value);}; + var property = $VirtualDom.property; + var stringProperty = F2(function (name,string) { return A2(property,name,$Json$Encode.string(string));}); + var $class = function (name) { return A2(stringProperty,"className",name);}; + var id = function (name) { return A2(stringProperty,"id",name);}; + var title = function (name) { return A2(stringProperty,"title",name);}; + var accesskey = function ($char) { return A2(stringProperty,"accessKey",$String.fromChar($char));}; + var dir = function (value) { return A2(stringProperty,"dir",value);}; + var draggable = function (value) { return A2(stringProperty,"draggable",value);}; + var dropzone = function (value) { return A2(stringProperty,"dropzone",value);}; + var itemprop = function (value) { return A2(stringProperty,"itemprop",value);}; + var lang = function (value) { return A2(stringProperty,"lang",value);}; + var tabindex = function (n) { return A2(stringProperty,"tabIndex",$Basics.toString(n));}; + var charset = function (value) { return A2(stringProperty,"charset",value);}; + var content = function (value) { return A2(stringProperty,"content",value);}; + var httpEquiv = function (value) { return A2(stringProperty,"httpEquiv",value);}; + var language = function (value) { return A2(stringProperty,"language",value);}; + var src = function (value) { return A2(stringProperty,"src",value);}; + var height = function (value) { return A2(stringProperty,"height",$Basics.toString(value));}; + var width = function (value) { return A2(stringProperty,"width",$Basics.toString(value));}; + var alt = function (value) { return A2(stringProperty,"alt",value);}; + var preload = function (value) { return A2(stringProperty,"preload",value);}; + var poster = function (value) { return A2(stringProperty,"poster",value);}; + var kind = function (value) { return A2(stringProperty,"kind",value);}; + var srclang = function (value) { return A2(stringProperty,"srclang",value);}; + var sandbox = function (value) { return A2(stringProperty,"sandbox",value);}; + var srcdoc = function (value) { return A2(stringProperty,"srcdoc",value);}; + var type$ = function (value) { return A2(stringProperty,"type",value);}; + var value = function (value) { return A2(stringProperty,"value",value);}; + var placeholder = function (value) { return A2(stringProperty,"placeholder",value);}; + var accept = function (value) { return A2(stringProperty,"accept",value);}; + var acceptCharset = function (value) { return A2(stringProperty,"acceptCharset",value);}; + var action = function (value) { return A2(stringProperty,"action",value);}; + var autocomplete = function (bool) { return A2(stringProperty,"autocomplete",bool ? "on" : "off");}; + var autosave = function (value) { return A2(stringProperty,"autosave",value);}; + var enctype = function (value) { return A2(stringProperty,"enctype",value);}; + var formaction = function (value) { return A2(stringProperty,"formAction",value);}; + var list = function (value) { return A2(stringProperty,"list",value);}; + var minlength = function (n) { return A2(stringProperty,"minLength",$Basics.toString(n));}; + var maxlength = function (n) { return A2(stringProperty,"maxLength",$Basics.toString(n));}; + var method = function (value) { return A2(stringProperty,"method",value);}; + var name = function (value) { return A2(stringProperty,"name",value);}; + var pattern = function (value) { return A2(stringProperty,"pattern",value);}; + var size = function (n) { return A2(stringProperty,"size",$Basics.toString(n));}; + var $for = function (value) { return A2(stringProperty,"htmlFor",value);}; + var form = function (value) { return A2(stringProperty,"form",value);}; + var max = function (value) { return A2(stringProperty,"max",value);}; + var min = function (value) { return A2(stringProperty,"min",value);}; + var step = function (n) { return A2(stringProperty,"step",n);}; + var cols = function (n) { return A2(stringProperty,"cols",$Basics.toString(n));}; + var rows = function (n) { return A2(stringProperty,"rows",$Basics.toString(n));}; + var wrap = function (value) { return A2(stringProperty,"wrap",value);}; + var usemap = function (value) { return A2(stringProperty,"useMap",value);}; + var shape = function (value) { return A2(stringProperty,"shape",value);}; + var coords = function (value) { return A2(stringProperty,"coords",value);}; + var challenge = function (value) { return A2(stringProperty,"challenge",value);}; + var keytype = function (value) { return A2(stringProperty,"keytype",value);}; + var align = function (value) { return A2(stringProperty,"align",value);}; + var cite = function (value) { return A2(stringProperty,"cite",value);}; + var href = function (value) { return A2(stringProperty,"href",value);}; + var target = function (value) { return A2(stringProperty,"target",value);}; + var downloadAs = function (value) { return A2(stringProperty,"download",value);}; + var hreflang = function (value) { return A2(stringProperty,"hreflang",value);}; + var media = function (value) { return A2(stringProperty,"media",value);}; + var ping = function (value) { return A2(stringProperty,"ping",value);}; + var rel = function (value) { return A2(stringProperty,"rel",value);}; + var datetime = function (value) { return A2(stringProperty,"datetime",value);}; + var pubdate = function (value) { return A2(stringProperty,"pubdate",value);}; + var start = function (n) { return A2(stringProperty,"start",$Basics.toString(n));}; + var colspan = function (n) { return A2(stringProperty,"colSpan",$Basics.toString(n));}; + var headers = function (value) { return A2(stringProperty,"headers",value);}; + var rowspan = function (n) { return A2(stringProperty,"rowSpan",$Basics.toString(n));}; + var scope = function (value) { return A2(stringProperty,"scope",value);}; + var manifest = function (value) { return A2(stringProperty,"manifest",value);}; + var boolProperty = F2(function (name,bool) { return A2(property,name,$Json$Encode.bool(bool));}); + var hidden = function (bool) { return A2(boolProperty,"hidden",bool);}; + var contenteditable = function (bool) { return A2(boolProperty,"contentEditable",bool);}; + var spellcheck = function (bool) { return A2(boolProperty,"spellcheck",bool);}; + var async = function (bool) { return A2(boolProperty,"async",bool);}; + var defer = function (bool) { return A2(boolProperty,"defer",bool);}; + var scoped = function (bool) { return A2(boolProperty,"scoped",bool);}; + var autoplay = function (bool) { return A2(boolProperty,"autoplay",bool);}; + var controls = function (bool) { return A2(boolProperty,"controls",bool);}; + var loop = function (bool) { return A2(boolProperty,"loop",bool);}; + var $default = function (bool) { return A2(boolProperty,"default",bool);}; + var seamless = function (bool) { return A2(boolProperty,"seamless",bool);}; + var checked = function (bool) { return A2(boolProperty,"checked",bool);}; + var selected = function (bool) { return A2(boolProperty,"selected",bool);}; + var autofocus = function (bool) { return A2(boolProperty,"autofocus",bool);}; + var disabled = function (bool) { return A2(boolProperty,"disabled",bool);}; + var multiple = function (bool) { return A2(boolProperty,"multiple",bool);}; + var novalidate = function (bool) { return A2(boolProperty,"noValidate",bool);}; + var readonly = function (bool) { return A2(boolProperty,"readOnly",bool);}; + var required = function (bool) { return A2(boolProperty,"required",bool);}; + var ismap = function (value) { return A2(boolProperty,"isMap",value);}; + var download = function (bool) { return A2(boolProperty,"download",bool);}; + var reversed = function (bool) { return A2(boolProperty,"reversed",bool);}; + var classList = function (list) { return $class(A2($String.join," ",A2($List.map,$Basics.fst,A2($List.filter,$Basics.snd,list))));}; + var style = function (props) { + return A2(property, + "style", + $Json$Encode.object(A2($List.map,function (_p0) { var _p1 = _p0;return {ctor: "_Tuple2",_0: _p1._0,_1: $Json$Encode.string(_p1._1)};},props))); + }; + var key = function (k) { return A2(stringProperty,"key",k);}; + return _elm.Html.Attributes.values = {_op: _op + ,key: key + ,style: style + ,$class: $class + ,classList: classList + ,id: id + ,title: title + ,hidden: hidden + ,type$: type$ + ,value: value + ,checked: checked + ,placeholder: placeholder + ,selected: selected + ,accept: accept + ,acceptCharset: acceptCharset + ,action: action + ,autocomplete: autocomplete + ,autofocus: autofocus + ,autosave: autosave + ,disabled: disabled + ,enctype: enctype + ,formaction: formaction + ,list: list + ,maxlength: maxlength + ,minlength: minlength + ,method: method + ,multiple: multiple + ,name: name + ,novalidate: novalidate + ,pattern: pattern + ,readonly: readonly + ,required: required + ,size: size + ,$for: $for + ,form: form + ,max: max + ,min: min + ,step: step + ,cols: cols + ,rows: rows + ,wrap: wrap + ,href: href + ,target: target + ,download: download + ,downloadAs: downloadAs + ,hreflang: hreflang + ,media: media + ,ping: ping + ,rel: rel + ,ismap: ismap + ,usemap: usemap + ,shape: shape + ,coords: coords + ,src: src + ,height: height + ,width: width + ,alt: alt + ,autoplay: autoplay + ,controls: controls + ,loop: loop + ,preload: preload + ,poster: poster + ,$default: $default + ,kind: kind + ,srclang: srclang + ,sandbox: sandbox + ,seamless: seamless + ,srcdoc: srcdoc + ,reversed: reversed + ,start: start + ,align: align + ,colspan: colspan + ,rowspan: rowspan + ,headers: headers + ,scope: scope + ,async: async + ,charset: charset + ,content: content + ,defer: defer + ,httpEquiv: httpEquiv + ,language: language + ,scoped: scoped + ,accesskey: accesskey + ,contenteditable: contenteditable + ,contextmenu: contextmenu + ,dir: dir + ,draggable: draggable + ,dropzone: dropzone + ,itemprop: itemprop + ,lang: lang + ,spellcheck: spellcheck + ,tabindex: tabindex + ,challenge: challenge + ,keytype: keytype + ,cite: cite + ,datetime: datetime + ,pubdate: pubdate + ,manifest: manifest + ,property: property + ,attribute: attribute}; +}; +Elm.Html = Elm.Html || {}; +Elm.Html.Events = Elm.Html.Events || {}; +Elm.Html.Events.make = function (_elm) { + "use strict"; + _elm.Html = _elm.Html || {}; + _elm.Html.Events = _elm.Html.Events || {}; + if (_elm.Html.Events.values) return _elm.Html.Events.values; + var _U = Elm.Native.Utils.make(_elm), + $Basics = Elm.Basics.make(_elm), + $Debug = Elm.Debug.make(_elm), + $Html = Elm.Html.make(_elm), + $Json$Decode = Elm.Json.Decode.make(_elm), + $List = Elm.List.make(_elm), + $Maybe = Elm.Maybe.make(_elm), + $Result = Elm.Result.make(_elm), + $Signal = Elm.Signal.make(_elm), + $VirtualDom = Elm.VirtualDom.make(_elm); + var _op = {}; + var keyCode = A2($Json$Decode._op[":="],"keyCode",$Json$Decode.$int); + var targetChecked = A2($Json$Decode.at,_U.list(["target","checked"]),$Json$Decode.bool); + var targetValue = A2($Json$Decode.at,_U.list(["target","value"]),$Json$Decode.string); + var defaultOptions = $VirtualDom.defaultOptions; + var Options = F2(function (a,b) { return {stopPropagation: a,preventDefault: b};}); + var onWithOptions = $VirtualDom.onWithOptions; + var on = $VirtualDom.on; + var messageOn = F3(function (name,addr,msg) { return A3(on,name,$Json$Decode.value,function (_p0) { return A2($Signal.message,addr,msg);});}); + var onClick = messageOn("click"); + var onDoubleClick = messageOn("dblclick"); + var onMouseMove = messageOn("mousemove"); + var onMouseDown = messageOn("mousedown"); + var onMouseUp = messageOn("mouseup"); + var onMouseEnter = messageOn("mouseenter"); + var onMouseLeave = messageOn("mouseleave"); + var onMouseOver = messageOn("mouseover"); + var onMouseOut = messageOn("mouseout"); + var onBlur = messageOn("blur"); + var onFocus = messageOn("focus"); + var onSubmit = messageOn("submit"); + var onKey = F3(function (name,addr,handler) { return A3(on,name,keyCode,function (code) { return A2($Signal.message,addr,handler(code));});}); + var onKeyUp = onKey("keyup"); + var onKeyDown = onKey("keydown"); + var onKeyPress = onKey("keypress"); + return _elm.Html.Events.values = {_op: _op + ,onBlur: onBlur + ,onFocus: onFocus + ,onSubmit: onSubmit + ,onKeyUp: onKeyUp + ,onKeyDown: onKeyDown + ,onKeyPress: onKeyPress + ,onClick: onClick + ,onDoubleClick: onDoubleClick + ,onMouseMove: onMouseMove + ,onMouseDown: onMouseDown + ,onMouseUp: onMouseUp + ,onMouseEnter: onMouseEnter + ,onMouseLeave: onMouseLeave + ,onMouseOver: onMouseOver + ,onMouseOut: onMouseOut + ,on: on + ,onWithOptions: onWithOptions + ,defaultOptions: defaultOptions + ,targetValue: targetValue + ,targetChecked: targetChecked + ,keyCode: keyCode + ,Options: Options}; +}; +Elm.Html = Elm.Html || {}; +Elm.Html.Lazy = Elm.Html.Lazy || {}; +Elm.Html.Lazy.make = function (_elm) { + "use strict"; + _elm.Html = _elm.Html || {}; + _elm.Html.Lazy = _elm.Html.Lazy || {}; + if (_elm.Html.Lazy.values) return _elm.Html.Lazy.values; + var _U = Elm.Native.Utils.make(_elm), + $Basics = Elm.Basics.make(_elm), + $Debug = Elm.Debug.make(_elm), + $Html = Elm.Html.make(_elm), + $List = Elm.List.make(_elm), + $Maybe = Elm.Maybe.make(_elm), + $Result = Elm.Result.make(_elm), + $Signal = Elm.Signal.make(_elm), + $VirtualDom = Elm.VirtualDom.make(_elm); + var _op = {}; + var lazy3 = $VirtualDom.lazy3; + var lazy2 = $VirtualDom.lazy2; + var lazy = $VirtualDom.lazy; + return _elm.Html.Lazy.values = {_op: _op,lazy: lazy,lazy2: lazy2,lazy3: lazy3}; +}; +Elm.Todo = Elm.Todo || {}; +Elm.Todo.make = function (_elm) { + "use strict"; + _elm.Todo = _elm.Todo || {}; + if (_elm.Todo.values) return _elm.Todo.values; + var _U = Elm.Native.Utils.make(_elm), + $Basics = Elm.Basics.make(_elm), + $Debug = Elm.Debug.make(_elm), + $Html = Elm.Html.make(_elm), + $Html$Attributes = Elm.Html.Attributes.make(_elm), + $Html$Events = Elm.Html.Events.make(_elm), + $Html$Lazy = Elm.Html.Lazy.make(_elm), + $Json$Decode = Elm.Json.Decode.make(_elm), + $List = Elm.List.make(_elm), + $Maybe = Elm.Maybe.make(_elm), + $Result = Elm.Result.make(_elm), + $Signal = Elm.Signal.make(_elm), + $String = Elm.String.make(_elm); + var _op = {}; + var infoFooter = A2($Html.footer, + _U.list([$Html$Attributes.$class("info")]), + _U.list([A2($Html.p,_U.list([]),_U.list([$Html.text("Double-click to edit a todo")])) + ,A2($Html.p, + _U.list([]), + _U.list([$Html.text("Written by ") + ,A2($Html.a,_U.list([$Html$Attributes.href("https://github.com/evancz")]),_U.list([$Html.text("Evan Czaplicki")]))])) + ,A2($Html.p, + _U.list([]), + _U.list([$Html.text("Part of "),A2($Html.a,_U.list([$Html$Attributes.href("http://todomvc.com")]),_U.list([$Html.text("TodoMVC")]))]))])); + var is13 = function (code) { return _U.eq(code,13) ? $Result.Ok({ctor: "_Tuple0"}) : $Result.Err("not the right key code");}; + var onEnter = F2(function (address,value) { + return A3($Html$Events.on, + "keydown", + A2($Json$Decode.customDecoder,$Html$Events.keyCode,is13), + function (_p0) { + return A2($Signal.message,address,value); + }); + }); + var ChangeVisibility = function (a) { return {ctor: "ChangeVisibility",_0: a};}; + var visibilitySwap = F4(function (address,uri,visibility,actualVisibility) { + return A2($Html.li, + _U.list([A2($Html$Events.onClick,address,ChangeVisibility(visibility))]), + _U.list([A2($Html.a, + _U.list([$Html$Attributes.href(uri),$Html$Attributes.classList(_U.list([{ctor: "_Tuple2",_0: "selected",_1: _U.eq(visibility,actualVisibility)}]))]), + _U.list([$Html.text(visibility)]))])); + }); + var CheckAll = function (a) { return {ctor: "CheckAll",_0: a};}; + var Check = F2(function (a,b) { return {ctor: "Check",_0: a,_1: b};}); + var DeleteComplete = {ctor: "DeleteComplete"}; + var controls = F3(function (address,visibility,tasks) { + var tasksCompleted = $List.length(A2($List.filter,function (_) { return _.completed;},tasks)); + var tasksLeft = $List.length(tasks) - tasksCompleted; + var item_ = _U.eq(tasksLeft,1) ? " item" : " items"; + return A2($Html.footer, + _U.list([$Html$Attributes.$class("footer"),$Html$Attributes.hidden($List.isEmpty(tasks))]), + _U.list([A2($Html.span, + _U.list([$Html$Attributes.$class("todo-count")]), + _U.list([A2($Html.strong,_U.list([]),_U.list([$Html.text($Basics.toString(tasksLeft))])),$Html.text(A2($Basics._op["++"],item_," left"))])) + ,A2($Html.ul, + _U.list([$Html$Attributes.$class("filters")]), + _U.list([A4(visibilitySwap,address,"#/","All",visibility) + ,$Html.text(" ") + ,A4(visibilitySwap,address,"#/active","Active",visibility) + ,$Html.text(" ") + ,A4(visibilitySwap,address,"#/completed","Completed",visibility)])) + ,A2($Html.button, + _U.list([$Html$Attributes.$class("clear-completed") + ,$Html$Attributes.hidden(_U.eq(tasksCompleted,0)) + ,A2($Html$Events.onClick,address,DeleteComplete)]), + _U.list([$Html.text(A2($Basics._op["++"],"Clear completed (",A2($Basics._op["++"],$Basics.toString(tasksCompleted),")")))]))])); + }); + var Delete = function (a) { return {ctor: "Delete",_0: a};}; + var Add = {ctor: "Add"}; + var UpdateTask = F2(function (a,b) { return {ctor: "UpdateTask",_0: a,_1: b};}); + var EditingTask = F2(function (a,b) { return {ctor: "EditingTask",_0: a,_1: b};}); + var todoItem = F2(function (address,todo) { + return A2($Html.li, + _U.list([$Html$Attributes.classList(_U.list([{ctor: "_Tuple2",_0: "completed",_1: todo.completed},{ctor: "_Tuple2",_0: "editing",_1: todo.editing}])) + ,$Html$Attributes.key($Basics.toString(todo.id))]), + _U.list([A2($Html.div, + _U.list([$Html$Attributes.$class("view")]), + _U.list([A2($Html.input, + _U.list([$Html$Attributes.$class("toggle") + ,$Html$Attributes.type$("checkbox") + ,$Html$Attributes.checked(todo.completed) + ,A2($Html$Events.onClick,address,A2(Check,todo.id,$Basics.not(todo.completed)))]), + _U.list([])) + ,A2($Html.label,_U.list([A2($Html$Events.onDoubleClick,address,A2(EditingTask,todo.id,true))]),_U.list([$Html.text(todo.description)])) + ,A2($Html.button,_U.list([$Html$Attributes.$class("destroy"),A2($Html$Events.onClick,address,Delete(todo.id))]),_U.list([]))])) + ,A2($Html.input, + _U.list([$Html$Attributes.$class("edit") + ,$Html$Attributes.value(todo.description) + ,$Html$Attributes.name("title") + ,$Html$Attributes.id(A2($Basics._op["++"],"todo-",$Basics.toString(todo.id))) + ,A3($Html$Events.on,"input",$Html$Events.targetValue,function (_p1) { return A2($Signal.message,address,A2(UpdateTask,todo.id,_p1));}) + ,A2($Html$Events.onBlur,address,A2(EditingTask,todo.id,false)) + ,A2(onEnter,address,A2(EditingTask,todo.id,false))]), + _U.list([]))])); + }); + var taskList = F3(function (address,visibility,tasks) { + var cssVisibility = $List.isEmpty(tasks) ? "hidden" : "visible"; + var allCompleted = A2($List.all,function (_) { return _.completed;},tasks); + var isVisible = function (todo) { + var _p2 = visibility; + switch (_p2) + {case "Completed": return todo.completed; + case "Active": return $Basics.not(todo.completed); + default: return true;} + }; + return A2($Html.section, + _U.list([$Html$Attributes.$class("main"),$Html$Attributes.style(_U.list([{ctor: "_Tuple2",_0: "visibility",_1: cssVisibility}]))]), + _U.list([A2($Html.input, + _U.list([$Html$Attributes.$class("toggle-all") + ,$Html$Attributes.type$("checkbox") + ,$Html$Attributes.name("toggle") + ,$Html$Attributes.checked(allCompleted) + ,A2($Html$Events.onClick,address,CheckAll($Basics.not(allCompleted)))]), + _U.list([])) + ,A2($Html.label,_U.list([$Html$Attributes.$for("toggle-all")]),_U.list([$Html.text("Mark all as complete")])) + ,A2($Html.ul,_U.list([$Html$Attributes.$class("todo-list")]),A2($List.map,todoItem(address),A2($List.filter,isVisible,tasks)))])); + }); + var UpdateField = function (a) { return {ctor: "UpdateField",_0: a};}; + var taskEntry = F2(function (address,task) { + return A2($Html.header, + _U.list([$Html$Attributes.$class("header")]), + _U.list([A2($Html.h1,_U.list([]),_U.list([$Html.text("todos")])) + ,A2($Html.input, + _U.list([$Html$Attributes.$class("new-todo") + ,$Html$Attributes.placeholder("What needs to be done?") + ,$Html$Attributes.autofocus(true) + ,$Html$Attributes.value(task) + ,$Html$Attributes.name("newTodo") + ,A3($Html$Events.on,"input",$Html$Events.targetValue,function (_p3) { return A2($Signal.message,address,UpdateField(_p3));}) + ,A2(onEnter,address,Add)]), + _U.list([]))])); + }); + var view = F2(function (address,model) { + return A2($Html.div, + _U.list([$Html$Attributes.$class("todomvc-wrapper"),$Html$Attributes.style(_U.list([{ctor: "_Tuple2",_0: "visibility",_1: "hidden"}]))]), + _U.list([A2($Html.section, + _U.list([$Html$Attributes.$class("todoapp")]), + _U.list([A3($Html$Lazy.lazy2,taskEntry,address,model.field) + ,A4($Html$Lazy.lazy3,taskList,address,model.visibility,model.tasks) + ,A4($Html$Lazy.lazy3,controls,address,model.visibility,model.tasks)])) + ,infoFooter])); + }); + var NoOp = {ctor: "NoOp"}; + var actions = $Signal.mailbox(NoOp); + var focus = Elm.Native.Port.make(_elm).outboundSignal("focus", + function (v) { + return v; + }, + function () { + var toSelector = function (act) { + var _p4 = act; + if (_p4.ctor === "EditingTask") { + return A2($Basics._op["++"],"#todo-",$Basics.toString(_p4._0)); + } else { + return ""; + } + }; + var needsFocus = function (act) { var _p5 = act;if (_p5.ctor === "EditingTask") { return _p5._1;} else { return false;}}; + return A2($Signal.map,toSelector,A3($Signal.filter,needsFocus,A2(EditingTask,0,true),actions.signal)); + }()); + var emptyModel = {tasks: _U.list([]),visibility: "All",field: "",uid: 0}; + var newTask = F2(function (desc,id) { return {description: desc,completed: false,editing: false,id: id};}); + var update = F2(function (action,model) { + var _p6 = action; + switch (_p6.ctor) + {case "NoOp": return model; + case "Add": return _U.update(model, + {uid: model.uid + 1 + ,field: "" + ,tasks: $String.isEmpty(model.field) ? model.tasks : A2($Basics._op["++"],model.tasks,_U.list([A2(newTask,model.field,model.uid)]))}); + case "UpdateField": return _U.update(model,{field: _p6._0}); + case "EditingTask": var updateTask = function (t) { return _U.eq(t.id,_p6._0) ? _U.update(t,{editing: _p6._1}) : t;}; + return _U.update(model,{tasks: A2($List.map,updateTask,model.tasks)}); + case "UpdateTask": var updateTask = function (t) { return _U.eq(t.id,_p6._0) ? _U.update(t,{description: _p6._1}) : t;}; + return _U.update(model,{tasks: A2($List.map,updateTask,model.tasks)}); + case "Delete": return _U.update(model,{tasks: A2($List.filter,function (t) { return !_U.eq(t.id,_p6._0);},model.tasks)}); + case "DeleteComplete": return _U.update(model, + {tasks: A2($List.filter,function (_p7) { return $Basics.not(function (_) { return _.completed;}(_p7));},model.tasks)}); + case "Check": var updateTask = function (t) { return _U.eq(t.id,_p6._0) ? _U.update(t,{completed: _p6._1}) : t;}; + return _U.update(model,{tasks: A2($List.map,updateTask,model.tasks)}); + case "CheckAll": var updateTask = function (t) { return _U.update(t,{completed: _p6._0});}; + return _U.update(model,{tasks: A2($List.map,updateTask,model.tasks)}); + default: return _U.update(model,{visibility: _p6._0});} + }); + var model = A3($Signal.foldp,update,emptyModel,actions.signal); + var main = A2($Signal.map,view(actions.address),model); + var Task = F4(function (a,b,c,d) { return {description: a,completed: b,editing: c,id: d};}); + var Model = F4(function (a,b,c,d) { return {tasks: a,field: b,uid: c,visibility: d};}); + return _elm.Todo.values = {_op: _op + ,Model: Model + ,Task: Task + ,newTask: newTask + ,emptyModel: emptyModel + ,NoOp: NoOp + ,UpdateField: UpdateField + ,EditingTask: EditingTask + ,UpdateTask: UpdateTask + ,Add: Add + ,Delete: Delete + ,DeleteComplete: DeleteComplete + ,Check: Check + ,CheckAll: CheckAll + ,ChangeVisibility: ChangeVisibility + ,update: update + ,view: view + ,onEnter: onEnter + ,is13: is13 + ,taskEntry: taskEntry + ,taskList: taskList + ,todoItem: todoItem + ,controls: controls + ,visibilitySwap: visibilitySwap + ,infoFooter: infoFooter + ,main: main + ,model: model + ,actions: actions}; +}; diff --git a/bench/implementations/elm-0.16-optimized/index.html b/bench/implementations/elm-0.16-optimized/index.html new file mode 100644 index 0000000..c9f689d --- /dev/null +++ b/bench/implementations/elm-0.16-optimized/index.html @@ -0,0 +1,26 @@ + + + + + + Elm • TodoMVC + + + + + + + + + + diff --git a/bench/implementations/elm-0.16-optimized/style.css b/bench/implementations/elm-0.16-optimized/style.css new file mode 100644 index 0000000..fc2e67b --- /dev/null +++ b/bench/implementations/elm-0.16-optimized/style.css @@ -0,0 +1,382 @@ +html, +body { + margin: 0; + padding: 0; +} + +.todomvc-wrapper { + visibility: visible !important; +} + +button { + margin: 0; + padding: 0; + border: 0; + background: none; + font-size: 100%; + vertical-align: baseline; + font-family: inherit; + font-weight: inherit; + color: inherit; + -webkit-appearance: none; + appearance: none; + -webkit-font-smoothing: antialiased; + -moz-font-smoothing: antialiased; + font-smoothing: antialiased; +} + +body { + font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif; + line-height: 1.4em; + background: #f5f5f5; + color: #4d4d4d; + min-width: 230px; + max-width: 550px; + margin: 0 auto; + -webkit-font-smoothing: antialiased; + -moz-font-smoothing: antialiased; + font-smoothing: antialiased; + font-weight: 300; +} + +button, +input[type="checkbox"] { + outline: none; +} + +.hidden { + display: none; +} + +.todoapp { + background: #fff; + margin: 130px 0 40px 0; + position: relative; + box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), + 0 25px 50px 0 rgba(0, 0, 0, 0.1); +} + +.todoapp input::-webkit-input-placeholder { + font-style: italic; + font-weight: 300; + color: #e6e6e6; +} + +.todoapp input::-moz-placeholder { + font-style: italic; + font-weight: 300; + color: #e6e6e6; +} + +.todoapp input::input-placeholder { + font-style: italic; + font-weight: 300; + color: #e6e6e6; +} + +.todoapp h1 { + position: absolute; + top: -155px; + width: 100%; + font-size: 100px; + font-weight: 100; + text-align: center; + color: rgba(175, 47, 47, 0.15); + -webkit-text-rendering: optimizeLegibility; + -moz-text-rendering: optimizeLegibility; + text-rendering: optimizeLegibility; +} + +.new-todo, +.edit { + position: relative; + margin: 0; + width: 100%; + font-size: 24px; + font-family: inherit; + font-weight: 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); + box-sizing: border-box; + -webkit-font-smoothing: antialiased; + -moz-font-smoothing: antialiased; + font-smoothing: antialiased; +} + +.new-todo { + padding: 16px 16px 16px 60px; + border: none; + background: rgba(0, 0, 0, 0.003); + box-shadow: inset 0 -2px 1px rgba(0,0,0,0.03); +} + +.main { + position: relative; + z-index: 2; + border-top: 1px solid #e6e6e6; +} + +label[for='toggle-all'] { + display: none; +} + +.toggle-all { + position: absolute; + top: -55px; + left: -12px; + width: 60px; + height: 34px; + text-align: center; + border: none; /* Mobile Safari */ +} + +.toggle-all:before { + content: '❯'; + font-size: 22px; + color: #e6e6e6; + padding: 10px 27px 10px 27px; +} + +.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 solid #ededed; +} + +.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; + appearance: none; +} + +.todo-list li .toggle:after { + content: url('data:image/svg+xml;utf8,'); +} + +.todo-list li .toggle:checked:after { + content: url('data:image/svg+xml;utf8,'); +} + +.todo-list li label { + white-space: pre-line; + word-break: break-all; + padding: 15px 60px 15px 15px; + margin-left: 45px; + display: block; + line-height: 1.2; + transition: color 0.4s; +} + +.todo-list li.completed label { + color: #d9d9d9; + 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: 30px; + color: #cc9a9a; + margin-bottom: 11px; + transition: color 0.2s ease-out; +} + +.todo-list li .destroy:hover { + color: #af5b5e; +} + +.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: 10px 15px; + height: 20px; + text-align: center; + border-top: 1px solid #e6e6e6; +} + +.footer:before { + content: ''; + position: absolute; + right: 0; + bottom: 0; + left: 0; + height: 50px; + overflow: hidden; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), + 0 8px 0 -3px #f6f6f6, + 0 9px 1px -3px rgba(0, 0, 0, 0.2), + 0 16px 0 -6px #f6f6f6, + 0 17px 2px -6px rgba(0, 0, 0, 0.2); +} + +.todo-count { + float: left; + text-align: left; +} + +.todo-count strong { + font-weight: 300; +} + +.filters { + margin: 0; + padding: 0; + list-style: none; + position: absolute; + right: 0; + left: 0; +} + +.filters li { + display: inline; +} + +.filters li a { + color: inherit; + margin: 3px; + padding: 3px 7px; + text-decoration: none; + border: 1px solid transparent; + border-radius: 3px; +} + +.filters li a.selected, +.filters li a:hover { + border-color: rgba(175, 47, 47, 0.1); +} + +.filters li a.selected { + border-color: rgba(175, 47, 47, 0.2); +} + +.clear-completed, +html .clear-completed:active { + float: right; + position: relative; + line-height: 20px; + text-decoration: none; + cursor: pointer; + position: relative; +} + +.clear-completed:hover { + text-decoration: underline; +} + +.info { + margin: 65px auto 0; + color: #bfbfbf; + font-size: 10px; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + text-align: center; +} + +.info p { + line-height: 1; +} + +.info a { + color: inherit; + text-decoration: none; + font-weight: 400; +} + +.info a:hover { + text-decoration: underline; +} + +/* + Hack to remove background from Mobile Safari. + Can't use it globally since it destroys checkboxes in Firefox +*/ +@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 { + -webkit-transform: rotate(90deg); + transform: rotate(90deg); + -webkit-appearance: none; + appearance: none; + } +} + +@media (max-width: 430px) { + .footer { + height: 50px; + } + + .filters { + bottom: 10px; + } +} \ No newline at end of file diff --git a/bench/implementations/elm-0.16/Todo.elm b/bench/implementations/elm-0.16/Todo.elm new file mode 100644 index 0000000..6e6fb76 --- /dev/null +++ b/bench/implementations/elm-0.16/Todo.elm @@ -0,0 +1,336 @@ +module Todo where +{-| TodoMVC implemented in Elm, using plain HTML and CSS for rendering. + +This application is broken up into four distinct parts: + + 1. Model - a full definition of the application's state + 2. Update - a way to step the application state forward + 3. View - a way to visualize our application state with HTML + 4. Inputs - the signals necessary to manage events + +This clean division of concerns is a core part of Elm. You can read more about +this in the Pong tutorial: http://elm-lang.org/blog/making-pong + +This program is not particularly large, so definitely see the following +for notes on structuring more complex GUIs with Elm: +https://github.com/evancz/elm-architecture-tutorial/ +-} + +import Html exposing (..) +import Html.Attributes exposing (..) +import Html.Events exposing (..) +import Json.Decode as Json +import Signal exposing (Signal, Address) +import String +import Window + + +---- MODEL ---- + +-- The full application state of our todo app. +type alias Model = + { tasks : List Task + , field : String + , uid : Int + , visibility : String + } + + +type alias Task = + { description : String + , completed : Bool + , editing : Bool + , id : Int + } + + +newTask : String -> Int -> Task +newTask desc id = + { description = desc + , completed = False + , editing = False + , id = id + } + + +emptyModel : Model +emptyModel = + { tasks = [] + , visibility = "All" + , field = "" + , uid = 0 + } + + +---- UPDATE ---- + +-- A description of the kinds of actions that can be performed on the model of +-- our application. See the following for more info on this pattern and +-- some alternatives: https://github.com/evancz/elm-architecture-tutorial/ +type Action + = NoOp + | UpdateField String + | EditingTask Int Bool + | UpdateTask Int String + | Add + | Delete Int + | DeleteComplete + | Check Int Bool + | CheckAll Bool + | ChangeVisibility String + + +-- How we update our Model on a given Action? +update : Action -> Model -> Model +update action model = + case action of + NoOp -> model + + Add -> + { model | + uid = model.uid + 1, + field = "", + tasks = + if String.isEmpty model.field + then model.tasks + else model.tasks ++ [newTask model.field model.uid] + } + + UpdateField str -> + { model | field = str } + + EditingTask id isEditing -> + let updateTask t = if t.id == id then { t | editing = isEditing } else t + in + { model | tasks = List.map updateTask model.tasks } + + UpdateTask id task -> + let updateTask t = if t.id == id then { t | description = task } else t + in + { model | tasks = List.map updateTask model.tasks } + + Delete id -> + { model | tasks = List.filter (\t -> t.id /= id) model.tasks } + + DeleteComplete -> + { model | tasks = List.filter (not << .completed) model.tasks } + + Check id isCompleted -> + let updateTask t = if t.id == id then { t | completed = isCompleted } else t + in + { model | tasks = List.map updateTask model.tasks } + + CheckAll isCompleted -> + let updateTask t = { t | completed = isCompleted } + in + { model | tasks = List.map updateTask model.tasks } + + ChangeVisibility visibility -> + { model | visibility = visibility } + + +---- VIEW ---- + +view : Address Action -> Model -> Html +view address model = + div + [ class "todomvc-wrapper" + , style [ ("visibility", "hidden") ] + ] + [ section + [ class "todoapp" ] + [ taskEntry address model.field + , taskList address model.visibility model.tasks + , controls address model.visibility model.tasks + ] + , infoFooter + ] + + +onEnter : Address a -> a -> Attribute +onEnter address value = + on "keydown" + (Json.customDecoder keyCode is13) + (\_ -> Signal.message address value) + + +is13 : Int -> Result String () +is13 code = + if code == 13 then Ok () else Err "not the right key code" + + +taskEntry : Address Action -> String -> Html +taskEntry address task = + header + [ class "header" ] + [ h1 [] [ text "todos" ] + , input + [ class "new-todo" + , placeholder "What needs to be done?" + , autofocus True + , value task + , name "newTodo" + , on "input" targetValue (Signal.message address << UpdateField) + , onEnter address Add + ] + [] + ] + + +taskList : Address Action -> String -> List Task -> Html +taskList address visibility tasks = + let isVisible todo = + case visibility of + "Completed" -> todo.completed + "Active" -> not todo.completed + _ -> True + + allCompleted = List.all .completed tasks + + cssVisibility = if List.isEmpty tasks then "hidden" else "visible" + in + section + [ class "main" + , style [ ("visibility", cssVisibility) ] + ] + [ input + [ class "toggle-all" + , type' "checkbox" + , name "toggle" + , checked allCompleted + , onClick address (CheckAll (not allCompleted)) + ] + [] + , label + [ for "toggle-all" ] + [ text "Mark all as complete" ] + , ul + [ class "todo-list" ] + (List.map (todoItem address) (List.filter isVisible tasks)) + ] + + +todoItem : Address Action -> Task -> Html +todoItem address todo = + li + [ classList [ ("completed", todo.completed), ("editing", todo.editing) ] ] + [ div + [ class "view" ] + [ input + [ class "toggle" + , type' "checkbox" + , checked todo.completed + , onClick address (Check todo.id (not todo.completed)) + ] + [] + , label + [ onDoubleClick address (EditingTask todo.id True) ] + [ text todo.description ] + , button + [ class "destroy" + , onClick address (Delete todo.id) + ] + [] + ] + , input + [ class "edit" + , value todo.description + , name "title" + , id ("todo-" ++ toString todo.id) + , on "input" targetValue (Signal.message address << UpdateTask todo.id) + , onBlur address (EditingTask todo.id False) + , onEnter address (EditingTask todo.id False) + ] + [] + ] + + +controls : Address Action -> String -> List Task -> Html +controls address visibility tasks = + let tasksCompleted = List.length (List.filter .completed tasks) + tasksLeft = List.length tasks - tasksCompleted + item_ = if tasksLeft == 1 then " item" else " items" + in + footer + [ class "footer" + , hidden (List.isEmpty tasks) + ] + [ span + [ class "todo-count" ] + [ strong [] [ text (toString tasksLeft) ] + , text (item_ ++ " left") + ] + , ul + [ class "filters" ] + [ visibilitySwap address "#/" "All" visibility + , text " " + , visibilitySwap address "#/active" "Active" visibility + , text " " + , visibilitySwap address "#/completed" "Completed" visibility + ] + , button + [ class "clear-completed" + , hidden (tasksCompleted == 0) + , onClick address DeleteComplete + ] + [ text ("Clear completed (" ++ toString tasksCompleted ++ ")") ] + ] + + +visibilitySwap : Address Action -> String -> String -> String -> Html +visibilitySwap address uri visibility actualVisibility = + li + [ onClick address (ChangeVisibility visibility) ] + [ a [ href uri, classList [("selected", visibility == actualVisibility)] ] [ text visibility ] ] + + +infoFooter : Html +infoFooter = + footer [ class "info" ] + [ p [] [ text "Double-click to edit a todo" ] + , p [] + [ text "Written by " + , a [ href "https://github.com/evancz" ] [ text "Evan Czaplicki" ] + ] + , p [] + [ text "Part of " + , a [ href "http://todomvc.com" ] [ text "TodoMVC" ] + ] + ] + + +---- INPUTS ---- + +-- wire the entire application together +main : Signal Html +main = + Signal.map (view actions.address) model + + +-- manage the model of our application over time +model : Signal Model +model = + Signal.foldp update emptyModel actions.signal + + +-- actions from user input +actions : Signal.Mailbox Action +actions = + Signal.mailbox NoOp + + +port focus : Signal String +port focus = + let needsFocus act = + case act of + EditingTask id bool -> bool + _ -> False + + toSelector act = + case act of + EditingTask id _ -> "#todo-" ++ toString id + _ -> "" + in + actions.signal + |> Signal.filter needsFocus (EditingTask 0 True) + |> Signal.map toSelector diff --git a/bench/implementations/elm-0.16/elm-package.json b/bench/implementations/elm-0.16/elm-package.json new file mode 100644 index 0000000..0c8a4c4 --- /dev/null +++ b/bench/implementations/elm-0.16/elm-package.json @@ -0,0 +1,15 @@ +{ + "version": "1.0.0", + "summary": "TodoMVC created with Elm and elm-html", + "repository": "https://github.com/evancz/elm-todomvc.git", + "license": "BSD3", + "source-directories": [ + "." + ], + "exposed-modules": [], + "dependencies": { + "elm-lang/core": "3.0.0 <= v < 4.0.0", + "evancz/elm-html": "4.0.2 <= v < 5.0.0" + }, + "elm-version": "0.16.0 <= v < 0.17.0" +} diff --git a/bench/implementations/elm-0.16/elm.js b/bench/implementations/elm-0.16/elm.js new file mode 100644 index 0000000..04532ee --- /dev/null +++ b/bench/implementations/elm-0.16/elm.js @@ -0,0 +1,10534 @@ +var Elm = Elm || { Native: {} }; +Elm.Native.Array = {}; +Elm.Native.Array.make = function(localRuntime) { + + localRuntime.Native = localRuntime.Native || {}; + localRuntime.Native.Array = localRuntime.Native.Array || {}; + if (localRuntime.Native.Array.values) + { + return localRuntime.Native.Array.values; + } + if ('values' in Elm.Native.Array) + { + return localRuntime.Native.Array.values = Elm.Native.Array.values; + } + + var List = Elm.Native.List.make(localRuntime); + + // A RRB-Tree has two distinct data types. + // Leaf -> "height" is always 0 + // "table" is an array of elements + // Node -> "height" is always greater than 0 + // "table" is an array of child nodes + // "lengths" is an array of accumulated lengths of the child nodes + + // M is the maximal table size. 32 seems fast. E is the allowed increase + // of search steps when concatting to find an index. Lower values will + // decrease balancing, but will increase search steps. + var M = 32; + var E = 2; + + // An empty array. + var empty = { + ctor: '_Array', + height: 0, + table: [] + }; + + + function get(i, array) + { + if (i < 0 || i >= length(array)) + { + throw new Error( + 'Index ' + i + ' is out of range. Check the length of ' + + 'your array first or use getMaybe or getWithDefault.'); + } + return unsafeGet(i, array); + } + + + function unsafeGet(i, array) + { + for (var x = array.height; x > 0; x--) + { + var slot = i >> (x * 5); + while (array.lengths[slot] <= i) + { + slot++; + } + if (slot > 0) + { + i -= array.lengths[slot - 1]; + } + array = array.table[slot]; + } + return array.table[i]; + } + + + // Sets the value at the index i. Only the nodes leading to i will get + // copied and updated. + function set(i, item, array) + { + if (i < 0 || length(array) <= i) + { + return array; + } + return unsafeSet(i, item, array); + } + + + function unsafeSet(i, item, array) + { + array = nodeCopy(array); + + if (array.height === 0) + { + array.table[i] = item; + } + else + { + var slot = getSlot(i, array); + if (slot > 0) + { + i -= array.lengths[slot - 1]; + } + array.table[slot] = unsafeSet(i, item, array.table[slot]); + } + return array; + } + + + function initialize(len, f) + { + if (len <= 0) + { + return empty; + } + var h = Math.floor( Math.log(len) / Math.log(M) ); + return initialize_(f, h, 0, len); + } + + function initialize_(f, h, from, to) + { + if (h === 0) + { + var table = new Array((to - from) % (M + 1)); + for (var i = 0; i < table.length; i++) + { + table[i] = f(from + i); + } + return { + ctor: '_Array', + height: 0, + table: table + }; + } + + var step = Math.pow(M, h); + var table = new Array(Math.ceil((to - from) / step)); + var lengths = new Array(table.length); + for (var i = 0; i < table.length; i++) + { + table[i] = initialize_(f, h - 1, from + (i * step), Math.min(from + ((i + 1) * step), to)); + lengths[i] = length(table[i]) + (i > 0 ? lengths[i-1] : 0); + } + return { + ctor: '_Array', + height: h, + table: table, + lengths: lengths + }; + } + + function fromList(list) + { + if (list === List.Nil) + { + return empty; + } + + // Allocate M sized blocks (table) and write list elements to it. + var table = new Array(M); + var nodes = []; + var i = 0; + + while (list.ctor !== '[]') + { + table[i] = list._0; + list = list._1; + i++; + + // table is full, so we can push a leaf containing it into the + // next node. + if (i === M) + { + var leaf = { + ctor: '_Array', + height: 0, + table: table + }; + fromListPush(leaf, nodes); + table = new Array(M); + i = 0; + } + } + + // Maybe there is something left on the table. + if (i > 0) + { + var leaf = { + ctor: '_Array', + height: 0, + table: table.splice(0, i) + }; + fromListPush(leaf, nodes); + } + + // Go through all of the nodes and eventually push them into higher nodes. + for (var h = 0; h < nodes.length - 1; h++) + { + if (nodes[h].table.length > 0) + { + fromListPush(nodes[h], nodes); + } + } + + var head = nodes[nodes.length - 1]; + if (head.height > 0 && head.table.length === 1) + { + return head.table[0]; + } + else + { + return head; + } + } + + // Push a node into a higher node as a child. + function fromListPush(toPush, nodes) + { + var h = toPush.height; + + // Maybe the node on this height does not exist. + if (nodes.length === h) + { + var node = { + ctor: '_Array', + height: h + 1, + table: [], + lengths: [] + }; + nodes.push(node); + } + + nodes[h].table.push(toPush); + var len = length(toPush); + if (nodes[h].lengths.length > 0) + { + len += nodes[h].lengths[nodes[h].lengths.length - 1]; + } + nodes[h].lengths.push(len); + + if (nodes[h].table.length === M) + { + fromListPush(nodes[h], nodes); + nodes[h] = { + ctor: '_Array', + height: h + 1, + table: [], + lengths: [] + }; + } + } + + // Pushes an item via push_ to the bottom right of a tree. + function push(item, a) + { + var pushed = push_(item, a); + if (pushed !== null) + { + return pushed; + } + + var newTree = create(item, a.height); + return siblise(a, newTree); + } + + // Recursively tries to push an item to the bottom-right most + // tree possible. If there is no space left for the item, + // null will be returned. + function push_(item, a) + { + // Handle resursion stop at leaf level. + if (a.height === 0) + { + if (a.table.length < M) + { + var newA = { + ctor: '_Array', + height: 0, + table: a.table.slice() + }; + newA.table.push(item); + return newA; + } + else + { + return null; + } + } + + // Recursively push + var pushed = push_(item, botRight(a)); + + // There was space in the bottom right tree, so the slot will + // be updated. + if (pushed !== null) + { + var newA = nodeCopy(a); + newA.table[newA.table.length - 1] = pushed; + newA.lengths[newA.lengths.length - 1]++; + return newA; + } + + // When there was no space left, check if there is space left + // for a new slot with a tree which contains only the item + // at the bottom. + if (a.table.length < M) + { + var newSlot = create(item, a.height - 1); + var newA = nodeCopy(a); + newA.table.push(newSlot); + newA.lengths.push(newA.lengths[newA.lengths.length - 1] + length(newSlot)); + return newA; + } + else + { + return null; + } + } + + // Converts an array into a list of elements. + function toList(a) + { + return toList_(List.Nil, a); + } + + function toList_(list, a) + { + for (var i = a.table.length - 1; i >= 0; i--) + { + list = + a.height === 0 + ? List.Cons(a.table[i], list) + : toList_(list, a.table[i]); + } + return list; + } + + // Maps a function over the elements of an array. + function map(f, a) + { + var newA = { + ctor: '_Array', + height: a.height, + table: new Array(a.table.length) + }; + if (a.height > 0) + { + newA.lengths = a.lengths; + } + for (var i = 0; i < a.table.length; i++) + { + newA.table[i] = + a.height === 0 + ? f(a.table[i]) + : map(f, a.table[i]); + } + return newA; + } + + // Maps a function over the elements with their index as first argument. + function indexedMap(f, a) + { + return indexedMap_(f, a, 0); + } + + function indexedMap_(f, a, from) + { + var newA = { + ctor: '_Array', + height: a.height, + table: new Array(a.table.length) + }; + if (a.height > 0) + { + newA.lengths = a.lengths; + } + for (var i = 0; i < a.table.length; i++) + { + newA.table[i] = + a.height === 0 + ? A2(f, from + i, a.table[i]) + : indexedMap_(f, a.table[i], i == 0 ? from : from + a.lengths[i - 1]); + } + return newA; + } + + function foldl(f, b, a) + { + if (a.height === 0) + { + for (var i = 0; i < a.table.length; i++) + { + b = A2(f, a.table[i], b); + } + } + else + { + for (var i = 0; i < a.table.length; i++) + { + b = foldl(f, b, a.table[i]); + } + } + return b; + } + + function foldr(f, b, a) + { + if (a.height === 0) + { + for (var i = a.table.length; i--; ) + { + b = A2(f, a.table[i], b); + } + } + else + { + for (var i = a.table.length; i--; ) + { + b = foldr(f, b, a.table[i]); + } + } + return b; + } + + // TODO: currently, it slices the right, then the left. This can be + // optimized. + function slice(from, to, a) + { + if (from < 0) + { + from += length(a); + } + if (to < 0) + { + to += length(a); + } + return sliceLeft(from, sliceRight(to, a)); + } + + function sliceRight(to, a) + { + if (to === length(a)) + { + return a; + } + + // Handle leaf level. + if (a.height === 0) + { + var newA = { ctor:'_Array', height:0 }; + newA.table = a.table.slice(0, to); + return newA; + } + + // Slice the right recursively. + var right = getSlot(to, a); + var sliced = sliceRight(to - (right > 0 ? a.lengths[right - 1] : 0), a.table[right]); + + // Maybe the a node is not even needed, as sliced contains the whole slice. + if (right === 0) + { + return sliced; + } + + // Create new node. + var newA = { + ctor: '_Array', + height: a.height, + table: a.table.slice(0, right), + lengths: a.lengths.slice(0, right) + }; + if (sliced.table.length > 0) + { + newA.table[right] = sliced; + newA.lengths[right] = length(sliced) + (right > 0 ? newA.lengths[right - 1] : 0); + } + return newA; + } + + function sliceLeft(from, a) + { + if (from === 0) + { + return a; + } + + // Handle leaf level. + if (a.height === 0) + { + var newA = { ctor:'_Array', height:0 }; + newA.table = a.table.slice(from, a.table.length + 1); + return newA; + } + + // Slice the left recursively. + var left = getSlot(from, a); + var sliced = sliceLeft(from - (left > 0 ? a.lengths[left - 1] : 0), a.table[left]); + + // Maybe the a node is not even needed, as sliced contains the whole slice. + if (left === a.table.length - 1) + { + return sliced; + } + + // Create new node. + var newA = { + ctor: '_Array', + height: a.height, + table: a.table.slice(left, a.table.length + 1), + lengths: new Array(a.table.length - left) + }; + newA.table[0] = sliced; + var len = 0; + for (var i = 0; i < newA.table.length; i++) + { + len += length(newA.table[i]); + newA.lengths[i] = len; + } + + return newA; + } + + // Appends two trees. + function append(a,b) + { + if (a.table.length === 0) + { + return b; + } + if (b.table.length === 0) + { + return a; + } + + var c = append_(a, b); + + // Check if both nodes can be crunshed together. + if (c[0].table.length + c[1].table.length <= M) + { + if (c[0].table.length === 0) + { + return c[1]; + } + if (c[1].table.length === 0) + { + return c[0]; + } + + // Adjust .table and .lengths + c[0].table = c[0].table.concat(c[1].table); + if (c[0].height > 0) + { + var len = length(c[0]); + for (var i = 0; i < c[1].lengths.length; i++) + { + c[1].lengths[i] += len; + } + c[0].lengths = c[0].lengths.concat(c[1].lengths); + } + + return c[0]; + } + + if (c[0].height > 0) + { + var toRemove = calcToRemove(a, b); + if (toRemove > E) + { + c = shuffle(c[0], c[1], toRemove); + } + } + + return siblise(c[0], c[1]); + } + + // Returns an array of two nodes; right and left. One node _may_ be empty. + function append_(a, b) + { + if (a.height === 0 && b.height === 0) + { + return [a, b]; + } + + if (a.height !== 1 || b.height !== 1) + { + if (a.height === b.height) + { + a = nodeCopy(a); + b = nodeCopy(b); + var appended = append_(botRight(a), botLeft(b)); + + insertRight(a, appended[1]); + insertLeft(b, appended[0]); + } + else if (a.height > b.height) + { + a = nodeCopy(a); + var appended = append_(botRight(a), b); + + insertRight(a, appended[0]); + b = parentise(appended[1], appended[1].height + 1); + } + else + { + b = nodeCopy(b); + var appended = append_(a, botLeft(b)); + + var left = appended[0].table.length === 0 ? 0 : 1; + var right = left === 0 ? 1 : 0; + insertLeft(b, appended[left]); + a = parentise(appended[right], appended[right].height + 1); + } + } + + // Check if balancing is needed and return based on that. + if (a.table.length === 0 || b.table.length === 0) + { + return [a, b]; + } + + var toRemove = calcToRemove(a, b); + if (toRemove <= E) + { + return [a, b]; + } + return shuffle(a, b, toRemove); + } + + // Helperfunctions for append_. Replaces a child node at the side of the parent. + function insertRight(parent, node) + { + var index = parent.table.length - 1; + parent.table[index] = node; + parent.lengths[index] = length(node); + parent.lengths[index] += index > 0 ? parent.lengths[index - 1] : 0; + } + + function insertLeft(parent, node) + { + if (node.table.length > 0) + { + parent.table[0] = node; + parent.lengths[0] = length(node); + + var len = length(parent.table[0]); + for (var i = 1; i < parent.lengths.length; i++) + { + len += length(parent.table[i]); + parent.lengths[i] = len; + } + } + else + { + parent.table.shift(); + for (var i = 1; i < parent.lengths.length; i++) + { + parent.lengths[i] = parent.lengths[i] - parent.lengths[0]; + } + parent.lengths.shift(); + } + } + + // Returns the extra search steps for E. Refer to the paper. + function calcToRemove(a, b) + { + var subLengths = 0; + for (var i = 0; i < a.table.length; i++) + { + subLengths += a.table[i].table.length; + } + for (var i = 0; i < b.table.length; i++) + { + subLengths += b.table[i].table.length; + } + + var toRemove = a.table.length + b.table.length; + return toRemove - (Math.floor((subLengths - 1) / M) + 1); + } + + // get2, set2 and saveSlot are helpers for accessing elements over two arrays. + function get2(a, b, index) + { + return index < a.length + ? a[index] + : b[index - a.length]; + } + + function set2(a, b, index, value) + { + if (index < a.length) + { + a[index] = value; + } + else + { + b[index - a.length] = value; + } + } + + function saveSlot(a, b, index, slot) + { + set2(a.table, b.table, index, slot); + + var l = (index === 0 || index === a.lengths.length) + ? 0 + : get2(a.lengths, a.lengths, index - 1); + + set2(a.lengths, b.lengths, index, l + length(slot)); + } + + // Creates a node or leaf with a given length at their arrays for perfomance. + // Is only used by shuffle. + function createNode(h, length) + { + if (length < 0) + { + length = 0; + } + var a = { + ctor: '_Array', + height: h, + table: new Array(length) + }; + if (h > 0) + { + a.lengths = new Array(length); + } + return a; + } + + // Returns an array of two balanced nodes. + function shuffle(a, b, toRemove) + { + var newA = createNode(a.height, Math.min(M, a.table.length + b.table.length - toRemove)); + var newB = createNode(a.height, newA.table.length - (a.table.length + b.table.length - toRemove)); + + // Skip the slots with size M. More precise: copy the slot references + // to the new node + var read = 0; + while (get2(a.table, b.table, read).table.length % M === 0) + { + set2(newA.table, newB.table, read, get2(a.table, b.table, read)); + set2(newA.lengths, newB.lengths, read, get2(a.lengths, b.lengths, read)); + read++; + } + + // Pulling items from left to right, caching in a slot before writing + // it into the new nodes. + var write = read; + var slot = new createNode(a.height - 1, 0); + var from = 0; + + // If the current slot is still containing data, then there will be at + // least one more write, so we do not break this loop yet. + while (read - write - (slot.table.length > 0 ? 1 : 0) < toRemove) + { + // Find out the max possible items for copying. + var source = get2(a.table, b.table, read); + var to = Math.min(M - slot.table.length, source.table.length); + + // Copy and adjust size table. + slot.table = slot.table.concat(source.table.slice(from, to)); + if (slot.height > 0) + { + var len = slot.lengths.length; + for (var i = len; i < len + to - from; i++) + { + slot.lengths[i] = length(slot.table[i]); + slot.lengths[i] += (i > 0 ? slot.lengths[i - 1] : 0); + } + } + + from += to; + + // Only proceed to next slots[i] if the current one was + // fully copied. + if (source.table.length <= to) + { + read++; from = 0; + } + + // Only create a new slot if the current one is filled up. + if (slot.table.length === M) + { + saveSlot(newA, newB, write, slot); + slot = createNode(a.height - 1, 0); + write++; + } + } + + // Cleanup after the loop. Copy the last slot into the new nodes. + if (slot.table.length > 0) + { + saveSlot(newA, newB, write, slot); + write++; + } + + // Shift the untouched slots to the left + while (read < a.table.length + b.table.length ) + { + saveSlot(newA, newB, write, get2(a.table, b.table, read)); + read++; + write++; + } + + return [newA, newB]; + } + + // Navigation functions + function botRight(a) + { + return a.table[a.table.length - 1]; + } + function botLeft(a) + { + return a.table[0]; + } + + // Copies a node for updating. Note that you should not use this if + // only updating only one of "table" or "lengths" for performance reasons. + function nodeCopy(a) + { + var newA = { + ctor: '_Array', + height: a.height, + table: a.table.slice() + }; + if (a.height > 0) + { + newA.lengths = a.lengths.slice(); + } + return newA; + } + + // Returns how many items are in the tree. + function length(array) + { + if (array.height === 0) + { + return array.table.length; + } + else + { + return array.lengths[array.lengths.length - 1]; + } + } + + // Calculates in which slot of "table" the item probably is, then + // find the exact slot via forward searching in "lengths". Returns the index. + function getSlot(i, a) + { + var slot = i >> (5 * a.height); + while (a.lengths[slot] <= i) + { + slot++; + } + return slot; + } + + // Recursively creates a tree with a given height containing + // only the given item. + function create(item, h) + { + if (h === 0) + { + return { + ctor: '_Array', + height: 0, + table: [item] + }; + } + return { + ctor: '_Array', + height: h, + table: [create(item, h - 1)], + lengths: [1] + }; + } + + // Recursively creates a tree that contains the given tree. + function parentise(tree, h) + { + if (h === tree.height) + { + return tree; + } + + return { + ctor: '_Array', + height: h, + table: [parentise(tree, h - 1)], + lengths: [length(tree)] + }; + } + + // Emphasizes blood brotherhood beneath two trees. + function siblise(a, b) + { + return { + ctor: '_Array', + height: a.height + 1, + table: [a, b], + lengths: [length(a), length(a) + length(b)] + }; + } + + function toJSArray(a) + { + var jsArray = new Array(length(a)); + toJSArray_(jsArray, 0, a); + return jsArray; + } + + function toJSArray_(jsArray, i, a) + { + for (var t = 0; t < a.table.length; t++) + { + if (a.height === 0) + { + jsArray[i + t] = a.table[t]; + } + else + { + var inc = t === 0 ? 0 : a.lengths[t - 1]; + toJSArray_(jsArray, i + inc, a.table[t]); + } + } + } + + function fromJSArray(jsArray) + { + if (jsArray.length === 0) + { + return empty; + } + var h = Math.floor(Math.log(jsArray.length) / Math.log(M)); + return fromJSArray_(jsArray, h, 0, jsArray.length); + } + + function fromJSArray_(jsArray, h, from, to) + { + if (h === 0) + { + return { + ctor: '_Array', + height: 0, + table: jsArray.slice(from, to) + }; + } + + var step = Math.pow(M, h); + var table = new Array(Math.ceil((to - from) / step)); + var lengths = new Array(table.length); + for (var i = 0; i < table.length; i++) + { + table[i] = fromJSArray_(jsArray, h - 1, from + (i * step), Math.min(from + ((i + 1) * step), to)); + lengths[i] = length(table[i]) + (i > 0 ? lengths[i - 1] : 0); + } + return { + ctor: '_Array', + height: h, + table: table, + lengths: lengths + }; + } + + Elm.Native.Array.values = { + empty: empty, + fromList: fromList, + toList: toList, + initialize: F2(initialize), + append: F2(append), + push: F2(push), + slice: F3(slice), + get: F2(get), + set: F3(set), + map: F2(map), + indexedMap: F2(indexedMap), + foldl: F3(foldl), + foldr: F3(foldr), + length: length, + + toJSArray: toJSArray, + fromJSArray: fromJSArray + }; + + return localRuntime.Native.Array.values = Elm.Native.Array.values; +}; + +Elm.Native.Basics = {}; +Elm.Native.Basics.make = function(localRuntime) { + localRuntime.Native = localRuntime.Native || {}; + localRuntime.Native.Basics = localRuntime.Native.Basics || {}; + if (localRuntime.Native.Basics.values) + { + return localRuntime.Native.Basics.values; + } + + var Utils = Elm.Native.Utils.make(localRuntime); + + function div(a, b) + { + return (a / b) | 0; + } + function rem(a, b) + { + return a % b; + } + function mod(a, b) + { + if (b === 0) + { + throw new Error('Cannot perform mod 0. Division by zero error.'); + } + var r = a % b; + var m = a === 0 ? 0 : (b > 0 ? (a >= 0 ? r : r + b) : -mod(-a, -b)); + + return m === b ? 0 : m; + } + function logBase(base, n) + { + return Math.log(n) / Math.log(base); + } + function negate(n) + { + return -n; + } + function abs(n) + { + return n < 0 ? -n : n; + } + + function min(a, b) + { + return Utils.cmp(a, b) < 0 ? a : b; + } + function max(a, b) + { + return Utils.cmp(a, b) > 0 ? a : b; + } + function clamp(lo, hi, n) + { + return Utils.cmp(n, lo) < 0 ? lo : Utils.cmp(n, hi) > 0 ? hi : n; + } + + function xor(a, b) + { + return a !== b; + } + function not(b) + { + return !b; + } + function isInfinite(n) + { + return n === Infinity || n === -Infinity; + } + + function truncate(n) + { + return n | 0; + } + + function degrees(d) + { + return d * Math.PI / 180; + } + function turns(t) + { + return 2 * Math.PI * t; + } + function fromPolar(point) + { + var r = point._0; + var t = point._1; + return Utils.Tuple2(r * Math.cos(t), r * Math.sin(t)); + } + function toPolar(point) + { + var x = point._0; + var y = point._1; + return Utils.Tuple2(Math.sqrt(x * x + y * y), Math.atan2(y, x)); + } + + return localRuntime.Native.Basics.values = { + div: F2(div), + rem: F2(rem), + mod: F2(mod), + + pi: Math.PI, + e: Math.E, + cos: Math.cos, + sin: Math.sin, + tan: Math.tan, + acos: Math.acos, + asin: Math.asin, + atan: Math.atan, + atan2: F2(Math.atan2), + + degrees: degrees, + turns: turns, + fromPolar: fromPolar, + toPolar: toPolar, + + sqrt: Math.sqrt, + logBase: F2(logBase), + negate: negate, + abs: abs, + min: F2(min), + max: F2(max), + clamp: F3(clamp), + compare: Utils.compare, + + xor: F2(xor), + not: not, + + truncate: truncate, + ceiling: Math.ceil, + floor: Math.floor, + round: Math.round, + toFloat: function(x) { return x; }, + isNaN: isNaN, + isInfinite: isInfinite + }; +}; + +Elm.Native.Port = {}; + +Elm.Native.Port.make = function(localRuntime) { + localRuntime.Native = localRuntime.Native || {}; + localRuntime.Native.Port = localRuntime.Native.Port || {}; + if (localRuntime.Native.Port.values) + { + return localRuntime.Native.Port.values; + } + + var NS; + + // INBOUND + + function inbound(name, type, converter) + { + if (!localRuntime.argsTracker[name]) + { + throw new Error( + 'Port Error:\n' + + 'No argument was given for the port named \'' + name + '\' with type:\n\n' + + ' ' + type.split('\n').join('\n ') + '\n\n' + + 'You need to provide an initial value!\n\n' + + 'Find out more about ports here ' + ); + } + var arg = localRuntime.argsTracker[name]; + arg.used = true; + + return jsToElm(name, type, converter, arg.value); + } + + + function inboundSignal(name, type, converter) + { + var initialValue = inbound(name, type, converter); + + if (!NS) + { + NS = Elm.Native.Signal.make(localRuntime); + } + var signal = NS.input('inbound-port-' + name, initialValue); + + function send(jsValue) + { + var elmValue = jsToElm(name, type, converter, jsValue); + setTimeout(function() { + localRuntime.notify(signal.id, elmValue); + }, 0); + } + + localRuntime.ports[name] = { send: send }; + + return signal; + } + + + function jsToElm(name, type, converter, value) + { + try + { + return converter(value); + } + catch(e) + { + throw new Error( + 'Port Error:\n' + + 'Regarding the port named \'' + name + '\' with type:\n\n' + + ' ' + type.split('\n').join('\n ') + '\n\n' + + 'You just sent the value:\n\n' + + ' ' + JSON.stringify(value) + '\n\n' + + 'but it cannot be converted to the necessary type.\n' + + e.message + ); + } + } + + + // OUTBOUND + + function outbound(name, converter, elmValue) + { + localRuntime.ports[name] = converter(elmValue); + } + + + function outboundSignal(name, converter, signal) + { + var subscribers = []; + + function subscribe(handler) + { + subscribers.push(handler); + } + function unsubscribe(handler) + { + subscribers.pop(subscribers.indexOf(handler)); + } + + function notify(elmValue) + { + var jsValue = converter(elmValue); + var len = subscribers.length; + for (var i = 0; i < len; ++i) + { + subscribers[i](jsValue); + } + } + + if (!NS) + { + NS = Elm.Native.Signal.make(localRuntime); + } + NS.output('outbound-port-' + name, notify, signal); + + localRuntime.ports[name] = { + subscribe: subscribe, + unsubscribe: unsubscribe + }; + + return signal; + } + + + return localRuntime.Native.Port.values = { + inbound: inbound, + outbound: outbound, + inboundSignal: inboundSignal, + outboundSignal: outboundSignal + }; +}; + +if (!Elm.fullscreen) { + (function() { + 'use strict'; + + var Display = { + FULLSCREEN: 0, + COMPONENT: 1, + NONE: 2 + }; + + Elm.fullscreen = function(module, args) + { + var container = document.createElement('div'); + document.body.appendChild(container); + return init(Display.FULLSCREEN, container, module, args || {}); + }; + + Elm.embed = function(module, container, args) + { + var tag = container.tagName; + if (tag !== 'DIV') + { + throw new Error('Elm.node must be given a DIV, not a ' + tag + '.'); + } + return init(Display.COMPONENT, container, module, args || {}); + }; + + Elm.worker = function(module, args) + { + return init(Display.NONE, {}, module, args || {}); + }; + + function init(display, container, module, args, moduleToReplace) + { + // defining state needed for an instance of the Elm RTS + var inputs = []; + + /* OFFSET + * Elm's time traveling debugger lets you pause time. This means + * "now" may be shifted a bit into the past. By wrapping Date.now() + * we can manage this. + */ + var timer = { + programStart: Date.now(), + now: function() + { + return Date.now(); + } + }; + + var updateInProgress = false; + function notify(id, v) + { + if (updateInProgress) + { + throw new Error( + 'The notify function has been called synchronously!\n' + + 'This can lead to frames being dropped.\n' + + 'Definitely report this to \n'); + } + updateInProgress = true; + var timestep = timer.now(); + for (var i = inputs.length; i--; ) + { + inputs[i].notify(timestep, id, v); + } + updateInProgress = false; + } + function setTimeout(func, delay) + { + return window.setTimeout(func, delay); + } + + var listeners = []; + function addListener(relevantInputs, domNode, eventName, func) + { + domNode.addEventListener(eventName, func); + var listener = { + relevantInputs: relevantInputs, + domNode: domNode, + eventName: eventName, + func: func + }; + listeners.push(listener); + } + + var argsTracker = {}; + for (var name in args) + { + argsTracker[name] = { + value: args[name], + used: false + }; + } + + // create the actual RTS. Any impure modules will attach themselves to this + // object. This permits many Elm programs to be embedded per document. + var elm = { + notify: notify, + setTimeout: setTimeout, + node: container, + addListener: addListener, + inputs: inputs, + timer: timer, + argsTracker: argsTracker, + ports: {}, + + isFullscreen: function() { return display === Display.FULLSCREEN; }, + isEmbed: function() { return display === Display.COMPONENT; }, + isWorker: function() { return display === Display.NONE; } + }; + + function swap(newModule) + { + removeListeners(listeners); + var div = document.createElement('div'); + var newElm = init(display, div, newModule, args, elm); + inputs = []; + + return newElm; + } + + function dispose() + { + removeListeners(listeners); + inputs = []; + } + + var Module = {}; + try + { + Module = module.make(elm); + checkInputs(elm); + } + catch (error) + { + if (typeof container.appendChild === "function") + { + container.appendChild(errorNode(error.message)); + } + else + { + console.error(error.message); + } + throw error; + } + + if (display !== Display.NONE) + { + var graphicsNode = initGraphics(elm, Module); + } + + var rootNode = { kids: inputs }; + trimDeadNodes(rootNode); + inputs = rootNode.kids; + filterListeners(inputs, listeners); + + addReceivers(elm.ports); + + if (typeof moduleToReplace !== 'undefined') + { + hotSwap(moduleToReplace, elm); + + // rerender scene if graphics are enabled. + if (typeof graphicsNode !== 'undefined') + { + graphicsNode.notify(0, true, 0); + } + } + + return { + swap: swap, + ports: elm.ports, + dispose: dispose + }; + } + + function checkInputs(elm) + { + var argsTracker = elm.argsTracker; + for (var name in argsTracker) + { + if (!argsTracker[name].used) + { + throw new Error( + "Port Error:\nYou provided an argument named '" + name + + "' but there is no corresponding port!\n\n" + + "Maybe add a port '" + name + "' to your Elm module?\n" + + "Maybe remove the '" + name + "' argument from your initialization code in JS?" + ); + } + } + } + + function errorNode(message) + { + var code = document.createElement('code'); + + var lines = message.split('\n'); + code.appendChild(document.createTextNode(lines[0])); + code.appendChild(document.createElement('br')); + code.appendChild(document.createElement('br')); + for (var i = 1; i < lines.length; ++i) + { + code.appendChild(document.createTextNode('\u00A0 \u00A0 ' + lines[i].replace(/ /g, '\u00A0 '))); + code.appendChild(document.createElement('br')); + } + code.appendChild(document.createElement('br')); + code.appendChild(document.createTextNode('Open the developer console for more details.')); + return code; + } + + + //// FILTER SIGNALS //// + + // TODO: move this code into the signal module and create a function + // Signal.initializeGraph that actually instantiates everything. + + function filterListeners(inputs, listeners) + { + loop: + for (var i = listeners.length; i--; ) + { + var listener = listeners[i]; + for (var j = inputs.length; j--; ) + { + if (listener.relevantInputs.indexOf(inputs[j].id) >= 0) + { + continue loop; + } + } + listener.domNode.removeEventListener(listener.eventName, listener.func); + } + } + + function removeListeners(listeners) + { + for (var i = listeners.length; i--; ) + { + var listener = listeners[i]; + listener.domNode.removeEventListener(listener.eventName, listener.func); + } + } + + // add receivers for built-in ports if they are defined + function addReceivers(ports) + { + if ('title' in ports) + { + if (typeof ports.title === 'string') + { + document.title = ports.title; + } + else + { + ports.title.subscribe(function(v) { document.title = v; }); + } + } + if ('redirect' in ports) + { + ports.redirect.subscribe(function(v) { + if (v.length > 0) + { + window.location = v; + } + }); + } + } + + + // returns a boolean representing whether the node is alive or not. + function trimDeadNodes(node) + { + if (node.isOutput) + { + return true; + } + + var liveKids = []; + for (var i = node.kids.length; i--; ) + { + var kid = node.kids[i]; + if (trimDeadNodes(kid)) + { + liveKids.push(kid); + } + } + node.kids = liveKids; + + return liveKids.length > 0; + } + + + //// RENDERING //// + + function initGraphics(elm, Module) + { + if (!('main' in Module)) + { + throw new Error("'main' is missing! What do I display?!"); + } + + var signalGraph = Module.main; + + // make sure the signal graph is actually a signal & extract the visual model + if (!('notify' in signalGraph)) + { + signalGraph = Elm.Signal.make(elm).constant(signalGraph); + } + var initialScene = signalGraph.value; + + // Figure out what the render functions should be + var render; + var update; + if (initialScene.ctor === 'Element_elm_builtin') + { + var Element = Elm.Native.Graphics.Element.make(elm); + render = Element.render; + update = Element.updateAndReplace; + } + else + { + var VirtualDom = Elm.Native.VirtualDom.make(elm); + render = VirtualDom.render; + update = VirtualDom.updateAndReplace; + } + + // Add the initialScene to the DOM + var container = elm.node; + var node = render(initialScene); + while (container.firstChild) + { + container.removeChild(container.firstChild); + } + container.appendChild(node); + + var _requestAnimationFrame = + typeof requestAnimationFrame !== 'undefined' + ? requestAnimationFrame + : function(cb) { setTimeout(cb, 1000 / 60); } + ; + + // domUpdate is called whenever the main Signal changes. + // + // domUpdate and drawCallback implement a small state machine in order + // to schedule only 1 draw per animation frame. This enforces that + // once draw has been called, it will not be called again until the + // next frame. + // + // drawCallback is scheduled whenever + // 1. The state transitions from PENDING_REQUEST to EXTRA_REQUEST, or + // 2. The state transitions from NO_REQUEST to PENDING_REQUEST + // + // Invariants: + // 1. In the NO_REQUEST state, there is never a scheduled drawCallback. + // 2. In the PENDING_REQUEST and EXTRA_REQUEST states, there is always exactly 1 + // scheduled drawCallback. + var NO_REQUEST = 0; + var PENDING_REQUEST = 1; + var EXTRA_REQUEST = 2; + var state = NO_REQUEST; + var savedScene = initialScene; + var scheduledScene = initialScene; + + function domUpdate(newScene) + { + scheduledScene = newScene; + + update(elm.node.firstChild, savedScene, scheduledScene); + if (elm.Native.Window) + { + elm.Native.Window.values.resizeIfNeeded(); + } + savedScene = scheduledScene; + } + + var renderer = Elm.Native.Signal.make(elm).output('main', domUpdate, signalGraph); + + // must check for resize after 'renderer' is created so + // that changes show up. + if (elm.Native.Window) + { + elm.Native.Window.values.resizeIfNeeded(); + } + + return renderer; + } + + //// HOT SWAPPING //// + + // Returns boolean indicating if the swap was successful. + // Requires that the two signal graphs have exactly the same + // structure. + function hotSwap(from, to) + { + function similar(nodeOld, nodeNew) + { + if (nodeOld.id !== nodeNew.id) + { + return false; + } + if (nodeOld.isOutput) + { + return nodeNew.isOutput; + } + return nodeOld.kids.length === nodeNew.kids.length; + } + function swap(nodeOld, nodeNew) + { + nodeNew.value = nodeOld.value; + return true; + } + var canSwap = depthFirstTraversals(similar, from.inputs, to.inputs); + if (canSwap) + { + depthFirstTraversals(swap, from.inputs, to.inputs); + } + from.node.parentNode.replaceChild(to.node, from.node); + + return canSwap; + } + + // Returns false if the node operation f ever fails. + function depthFirstTraversals(f, queueOld, queueNew) + { + if (queueOld.length !== queueNew.length) + { + return false; + } + queueOld = queueOld.slice(0); + queueNew = queueNew.slice(0); + + var seen = []; + while (queueOld.length > 0 && queueNew.length > 0) + { + var nodeOld = queueOld.pop(); + var nodeNew = queueNew.pop(); + if (seen.indexOf(nodeOld.id) < 0) + { + if (!f(nodeOld, nodeNew)) + { + return false; + } + queueOld = queueOld.concat(nodeOld.kids || []); + queueNew = queueNew.concat(nodeNew.kids || []); + seen.push(nodeOld.id); + } + } + return true; + } + }()); + + function F2(fun) + { + function wrapper(a) { return function(b) { return fun(a,b); }; } + wrapper.arity = 2; + wrapper.func = fun; + return wrapper; + } + + function F3(fun) + { + function wrapper(a) { + return function(b) { return function(c) { return fun(a, b, c); }; }; + } + wrapper.arity = 3; + wrapper.func = fun; + return wrapper; + } + + function F4(fun) + { + function wrapper(a) { return function(b) { return function(c) { + return function(d) { return fun(a, b, c, d); }; }; }; + } + wrapper.arity = 4; + wrapper.func = fun; + return wrapper; + } + + function F5(fun) + { + function wrapper(a) { return function(b) { return function(c) { + return function(d) { return function(e) { return fun(a, b, c, d, e); }; }; }; }; + } + wrapper.arity = 5; + wrapper.func = fun; + return wrapper; + } + + function F6(fun) + { + function wrapper(a) { return function(b) { return function(c) { + return function(d) { return function(e) { return function(f) { + return fun(a, b, c, d, e, f); }; }; }; }; }; + } + wrapper.arity = 6; + wrapper.func = fun; + return wrapper; + } + + function F7(fun) + { + function wrapper(a) { return function(b) { return function(c) { + return function(d) { return function(e) { return function(f) { + return function(g) { return fun(a, b, c, d, e, f, g); }; }; }; }; }; }; + } + wrapper.arity = 7; + wrapper.func = fun; + return wrapper; + } + + function F8(fun) + { + function wrapper(a) { return function(b) { return function(c) { + return function(d) { return function(e) { return function(f) { + return function(g) { return function(h) { + return fun(a, b, c, d, e, f, g, h); }; }; }; }; }; }; }; + } + wrapper.arity = 8; + wrapper.func = fun; + return wrapper; + } + + function F9(fun) + { + function wrapper(a) { return function(b) { return function(c) { + return function(d) { return function(e) { return function(f) { + return function(g) { return function(h) { return function(i) { + return fun(a, b, c, d, e, f, g, h, i); }; }; }; }; }; }; }; }; + } + wrapper.arity = 9; + wrapper.func = fun; + return wrapper; + } + + function A2(fun, a, b) + { + return fun.arity === 2 + ? fun.func(a, b) + : fun(a)(b); + } + function A3(fun, a, b, c) + { + return fun.arity === 3 + ? fun.func(a, b, c) + : fun(a)(b)(c); + } + function A4(fun, a, b, c, d) + { + return fun.arity === 4 + ? fun.func(a, b, c, d) + : fun(a)(b)(c)(d); + } + function A5(fun, a, b, c, d, e) + { + return fun.arity === 5 + ? fun.func(a, b, c, d, e) + : fun(a)(b)(c)(d)(e); + } + function A6(fun, a, b, c, d, e, f) + { + return fun.arity === 6 + ? fun.func(a, b, c, d, e, f) + : fun(a)(b)(c)(d)(e)(f); + } + function A7(fun, a, b, c, d, e, f, g) + { + return fun.arity === 7 + ? fun.func(a, b, c, d, e, f, g) + : fun(a)(b)(c)(d)(e)(f)(g); + } + function A8(fun, a, b, c, d, e, f, g, h) + { + return fun.arity === 8 + ? fun.func(a, b, c, d, e, f, g, h) + : fun(a)(b)(c)(d)(e)(f)(g)(h); + } + function A9(fun, a, b, c, d, e, f, g, h, i) + { + return fun.arity === 9 + ? fun.func(a, b, c, d, e, f, g, h, i) + : fun(a)(b)(c)(d)(e)(f)(g)(h)(i); + } +} + +Elm.Native = Elm.Native || {}; +Elm.Native.Utils = {}; +Elm.Native.Utils.make = function(localRuntime) { + localRuntime.Native = localRuntime.Native || {}; + localRuntime.Native.Utils = localRuntime.Native.Utils || {}; + if (localRuntime.Native.Utils.values) + { + return localRuntime.Native.Utils.values; + } + + + // COMPARISONS + + function eq(l, r) + { + var stack = [{'x': l, 'y': r}]; + while (stack.length > 0) + { + var front = stack.pop(); + var x = front.x; + var y = front.y; + if (x === y) + { + continue; + } + if (typeof x === 'object') + { + var c = 0; + for (var i in x) + { + ++c; + if (i in y) + { + if (i !== 'ctor') + { + stack.push({ 'x': x[i], 'y': y[i] }); + } + } + else + { + return false; + } + } + if ('ctor' in x) + { + stack.push({'x': x.ctor, 'y': y.ctor}); + } + if (c !== Object.keys(y).length) + { + return false; + } + } + else if (typeof x === 'function') + { + throw new Error('Equality error: general function equality is ' + + 'undecidable, and therefore, unsupported'); + } + else + { + return false; + } + } + return true; + } + + // code in Generate/JavaScript.hs depends on the particular + // integer values assigned to LT, EQ, and GT + var LT = -1, EQ = 0, GT = 1, ord = ['LT', 'EQ', 'GT']; + + function compare(x, y) + { + return { + ctor: ord[cmp(x, y) + 1] + }; + } + + function cmp(x, y) { + var ord; + if (typeof x !== 'object') + { + return x === y ? EQ : x < y ? LT : GT; + } + else if (x.isChar) + { + var a = x.toString(); + var b = y.toString(); + return a === b + ? EQ + : a < b + ? LT + : GT; + } + else if (x.ctor === '::' || x.ctor === '[]') + { + while (true) + { + if (x.ctor === '[]' && y.ctor === '[]') + { + return EQ; + } + if (x.ctor !== y.ctor) + { + return x.ctor === '[]' ? LT : GT; + } + ord = cmp(x._0, y._0); + if (ord !== EQ) + { + return ord; + } + x = x._1; + y = y._1; + } + } + else if (x.ctor.slice(0, 6) === '_Tuple') + { + var n = x.ctor.slice(6) - 0; + var err = 'cannot compare tuples with more than 6 elements.'; + if (n === 0) return EQ; + if (n >= 1) { ord = cmp(x._0, y._0); if (ord !== EQ) return ord; + if (n >= 2) { ord = cmp(x._1, y._1); if (ord !== EQ) return ord; + if (n >= 3) { ord = cmp(x._2, y._2); if (ord !== EQ) return ord; + if (n >= 4) { ord = cmp(x._3, y._3); if (ord !== EQ) return ord; + if (n >= 5) { ord = cmp(x._4, y._4); if (ord !== EQ) return ord; + if (n >= 6) { ord = cmp(x._5, y._5); if (ord !== EQ) return ord; + if (n >= 7) throw new Error('Comparison error: ' + err); } } } } } } + return EQ; + } + else + { + throw new Error('Comparison error: comparison is only defined on ints, ' + + 'floats, times, chars, strings, lists of comparable values, ' + + 'and tuples of comparable values.'); + } + } + + + // TUPLES + + var Tuple0 = { + ctor: '_Tuple0' + }; + + function Tuple2(x, y) + { + return { + ctor: '_Tuple2', + _0: x, + _1: y + }; + } + + + // LITERALS + + function chr(c) + { + var x = new String(c); + x.isChar = true; + return x; + } + + function txt(str) + { + var t = new String(str); + t.text = true; + return t; + } + + + // GUID + + var count = 0; + function guid(_) + { + return count++; + } + + + // RECORDS + + function update(oldRecord, updatedFields) + { + var newRecord = {}; + for (var key in oldRecord) + { + var value = (key in updatedFields) ? updatedFields[key] : oldRecord[key]; + newRecord[key] = value; + } + return newRecord; + } + + + // MOUSE COORDINATES + + function getXY(e) + { + var posx = 0; + var posy = 0; + if (e.pageX || e.pageY) + { + posx = e.pageX; + posy = e.pageY; + } + else if (e.clientX || e.clientY) + { + posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft; + posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop; + } + + if (localRuntime.isEmbed()) + { + var rect = localRuntime.node.getBoundingClientRect(); + var relx = rect.left + document.body.scrollLeft + document.documentElement.scrollLeft; + var rely = rect.top + document.body.scrollTop + document.documentElement.scrollTop; + // TODO: figure out if there is a way to avoid rounding here + posx = posx - Math.round(relx) - localRuntime.node.clientLeft; + posy = posy - Math.round(rely) - localRuntime.node.clientTop; + } + return Tuple2(posx, posy); + } + + + //// LIST STUFF //// + + var Nil = { ctor: '[]' }; + + function Cons(hd, tl) + { + return { + ctor: '::', + _0: hd, + _1: tl + }; + } + + function list(arr) + { + var out = Nil; + for (var i = arr.length; i--; ) + { + out = Cons(arr[i], out); + } + return out; + } + + function range(lo, hi) + { + var list = Nil; + if (lo <= hi) + { + do + { + list = Cons(hi, list); + } + while (hi-- > lo); + } + return list; + } + + function append(xs, ys) + { + // append Strings + if (typeof xs === 'string') + { + return xs + ys; + } + + // append Text + if (xs.ctor.slice(0, 5) === 'Text:') + { + return { + ctor: 'Text:Append', + _0: xs, + _1: ys + }; + } + + + // append Lists + if (xs.ctor === '[]') + { + return ys; + } + var root = Cons(xs._0, Nil); + var curr = root; + xs = xs._1; + while (xs.ctor !== '[]') + { + curr._1 = Cons(xs._0, Nil); + xs = xs._1; + curr = curr._1; + } + curr._1 = ys; + return root; + } + + + // CRASHES + + function crash(moduleName, region) + { + return function(message) { + throw new Error( + 'Ran into a `Debug.crash` in module `' + moduleName + '` ' + regionToString(region) + '\n' + + 'The message provided by the code author is:\n\n ' + + message + ); + }; + } + + function crashCase(moduleName, region, value) + { + return function(message) { + throw new Error( + 'Ran into a `Debug.crash` in module `' + moduleName + '`\n\n' + + 'This was caused by the `case` expression ' + regionToString(region) + '.\n' + + 'One of the branches ended with a crash and the following value got through:\n\n ' + toString(value) + '\n\n' + + 'The message provided by the code author is:\n\n ' + + message + ); + }; + } + + function regionToString(region) + { + if (region.start.line == region.end.line) + { + return 'on line ' + region.start.line; + } + return 'between lines ' + region.start.line + ' and ' + region.end.line; + } + + + // BAD PORTS + + function badPort(expected, received) + { + throw new Error( + 'Runtime error when sending values through a port.\n\n' + + 'Expecting ' + expected + ' but was given ' + formatValue(received) + ); + } + + function formatValue(value) + { + // Explicity format undefined values as "undefined" + // because JSON.stringify(undefined) unhelpfully returns "" + return (value === undefined) ? "undefined" : JSON.stringify(value); + } + + + // TO STRING + + var _Array; + var Dict; + var List; + + var toString = function(v) + { + var type = typeof v; + if (type === 'function') + { + var name = v.func ? v.func.name : v.name; + return ''; + } + else if (type === 'boolean') + { + return v ? 'True' : 'False'; + } + else if (type === 'number') + { + return v + ''; + } + else if ((v instanceof String) && v.isChar) + { + return '\'' + addSlashes(v, true) + '\''; + } + else if (type === 'string') + { + return '"' + addSlashes(v, false) + '"'; + } + else if (type === 'object' && 'ctor' in v) + { + if (v.ctor.substring(0, 6) === '_Tuple') + { + var output = []; + for (var k in v) + { + if (k === 'ctor') continue; + output.push(toString(v[k])); + } + return '(' + output.join(',') + ')'; + } + else if (v.ctor === '_Array') + { + if (!_Array) + { + _Array = Elm.Array.make(localRuntime); + } + var list = _Array.toList(v); + return 'Array.fromList ' + toString(list); + } + else if (v.ctor === '::') + { + var output = '[' + toString(v._0); + v = v._1; + while (v.ctor === '::') + { + output += ',' + toString(v._0); + v = v._1; + } + return output + ']'; + } + else if (v.ctor === '[]') + { + return '[]'; + } + else if (v.ctor === 'RBNode_elm_builtin' || v.ctor === 'RBEmpty_elm_builtin' || v.ctor === 'Set_elm_builtin') + { + if (!Dict) + { + Dict = Elm.Dict.make(localRuntime); + } + var list; + var name; + if (v.ctor === 'Set_elm_builtin') + { + if (!List) + { + List = Elm.List.make(localRuntime); + } + name = 'Set'; + list = A2(List.map, function(x) {return x._0; }, Dict.toList(v._0)); + } + else + { + name = 'Dict'; + list = Dict.toList(v); + } + return name + '.fromList ' + toString(list); + } + else if (v.ctor.slice(0, 5) === 'Text:') + { + return ''; + } + else if (v.ctor === 'Element_elm_builtin') + { + return '' + } + else if (v.ctor === 'Form_elm_builtin') + { + return '' + } + else + { + var output = ''; + for (var i in v) + { + if (i === 'ctor') continue; + var str = toString(v[i]); + var parenless = str[0] === '{' || str[0] === '<' || str.indexOf(' ') < 0; + output += ' ' + (parenless ? str : '(' + str + ')'); + } + return v.ctor + output; + } + } + else if (type === 'object' && 'notify' in v && 'id' in v) + { + return ''; + } + else if (type === 'object') + { + var output = []; + for (var k in v) + { + output.push(k + ' = ' + toString(v[k])); + } + if (output.length === 0) + { + return '{}'; + } + return '{ ' + output.join(', ') + ' }'; + } + return ''; + }; + + function addSlashes(str, isChar) + { + var s = str.replace(/\\/g, '\\\\') + .replace(/\n/g, '\\n') + .replace(/\t/g, '\\t') + .replace(/\r/g, '\\r') + .replace(/\v/g, '\\v') + .replace(/\0/g, '\\0'); + if (isChar) + { + return s.replace(/\'/g, '\\\''); + } + else + { + return s.replace(/\"/g, '\\"'); + } + } + + + return localRuntime.Native.Utils.values = { + eq: eq, + cmp: cmp, + compare: F2(compare), + Tuple0: Tuple0, + Tuple2: Tuple2, + chr: chr, + txt: txt, + update: update, + guid: guid, + getXY: getXY, + + Nil: Nil, + Cons: Cons, + list: list, + range: range, + append: F2(append), + + crash: crash, + crashCase: crashCase, + badPort: badPort, + + toString: toString + }; +}; + +Elm.Basics = Elm.Basics || {}; +Elm.Basics.make = function (_elm) { + "use strict"; + _elm.Basics = _elm.Basics || {}; + if (_elm.Basics.values) return _elm.Basics.values; + var _U = Elm.Native.Utils.make(_elm),$Native$Basics = Elm.Native.Basics.make(_elm),$Native$Utils = Elm.Native.Utils.make(_elm); + var _op = {}; + var uncurry = F2(function (f,_p0) { var _p1 = _p0;return A2(f,_p1._0,_p1._1);}); + var curry = F3(function (f,a,b) { return f({ctor: "_Tuple2",_0: a,_1: b});}); + var flip = F3(function (f,b,a) { return A2(f,a,b);}); + var snd = function (_p2) { var _p3 = _p2;return _p3._1;}; + var fst = function (_p4) { var _p5 = _p4;return _p5._0;}; + var always = F2(function (a,_p6) { return a;}); + var identity = function (x) { return x;}; + _op["<|"] = F2(function (f,x) { return f(x);}); + _op["|>"] = F2(function (x,f) { return f(x);}); + _op[">>"] = F3(function (f,g,x) { return g(f(x));}); + _op["<<"] = F3(function (g,f,x) { return g(f(x));}); + _op["++"] = $Native$Utils.append; + var toString = $Native$Utils.toString; + var isInfinite = $Native$Basics.isInfinite; + var isNaN = $Native$Basics.isNaN; + var toFloat = $Native$Basics.toFloat; + var ceiling = $Native$Basics.ceiling; + var floor = $Native$Basics.floor; + var truncate = $Native$Basics.truncate; + var round = $Native$Basics.round; + var not = $Native$Basics.not; + var xor = $Native$Basics.xor; + _op["||"] = $Native$Basics.or; + _op["&&"] = $Native$Basics.and; + var max = $Native$Basics.max; + var min = $Native$Basics.min; + var GT = {ctor: "GT"}; + var EQ = {ctor: "EQ"}; + var LT = {ctor: "LT"}; + var compare = $Native$Basics.compare; + _op[">="] = $Native$Basics.ge; + _op["<="] = $Native$Basics.le; + _op[">"] = $Native$Basics.gt; + _op["<"] = $Native$Basics.lt; + _op["/="] = $Native$Basics.neq; + _op["=="] = $Native$Basics.eq; + var e = $Native$Basics.e; + var pi = $Native$Basics.pi; + var clamp = $Native$Basics.clamp; + var logBase = $Native$Basics.logBase; + var abs = $Native$Basics.abs; + var negate = $Native$Basics.negate; + var sqrt = $Native$Basics.sqrt; + var atan2 = $Native$Basics.atan2; + var atan = $Native$Basics.atan; + var asin = $Native$Basics.asin; + var acos = $Native$Basics.acos; + var tan = $Native$Basics.tan; + var sin = $Native$Basics.sin; + var cos = $Native$Basics.cos; + _op["^"] = $Native$Basics.exp; + _op["%"] = $Native$Basics.mod; + var rem = $Native$Basics.rem; + _op["//"] = $Native$Basics.div; + _op["/"] = $Native$Basics.floatDiv; + _op["*"] = $Native$Basics.mul; + _op["-"] = $Native$Basics.sub; + _op["+"] = $Native$Basics.add; + var toPolar = $Native$Basics.toPolar; + var fromPolar = $Native$Basics.fromPolar; + var turns = $Native$Basics.turns; + var degrees = $Native$Basics.degrees; + var radians = function (t) { return t;}; + return _elm.Basics.values = {_op: _op + ,max: max + ,min: min + ,compare: compare + ,not: not + ,xor: xor + ,rem: rem + ,negate: negate + ,abs: abs + ,sqrt: sqrt + ,clamp: clamp + ,logBase: logBase + ,e: e + ,pi: pi + ,cos: cos + ,sin: sin + ,tan: tan + ,acos: acos + ,asin: asin + ,atan: atan + ,atan2: atan2 + ,round: round + ,floor: floor + ,ceiling: ceiling + ,truncate: truncate + ,toFloat: toFloat + ,degrees: degrees + ,radians: radians + ,turns: turns + ,toPolar: toPolar + ,fromPolar: fromPolar + ,isNaN: isNaN + ,isInfinite: isInfinite + ,toString: toString + ,fst: fst + ,snd: snd + ,identity: identity + ,always: always + ,flip: flip + ,curry: curry + ,uncurry: uncurry + ,LT: LT + ,EQ: EQ + ,GT: GT}; +}; +Elm.Maybe = Elm.Maybe || {}; +Elm.Maybe.make = function (_elm) { + "use strict"; + _elm.Maybe = _elm.Maybe || {}; + if (_elm.Maybe.values) return _elm.Maybe.values; + var _U = Elm.Native.Utils.make(_elm); + var _op = {}; + var withDefault = F2(function ($default,maybe) { var _p0 = maybe;if (_p0.ctor === "Just") { return _p0._0;} else { return $default;}}); + var Nothing = {ctor: "Nothing"}; + var oneOf = function (maybes) { + oneOf: while (true) { + var _p1 = maybes; + if (_p1.ctor === "[]") { + return Nothing; + } else { + var _p3 = _p1._0; + var _p2 = _p3; + if (_p2.ctor === "Nothing") { + var _v3 = _p1._1; + maybes = _v3; + continue oneOf; + } else { + return _p3; + } + } + } + }; + var andThen = F2(function (maybeValue,callback) { + var _p4 = maybeValue; + if (_p4.ctor === "Just") { + return callback(_p4._0); + } else { + return Nothing; + } + }); + var Just = function (a) { return {ctor: "Just",_0: a};}; + var map = F2(function (f,maybe) { var _p5 = maybe;if (_p5.ctor === "Just") { return Just(f(_p5._0));} else { return Nothing;}}); + var map2 = F3(function (func,ma,mb) { + var _p6 = {ctor: "_Tuple2",_0: ma,_1: mb}; + if (_p6.ctor === "_Tuple2" && _p6._0.ctor === "Just" && _p6._1.ctor === "Just") { + return Just(A2(func,_p6._0._0,_p6._1._0)); + } else { + return Nothing; + } + }); + var map3 = F4(function (func,ma,mb,mc) { + var _p7 = {ctor: "_Tuple3",_0: ma,_1: mb,_2: mc}; + if (_p7.ctor === "_Tuple3" && _p7._0.ctor === "Just" && _p7._1.ctor === "Just" && _p7._2.ctor === "Just") { + return Just(A3(func,_p7._0._0,_p7._1._0,_p7._2._0)); + } else { + return Nothing; + } + }); + var map4 = F5(function (func,ma,mb,mc,md) { + var _p8 = {ctor: "_Tuple4",_0: ma,_1: mb,_2: mc,_3: md}; + if (_p8.ctor === "_Tuple4" && _p8._0.ctor === "Just" && _p8._1.ctor === "Just" && _p8._2.ctor === "Just" && _p8._3.ctor === "Just") { + return Just(A4(func,_p8._0._0,_p8._1._0,_p8._2._0,_p8._3._0)); + } else { + return Nothing; + } + }); + var map5 = F6(function (func,ma,mb,mc,md,me) { + var _p9 = {ctor: "_Tuple5",_0: ma,_1: mb,_2: mc,_3: md,_4: me}; + if (_p9.ctor === "_Tuple5" && _p9._0.ctor === "Just" && _p9._1.ctor === "Just" && _p9._2.ctor === "Just" && _p9._3.ctor === "Just" && _p9._4.ctor === "Just") + { + return Just(A5(func,_p9._0._0,_p9._1._0,_p9._2._0,_p9._3._0,_p9._4._0)); + } else { + return Nothing; + } + }); + return _elm.Maybe.values = {_op: _op + ,andThen: andThen + ,map: map + ,map2: map2 + ,map3: map3 + ,map4: map4 + ,map5: map5 + ,withDefault: withDefault + ,oneOf: oneOf + ,Just: Just + ,Nothing: Nothing}; +}; +Elm.Native.List = {}; +Elm.Native.List.make = function(localRuntime) { + localRuntime.Native = localRuntime.Native || {}; + localRuntime.Native.List = localRuntime.Native.List || {}; + if (localRuntime.Native.List.values) + { + return localRuntime.Native.List.values; + } + if ('values' in Elm.Native.List) + { + return localRuntime.Native.List.values = Elm.Native.List.values; + } + + var Utils = Elm.Native.Utils.make(localRuntime); + + var Nil = Utils.Nil; + var Cons = Utils.Cons; + + var fromArray = Utils.list; + + function toArray(xs) + { + var out = []; + while (xs.ctor !== '[]') + { + out.push(xs._0); + xs = xs._1; + } + return out; + } + + // f defined similarly for both foldl and foldr (NB: different from Haskell) + // ie, foldl : (a -> b -> b) -> b -> [a] -> b + function foldl(f, b, xs) + { + var acc = b; + while (xs.ctor !== '[]') + { + acc = A2(f, xs._0, acc); + xs = xs._1; + } + return acc; + } + + function foldr(f, b, xs) + { + var arr = toArray(xs); + var acc = b; + for (var i = arr.length; i--; ) + { + acc = A2(f, arr[i], acc); + } + return acc; + } + + function map2(f, xs, ys) + { + var arr = []; + while (xs.ctor !== '[]' && ys.ctor !== '[]') + { + arr.push(A2(f, xs._0, ys._0)); + xs = xs._1; + ys = ys._1; + } + return fromArray(arr); + } + + function map3(f, xs, ys, zs) + { + var arr = []; + while (xs.ctor !== '[]' && ys.ctor !== '[]' && zs.ctor !== '[]') + { + arr.push(A3(f, xs._0, ys._0, zs._0)); + xs = xs._1; + ys = ys._1; + zs = zs._1; + } + return fromArray(arr); + } + + function map4(f, ws, xs, ys, zs) + { + var arr = []; + while ( ws.ctor !== '[]' + && xs.ctor !== '[]' + && ys.ctor !== '[]' + && zs.ctor !== '[]') + { + arr.push(A4(f, ws._0, xs._0, ys._0, zs._0)); + ws = ws._1; + xs = xs._1; + ys = ys._1; + zs = zs._1; + } + return fromArray(arr); + } + + function map5(f, vs, ws, xs, ys, zs) + { + var arr = []; + while ( vs.ctor !== '[]' + && ws.ctor !== '[]' + && xs.ctor !== '[]' + && ys.ctor !== '[]' + && zs.ctor !== '[]') + { + arr.push(A5(f, vs._0, ws._0, xs._0, ys._0, zs._0)); + vs = vs._1; + ws = ws._1; + xs = xs._1; + ys = ys._1; + zs = zs._1; + } + return fromArray(arr); + } + + function sortBy(f, xs) + { + return fromArray(toArray(xs).sort(function(a, b) { + return Utils.cmp(f(a), f(b)); + })); + } + + function sortWith(f, xs) + { + return fromArray(toArray(xs).sort(function(a, b) { + var ord = f(a)(b).ctor; + return ord === 'EQ' ? 0 : ord === 'LT' ? -1 : 1; + })); + } + + function take(n, xs) + { + var arr = []; + while (xs.ctor !== '[]' && n > 0) + { + arr.push(xs._0); + xs = xs._1; + --n; + } + return fromArray(arr); + } + + + Elm.Native.List.values = { + Nil: Nil, + Cons: Cons, + cons: F2(Cons), + toArray: toArray, + fromArray: fromArray, + + foldl: F3(foldl), + foldr: F3(foldr), + + map2: F3(map2), + map3: F4(map3), + map4: F5(map4), + map5: F6(map5), + sortBy: F2(sortBy), + sortWith: F2(sortWith), + take: F2(take) + }; + return localRuntime.Native.List.values = Elm.Native.List.values; +}; + +Elm.List = Elm.List || {}; +Elm.List.make = function (_elm) { + "use strict"; + _elm.List = _elm.List || {}; + if (_elm.List.values) return _elm.List.values; + var _U = Elm.Native.Utils.make(_elm),$Basics = Elm.Basics.make(_elm),$Maybe = Elm.Maybe.make(_elm),$Native$List = Elm.Native.List.make(_elm); + var _op = {}; + var sortWith = $Native$List.sortWith; + var sortBy = $Native$List.sortBy; + var sort = function (xs) { return A2(sortBy,$Basics.identity,xs);}; + var drop = F2(function (n,list) { + drop: while (true) if (_U.cmp(n,0) < 1) return list; else { + var _p0 = list; + if (_p0.ctor === "[]") { + return list; + } else { + var _v1 = n - 1,_v2 = _p0._1; + n = _v1; + list = _v2; + continue drop; + } + } + }); + var take = $Native$List.take; + var map5 = $Native$List.map5; + var map4 = $Native$List.map4; + var map3 = $Native$List.map3; + var map2 = $Native$List.map2; + var any = F2(function (isOkay,list) { + any: while (true) { + var _p1 = list; + if (_p1.ctor === "[]") { + return false; + } else { + if (isOkay(_p1._0)) return true; else { + var _v4 = isOkay,_v5 = _p1._1; + isOkay = _v4; + list = _v5; + continue any; + } + } + } + }); + var all = F2(function (isOkay,list) { return $Basics.not(A2(any,function (_p2) { return $Basics.not(isOkay(_p2));},list));}); + var foldr = $Native$List.foldr; + var foldl = $Native$List.foldl; + var length = function (xs) { return A3(foldl,F2(function (_p3,i) { return i + 1;}),0,xs);}; + var sum = function (numbers) { return A3(foldl,F2(function (x,y) { return x + y;}),0,numbers);}; + var product = function (numbers) { return A3(foldl,F2(function (x,y) { return x * y;}),1,numbers);}; + var maximum = function (list) { + var _p4 = list; + if (_p4.ctor === "::") { + return $Maybe.Just(A3(foldl,$Basics.max,_p4._0,_p4._1)); + } else { + return $Maybe.Nothing; + } + }; + var minimum = function (list) { + var _p5 = list; + if (_p5.ctor === "::") { + return $Maybe.Just(A3(foldl,$Basics.min,_p5._0,_p5._1)); + } else { + return $Maybe.Nothing; + } + }; + var indexedMap = F2(function (f,xs) { return A3(map2,f,_U.range(0,length(xs) - 1),xs);}); + var member = F2(function (x,xs) { return A2(any,function (a) { return _U.eq(a,x);},xs);}); + var isEmpty = function (xs) { var _p6 = xs;if (_p6.ctor === "[]") { return true;} else { return false;}}; + var tail = function (list) { var _p7 = list;if (_p7.ctor === "::") { return $Maybe.Just(_p7._1);} else { return $Maybe.Nothing;}}; + var head = function (list) { var _p8 = list;if (_p8.ctor === "::") { return $Maybe.Just(_p8._0);} else { return $Maybe.Nothing;}}; + _op["::"] = $Native$List.cons; + var map = F2(function (f,xs) { return A3(foldr,F2(function (x,acc) { return A2(_op["::"],f(x),acc);}),_U.list([]),xs);}); + var filter = F2(function (pred,xs) { + var conditionalCons = F2(function (x,xs$) { return pred(x) ? A2(_op["::"],x,xs$) : xs$;}); + return A3(foldr,conditionalCons,_U.list([]),xs); + }); + var maybeCons = F3(function (f,mx,xs) { var _p9 = f(mx);if (_p9.ctor === "Just") { return A2(_op["::"],_p9._0,xs);} else { return xs;}}); + var filterMap = F2(function (f,xs) { return A3(foldr,maybeCons(f),_U.list([]),xs);}); + var reverse = function (list) { return A3(foldl,F2(function (x,y) { return A2(_op["::"],x,y);}),_U.list([]),list);}; + var scanl = F3(function (f,b,xs) { + var scan1 = F2(function (x,accAcc) { + var _p10 = accAcc; + if (_p10.ctor === "::") { + return A2(_op["::"],A2(f,x,_p10._0),accAcc); + } else { + return _U.list([]); + } + }); + return reverse(A3(foldl,scan1,_U.list([b]),xs)); + }); + var append = F2(function (xs,ys) { + var _p11 = ys; + if (_p11.ctor === "[]") { + return xs; + } else { + return A3(foldr,F2(function (x,y) { return A2(_op["::"],x,y);}),ys,xs); + } + }); + var concat = function (lists) { return A3(foldr,append,_U.list([]),lists);}; + var concatMap = F2(function (f,list) { return concat(A2(map,f,list));}); + var partition = F2(function (pred,list) { + var step = F2(function (x,_p12) { + var _p13 = _p12; + var _p15 = _p13._0; + var _p14 = _p13._1; + return pred(x) ? {ctor: "_Tuple2",_0: A2(_op["::"],x,_p15),_1: _p14} : {ctor: "_Tuple2",_0: _p15,_1: A2(_op["::"],x,_p14)}; + }); + return A3(foldr,step,{ctor: "_Tuple2",_0: _U.list([]),_1: _U.list([])},list); + }); + var unzip = function (pairs) { + var step = F2(function (_p17,_p16) { + var _p18 = _p17; + var _p19 = _p16; + return {ctor: "_Tuple2",_0: A2(_op["::"],_p18._0,_p19._0),_1: A2(_op["::"],_p18._1,_p19._1)}; + }); + return A3(foldr,step,{ctor: "_Tuple2",_0: _U.list([]),_1: _U.list([])},pairs); + }; + var intersperse = F2(function (sep,xs) { + var _p20 = xs; + if (_p20.ctor === "[]") { + return _U.list([]); + } else { + var step = F2(function (x,rest) { return A2(_op["::"],sep,A2(_op["::"],x,rest));}); + var spersed = A3(foldr,step,_U.list([]),_p20._1); + return A2(_op["::"],_p20._0,spersed); + } + }); + var repeatHelp = F3(function (result,n,value) { + repeatHelp: while (true) if (_U.cmp(n,0) < 1) return result; else { + var _v18 = A2(_op["::"],value,result),_v19 = n - 1,_v20 = value; + result = _v18; + n = _v19; + value = _v20; + continue repeatHelp; + } + }); + var repeat = F2(function (n,value) { return A3(repeatHelp,_U.list([]),n,value);}); + return _elm.List.values = {_op: _op + ,isEmpty: isEmpty + ,length: length + ,reverse: reverse + ,member: member + ,head: head + ,tail: tail + ,filter: filter + ,take: take + ,drop: drop + ,repeat: repeat + ,append: append + ,concat: concat + ,intersperse: intersperse + ,partition: partition + ,unzip: unzip + ,map: map + ,map2: map2 + ,map3: map3 + ,map4: map4 + ,map5: map5 + ,filterMap: filterMap + ,concatMap: concatMap + ,indexedMap: indexedMap + ,foldr: foldr + ,foldl: foldl + ,sum: sum + ,product: product + ,maximum: maximum + ,minimum: minimum + ,all: all + ,any: any + ,scanl: scanl + ,sort: sort + ,sortBy: sortBy + ,sortWith: sortWith}; +}; +Elm.Array = Elm.Array || {}; +Elm.Array.make = function (_elm) { + "use strict"; + _elm.Array = _elm.Array || {}; + if (_elm.Array.values) return _elm.Array.values; + var _U = Elm.Native.Utils.make(_elm), + $Basics = Elm.Basics.make(_elm), + $List = Elm.List.make(_elm), + $Maybe = Elm.Maybe.make(_elm), + $Native$Array = Elm.Native.Array.make(_elm); + var _op = {}; + var append = $Native$Array.append; + var length = $Native$Array.length; + var isEmpty = function (array) { return _U.eq(length(array),0);}; + var slice = $Native$Array.slice; + var set = $Native$Array.set; + var get = F2(function (i,array) { + return _U.cmp(0,i) < 1 && _U.cmp(i,$Native$Array.length(array)) < 0 ? $Maybe.Just(A2($Native$Array.get,i,array)) : $Maybe.Nothing; + }); + var push = $Native$Array.push; + var empty = $Native$Array.empty; + var filter = F2(function (isOkay,arr) { + var update = F2(function (x,xs) { return isOkay(x) ? A2($Native$Array.push,x,xs) : xs;}); + return A3($Native$Array.foldl,update,$Native$Array.empty,arr); + }); + var foldr = $Native$Array.foldr; + var foldl = $Native$Array.foldl; + var indexedMap = $Native$Array.indexedMap; + var map = $Native$Array.map; + var toIndexedList = function (array) { + return A3($List.map2, + F2(function (v0,v1) { return {ctor: "_Tuple2",_0: v0,_1: v1};}), + _U.range(0,$Native$Array.length(array) - 1), + $Native$Array.toList(array)); + }; + var toList = $Native$Array.toList; + var fromList = $Native$Array.fromList; + var initialize = $Native$Array.initialize; + var repeat = F2(function (n,e) { return A2(initialize,n,$Basics.always(e));}); + var Array = {ctor: "Array"}; + return _elm.Array.values = {_op: _op + ,empty: empty + ,repeat: repeat + ,initialize: initialize + ,fromList: fromList + ,isEmpty: isEmpty + ,length: length + ,push: push + ,append: append + ,get: get + ,set: set + ,slice: slice + ,toList: toList + ,toIndexedList: toIndexedList + ,map: map + ,indexedMap: indexedMap + ,filter: filter + ,foldl: foldl + ,foldr: foldr}; +}; +Elm.Native.Char = {}; +Elm.Native.Char.make = function(localRuntime) { + localRuntime.Native = localRuntime.Native || {}; + localRuntime.Native.Char = localRuntime.Native.Char || {}; + if (localRuntime.Native.Char.values) + { + return localRuntime.Native.Char.values; + } + + var Utils = Elm.Native.Utils.make(localRuntime); + + return localRuntime.Native.Char.values = { + fromCode: function(c) { return Utils.chr(String.fromCharCode(c)); }, + toCode: function(c) { return c.charCodeAt(0); }, + toUpper: function(c) { return Utils.chr(c.toUpperCase()); }, + toLower: function(c) { return Utils.chr(c.toLowerCase()); }, + toLocaleUpper: function(c) { return Utils.chr(c.toLocaleUpperCase()); }, + toLocaleLower: function(c) { return Utils.chr(c.toLocaleLowerCase()); } + }; +}; + +Elm.Char = Elm.Char || {}; +Elm.Char.make = function (_elm) { + "use strict"; + _elm.Char = _elm.Char || {}; + if (_elm.Char.values) return _elm.Char.values; + var _U = Elm.Native.Utils.make(_elm),$Basics = Elm.Basics.make(_elm),$Native$Char = Elm.Native.Char.make(_elm); + var _op = {}; + var fromCode = $Native$Char.fromCode; + var toCode = $Native$Char.toCode; + var toLocaleLower = $Native$Char.toLocaleLower; + var toLocaleUpper = $Native$Char.toLocaleUpper; + var toLower = $Native$Char.toLower; + var toUpper = $Native$Char.toUpper; + var isBetween = F3(function (low,high,$char) { var code = toCode($char);return _U.cmp(code,toCode(low)) > -1 && _U.cmp(code,toCode(high)) < 1;}); + var isUpper = A2(isBetween,_U.chr("A"),_U.chr("Z")); + var isLower = A2(isBetween,_U.chr("a"),_U.chr("z")); + var isDigit = A2(isBetween,_U.chr("0"),_U.chr("9")); + var isOctDigit = A2(isBetween,_U.chr("0"),_U.chr("7")); + var isHexDigit = function ($char) { + return isDigit($char) || (A3(isBetween,_U.chr("a"),_U.chr("f"),$char) || A3(isBetween,_U.chr("A"),_U.chr("F"),$char)); + }; + return _elm.Char.values = {_op: _op + ,isUpper: isUpper + ,isLower: isLower + ,isDigit: isDigit + ,isOctDigit: isOctDigit + ,isHexDigit: isHexDigit + ,toUpper: toUpper + ,toLower: toLower + ,toLocaleUpper: toLocaleUpper + ,toLocaleLower: toLocaleLower + ,toCode: toCode + ,fromCode: fromCode}; +}; +Elm.Native.Color = {}; +Elm.Native.Color.make = function(localRuntime) { + localRuntime.Native = localRuntime.Native || {}; + localRuntime.Native.Color = localRuntime.Native.Color || {}; + if (localRuntime.Native.Color.values) + { + return localRuntime.Native.Color.values; + } + + function toCss(c) + { + var format = ''; + var colors = ''; + if (c.ctor === 'RGBA') + { + format = 'rgb'; + colors = c._0 + ', ' + c._1 + ', ' + c._2; + } + else + { + format = 'hsl'; + colors = (c._0 * 180 / Math.PI) + ', ' + + (c._1 * 100) + '%, ' + + (c._2 * 100) + '%'; + } + if (c._3 === 1) + { + return format + '(' + colors + ')'; + } + else + { + return format + 'a(' + colors + ', ' + c._3 + ')'; + } + } + + return localRuntime.Native.Color.values = { + toCss: toCss + }; +}; + +Elm.Color = Elm.Color || {}; +Elm.Color.make = function (_elm) { + "use strict"; + _elm.Color = _elm.Color || {}; + if (_elm.Color.values) return _elm.Color.values; + var _U = Elm.Native.Utils.make(_elm),$Basics = Elm.Basics.make(_elm); + var _op = {}; + var Radial = F5(function (a,b,c,d,e) { return {ctor: "Radial",_0: a,_1: b,_2: c,_3: d,_4: e};}); + var radial = Radial; + var Linear = F3(function (a,b,c) { return {ctor: "Linear",_0: a,_1: b,_2: c};}); + var linear = Linear; + var fmod = F2(function (f,n) { var integer = $Basics.floor(f);return $Basics.toFloat(A2($Basics._op["%"],integer,n)) + f - $Basics.toFloat(integer);}); + var rgbToHsl = F3(function (red,green,blue) { + var b = $Basics.toFloat(blue) / 255; + var g = $Basics.toFloat(green) / 255; + var r = $Basics.toFloat(red) / 255; + var cMax = A2($Basics.max,A2($Basics.max,r,g),b); + var cMin = A2($Basics.min,A2($Basics.min,r,g),b); + var c = cMax - cMin; + var lightness = (cMax + cMin) / 2; + var saturation = _U.eq(lightness,0) ? 0 : c / (1 - $Basics.abs(2 * lightness - 1)); + var hue = $Basics.degrees(60) * (_U.eq(cMax,r) ? A2(fmod,(g - b) / c,6) : _U.eq(cMax,g) ? (b - r) / c + 2 : (r - g) / c + 4); + return {ctor: "_Tuple3",_0: hue,_1: saturation,_2: lightness}; + }); + var hslToRgb = F3(function (hue,saturation,lightness) { + var hue$ = hue / $Basics.degrees(60); + var chroma = (1 - $Basics.abs(2 * lightness - 1)) * saturation; + var x = chroma * (1 - $Basics.abs(A2(fmod,hue$,2) - 1)); + var _p0 = _U.cmp(hue$,0) < 0 ? {ctor: "_Tuple3",_0: 0,_1: 0,_2: 0} : _U.cmp(hue$,1) < 0 ? {ctor: "_Tuple3",_0: chroma,_1: x,_2: 0} : _U.cmp(hue$, + 2) < 0 ? {ctor: "_Tuple3",_0: x,_1: chroma,_2: 0} : _U.cmp(hue$,3) < 0 ? {ctor: "_Tuple3",_0: 0,_1: chroma,_2: x} : _U.cmp(hue$,4) < 0 ? {ctor: "_Tuple3" + ,_0: 0 + ,_1: x + ,_2: chroma} : _U.cmp(hue$, + 5) < 0 ? {ctor: "_Tuple3",_0: x,_1: 0,_2: chroma} : _U.cmp(hue$,6) < 0 ? {ctor: "_Tuple3",_0: chroma,_1: 0,_2: x} : {ctor: "_Tuple3",_0: 0,_1: 0,_2: 0}; + var r = _p0._0; + var g = _p0._1; + var b = _p0._2; + var m = lightness - chroma / 2; + return {ctor: "_Tuple3",_0: r + m,_1: g + m,_2: b + m}; + }); + var toRgb = function (color) { + var _p1 = color; + if (_p1.ctor === "RGBA") { + return {red: _p1._0,green: _p1._1,blue: _p1._2,alpha: _p1._3}; + } else { + var _p2 = A3(hslToRgb,_p1._0,_p1._1,_p1._2); + var r = _p2._0; + var g = _p2._1; + var b = _p2._2; + return {red: $Basics.round(255 * r),green: $Basics.round(255 * g),blue: $Basics.round(255 * b),alpha: _p1._3}; + } + }; + var toHsl = function (color) { + var _p3 = color; + if (_p3.ctor === "HSLA") { + return {hue: _p3._0,saturation: _p3._1,lightness: _p3._2,alpha: _p3._3}; + } else { + var _p4 = A3(rgbToHsl,_p3._0,_p3._1,_p3._2); + var h = _p4._0; + var s = _p4._1; + var l = _p4._2; + return {hue: h,saturation: s,lightness: l,alpha: _p3._3}; + } + }; + var HSLA = F4(function (a,b,c,d) { return {ctor: "HSLA",_0: a,_1: b,_2: c,_3: d};}); + var hsla = F4(function (hue,saturation,lightness,alpha) { + return A4(HSLA,hue - $Basics.turns($Basics.toFloat($Basics.floor(hue / (2 * $Basics.pi)))),saturation,lightness,alpha); + }); + var hsl = F3(function (hue,saturation,lightness) { return A4(hsla,hue,saturation,lightness,1);}); + var complement = function (color) { + var _p5 = color; + if (_p5.ctor === "HSLA") { + return A4(hsla,_p5._0 + $Basics.degrees(180),_p5._1,_p5._2,_p5._3); + } else { + var _p6 = A3(rgbToHsl,_p5._0,_p5._1,_p5._2); + var h = _p6._0; + var s = _p6._1; + var l = _p6._2; + return A4(hsla,h + $Basics.degrees(180),s,l,_p5._3); + } + }; + var grayscale = function (p) { return A4(HSLA,0,0,1 - p,1);}; + var greyscale = function (p) { return A4(HSLA,0,0,1 - p,1);}; + var RGBA = F4(function (a,b,c,d) { return {ctor: "RGBA",_0: a,_1: b,_2: c,_3: d};}); + var rgba = RGBA; + var rgb = F3(function (r,g,b) { return A4(RGBA,r,g,b,1);}); + var lightRed = A4(RGBA,239,41,41,1); + var red = A4(RGBA,204,0,0,1); + var darkRed = A4(RGBA,164,0,0,1); + var lightOrange = A4(RGBA,252,175,62,1); + var orange = A4(RGBA,245,121,0,1); + var darkOrange = A4(RGBA,206,92,0,1); + var lightYellow = A4(RGBA,255,233,79,1); + var yellow = A4(RGBA,237,212,0,1); + var darkYellow = A4(RGBA,196,160,0,1); + var lightGreen = A4(RGBA,138,226,52,1); + var green = A4(RGBA,115,210,22,1); + var darkGreen = A4(RGBA,78,154,6,1); + var lightBlue = A4(RGBA,114,159,207,1); + var blue = A4(RGBA,52,101,164,1); + var darkBlue = A4(RGBA,32,74,135,1); + var lightPurple = A4(RGBA,173,127,168,1); + var purple = A4(RGBA,117,80,123,1); + var darkPurple = A4(RGBA,92,53,102,1); + var lightBrown = A4(RGBA,233,185,110,1); + var brown = A4(RGBA,193,125,17,1); + var darkBrown = A4(RGBA,143,89,2,1); + var black = A4(RGBA,0,0,0,1); + var white = A4(RGBA,255,255,255,1); + var lightGrey = A4(RGBA,238,238,236,1); + var grey = A4(RGBA,211,215,207,1); + var darkGrey = A4(RGBA,186,189,182,1); + var lightGray = A4(RGBA,238,238,236,1); + var gray = A4(RGBA,211,215,207,1); + var darkGray = A4(RGBA,186,189,182,1); + var lightCharcoal = A4(RGBA,136,138,133,1); + var charcoal = A4(RGBA,85,87,83,1); + var darkCharcoal = A4(RGBA,46,52,54,1); + return _elm.Color.values = {_op: _op + ,rgb: rgb + ,rgba: rgba + ,hsl: hsl + ,hsla: hsla + ,greyscale: greyscale + ,grayscale: grayscale + ,complement: complement + ,linear: linear + ,radial: radial + ,toRgb: toRgb + ,toHsl: toHsl + ,red: red + ,orange: orange + ,yellow: yellow + ,green: green + ,blue: blue + ,purple: purple + ,brown: brown + ,lightRed: lightRed + ,lightOrange: lightOrange + ,lightYellow: lightYellow + ,lightGreen: lightGreen + ,lightBlue: lightBlue + ,lightPurple: lightPurple + ,lightBrown: lightBrown + ,darkRed: darkRed + ,darkOrange: darkOrange + ,darkYellow: darkYellow + ,darkGreen: darkGreen + ,darkBlue: darkBlue + ,darkPurple: darkPurple + ,darkBrown: darkBrown + ,white: white + ,lightGrey: lightGrey + ,grey: grey + ,darkGrey: darkGrey + ,lightCharcoal: lightCharcoal + ,charcoal: charcoal + ,darkCharcoal: darkCharcoal + ,black: black + ,lightGray: lightGray + ,gray: gray + ,darkGray: darkGray}; +}; +Elm.Native.Signal = {}; + +Elm.Native.Signal.make = function(localRuntime) { + localRuntime.Native = localRuntime.Native || {}; + localRuntime.Native.Signal = localRuntime.Native.Signal || {}; + if (localRuntime.Native.Signal.values) + { + return localRuntime.Native.Signal.values; + } + + + var Task = Elm.Native.Task.make(localRuntime); + var Utils = Elm.Native.Utils.make(localRuntime); + + + function broadcastToKids(node, timestamp, update) + { + var kids = node.kids; + for (var i = kids.length; i--; ) + { + kids[i].notify(timestamp, update, node.id); + } + } + + + // INPUT + + function input(name, base) + { + var node = { + id: Utils.guid(), + name: 'input-' + name, + value: base, + parents: [], + kids: [] + }; + + node.notify = function(timestamp, targetId, value) { + var update = targetId === node.id; + if (update) + { + node.value = value; + } + broadcastToKids(node, timestamp, update); + return update; + }; + + localRuntime.inputs.push(node); + + return node; + } + + function constant(value) + { + return input('constant', value); + } + + + // MAILBOX + + function mailbox(base) + { + var signal = input('mailbox', base); + + function send(value) { + return Task.asyncFunction(function(callback) { + localRuntime.setTimeout(function() { + localRuntime.notify(signal.id, value); + }, 0); + callback(Task.succeed(Utils.Tuple0)); + }); + } + + return { + signal: signal, + address: { + ctor: 'Address', + _0: send + } + }; + } + + function sendMessage(message) + { + Task.perform(message._0); + } + + + // OUTPUT + + function output(name, handler, parent) + { + var node = { + id: Utils.guid(), + name: 'output-' + name, + parents: [parent], + isOutput: true + }; + + node.notify = function(timestamp, parentUpdate, parentID) + { + if (parentUpdate) + { + handler(parent.value); + } + }; + + parent.kids.push(node); + + return node; + } + + + // MAP + + function mapMany(refreshValue, args) + { + var node = { + id: Utils.guid(), + name: 'map' + args.length, + value: refreshValue(), + parents: args, + kids: [] + }; + + var numberOfParents = args.length; + var count = 0; + var update = false; + + node.notify = function(timestamp, parentUpdate, parentID) + { + ++count; + + update = update || parentUpdate; + + if (count === numberOfParents) + { + if (update) + { + node.value = refreshValue(); + } + broadcastToKids(node, timestamp, update); + update = false; + count = 0; + } + }; + + for (var i = numberOfParents; i--; ) + { + args[i].kids.push(node); + } + + return node; + } + + + function map(func, a) + { + function refreshValue() + { + return func(a.value); + } + return mapMany(refreshValue, [a]); + } + + + function map2(func, a, b) + { + function refreshValue() + { + return A2( func, a.value, b.value ); + } + return mapMany(refreshValue, [a, b]); + } + + + function map3(func, a, b, c) + { + function refreshValue() + { + return A3( func, a.value, b.value, c.value ); + } + return mapMany(refreshValue, [a, b, c]); + } + + + function map4(func, a, b, c, d) + { + function refreshValue() + { + return A4( func, a.value, b.value, c.value, d.value ); + } + return mapMany(refreshValue, [a, b, c, d]); + } + + + function map5(func, a, b, c, d, e) + { + function refreshValue() + { + return A5( func, a.value, b.value, c.value, d.value, e.value ); + } + return mapMany(refreshValue, [a, b, c, d, e]); + } + + + // FOLD + + function foldp(update, state, signal) + { + var node = { + id: Utils.guid(), + name: 'foldp', + parents: [signal], + kids: [], + value: state + }; + + node.notify = function(timestamp, parentUpdate, parentID) + { + if (parentUpdate) + { + node.value = A2( update, signal.value, node.value ); + } + broadcastToKids(node, timestamp, parentUpdate); + }; + + signal.kids.push(node); + + return node; + } + + + // TIME + + function timestamp(signal) + { + var node = { + id: Utils.guid(), + name: 'timestamp', + value: Utils.Tuple2(localRuntime.timer.programStart, signal.value), + parents: [signal], + kids: [] + }; + + node.notify = function(timestamp, parentUpdate, parentID) + { + if (parentUpdate) + { + node.value = Utils.Tuple2(timestamp, signal.value); + } + broadcastToKids(node, timestamp, parentUpdate); + }; + + signal.kids.push(node); + + return node; + } + + + function delay(time, signal) + { + var delayed = input('delay-input-' + time, signal.value); + + function handler(value) + { + setTimeout(function() { + localRuntime.notify(delayed.id, value); + }, time); + } + + output('delay-output-' + time, handler, signal); + + return delayed; + } + + + // MERGING + + function genericMerge(tieBreaker, leftStream, rightStream) + { + var node = { + id: Utils.guid(), + name: 'merge', + value: A2(tieBreaker, leftStream.value, rightStream.value), + parents: [leftStream, rightStream], + kids: [] + }; + + var left = { touched: false, update: false, value: null }; + var right = { touched: false, update: false, value: null }; + + node.notify = function(timestamp, parentUpdate, parentID) + { + if (parentID === leftStream.id) + { + left.touched = true; + left.update = parentUpdate; + left.value = leftStream.value; + } + if (parentID === rightStream.id) + { + right.touched = true; + right.update = parentUpdate; + right.value = rightStream.value; + } + + if (left.touched && right.touched) + { + var update = false; + if (left.update && right.update) + { + node.value = A2(tieBreaker, left.value, right.value); + update = true; + } + else if (left.update) + { + node.value = left.value; + update = true; + } + else if (right.update) + { + node.value = right.value; + update = true; + } + left.touched = false; + right.touched = false; + + broadcastToKids(node, timestamp, update); + } + }; + + leftStream.kids.push(node); + rightStream.kids.push(node); + + return node; + } + + + // FILTERING + + function filterMap(toMaybe, base, signal) + { + var maybe = toMaybe(signal.value); + var node = { + id: Utils.guid(), + name: 'filterMap', + value: maybe.ctor === 'Nothing' ? base : maybe._0, + parents: [signal], + kids: [] + }; + + node.notify = function(timestamp, parentUpdate, parentID) + { + var update = false; + if (parentUpdate) + { + var maybe = toMaybe(signal.value); + if (maybe.ctor === 'Just') + { + update = true; + node.value = maybe._0; + } + } + broadcastToKids(node, timestamp, update); + }; + + signal.kids.push(node); + + return node; + } + + + // SAMPLING + + function sampleOn(ticker, signal) + { + var node = { + id: Utils.guid(), + name: 'sampleOn', + value: signal.value, + parents: [ticker, signal], + kids: [] + }; + + var signalTouch = false; + var tickerTouch = false; + var tickerUpdate = false; + + node.notify = function(timestamp, parentUpdate, parentID) + { + if (parentID === ticker.id) + { + tickerTouch = true; + tickerUpdate = parentUpdate; + } + if (parentID === signal.id) + { + signalTouch = true; + } + + if (tickerTouch && signalTouch) + { + if (tickerUpdate) + { + node.value = signal.value; + } + tickerTouch = false; + signalTouch = false; + + broadcastToKids(node, timestamp, tickerUpdate); + } + }; + + ticker.kids.push(node); + signal.kids.push(node); + + return node; + } + + + // DROP REPEATS + + function dropRepeats(signal) + { + var node = { + id: Utils.guid(), + name: 'dropRepeats', + value: signal.value, + parents: [signal], + kids: [] + }; + + node.notify = function(timestamp, parentUpdate, parentID) + { + var update = false; + if (parentUpdate && !Utils.eq(node.value, signal.value)) + { + node.value = signal.value; + update = true; + } + broadcastToKids(node, timestamp, update); + }; + + signal.kids.push(node); + + return node; + } + + + return localRuntime.Native.Signal.values = { + input: input, + constant: constant, + mailbox: mailbox, + sendMessage: sendMessage, + output: output, + map: F2(map), + map2: F3(map2), + map3: F4(map3), + map4: F5(map4), + map5: F6(map5), + foldp: F3(foldp), + genericMerge: F3(genericMerge), + filterMap: F3(filterMap), + sampleOn: F2(sampleOn), + dropRepeats: dropRepeats, + timestamp: timestamp, + delay: F2(delay) + }; +}; + +Elm.Native.Transform2D = {}; +Elm.Native.Transform2D.make = function(localRuntime) { + localRuntime.Native = localRuntime.Native || {}; + localRuntime.Native.Transform2D = localRuntime.Native.Transform2D || {}; + if (localRuntime.Native.Transform2D.values) + { + return localRuntime.Native.Transform2D.values; + } + + var A; + if (typeof Float32Array === 'undefined') + { + A = function(arr) + { + this.length = arr.length; + this[0] = arr[0]; + this[1] = arr[1]; + this[2] = arr[2]; + this[3] = arr[3]; + this[4] = arr[4]; + this[5] = arr[5]; + }; + } + else + { + A = Float32Array; + } + + // layout of matrix in an array is + // + // | m11 m12 dx | + // | m21 m22 dy | + // | 0 0 1 | + // + // new A([ m11, m12, dx, m21, m22, dy ]) + + var identity = new A([1, 0, 0, 0, 1, 0]); + function matrix(m11, m12, m21, m22, dx, dy) + { + return new A([m11, m12, dx, m21, m22, dy]); + } + + function rotation(t) + { + var c = Math.cos(t); + var s = Math.sin(t); + return new A([c, -s, 0, s, c, 0]); + } + + function rotate(t, m) + { + var c = Math.cos(t); + var s = Math.sin(t); + var m11 = m[0], m12 = m[1], m21 = m[3], m22 = m[4]; + return new A([m11 * c + m12 * s, -m11 * s + m12 * c, m[2], + m21 * c + m22 * s, -m21 * s + m22 * c, m[5]]); + } + /* + function move(xy,m) { + var x = xy._0; + var y = xy._1; + var m11 = m[0], m12 = m[1], m21 = m[3], m22 = m[4]; + return new A([m11, m12, m11*x + m12*y + m[2], + m21, m22, m21*x + m22*y + m[5]]); + } + function scale(s,m) { return new A([m[0]*s, m[1]*s, m[2], m[3]*s, m[4]*s, m[5]]); } + function scaleX(x,m) { return new A([m[0]*x, m[1], m[2], m[3]*x, m[4], m[5]]); } + function scaleY(y,m) { return new A([m[0], m[1]*y, m[2], m[3], m[4]*y, m[5]]); } + function reflectX(m) { return new A([-m[0], m[1], m[2], -m[3], m[4], m[5]]); } + function reflectY(m) { return new A([m[0], -m[1], m[2], m[3], -m[4], m[5]]); } + + function transform(m11, m21, m12, m22, mdx, mdy, n) { + var n11 = n[0], n12 = n[1], n21 = n[3], n22 = n[4], ndx = n[2], ndy = n[5]; + return new A([m11*n11 + m12*n21, + m11*n12 + m12*n22, + m11*ndx + m12*ndy + mdx, + m21*n11 + m22*n21, + m21*n12 + m22*n22, + m21*ndx + m22*ndy + mdy]); + } + */ + function multiply(m, n) + { + var m11 = m[0], m12 = m[1], m21 = m[3], m22 = m[4], mdx = m[2], mdy = m[5]; + var n11 = n[0], n12 = n[1], n21 = n[3], n22 = n[4], ndx = n[2], ndy = n[5]; + return new A([m11 * n11 + m12 * n21, + m11 * n12 + m12 * n22, + m11 * ndx + m12 * ndy + mdx, + m21 * n11 + m22 * n21, + m21 * n12 + m22 * n22, + m21 * ndx + m22 * ndy + mdy]); + } + + return localRuntime.Native.Transform2D.values = { + identity: identity, + matrix: F6(matrix), + rotation: rotation, + multiply: F2(multiply) + /* + transform: F7(transform), + rotate: F2(rotate), + move: F2(move), + scale: F2(scale), + scaleX: F2(scaleX), + scaleY: F2(scaleY), + reflectX: reflectX, + reflectY: reflectY + */ + }; +}; + +Elm.Transform2D = Elm.Transform2D || {}; +Elm.Transform2D.make = function (_elm) { + "use strict"; + _elm.Transform2D = _elm.Transform2D || {}; + if (_elm.Transform2D.values) return _elm.Transform2D.values; + var _U = Elm.Native.Utils.make(_elm),$Native$Transform2D = Elm.Native.Transform2D.make(_elm); + var _op = {}; + var multiply = $Native$Transform2D.multiply; + var rotation = $Native$Transform2D.rotation; + var matrix = $Native$Transform2D.matrix; + var translation = F2(function (x,y) { return A6(matrix,1,0,0,1,x,y);}); + var scale = function (s) { return A6(matrix,s,0,0,s,0,0);}; + var scaleX = function (x) { return A6(matrix,x,0,0,1,0,0);}; + var scaleY = function (y) { return A6(matrix,1,0,0,y,0,0);}; + var identity = $Native$Transform2D.identity; + var Transform2D = {ctor: "Transform2D"}; + return _elm.Transform2D.values = {_op: _op + ,identity: identity + ,matrix: matrix + ,multiply: multiply + ,rotation: rotation + ,translation: translation + ,scale: scale + ,scaleX: scaleX + ,scaleY: scaleY}; +}; + +// setup +Elm.Native = Elm.Native || {}; +Elm.Native.Graphics = Elm.Native.Graphics || {}; +Elm.Native.Graphics.Collage = Elm.Native.Graphics.Collage || {}; + +// definition +Elm.Native.Graphics.Collage.make = function(localRuntime) { + 'use strict'; + + // attempt to short-circuit + localRuntime.Native = localRuntime.Native || {}; + localRuntime.Native.Graphics = localRuntime.Native.Graphics || {}; + localRuntime.Native.Graphics.Collage = localRuntime.Native.Graphics.Collage || {}; + if ('values' in localRuntime.Native.Graphics.Collage) + { + return localRuntime.Native.Graphics.Collage.values; + } + + // okay, we cannot short-ciruit, so now we define everything + var Color = Elm.Native.Color.make(localRuntime); + var List = Elm.Native.List.make(localRuntime); + var NativeElement = Elm.Native.Graphics.Element.make(localRuntime); + var Transform = Elm.Transform2D.make(localRuntime); + var Utils = Elm.Native.Utils.make(localRuntime); + + function setStrokeStyle(ctx, style) + { + ctx.lineWidth = style.width; + + var cap = style.cap.ctor; + ctx.lineCap = cap === 'Flat' + ? 'butt' + : cap === 'Round' + ? 'round' + : 'square'; + + var join = style.join.ctor; + ctx.lineJoin = join === 'Smooth' + ? 'round' + : join === 'Sharp' + ? 'miter' + : 'bevel'; + + ctx.miterLimit = style.join._0 || 10; + ctx.strokeStyle = Color.toCss(style.color); + } + + function setFillStyle(redo, ctx, style) + { + var sty = style.ctor; + ctx.fillStyle = sty === 'Solid' + ? Color.toCss(style._0) + : sty === 'Texture' + ? texture(redo, ctx, style._0) + : gradient(ctx, style._0); + } + + function trace(ctx, path) + { + var points = List.toArray(path); + var i = points.length - 1; + if (i <= 0) + { + return; + } + ctx.moveTo(points[i]._0, points[i]._1); + while (i--) + { + ctx.lineTo(points[i]._0, points[i]._1); + } + if (path.closed) + { + i = points.length - 1; + ctx.lineTo(points[i]._0, points[i]._1); + } + } + + function line(ctx, style, path) + { + if (style.dashing.ctor === '[]') + { + trace(ctx, path); + } + else + { + customLineHelp(ctx, style, path); + } + ctx.scale(1, -1); + ctx.stroke(); + } + + function customLineHelp(ctx, style, path) + { + var points = List.toArray(path); + if (path.closed) + { + points.push(points[0]); + } + var pattern = List.toArray(style.dashing); + var i = points.length - 1; + if (i <= 0) + { + return; + } + var x0 = points[i]._0, y0 = points[i]._1; + var x1 = 0, y1 = 0, dx = 0, dy = 0, remaining = 0; + var pindex = 0, plen = pattern.length; + var draw = true, segmentLength = pattern[0]; + ctx.moveTo(x0, y0); + while (i--) + { + x1 = points[i]._0; + y1 = points[i]._1; + dx = x1 - x0; + dy = y1 - y0; + remaining = Math.sqrt(dx * dx + dy * dy); + while (segmentLength <= remaining) + { + x0 += dx * segmentLength / remaining; + y0 += dy * segmentLength / remaining; + ctx[draw ? 'lineTo' : 'moveTo'](x0, y0); + // update starting position + dx = x1 - x0; + dy = y1 - y0; + remaining = Math.sqrt(dx * dx + dy * dy); + // update pattern + draw = !draw; + pindex = (pindex + 1) % plen; + segmentLength = pattern[pindex]; + } + if (remaining > 0) + { + ctx[draw ? 'lineTo' : 'moveTo'](x1, y1); + segmentLength -= remaining; + } + x0 = x1; + y0 = y1; + } + } + + function drawLine(ctx, style, path) + { + setStrokeStyle(ctx, style); + return line(ctx, style, path); + } + + function texture(redo, ctx, src) + { + var img = new Image(); + img.src = src; + img.onload = redo; + return ctx.createPattern(img, 'repeat'); + } + + function gradient(ctx, grad) + { + var g; + var stops = []; + if (grad.ctor === 'Linear') + { + var p0 = grad._0, p1 = grad._1; + g = ctx.createLinearGradient(p0._0, -p0._1, p1._0, -p1._1); + stops = List.toArray(grad._2); + } + else + { + var p0 = grad._0, p2 = grad._2; + g = ctx.createRadialGradient(p0._0, -p0._1, grad._1, p2._0, -p2._1, grad._3); + stops = List.toArray(grad._4); + } + var len = stops.length; + for (var i = 0; i < len; ++i) + { + var stop = stops[i]; + g.addColorStop(stop._0, Color.toCss(stop._1)); + } + return g; + } + + function drawShape(redo, ctx, style, path) + { + trace(ctx, path); + setFillStyle(redo, ctx, style); + ctx.scale(1, -1); + ctx.fill(); + } + + + // TEXT RENDERING + + function fillText(redo, ctx, text) + { + drawText(ctx, text, ctx.fillText); + } + + function strokeText(redo, ctx, style, text) + { + setStrokeStyle(ctx, style); + // Use native canvas API for dashes only for text for now + // Degrades to non-dashed on IE 9 + 10 + if (style.dashing.ctor !== '[]' && ctx.setLineDash) + { + var pattern = List.toArray(style.dashing); + ctx.setLineDash(pattern); + } + drawText(ctx, text, ctx.strokeText); + } + + function drawText(ctx, text, canvasDrawFn) + { + var textChunks = chunkText(defaultContext, text); + + var totalWidth = 0; + var maxHeight = 0; + var numChunks = textChunks.length; + + ctx.scale(1,-1); + + for (var i = numChunks; i--; ) + { + var chunk = textChunks[i]; + ctx.font = chunk.font; + var metrics = ctx.measureText(chunk.text); + chunk.width = metrics.width; + totalWidth += chunk.width; + if (chunk.height > maxHeight) + { + maxHeight = chunk.height; + } + } + + var x = -totalWidth / 2.0; + for (var i = 0; i < numChunks; ++i) + { + var chunk = textChunks[i]; + ctx.font = chunk.font; + ctx.fillStyle = chunk.color; + canvasDrawFn.call(ctx, chunk.text, x, maxHeight / 2); + x += chunk.width; + } + } + + function toFont(props) + { + return [ + props['font-style'], + props['font-variant'], + props['font-weight'], + props['font-size'], + props['font-family'] + ].join(' '); + } + + + // Convert the object returned by the text module + // into something we can use for styling canvas text + function chunkText(context, text) + { + var tag = text.ctor; + if (tag === 'Text:Append') + { + var leftChunks = chunkText(context, text._0); + var rightChunks = chunkText(context, text._1); + return leftChunks.concat(rightChunks); + } + if (tag === 'Text:Text') + { + return [{ + text: text._0, + color: context.color, + height: context['font-size'].slice(0, -2) | 0, + font: toFont(context) + }]; + } + if (tag === 'Text:Meta') + { + var newContext = freshContext(text._0, context); + return chunkText(newContext, text._1); + } + } + + function freshContext(props, ctx) + { + return { + 'font-style': props['font-style'] || ctx['font-style'], + 'font-variant': props['font-variant'] || ctx['font-variant'], + 'font-weight': props['font-weight'] || ctx['font-weight'], + 'font-size': props['font-size'] || ctx['font-size'], + 'font-family': props['font-family'] || ctx['font-family'], + 'color': props['color'] || ctx['color'] + }; + } + + var defaultContext = { + 'font-style': 'normal', + 'font-variant': 'normal', + 'font-weight': 'normal', + 'font-size': '12px', + 'font-family': 'sans-serif', + 'color': 'black' + }; + + + // IMAGES + + function drawImage(redo, ctx, form) + { + var img = new Image(); + img.onload = redo; + img.src = form._3; + var w = form._0, + h = form._1, + pos = form._2, + srcX = pos._0, + srcY = pos._1, + srcW = w, + srcH = h, + destX = -w / 2, + destY = -h / 2, + destW = w, + destH = h; + + ctx.scale(1, -1); + ctx.drawImage(img, srcX, srcY, srcW, srcH, destX, destY, destW, destH); + } + + function renderForm(redo, ctx, form) + { + ctx.save(); + + var x = form.x, + y = form.y, + theta = form.theta, + scale = form.scale; + + if (x !== 0 || y !== 0) + { + ctx.translate(x, y); + } + if (theta !== 0) + { + ctx.rotate(theta % (Math.PI * 2)); + } + if (scale !== 1) + { + ctx.scale(scale, scale); + } + if (form.alpha !== 1) + { + ctx.globalAlpha = ctx.globalAlpha * form.alpha; + } + + ctx.beginPath(); + var f = form.form; + switch (f.ctor) + { + case 'FPath': + drawLine(ctx, f._0, f._1); + break; + + case 'FImage': + drawImage(redo, ctx, f); + break; + + case 'FShape': + if (f._0.ctor === 'Line') + { + f._1.closed = true; + drawLine(ctx, f._0._0, f._1); + } + else + { + drawShape(redo, ctx, f._0._0, f._1); + } + break; + + case 'FText': + fillText(redo, ctx, f._0); + break; + + case 'FOutlinedText': + strokeText(redo, ctx, f._0, f._1); + break; + } + ctx.restore(); + } + + function formToMatrix(form) + { + var scale = form.scale; + var matrix = A6( Transform.matrix, scale, 0, 0, scale, form.x, form.y ); + + var theta = form.theta; + if (theta !== 0) + { + matrix = A2( Transform.multiply, matrix, Transform.rotation(theta) ); + } + + return matrix; + } + + function str(n) + { + if (n < 0.00001 && n > -0.00001) + { + return 0; + } + return n; + } + + function makeTransform(w, h, form, matrices) + { + var props = form.form._0._0.props; + var m = A6( Transform.matrix, 1, 0, 0, -1, + (w - props.width ) / 2, + (h - props.height) / 2 ); + var len = matrices.length; + for (var i = 0; i < len; ++i) + { + m = A2( Transform.multiply, m, matrices[i] ); + } + m = A2( Transform.multiply, m, formToMatrix(form) ); + + return 'matrix(' + + str( m[0]) + ', ' + str( m[3]) + ', ' + + str(-m[1]) + ', ' + str(-m[4]) + ', ' + + str( m[2]) + ', ' + str( m[5]) + ')'; + } + + function stepperHelp(list) + { + var arr = List.toArray(list); + var i = 0; + function peekNext() + { + return i < arr.length ? arr[i]._0.form.ctor : ''; + } + // assumes that there is a next element + function next() + { + var out = arr[i]._0; + ++i; + return out; + } + return { + peekNext: peekNext, + next: next + }; + } + + function formStepper(forms) + { + var ps = [stepperHelp(forms)]; + var matrices = []; + var alphas = []; + function peekNext() + { + var len = ps.length; + var formType = ''; + for (var i = 0; i < len; ++i ) + { + if (formType = ps[i].peekNext()) return formType; + } + return ''; + } + // assumes that there is a next element + function next(ctx) + { + while (!ps[0].peekNext()) + { + ps.shift(); + matrices.pop(); + alphas.shift(); + if (ctx) + { + ctx.restore(); + } + } + var out = ps[0].next(); + var f = out.form; + if (f.ctor === 'FGroup') + { + ps.unshift(stepperHelp(f._1)); + var m = A2(Transform.multiply, f._0, formToMatrix(out)); + ctx.save(); + ctx.transform(m[0], m[3], m[1], m[4], m[2], m[5]); + matrices.push(m); + + var alpha = (alphas[0] || 1) * out.alpha; + alphas.unshift(alpha); + ctx.globalAlpha = alpha; + } + return out; + } + function transforms() + { + return matrices; + } + function alpha() + { + return alphas[0] || 1; + } + return { + peekNext: peekNext, + next: next, + transforms: transforms, + alpha: alpha + }; + } + + function makeCanvas(w, h) + { + var canvas = NativeElement.createNode('canvas'); + canvas.style.width = w + 'px'; + canvas.style.height = h + 'px'; + canvas.style.display = 'block'; + canvas.style.position = 'absolute'; + var ratio = window.devicePixelRatio || 1; + canvas.width = w * ratio; + canvas.height = h * ratio; + return canvas; + } + + function render(model) + { + var div = NativeElement.createNode('div'); + div.style.overflow = 'hidden'; + div.style.position = 'relative'; + update(div, model, model); + return div; + } + + function nodeStepper(w, h, div) + { + var kids = div.childNodes; + var i = 0; + var ratio = window.devicePixelRatio || 1; + + function transform(transforms, ctx) + { + ctx.translate( w / 2 * ratio, h / 2 * ratio ); + ctx.scale( ratio, -ratio ); + var len = transforms.length; + for (var i = 0; i < len; ++i) + { + var m = transforms[i]; + ctx.save(); + ctx.transform(m[0], m[3], m[1], m[4], m[2], m[5]); + } + return ctx; + } + function nextContext(transforms) + { + while (i < kids.length) + { + var node = kids[i]; + if (node.getContext) + { + node.width = w * ratio; + node.height = h * ratio; + node.style.width = w + 'px'; + node.style.height = h + 'px'; + ++i; + return transform(transforms, node.getContext('2d')); + } + div.removeChild(node); + } + var canvas = makeCanvas(w, h); + div.appendChild(canvas); + // we have added a new node, so we must step our position + ++i; + return transform(transforms, canvas.getContext('2d')); + } + function addElement(matrices, alpha, form) + { + var kid = kids[i]; + var elem = form.form._0; + + var node = (!kid || kid.getContext) + ? NativeElement.render(elem) + : NativeElement.update(kid, kid.oldElement, elem); + + node.style.position = 'absolute'; + node.style.opacity = alpha * form.alpha * elem._0.props.opacity; + NativeElement.addTransform(node.style, makeTransform(w, h, form, matrices)); + node.oldElement = elem; + ++i; + if (!kid) + { + div.appendChild(node); + } + else + { + div.insertBefore(node, kid); + } + } + function clearRest() + { + while (i < kids.length) + { + div.removeChild(kids[i]); + } + } + return { + nextContext: nextContext, + addElement: addElement, + clearRest: clearRest + }; + } + + + function update(div, _, model) + { + var w = model.w; + var h = model.h; + + var forms = formStepper(model.forms); + var nodes = nodeStepper(w, h, div); + var ctx = null; + var formType = ''; + + while (formType = forms.peekNext()) + { + // make sure we have context if we need it + if (ctx === null && formType !== 'FElement') + { + ctx = nodes.nextContext(forms.transforms()); + ctx.globalAlpha = forms.alpha(); + } + + var form = forms.next(ctx); + // if it is FGroup, all updates are made within formStepper when next is called. + if (formType === 'FElement') + { + // update or insert an element, get a new context + nodes.addElement(forms.transforms(), forms.alpha(), form); + ctx = null; + } + else if (formType !== 'FGroup') + { + renderForm(function() { update(div, model, model); }, ctx, form); + } + } + nodes.clearRest(); + return div; + } + + + function collage(w, h, forms) + { + return A3(NativeElement.newElement, w, h, { + ctor: 'Custom', + type: 'Collage', + render: render, + update: update, + model: {w: w, h: h, forms: forms} + }); + } + + return localRuntime.Native.Graphics.Collage.values = { + collage: F3(collage) + }; +}; + + +// setup +Elm.Native = Elm.Native || {}; +Elm.Native.Graphics = Elm.Native.Graphics || {}; +Elm.Native.Graphics.Element = Elm.Native.Graphics.Element || {}; + +// definition +Elm.Native.Graphics.Element.make = function(localRuntime) { + 'use strict'; + + // attempt to short-circuit + localRuntime.Native = localRuntime.Native || {}; + localRuntime.Native.Graphics = localRuntime.Native.Graphics || {}; + localRuntime.Native.Graphics.Element = localRuntime.Native.Graphics.Element || {}; + if ('values' in localRuntime.Native.Graphics.Element) + { + return localRuntime.Native.Graphics.Element.values; + } + + var Color = Elm.Native.Color.make(localRuntime); + var List = Elm.Native.List.make(localRuntime); + var Maybe = Elm.Maybe.make(localRuntime); + var Text = Elm.Native.Text.make(localRuntime); + var Utils = Elm.Native.Utils.make(localRuntime); + + + // CREATION + + var createNode = + typeof document === 'undefined' + ? + function(_) + { + return { + style: {}, + appendChild: function() {} + }; + } + : + function(elementType) + { + var node = document.createElement(elementType); + node.style.padding = '0'; + node.style.margin = '0'; + return node; + } + ; + + + function newElement(width, height, elementPrim) + { + return { + ctor: 'Element_elm_builtin', + _0: { + element: elementPrim, + props: { + id: Utils.guid(), + width: width, + height: height, + opacity: 1, + color: Maybe.Nothing, + href: '', + tag: '', + hover: Utils.Tuple0, + click: Utils.Tuple0 + } + } + }; + } + + + // PROPERTIES + + function setProps(elem, node) + { + var props = elem.props; + + var element = elem.element; + var width = props.width - (element.adjustWidth || 0); + var height = props.height - (element.adjustHeight || 0); + node.style.width = (width | 0) + 'px'; + node.style.height = (height | 0) + 'px'; + + if (props.opacity !== 1) + { + node.style.opacity = props.opacity; + } + + if (props.color.ctor === 'Just') + { + node.style.backgroundColor = Color.toCss(props.color._0); + } + + if (props.tag !== '') + { + node.id = props.tag; + } + + if (props.hover.ctor !== '_Tuple0') + { + addHover(node, props.hover); + } + + if (props.click.ctor !== '_Tuple0') + { + addClick(node, props.click); + } + + if (props.href !== '') + { + var anchor = createNode('a'); + anchor.href = props.href; + anchor.style.display = 'block'; + anchor.style.pointerEvents = 'auto'; + anchor.appendChild(node); + node = anchor; + } + + return node; + } + + function addClick(e, handler) + { + e.style.pointerEvents = 'auto'; + e.elm_click_handler = handler; + function trigger(ev) + { + e.elm_click_handler(Utils.Tuple0); + ev.stopPropagation(); + } + e.elm_click_trigger = trigger; + e.addEventListener('click', trigger); + } + + function removeClick(e, handler) + { + if (e.elm_click_trigger) + { + e.removeEventListener('click', e.elm_click_trigger); + e.elm_click_trigger = null; + e.elm_click_handler = null; + } + } + + function addHover(e, handler) + { + e.style.pointerEvents = 'auto'; + e.elm_hover_handler = handler; + e.elm_hover_count = 0; + + function over(evt) + { + if (e.elm_hover_count++ > 0) return; + e.elm_hover_handler(true); + evt.stopPropagation(); + } + function out(evt) + { + if (e.contains(evt.toElement || evt.relatedTarget)) return; + e.elm_hover_count = 0; + e.elm_hover_handler(false); + evt.stopPropagation(); + } + e.elm_hover_over = over; + e.elm_hover_out = out; + e.addEventListener('mouseover', over); + e.addEventListener('mouseout', out); + } + + function removeHover(e) + { + e.elm_hover_handler = null; + if (e.elm_hover_over) + { + e.removeEventListener('mouseover', e.elm_hover_over); + e.elm_hover_over = null; + } + if (e.elm_hover_out) + { + e.removeEventListener('mouseout', e.elm_hover_out); + e.elm_hover_out = null; + } + } + + + // IMAGES + + function image(props, img) + { + switch (img._0.ctor) + { + case 'Plain': + return plainImage(img._3); + + case 'Fitted': + return fittedImage(props.width, props.height, img._3); + + case 'Cropped': + return croppedImage(img, props.width, props.height, img._3); + + case 'Tiled': + return tiledImage(img._3); + } + } + + function plainImage(src) + { + var img = createNode('img'); + img.src = src; + img.name = src; + img.style.display = 'block'; + return img; + } + + function tiledImage(src) + { + var div = createNode('div'); + div.style.backgroundImage = 'url(' + src + ')'; + return div; + } + + function fittedImage(w, h, src) + { + var div = createNode('div'); + div.style.background = 'url(' + src + ') no-repeat center'; + div.style.webkitBackgroundSize = 'cover'; + div.style.MozBackgroundSize = 'cover'; + div.style.OBackgroundSize = 'cover'; + div.style.backgroundSize = 'cover'; + return div; + } + + function croppedImage(elem, w, h, src) + { + var pos = elem._0._0; + var e = createNode('div'); + e.style.overflow = 'hidden'; + + var img = createNode('img'); + img.onload = function() { + var sw = w / elem._1, sh = h / elem._2; + img.style.width = ((this.width * sw) | 0) + 'px'; + img.style.height = ((this.height * sh) | 0) + 'px'; + img.style.marginLeft = ((- pos._0 * sw) | 0) + 'px'; + img.style.marginTop = ((- pos._1 * sh) | 0) + 'px'; + }; + img.src = src; + img.name = src; + e.appendChild(img); + return e; + } + + + // FLOW + + function goOut(node) + { + node.style.position = 'absolute'; + return node; + } + function goDown(node) + { + return node; + } + function goRight(node) + { + node.style.styleFloat = 'left'; + node.style.cssFloat = 'left'; + return node; + } + + var directionTable = { + DUp: goDown, + DDown: goDown, + DLeft: goRight, + DRight: goRight, + DIn: goOut, + DOut: goOut + }; + function needsReversal(dir) + { + return dir === 'DUp' || dir === 'DLeft' || dir === 'DIn'; + } + + function flow(dir, elist) + { + var array = List.toArray(elist); + var container = createNode('div'); + var goDir = directionTable[dir]; + if (goDir === goOut) + { + container.style.pointerEvents = 'none'; + } + if (needsReversal(dir)) + { + array.reverse(); + } + var len = array.length; + for (var i = 0; i < len; ++i) + { + container.appendChild(goDir(render(array[i]))); + } + return container; + } + + + // CONTAINER + + function toPos(pos) + { + return pos.ctor === 'Absolute' + ? pos._0 + 'px' + : (pos._0 * 100) + '%'; + } + + // must clear right, left, top, bottom, and transform + // before calling this function + function setPos(pos, wrappedElement, e) + { + var elem = wrappedElement._0; + var element = elem.element; + var props = elem.props; + var w = props.width + (element.adjustWidth ? element.adjustWidth : 0); + var h = props.height + (element.adjustHeight ? element.adjustHeight : 0); + + e.style.position = 'absolute'; + e.style.margin = 'auto'; + var transform = ''; + + switch (pos.horizontal.ctor) + { + case 'P': + e.style.right = toPos(pos.x); + e.style.removeProperty('left'); + break; + + case 'Z': + transform = 'translateX(' + ((-w / 2) | 0) + 'px) '; + + case 'N': + e.style.left = toPos(pos.x); + e.style.removeProperty('right'); + break; + } + switch (pos.vertical.ctor) + { + case 'N': + e.style.bottom = toPos(pos.y); + e.style.removeProperty('top'); + break; + + case 'Z': + transform += 'translateY(' + ((-h / 2) | 0) + 'px)'; + + case 'P': + e.style.top = toPos(pos.y); + e.style.removeProperty('bottom'); + break; + } + if (transform !== '') + { + addTransform(e.style, transform); + } + return e; + } + + function addTransform(style, transform) + { + style.transform = transform; + style.msTransform = transform; + style.MozTransform = transform; + style.webkitTransform = transform; + style.OTransform = transform; + } + + function container(pos, elem) + { + var e = render(elem); + setPos(pos, elem, e); + var div = createNode('div'); + div.style.position = 'relative'; + div.style.overflow = 'hidden'; + div.appendChild(e); + return div; + } + + + function rawHtml(elem) + { + var html = elem.html; + var align = elem.align; + + var div = createNode('div'); + div.innerHTML = html; + div.style.visibility = 'hidden'; + if (align) + { + div.style.textAlign = align; + } + div.style.visibility = 'visible'; + div.style.pointerEvents = 'auto'; + return div; + } + + + // RENDER + + function render(wrappedElement) + { + var elem = wrappedElement._0; + return setProps(elem, makeElement(elem)); + } + + function makeElement(e) + { + var elem = e.element; + switch (elem.ctor) + { + case 'Image': + return image(e.props, elem); + + case 'Flow': + return flow(elem._0.ctor, elem._1); + + case 'Container': + return container(elem._0, elem._1); + + case 'Spacer': + return createNode('div'); + + case 'RawHtml': + return rawHtml(elem); + + case 'Custom': + return elem.render(elem.model); + } + } + + function updateAndReplace(node, curr, next) + { + var newNode = update(node, curr, next); + if (newNode !== node) + { + node.parentNode.replaceChild(newNode, node); + } + return newNode; + } + + + // UPDATE + + function update(node, wrappedCurrent, wrappedNext) + { + var curr = wrappedCurrent._0; + var next = wrappedNext._0; + var rootNode = node; + if (node.tagName === 'A') + { + node = node.firstChild; + } + if (curr.props.id === next.props.id) + { + updateProps(node, curr, next); + return rootNode; + } + if (curr.element.ctor !== next.element.ctor) + { + return render(wrappedNext); + } + var nextE = next.element; + var currE = curr.element; + switch (nextE.ctor) + { + case 'Spacer': + updateProps(node, curr, next); + return rootNode; + + case 'RawHtml': + if(currE.html.valueOf() !== nextE.html.valueOf()) + { + node.innerHTML = nextE.html; + } + updateProps(node, curr, next); + return rootNode; + + case 'Image': + if (nextE._0.ctor === 'Plain') + { + if (nextE._3 !== currE._3) + { + node.src = nextE._3; + } + } + else if (!Utils.eq(nextE, currE) + || next.props.width !== curr.props.width + || next.props.height !== curr.props.height) + { + return render(wrappedNext); + } + updateProps(node, curr, next); + return rootNode; + + case 'Flow': + var arr = List.toArray(nextE._1); + for (var i = arr.length; i--; ) + { + arr[i] = arr[i]._0.element.ctor; + } + if (nextE._0.ctor !== currE._0.ctor) + { + return render(wrappedNext); + } + var nexts = List.toArray(nextE._1); + var kids = node.childNodes; + if (nexts.length !== kids.length) + { + return render(wrappedNext); + } + var currs = List.toArray(currE._1); + var dir = nextE._0.ctor; + var goDir = directionTable[dir]; + var toReverse = needsReversal(dir); + var len = kids.length; + for (var i = len; i--; ) + { + var subNode = kids[toReverse ? len - i - 1 : i]; + goDir(updateAndReplace(subNode, currs[i], nexts[i])); + } + updateProps(node, curr, next); + return rootNode; + + case 'Container': + var subNode = node.firstChild; + var newSubNode = updateAndReplace(subNode, currE._1, nextE._1); + setPos(nextE._0, nextE._1, newSubNode); + updateProps(node, curr, next); + return rootNode; + + case 'Custom': + if (currE.type === nextE.type) + { + var updatedNode = nextE.update(node, currE.model, nextE.model); + updateProps(updatedNode, curr, next); + return updatedNode; + } + return render(wrappedNext); + } + } + + function updateProps(node, curr, next) + { + var nextProps = next.props; + var currProps = curr.props; + + var element = next.element; + var width = nextProps.width - (element.adjustWidth || 0); + var height = nextProps.height - (element.adjustHeight || 0); + if (width !== currProps.width) + { + node.style.width = (width | 0) + 'px'; + } + if (height !== currProps.height) + { + node.style.height = (height | 0) + 'px'; + } + + if (nextProps.opacity !== currProps.opacity) + { + node.style.opacity = nextProps.opacity; + } + + var nextColor = nextProps.color.ctor === 'Just' + ? Color.toCss(nextProps.color._0) + : ''; + if (node.style.backgroundColor !== nextColor) + { + node.style.backgroundColor = nextColor; + } + + if (nextProps.tag !== currProps.tag) + { + node.id = nextProps.tag; + } + + if (nextProps.href !== currProps.href) + { + if (currProps.href === '') + { + // add a surrounding href + var anchor = createNode('a'); + anchor.href = nextProps.href; + anchor.style.display = 'block'; + anchor.style.pointerEvents = 'auto'; + + node.parentNode.replaceChild(anchor, node); + anchor.appendChild(node); + } + else if (nextProps.href === '') + { + // remove the surrounding href + var anchor = node.parentNode; + anchor.parentNode.replaceChild(node, anchor); + } + else + { + // just update the link + node.parentNode.href = nextProps.href; + } + } + + // update click and hover handlers + var removed = false; + + // update hover handlers + if (currProps.hover.ctor === '_Tuple0') + { + if (nextProps.hover.ctor !== '_Tuple0') + { + addHover(node, nextProps.hover); + } + } + else + { + if (nextProps.hover.ctor === '_Tuple0') + { + removed = true; + removeHover(node); + } + else + { + node.elm_hover_handler = nextProps.hover; + } + } + + // update click handlers + if (currProps.click.ctor === '_Tuple0') + { + if (nextProps.click.ctor !== '_Tuple0') + { + addClick(node, nextProps.click); + } + } + else + { + if (nextProps.click.ctor === '_Tuple0') + { + removed = true; + removeClick(node); + } + else + { + node.elm_click_handler = nextProps.click; + } + } + + // stop capturing clicks if + if (removed + && nextProps.hover.ctor === '_Tuple0' + && nextProps.click.ctor === '_Tuple0') + { + node.style.pointerEvents = 'none'; + } + } + + + // TEXT + + function block(align) + { + return function(text) + { + var raw = { + ctor: 'RawHtml', + html: Text.renderHtml(text), + align: align + }; + var pos = htmlHeight(0, raw); + return newElement(pos._0, pos._1, raw); + }; + } + + function markdown(text) + { + var raw = { + ctor: 'RawHtml', + html: text, + align: null + }; + var pos = htmlHeight(0, raw); + return newElement(pos._0, pos._1, raw); + } + + var htmlHeight = + typeof document !== 'undefined' + ? realHtmlHeight + : function(a, b) { return Utils.Tuple2(0, 0); }; + + function realHtmlHeight(width, rawHtml) + { + // create dummy node + var temp = document.createElement('div'); + temp.innerHTML = rawHtml.html; + if (width > 0) + { + temp.style.width = width + 'px'; + } + temp.style.visibility = 'hidden'; + temp.style.styleFloat = 'left'; + temp.style.cssFloat = 'left'; + + document.body.appendChild(temp); + + // get dimensions + var style = window.getComputedStyle(temp, null); + var w = Math.ceil(style.getPropertyValue('width').slice(0, -2) - 0); + var h = Math.ceil(style.getPropertyValue('height').slice(0, -2) - 0); + document.body.removeChild(temp); + return Utils.Tuple2(w, h); + } + + + return localRuntime.Native.Graphics.Element.values = { + render: render, + update: update, + updateAndReplace: updateAndReplace, + + createNode: createNode, + newElement: F3(newElement), + addTransform: addTransform, + htmlHeight: F2(htmlHeight), + guid: Utils.guid, + + block: block, + markdown: markdown + }; +}; + +Elm.Native.Text = {}; +Elm.Native.Text.make = function(localRuntime) { + localRuntime.Native = localRuntime.Native || {}; + localRuntime.Native.Text = localRuntime.Native.Text || {}; + if (localRuntime.Native.Text.values) + { + return localRuntime.Native.Text.values; + } + + var toCss = Elm.Native.Color.make(localRuntime).toCss; + var List = Elm.Native.List.make(localRuntime); + + + // CONSTRUCTORS + + function fromString(str) + { + return { + ctor: 'Text:Text', + _0: str + }; + } + + function append(a, b) + { + return { + ctor: 'Text:Append', + _0: a, + _1: b + }; + } + + function addMeta(field, value, text) + { + var newProps = {}; + var newText = { + ctor: 'Text:Meta', + _0: newProps, + _1: text + }; + + if (text.ctor === 'Text:Meta') + { + newText._1 = text._1; + var props = text._0; + for (var i = metaKeys.length; i--; ) + { + var key = metaKeys[i]; + var val = props[key]; + if (val) + { + newProps[key] = val; + } + } + } + newProps[field] = value; + return newText; + } + + var metaKeys = [ + 'font-size', + 'font-family', + 'font-style', + 'font-weight', + 'href', + 'text-decoration', + 'color' + ]; + + + // conversions from Elm values to CSS + + function toTypefaces(list) + { + var typefaces = List.toArray(list); + for (var i = typefaces.length; i--; ) + { + var typeface = typefaces[i]; + if (typeface.indexOf(' ') > -1) + { + typefaces[i] = "'" + typeface + "'"; + } + } + return typefaces.join(','); + } + + function toLine(line) + { + var ctor = line.ctor; + return ctor === 'Under' + ? 'underline' + : ctor === 'Over' + ? 'overline' + : 'line-through'; + } + + // setting styles of Text + + function style(style, text) + { + var newText = addMeta('color', toCss(style.color), text); + var props = newText._0; + + if (style.typeface.ctor !== '[]') + { + props['font-family'] = toTypefaces(style.typeface); + } + if (style.height.ctor !== 'Nothing') + { + props['font-size'] = style.height._0 + 'px'; + } + if (style.bold) + { + props['font-weight'] = 'bold'; + } + if (style.italic) + { + props['font-style'] = 'italic'; + } + if (style.line.ctor !== 'Nothing') + { + props['text-decoration'] = toLine(style.line._0); + } + return newText; + } + + function height(px, text) + { + return addMeta('font-size', px + 'px', text); + } + + function typeface(names, text) + { + return addMeta('font-family', toTypefaces(names), text); + } + + function monospace(text) + { + return addMeta('font-family', 'monospace', text); + } + + function italic(text) + { + return addMeta('font-style', 'italic', text); + } + + function bold(text) + { + return addMeta('font-weight', 'bold', text); + } + + function link(href, text) + { + return addMeta('href', href, text); + } + + function line(line, text) + { + return addMeta('text-decoration', toLine(line), text); + } + + function color(color, text) + { + return addMeta('color', toCss(color), text); + } + + + // RENDER + + function renderHtml(text) + { + var tag = text.ctor; + if (tag === 'Text:Append') + { + return renderHtml(text._0) + renderHtml(text._1); + } + if (tag === 'Text:Text') + { + return properEscape(text._0); + } + if (tag === 'Text:Meta') + { + return renderMeta(text._0, renderHtml(text._1)); + } + } + + function renderMeta(metas, string) + { + var href = metas.href; + if (href) + { + string = '' + string + ''; + } + var styles = ''; + for (var key in metas) + { + if (key === 'href') + { + continue; + } + styles += key + ':' + metas[key] + ';'; + } + if (styles) + { + string = '' + string + ''; + } + return string; + } + + function properEscape(str) + { + if (str.length === 0) + { + return str; + } + str = str //.replace(/&/g, '&') + .replace(/"/g, '"') + .replace(/'/g, ''') + .replace(//g, '>'); + var arr = str.split('\n'); + for (var i = arr.length; i--; ) + { + arr[i] = makeSpaces(arr[i]); + } + return arr.join('
'); + } + + function makeSpaces(s) + { + if (s.length === 0) + { + return s; + } + var arr = s.split(''); + if (arr[0] === ' ') + { + arr[0] = ' '; + } + for (var i = arr.length; --i; ) + { + if (arr[i][0] === ' ' && arr[i - 1] === ' ') + { + arr[i - 1] = arr[i - 1] + arr[i]; + arr[i] = ''; + } + } + for (var i = arr.length; i--; ) + { + if (arr[i].length > 1 && arr[i][0] === ' ') + { + var spaces = arr[i].split(''); + for (var j = spaces.length - 2; j >= 0; j -= 2) + { + spaces[j] = ' '; + } + arr[i] = spaces.join(''); + } + } + arr = arr.join(''); + if (arr[arr.length - 1] === ' ') + { + return arr.slice(0, -1) + ' '; + } + return arr; + } + + + return localRuntime.Native.Text.values = { + fromString: fromString, + append: F2(append), + + height: F2(height), + italic: italic, + bold: bold, + line: F2(line), + monospace: monospace, + typeface: F2(typeface), + color: F2(color), + link: F2(link), + style: F2(style), + + toTypefaces: toTypefaces, + toLine: toLine, + renderHtml: renderHtml + }; +}; + +Elm.Text = Elm.Text || {}; +Elm.Text.make = function (_elm) { + "use strict"; + _elm.Text = _elm.Text || {}; + if (_elm.Text.values) return _elm.Text.values; + var _U = Elm.Native.Utils.make(_elm), + $Color = Elm.Color.make(_elm), + $List = Elm.List.make(_elm), + $Maybe = Elm.Maybe.make(_elm), + $Native$Text = Elm.Native.Text.make(_elm); + var _op = {}; + var line = $Native$Text.line; + var italic = $Native$Text.italic; + var bold = $Native$Text.bold; + var color = $Native$Text.color; + var height = $Native$Text.height; + var link = $Native$Text.link; + var monospace = $Native$Text.monospace; + var typeface = $Native$Text.typeface; + var style = $Native$Text.style; + var append = $Native$Text.append; + var fromString = $Native$Text.fromString; + var empty = fromString(""); + var concat = function (texts) { return A3($List.foldr,append,empty,texts);}; + var join = F2(function (seperator,texts) { return concat(A2($List.intersperse,seperator,texts));}); + var defaultStyle = {typeface: _U.list([]),height: $Maybe.Nothing,color: $Color.black,bold: false,italic: false,line: $Maybe.Nothing}; + var Style = F6(function (a,b,c,d,e,f) { return {typeface: a,height: b,color: c,bold: d,italic: e,line: f};}); + var Through = {ctor: "Through"}; + var Over = {ctor: "Over"}; + var Under = {ctor: "Under"}; + var Text = {ctor: "Text"}; + return _elm.Text.values = {_op: _op + ,fromString: fromString + ,empty: empty + ,append: append + ,concat: concat + ,join: join + ,link: link + ,style: style + ,defaultStyle: defaultStyle + ,typeface: typeface + ,monospace: monospace + ,height: height + ,color: color + ,bold: bold + ,italic: italic + ,line: line + ,Style: Style + ,Under: Under + ,Over: Over + ,Through: Through}; +}; +Elm.Graphics = Elm.Graphics || {}; +Elm.Graphics.Element = Elm.Graphics.Element || {}; +Elm.Graphics.Element.make = function (_elm) { + "use strict"; + _elm.Graphics = _elm.Graphics || {}; + _elm.Graphics.Element = _elm.Graphics.Element || {}; + if (_elm.Graphics.Element.values) return _elm.Graphics.Element.values; + var _U = Elm.Native.Utils.make(_elm), + $Basics = Elm.Basics.make(_elm), + $Color = Elm.Color.make(_elm), + $List = Elm.List.make(_elm), + $Maybe = Elm.Maybe.make(_elm), + $Native$Graphics$Element = Elm.Native.Graphics.Element.make(_elm), + $Text = Elm.Text.make(_elm); + var _op = {}; + var DOut = {ctor: "DOut"}; + var outward = DOut; + var DIn = {ctor: "DIn"}; + var inward = DIn; + var DRight = {ctor: "DRight"}; + var right = DRight; + var DLeft = {ctor: "DLeft"}; + var left = DLeft; + var DDown = {ctor: "DDown"}; + var down = DDown; + var DUp = {ctor: "DUp"}; + var up = DUp; + var RawPosition = F4(function (a,b,c,d) { return {horizontal: a,vertical: b,x: c,y: d};}); + var Position = function (a) { return {ctor: "Position",_0: a};}; + var Relative = function (a) { return {ctor: "Relative",_0: a};}; + var relative = Relative; + var Absolute = function (a) { return {ctor: "Absolute",_0: a};}; + var absolute = Absolute; + var N = {ctor: "N"}; + var bottomLeft = Position({horizontal: N,vertical: N,x: Absolute(0),y: Absolute(0)}); + var bottomLeftAt = F2(function (x,y) { return Position({horizontal: N,vertical: N,x: x,y: y});}); + var Z = {ctor: "Z"}; + var middle = Position({horizontal: Z,vertical: Z,x: Relative(0.5),y: Relative(0.5)}); + var midLeft = Position({horizontal: N,vertical: Z,x: Absolute(0),y: Relative(0.5)}); + var midBottom = Position({horizontal: Z,vertical: N,x: Relative(0.5),y: Absolute(0)}); + var middleAt = F2(function (x,y) { return Position({horizontal: Z,vertical: Z,x: x,y: y});}); + var midLeftAt = F2(function (x,y) { return Position({horizontal: N,vertical: Z,x: x,y: y});}); + var midBottomAt = F2(function (x,y) { return Position({horizontal: Z,vertical: N,x: x,y: y});}); + var P = {ctor: "P"}; + var topLeft = Position({horizontal: N,vertical: P,x: Absolute(0),y: Absolute(0)}); + var topRight = Position({horizontal: P,vertical: P,x: Absolute(0),y: Absolute(0)}); + var bottomRight = Position({horizontal: P,vertical: N,x: Absolute(0),y: Absolute(0)}); + var midRight = Position({horizontal: P,vertical: Z,x: Absolute(0),y: Relative(0.5)}); + var midTop = Position({horizontal: Z,vertical: P,x: Relative(0.5),y: Absolute(0)}); + var topLeftAt = F2(function (x,y) { return Position({horizontal: N,vertical: P,x: x,y: y});}); + var topRightAt = F2(function (x,y) { return Position({horizontal: P,vertical: P,x: x,y: y});}); + var bottomRightAt = F2(function (x,y) { return Position({horizontal: P,vertical: N,x: x,y: y});}); + var midRightAt = F2(function (x,y) { return Position({horizontal: P,vertical: Z,x: x,y: y});}); + var midTopAt = F2(function (x,y) { return Position({horizontal: Z,vertical: P,x: x,y: y});}); + var justified = $Native$Graphics$Element.block("justify"); + var centered = $Native$Graphics$Element.block("center"); + var rightAligned = $Native$Graphics$Element.block("right"); + var leftAligned = $Native$Graphics$Element.block("left"); + var show = function (value) { return leftAligned($Text.monospace($Text.fromString($Basics.toString(value))));}; + var Tiled = {ctor: "Tiled"}; + var Cropped = function (a) { return {ctor: "Cropped",_0: a};}; + var Fitted = {ctor: "Fitted"}; + var Plain = {ctor: "Plain"}; + var Custom = {ctor: "Custom"}; + var RawHtml = {ctor: "RawHtml"}; + var Spacer = {ctor: "Spacer"}; + var Flow = F2(function (a,b) { return {ctor: "Flow",_0: a,_1: b};}); + var Container = F2(function (a,b) { return {ctor: "Container",_0: a,_1: b};}); + var Image = F4(function (a,b,c,d) { return {ctor: "Image",_0: a,_1: b,_2: c,_3: d};}); + var newElement = $Native$Graphics$Element.newElement; + var image = F3(function (w,h,src) { return A3(newElement,w,h,A4(Image,Plain,w,h,src));}); + var fittedImage = F3(function (w,h,src) { return A3(newElement,w,h,A4(Image,Fitted,w,h,src));}); + var croppedImage = F4(function (pos,w,h,src) { return A3(newElement,w,h,A4(Image,Cropped(pos),w,h,src));}); + var tiledImage = F3(function (w,h,src) { return A3(newElement,w,h,A4(Image,Tiled,w,h,src));}); + var container = F4(function (w,h,_p0,e) { var _p1 = _p0;return A3(newElement,w,h,A2(Container,_p1._0,e));}); + var spacer = F2(function (w,h) { return A3(newElement,w,h,Spacer);}); + var sizeOf = function (_p2) { var _p3 = _p2;var _p4 = _p3._0;return {ctor: "_Tuple2",_0: _p4.props.width,_1: _p4.props.height};}; + var heightOf = function (_p5) { var _p6 = _p5;return _p6._0.props.height;}; + var widthOf = function (_p7) { var _p8 = _p7;return _p8._0.props.width;}; + var above = F2(function (hi,lo) { + return A3(newElement,A2($Basics.max,widthOf(hi),widthOf(lo)),heightOf(hi) + heightOf(lo),A2(Flow,DDown,_U.list([hi,lo]))); + }); + var below = F2(function (lo,hi) { + return A3(newElement,A2($Basics.max,widthOf(hi),widthOf(lo)),heightOf(hi) + heightOf(lo),A2(Flow,DDown,_U.list([hi,lo]))); + }); + var beside = F2(function (lft,rht) { + return A3(newElement,widthOf(lft) + widthOf(rht),A2($Basics.max,heightOf(lft),heightOf(rht)),A2(Flow,right,_U.list([lft,rht]))); + }); + var layers = function (es) { + var hs = A2($List.map,heightOf,es); + var ws = A2($List.map,widthOf,es); + return A3(newElement,A2($Maybe.withDefault,0,$List.maximum(ws)),A2($Maybe.withDefault,0,$List.maximum(hs)),A2(Flow,DOut,es)); + }; + var empty = A2(spacer,0,0); + var flow = F2(function (dir,es) { + var newFlow = F2(function (w,h) { return A3(newElement,w,h,A2(Flow,dir,es));}); + var maxOrZero = function (list) { return A2($Maybe.withDefault,0,$List.maximum(list));}; + var hs = A2($List.map,heightOf,es); + var ws = A2($List.map,widthOf,es); + if (_U.eq(es,_U.list([]))) return empty; else { + var _p9 = dir; + switch (_p9.ctor) + {case "DUp": return A2(newFlow,maxOrZero(ws),$List.sum(hs)); + case "DDown": return A2(newFlow,maxOrZero(ws),$List.sum(hs)); + case "DLeft": return A2(newFlow,$List.sum(ws),maxOrZero(hs)); + case "DRight": return A2(newFlow,$List.sum(ws),maxOrZero(hs)); + case "DIn": return A2(newFlow,maxOrZero(ws),maxOrZero(hs)); + default: return A2(newFlow,maxOrZero(ws),maxOrZero(hs));} + } + }); + var Properties = F9(function (a,b,c,d,e,f,g,h,i) { return {id: a,width: b,height: c,opacity: d,color: e,href: f,tag: g,hover: h,click: i};}); + var Element_elm_builtin = function (a) { return {ctor: "Element_elm_builtin",_0: a};}; + var width = F2(function (newWidth,_p10) { + var _p11 = _p10; + var _p14 = _p11._0.props; + var _p13 = _p11._0.element; + var newHeight = function () { + var _p12 = _p13; + switch (_p12.ctor) + {case "Image": return $Basics.round($Basics.toFloat(_p12._2) / $Basics.toFloat(_p12._1) * $Basics.toFloat(newWidth)); + case "RawHtml": return $Basics.snd(A2($Native$Graphics$Element.htmlHeight,newWidth,_p13)); + default: return _p14.height;} + }(); + return Element_elm_builtin({element: _p13,props: _U.update(_p14,{width: newWidth,height: newHeight})}); + }); + var height = F2(function (newHeight,_p15) { + var _p16 = _p15; + return Element_elm_builtin({element: _p16._0.element,props: _U.update(_p16._0.props,{height: newHeight})}); + }); + var size = F3(function (w,h,e) { return A2(height,h,A2(width,w,e));}); + var opacity = F2(function (givenOpacity,_p17) { + var _p18 = _p17; + return Element_elm_builtin({element: _p18._0.element,props: _U.update(_p18._0.props,{opacity: givenOpacity})}); + }); + var color = F2(function (clr,_p19) { + var _p20 = _p19; + return Element_elm_builtin({element: _p20._0.element,props: _U.update(_p20._0.props,{color: $Maybe.Just(clr)})}); + }); + var tag = F2(function (name,_p21) { var _p22 = _p21;return Element_elm_builtin({element: _p22._0.element,props: _U.update(_p22._0.props,{tag: name})});}); + var link = F2(function (href,_p23) { + var _p24 = _p23; + return Element_elm_builtin({element: _p24._0.element,props: _U.update(_p24._0.props,{href: href})}); + }); + return _elm.Graphics.Element.values = {_op: _op + ,image: image + ,fittedImage: fittedImage + ,croppedImage: croppedImage + ,tiledImage: tiledImage + ,leftAligned: leftAligned + ,rightAligned: rightAligned + ,centered: centered + ,justified: justified + ,show: show + ,width: width + ,height: height + ,size: size + ,color: color + ,opacity: opacity + ,link: link + ,tag: tag + ,widthOf: widthOf + ,heightOf: heightOf + ,sizeOf: sizeOf + ,flow: flow + ,up: up + ,down: down + ,left: left + ,right: right + ,inward: inward + ,outward: outward + ,layers: layers + ,above: above + ,below: below + ,beside: beside + ,empty: empty + ,spacer: spacer + ,container: container + ,middle: middle + ,midTop: midTop + ,midBottom: midBottom + ,midLeft: midLeft + ,midRight: midRight + ,topLeft: topLeft + ,topRight: topRight + ,bottomLeft: bottomLeft + ,bottomRight: bottomRight + ,absolute: absolute + ,relative: relative + ,middleAt: middleAt + ,midTopAt: midTopAt + ,midBottomAt: midBottomAt + ,midLeftAt: midLeftAt + ,midRightAt: midRightAt + ,topLeftAt: topLeftAt + ,topRightAt: topRightAt + ,bottomLeftAt: bottomLeftAt + ,bottomRightAt: bottomRightAt}; +}; +Elm.Graphics = Elm.Graphics || {}; +Elm.Graphics.Collage = Elm.Graphics.Collage || {}; +Elm.Graphics.Collage.make = function (_elm) { + "use strict"; + _elm.Graphics = _elm.Graphics || {}; + _elm.Graphics.Collage = _elm.Graphics.Collage || {}; + if (_elm.Graphics.Collage.values) return _elm.Graphics.Collage.values; + var _U = Elm.Native.Utils.make(_elm), + $Basics = Elm.Basics.make(_elm), + $Color = Elm.Color.make(_elm), + $Graphics$Element = Elm.Graphics.Element.make(_elm), + $List = Elm.List.make(_elm), + $Native$Graphics$Collage = Elm.Native.Graphics.Collage.make(_elm), + $Text = Elm.Text.make(_elm), + $Transform2D = Elm.Transform2D.make(_elm); + var _op = {}; + var Shape = function (a) { return {ctor: "Shape",_0: a};}; + var polygon = function (points) { return Shape(points);}; + var rect = F2(function (w,h) { + var hh = h / 2; + var hw = w / 2; + return Shape(_U.list([{ctor: "_Tuple2",_0: 0 - hw,_1: 0 - hh} + ,{ctor: "_Tuple2",_0: 0 - hw,_1: hh} + ,{ctor: "_Tuple2",_0: hw,_1: hh} + ,{ctor: "_Tuple2",_0: hw,_1: 0 - hh}])); + }); + var square = function (n) { return A2(rect,n,n);}; + var oval = F2(function (w,h) { + var hh = h / 2; + var hw = w / 2; + var n = 50; + var t = 2 * $Basics.pi / n; + var f = function (i) { return {ctor: "_Tuple2",_0: hw * $Basics.cos(t * i),_1: hh * $Basics.sin(t * i)};}; + return Shape(A2($List.map,f,_U.range(0,n - 1))); + }); + var circle = function (r) { return A2(oval,2 * r,2 * r);}; + var ngon = F2(function (n,r) { + var m = $Basics.toFloat(n); + var t = 2 * $Basics.pi / m; + var f = function (i) { return {ctor: "_Tuple2",_0: r * $Basics.cos(t * i),_1: r * $Basics.sin(t * i)};}; + return Shape(A2($List.map,f,_U.range(0,m - 1))); + }); + var Path = function (a) { return {ctor: "Path",_0: a};}; + var path = function (ps) { return Path(ps);}; + var segment = F2(function (p1,p2) { return Path(_U.list([p1,p2]));}); + var collage = $Native$Graphics$Collage.collage; + var Fill = function (a) { return {ctor: "Fill",_0: a};}; + var Line = function (a) { return {ctor: "Line",_0: a};}; + var FGroup = F2(function (a,b) { return {ctor: "FGroup",_0: a,_1: b};}); + var FElement = function (a) { return {ctor: "FElement",_0: a};}; + var FImage = F4(function (a,b,c,d) { return {ctor: "FImage",_0: a,_1: b,_2: c,_3: d};}); + var FText = function (a) { return {ctor: "FText",_0: a};}; + var FOutlinedText = F2(function (a,b) { return {ctor: "FOutlinedText",_0: a,_1: b};}); + var FShape = F2(function (a,b) { return {ctor: "FShape",_0: a,_1: b};}); + var FPath = F2(function (a,b) { return {ctor: "FPath",_0: a,_1: b};}); + var LineStyle = F6(function (a,b,c,d,e,f) { return {color: a,width: b,cap: c,join: d,dashing: e,dashOffset: f};}); + var Clipped = {ctor: "Clipped"}; + var Sharp = function (a) { return {ctor: "Sharp",_0: a};}; + var Smooth = {ctor: "Smooth"}; + var Padded = {ctor: "Padded"}; + var Round = {ctor: "Round"}; + var Flat = {ctor: "Flat"}; + var defaultLine = {color: $Color.black,width: 1,cap: Flat,join: Sharp(10),dashing: _U.list([]),dashOffset: 0}; + var solid = function (clr) { return _U.update(defaultLine,{color: clr});}; + var dashed = function (clr) { return _U.update(defaultLine,{color: clr,dashing: _U.list([8,4])});}; + var dotted = function (clr) { return _U.update(defaultLine,{color: clr,dashing: _U.list([3,3])});}; + var Grad = function (a) { return {ctor: "Grad",_0: a};}; + var Texture = function (a) { return {ctor: "Texture",_0: a};}; + var Solid = function (a) { return {ctor: "Solid",_0: a};}; + var Form_elm_builtin = function (a) { return {ctor: "Form_elm_builtin",_0: a};}; + var form = function (f) { return Form_elm_builtin({theta: 0,scale: 1,x: 0,y: 0,alpha: 1,form: f});}; + var fill = F2(function (style,_p0) { var _p1 = _p0;return form(A2(FShape,Fill(style),_p1._0));}); + var filled = F2(function (color,shape) { return A2(fill,Solid(color),shape);}); + var textured = F2(function (src,shape) { return A2(fill,Texture(src),shape);}); + var gradient = F2(function (grad,shape) { return A2(fill,Grad(grad),shape);}); + var outlined = F2(function (style,_p2) { var _p3 = _p2;return form(A2(FShape,Line(style),_p3._0));}); + var traced = F2(function (style,_p4) { var _p5 = _p4;return form(A2(FPath,style,_p5._0));}); + var sprite = F4(function (w,h,pos,src) { return form(A4(FImage,w,h,pos,src));}); + var toForm = function (e) { return form(FElement(e));}; + var group = function (fs) { return form(A2(FGroup,$Transform2D.identity,fs));}; + var groupTransform = F2(function (matrix,fs) { return form(A2(FGroup,matrix,fs));}); + var text = function (t) { return form(FText(t));}; + var outlinedText = F2(function (ls,t) { return form(A2(FOutlinedText,ls,t));}); + var move = F2(function (_p7,_p6) { + var _p8 = _p7; + var _p9 = _p6; + var _p10 = _p9._0; + return Form_elm_builtin(_U.update(_p10,{x: _p10.x + _p8._0,y: _p10.y + _p8._1})); + }); + var moveX = F2(function (x,_p11) { var _p12 = _p11;var _p13 = _p12._0;return Form_elm_builtin(_U.update(_p13,{x: _p13.x + x}));}); + var moveY = F2(function (y,_p14) { var _p15 = _p14;var _p16 = _p15._0;return Form_elm_builtin(_U.update(_p16,{y: _p16.y + y}));}); + var scale = F2(function (s,_p17) { var _p18 = _p17;var _p19 = _p18._0;return Form_elm_builtin(_U.update(_p19,{scale: _p19.scale * s}));}); + var rotate = F2(function (t,_p20) { var _p21 = _p20;var _p22 = _p21._0;return Form_elm_builtin(_U.update(_p22,{theta: _p22.theta + t}));}); + var alpha = F2(function (a,_p23) { var _p24 = _p23;return Form_elm_builtin(_U.update(_p24._0,{alpha: a}));}); + return _elm.Graphics.Collage.values = {_op: _op + ,collage: collage + ,toForm: toForm + ,filled: filled + ,textured: textured + ,gradient: gradient + ,outlined: outlined + ,traced: traced + ,text: text + ,outlinedText: outlinedText + ,move: move + ,moveX: moveX + ,moveY: moveY + ,scale: scale + ,rotate: rotate + ,alpha: alpha + ,group: group + ,groupTransform: groupTransform + ,rect: rect + ,oval: oval + ,square: square + ,circle: circle + ,ngon: ngon + ,polygon: polygon + ,segment: segment + ,path: path + ,solid: solid + ,dashed: dashed + ,dotted: dotted + ,defaultLine: defaultLine + ,LineStyle: LineStyle + ,Flat: Flat + ,Round: Round + ,Padded: Padded + ,Smooth: Smooth + ,Sharp: Sharp + ,Clipped: Clipped}; +}; +Elm.Native.Debug = {}; +Elm.Native.Debug.make = function(localRuntime) { + localRuntime.Native = localRuntime.Native || {}; + localRuntime.Native.Debug = localRuntime.Native.Debug || {}; + if (localRuntime.Native.Debug.values) + { + return localRuntime.Native.Debug.values; + } + + var toString = Elm.Native.Utils.make(localRuntime).toString; + + function log(tag, value) + { + var msg = tag + ': ' + toString(value); + var process = process || {}; + if (process.stdout) + { + process.stdout.write(msg); + } + else + { + console.log(msg); + } + return value; + } + + function crash(message) + { + throw new Error(message); + } + + function tracePath(tag, form) + { + if (localRuntime.debug) + { + return localRuntime.debug.trace(tag, form); + } + return form; + } + + function watch(tag, value) + { + if (localRuntime.debug) + { + localRuntime.debug.watch(tag, value); + } + return value; + } + + function watchSummary(tag, summarize, value) + { + if (localRuntime.debug) + { + localRuntime.debug.watch(tag, summarize(value)); + } + return value; + } + + return localRuntime.Native.Debug.values = { + crash: crash, + tracePath: F2(tracePath), + log: F2(log), + watch: F2(watch), + watchSummary: F3(watchSummary) + }; +}; + +Elm.Debug = Elm.Debug || {}; +Elm.Debug.make = function (_elm) { + "use strict"; + _elm.Debug = _elm.Debug || {}; + if (_elm.Debug.values) return _elm.Debug.values; + var _U = Elm.Native.Utils.make(_elm),$Graphics$Collage = Elm.Graphics.Collage.make(_elm),$Native$Debug = Elm.Native.Debug.make(_elm); + var _op = {}; + var trace = $Native$Debug.tracePath; + var watchSummary = $Native$Debug.watchSummary; + var watch = $Native$Debug.watch; + var crash = $Native$Debug.crash; + var log = $Native$Debug.log; + return _elm.Debug.values = {_op: _op,log: log,crash: crash,watch: watch,watchSummary: watchSummary,trace: trace}; +}; +Elm.Native.Task = {}; + +Elm.Native.Task.make = function(localRuntime) { + localRuntime.Native = localRuntime.Native || {}; + localRuntime.Native.Task = localRuntime.Native.Task || {}; + if (localRuntime.Native.Task.values) + { + return localRuntime.Native.Task.values; + } + + var Result = Elm.Result.make(localRuntime); + var Signal; + var Utils = Elm.Native.Utils.make(localRuntime); + + + // CONSTRUCTORS + + function succeed(value) + { + return { + tag: 'Succeed', + value: value + }; + } + + function fail(error) + { + return { + tag: 'Fail', + value: error + }; + } + + function asyncFunction(func) + { + return { + tag: 'Async', + asyncFunction: func + }; + } + + function andThen(task, callback) + { + return { + tag: 'AndThen', + task: task, + callback: callback + }; + } + + function catch_(task, callback) + { + return { + tag: 'Catch', + task: task, + callback: callback + }; + } + + + // RUNNER + + function perform(task) { + runTask({ task: task }, function() {}); + } + + function performSignal(name, signal) + { + var workQueue = []; + + function onComplete() + { + workQueue.shift(); + + if (workQueue.length > 0) + { + var task = workQueue[0]; + + setTimeout(function() { + runTask(task, onComplete); + }, 0); + } + } + + function register(task) + { + var root = { task: task }; + workQueue.push(root); + if (workQueue.length === 1) + { + runTask(root, onComplete); + } + } + + if (!Signal) + { + Signal = Elm.Native.Signal.make(localRuntime); + } + Signal.output('perform-tasks-' + name, register, signal); + + register(signal.value); + + return signal; + } + + function mark(status, task) + { + return { status: status, task: task }; + } + + function runTask(root, onComplete) + { + var result = mark('runnable', root.task); + while (result.status === 'runnable') + { + result = stepTask(onComplete, root, result.task); + } + + if (result.status === 'done') + { + root.task = result.task; + onComplete(); + } + + if (result.status === 'blocked') + { + root.task = result.task; + } + } + + function stepTask(onComplete, root, task) + { + var tag = task.tag; + + if (tag === 'Succeed' || tag === 'Fail') + { + return mark('done', task); + } + + if (tag === 'Async') + { + var placeHolder = {}; + var couldBeSync = true; + var wasSync = false; + + task.asyncFunction(function(result) { + placeHolder.tag = result.tag; + placeHolder.value = result.value; + if (couldBeSync) + { + wasSync = true; + } + else + { + runTask(root, onComplete); + } + }); + couldBeSync = false; + return mark(wasSync ? 'done' : 'blocked', placeHolder); + } + + if (tag === 'AndThen' || tag === 'Catch') + { + var result = mark('runnable', task.task); + while (result.status === 'runnable') + { + result = stepTask(onComplete, root, result.task); + } + + if (result.status === 'done') + { + var activeTask = result.task; + var activeTag = activeTask.tag; + + var succeedChain = activeTag === 'Succeed' && tag === 'AndThen'; + var failChain = activeTag === 'Fail' && tag === 'Catch'; + + return (succeedChain || failChain) + ? mark('runnable', task.callback(activeTask.value)) + : mark('runnable', activeTask); + } + if (result.status === 'blocked') + { + return mark('blocked', { + tag: tag, + task: result.task, + callback: task.callback + }); + } + } + } + + + // THREADS + + function sleep(time) { + return asyncFunction(function(callback) { + setTimeout(function() { + callback(succeed(Utils.Tuple0)); + }, time); + }); + } + + function spawn(task) { + return asyncFunction(function(callback) { + var id = setTimeout(function() { + perform(task); + }, 0); + callback(succeed(id)); + }); + } + + + return localRuntime.Native.Task.values = { + succeed: succeed, + fail: fail, + asyncFunction: asyncFunction, + andThen: F2(andThen), + catch_: F2(catch_), + perform: perform, + performSignal: performSignal, + spawn: spawn, + sleep: sleep + }; +}; + +Elm.Result = Elm.Result || {}; +Elm.Result.make = function (_elm) { + "use strict"; + _elm.Result = _elm.Result || {}; + if (_elm.Result.values) return _elm.Result.values; + var _U = Elm.Native.Utils.make(_elm),$Maybe = Elm.Maybe.make(_elm); + var _op = {}; + var toMaybe = function (result) { var _p0 = result;if (_p0.ctor === "Ok") { return $Maybe.Just(_p0._0);} else { return $Maybe.Nothing;}}; + var withDefault = F2(function (def,result) { var _p1 = result;if (_p1.ctor === "Ok") { return _p1._0;} else { return def;}}); + var Err = function (a) { return {ctor: "Err",_0: a};}; + var andThen = F2(function (result,callback) { var _p2 = result;if (_p2.ctor === "Ok") { return callback(_p2._0);} else { return Err(_p2._0);}}); + var Ok = function (a) { return {ctor: "Ok",_0: a};}; + var map = F2(function (func,ra) { var _p3 = ra;if (_p3.ctor === "Ok") { return Ok(func(_p3._0));} else { return Err(_p3._0);}}); + var map2 = F3(function (func,ra,rb) { + var _p4 = {ctor: "_Tuple2",_0: ra,_1: rb}; + if (_p4._0.ctor === "Ok") { + if (_p4._1.ctor === "Ok") { + return Ok(A2(func,_p4._0._0,_p4._1._0)); + } else { + return Err(_p4._1._0); + } + } else { + return Err(_p4._0._0); + } + }); + var map3 = F4(function (func,ra,rb,rc) { + var _p5 = {ctor: "_Tuple3",_0: ra,_1: rb,_2: rc}; + if (_p5._0.ctor === "Ok") { + if (_p5._1.ctor === "Ok") { + if (_p5._2.ctor === "Ok") { + return Ok(A3(func,_p5._0._0,_p5._1._0,_p5._2._0)); + } else { + return Err(_p5._2._0); + } + } else { + return Err(_p5._1._0); + } + } else { + return Err(_p5._0._0); + } + }); + var map4 = F5(function (func,ra,rb,rc,rd) { + var _p6 = {ctor: "_Tuple4",_0: ra,_1: rb,_2: rc,_3: rd}; + if (_p6._0.ctor === "Ok") { + if (_p6._1.ctor === "Ok") { + if (_p6._2.ctor === "Ok") { + if (_p6._3.ctor === "Ok") { + return Ok(A4(func,_p6._0._0,_p6._1._0,_p6._2._0,_p6._3._0)); + } else { + return Err(_p6._3._0); + } + } else { + return Err(_p6._2._0); + } + } else { + return Err(_p6._1._0); + } + } else { + return Err(_p6._0._0); + } + }); + var map5 = F6(function (func,ra,rb,rc,rd,re) { + var _p7 = {ctor: "_Tuple5",_0: ra,_1: rb,_2: rc,_3: rd,_4: re}; + if (_p7._0.ctor === "Ok") { + if (_p7._1.ctor === "Ok") { + if (_p7._2.ctor === "Ok") { + if (_p7._3.ctor === "Ok") { + if (_p7._4.ctor === "Ok") { + return Ok(A5(func,_p7._0._0,_p7._1._0,_p7._2._0,_p7._3._0,_p7._4._0)); + } else { + return Err(_p7._4._0); + } + } else { + return Err(_p7._3._0); + } + } else { + return Err(_p7._2._0); + } + } else { + return Err(_p7._1._0); + } + } else { + return Err(_p7._0._0); + } + }); + var formatError = F2(function (f,result) { var _p8 = result;if (_p8.ctor === "Ok") { return Ok(_p8._0);} else { return Err(f(_p8._0));}}); + var fromMaybe = F2(function (err,maybe) { var _p9 = maybe;if (_p9.ctor === "Just") { return Ok(_p9._0);} else { return Err(err);}}); + return _elm.Result.values = {_op: _op + ,withDefault: withDefault + ,map: map + ,map2: map2 + ,map3: map3 + ,map4: map4 + ,map5: map5 + ,andThen: andThen + ,toMaybe: toMaybe + ,fromMaybe: fromMaybe + ,formatError: formatError + ,Ok: Ok + ,Err: Err}; +}; +Elm.Task = Elm.Task || {}; +Elm.Task.make = function (_elm) { + "use strict"; + _elm.Task = _elm.Task || {}; + if (_elm.Task.values) return _elm.Task.values; + var _U = Elm.Native.Utils.make(_elm), + $List = Elm.List.make(_elm), + $Maybe = Elm.Maybe.make(_elm), + $Native$Task = Elm.Native.Task.make(_elm), + $Result = Elm.Result.make(_elm); + var _op = {}; + var sleep = $Native$Task.sleep; + var spawn = $Native$Task.spawn; + var ThreadID = function (a) { return {ctor: "ThreadID",_0: a};}; + var onError = $Native$Task.catch_; + var andThen = $Native$Task.andThen; + var fail = $Native$Task.fail; + var mapError = F2(function (f,task) { return A2(onError,task,function (err) { return fail(f(err));});}); + var succeed = $Native$Task.succeed; + var map = F2(function (func,taskA) { return A2(andThen,taskA,function (a) { return succeed(func(a));});}); + var map2 = F3(function (func,taskA,taskB) { + return A2(andThen,taskA,function (a) { return A2(andThen,taskB,function (b) { return succeed(A2(func,a,b));});}); + }); + var map3 = F4(function (func,taskA,taskB,taskC) { + return A2(andThen, + taskA, + function (a) { + return A2(andThen,taskB,function (b) { return A2(andThen,taskC,function (c) { return succeed(A3(func,a,b,c));});}); + }); + }); + var map4 = F5(function (func,taskA,taskB,taskC,taskD) { + return A2(andThen, + taskA, + function (a) { + return A2(andThen, + taskB, + function (b) { + return A2(andThen,taskC,function (c) { return A2(andThen,taskD,function (d) { return succeed(A4(func,a,b,c,d));});}); + }); + }); + }); + var map5 = F6(function (func,taskA,taskB,taskC,taskD,taskE) { + return A2(andThen, + taskA, + function (a) { + return A2(andThen, + taskB, + function (b) { + return A2(andThen, + taskC, + function (c) { + return A2(andThen,taskD,function (d) { return A2(andThen,taskE,function (e) { return succeed(A5(func,a,b,c,d,e));});}); + }); + }); + }); + }); + var andMap = F2(function (taskFunc,taskValue) { + return A2(andThen,taskFunc,function (func) { return A2(andThen,taskValue,function (value) { return succeed(func(value));});}); + }); + var sequence = function (tasks) { + var _p0 = tasks; + if (_p0.ctor === "[]") { + return succeed(_U.list([])); + } else { + return A3(map2,F2(function (x,y) { return A2($List._op["::"],x,y);}),_p0._0,sequence(_p0._1)); + } + }; + var toMaybe = function (task) { return A2(onError,A2(map,$Maybe.Just,task),function (_p1) { return succeed($Maybe.Nothing);});}; + var fromMaybe = F2(function ($default,maybe) { var _p2 = maybe;if (_p2.ctor === "Just") { return succeed(_p2._0);} else { return fail($default);}}); + var toResult = function (task) { return A2(onError,A2(map,$Result.Ok,task),function (msg) { return succeed($Result.Err(msg));});}; + var fromResult = function (result) { var _p3 = result;if (_p3.ctor === "Ok") { return succeed(_p3._0);} else { return fail(_p3._0);}}; + var Task = {ctor: "Task"}; + return _elm.Task.values = {_op: _op + ,succeed: succeed + ,fail: fail + ,map: map + ,map2: map2 + ,map3: map3 + ,map4: map4 + ,map5: map5 + ,andMap: andMap + ,sequence: sequence + ,andThen: andThen + ,onError: onError + ,mapError: mapError + ,toMaybe: toMaybe + ,fromMaybe: fromMaybe + ,toResult: toResult + ,fromResult: fromResult + ,spawn: spawn + ,sleep: sleep}; +}; +Elm.Signal = Elm.Signal || {}; +Elm.Signal.make = function (_elm) { + "use strict"; + _elm.Signal = _elm.Signal || {}; + if (_elm.Signal.values) return _elm.Signal.values; + var _U = Elm.Native.Utils.make(_elm), + $Basics = Elm.Basics.make(_elm), + $Debug = Elm.Debug.make(_elm), + $List = Elm.List.make(_elm), + $Maybe = Elm.Maybe.make(_elm), + $Native$Signal = Elm.Native.Signal.make(_elm), + $Task = Elm.Task.make(_elm); + var _op = {}; + var send = F2(function (_p0,value) { + var _p1 = _p0; + return A2($Task.onError,_p1._0(value),function (_p2) { return $Task.succeed({ctor: "_Tuple0"});}); + }); + var Message = function (a) { return {ctor: "Message",_0: a};}; + var message = F2(function (_p3,value) { var _p4 = _p3;return Message(_p4._0(value));}); + var mailbox = $Native$Signal.mailbox; + var Address = function (a) { return {ctor: "Address",_0: a};}; + var forwardTo = F2(function (_p5,f) { var _p6 = _p5;return Address(function (x) { return _p6._0(f(x));});}); + var Mailbox = F2(function (a,b) { return {address: a,signal: b};}); + var sampleOn = $Native$Signal.sampleOn; + var dropRepeats = $Native$Signal.dropRepeats; + var filterMap = $Native$Signal.filterMap; + var filter = F3(function (isOk,base,signal) { + return A3(filterMap,function (value) { return isOk(value) ? $Maybe.Just(value) : $Maybe.Nothing;},base,signal); + }); + var merge = F2(function (left,right) { return A3($Native$Signal.genericMerge,$Basics.always,left,right);}); + var mergeMany = function (signalList) { + var _p7 = $List.reverse(signalList); + if (_p7.ctor === "[]") { + return _U.crashCase("Signal",{start: {line: 184,column: 3},end: {line: 189,column: 40}},_p7)("mergeMany was given an empty list!"); + } else { + return A3($List.foldl,merge,_p7._0,_p7._1); + } + }; + var foldp = $Native$Signal.foldp; + var map5 = $Native$Signal.map5; + var map4 = $Native$Signal.map4; + var map3 = $Native$Signal.map3; + var map2 = $Native$Signal.map2; + var map = $Native$Signal.map; + var constant = $Native$Signal.constant; + var Signal = {ctor: "Signal"}; + return _elm.Signal.values = {_op: _op + ,merge: merge + ,mergeMany: mergeMany + ,map: map + ,map2: map2 + ,map3: map3 + ,map4: map4 + ,map5: map5 + ,constant: constant + ,dropRepeats: dropRepeats + ,filter: filter + ,filterMap: filterMap + ,sampleOn: sampleOn + ,foldp: foldp + ,mailbox: mailbox + ,send: send + ,message: message + ,forwardTo: forwardTo + ,Mailbox: Mailbox}; +}; +Elm.Native.String = {}; + +Elm.Native.String.make = function(localRuntime) { + localRuntime.Native = localRuntime.Native || {}; + localRuntime.Native.String = localRuntime.Native.String || {}; + if (localRuntime.Native.String.values) + { + return localRuntime.Native.String.values; + } + if ('values' in Elm.Native.String) + { + return localRuntime.Native.String.values = Elm.Native.String.values; + } + + + var Char = Elm.Char.make(localRuntime); + var List = Elm.Native.List.make(localRuntime); + var Maybe = Elm.Maybe.make(localRuntime); + var Result = Elm.Result.make(localRuntime); + var Utils = Elm.Native.Utils.make(localRuntime); + + function isEmpty(str) + { + return str.length === 0; + } + function cons(chr, str) + { + return chr + str; + } + function uncons(str) + { + var hd = str[0]; + if (hd) + { + return Maybe.Just(Utils.Tuple2(Utils.chr(hd), str.slice(1))); + } + return Maybe.Nothing; + } + function append(a, b) + { + return a + b; + } + function concat(strs) + { + return List.toArray(strs).join(''); + } + function length(str) + { + return str.length; + } + function map(f, str) + { + var out = str.split(''); + for (var i = out.length; i--; ) + { + out[i] = f(Utils.chr(out[i])); + } + return out.join(''); + } + function filter(pred, str) + { + return str.split('').map(Utils.chr).filter(pred).join(''); + } + function reverse(str) + { + return str.split('').reverse().join(''); + } + function foldl(f, b, str) + { + var len = str.length; + for (var i = 0; i < len; ++i) + { + b = A2(f, Utils.chr(str[i]), b); + } + return b; + } + function foldr(f, b, str) + { + for (var i = str.length; i--; ) + { + b = A2(f, Utils.chr(str[i]), b); + } + return b; + } + function split(sep, str) + { + return List.fromArray(str.split(sep)); + } + function join(sep, strs) + { + return List.toArray(strs).join(sep); + } + function repeat(n, str) + { + var result = ''; + while (n > 0) + { + if (n & 1) + { + result += str; + } + n >>= 1, str += str; + } + return result; + } + function slice(start, end, str) + { + return str.slice(start, end); + } + function left(n, str) + { + return n < 1 ? '' : str.slice(0, n); + } + function right(n, str) + { + return n < 1 ? '' : str.slice(-n); + } + function dropLeft(n, str) + { + return n < 1 ? str : str.slice(n); + } + function dropRight(n, str) + { + return n < 1 ? str : str.slice(0, -n); + } + function pad(n, chr, str) + { + var half = (n - str.length) / 2; + return repeat(Math.ceil(half), chr) + str + repeat(half | 0, chr); + } + function padRight(n, chr, str) + { + return str + repeat(n - str.length, chr); + } + function padLeft(n, chr, str) + { + return repeat(n - str.length, chr) + str; + } + + function trim(str) + { + return str.trim(); + } + function trimLeft(str) + { + return str.replace(/^\s+/, ''); + } + function trimRight(str) + { + return str.replace(/\s+$/, ''); + } + + function words(str) + { + return List.fromArray(str.trim().split(/\s+/g)); + } + function lines(str) + { + return List.fromArray(str.split(/\r\n|\r|\n/g)); + } + + function toUpper(str) + { + return str.toUpperCase(); + } + function toLower(str) + { + return str.toLowerCase(); + } + + function any(pred, str) + { + for (var i = str.length; i--; ) + { + if (pred(Utils.chr(str[i]))) + { + return true; + } + } + return false; + } + function all(pred, str) + { + for (var i = str.length; i--; ) + { + if (!pred(Utils.chr(str[i]))) + { + return false; + } + } + return true; + } + + function contains(sub, str) + { + return str.indexOf(sub) > -1; + } + function startsWith(sub, str) + { + return str.indexOf(sub) === 0; + } + function endsWith(sub, str) + { + return str.length >= sub.length && + str.lastIndexOf(sub) === str.length - sub.length; + } + function indexes(sub, str) + { + var subLen = sub.length; + var i = 0; + var is = []; + while ((i = str.indexOf(sub, i)) > -1) + { + is.push(i); + i = i + subLen; + } + return List.fromArray(is); + } + + function toInt(s) + { + var len = s.length; + if (len === 0) + { + return Result.Err("could not convert string '" + s + "' to an Int" ); + } + var start = 0; + if (s[0] === '-') + { + if (len === 1) + { + return Result.Err("could not convert string '" + s + "' to an Int" ); + } + start = 1; + } + for (var i = start; i < len; ++i) + { + if (!Char.isDigit(s[i])) + { + return Result.Err("could not convert string '" + s + "' to an Int" ); + } + } + return Result.Ok(parseInt(s, 10)); + } + + function toFloat(s) + { + var len = s.length; + if (len === 0) + { + return Result.Err("could not convert string '" + s + "' to a Float" ); + } + var start = 0; + if (s[0] === '-') + { + if (len === 1) + { + return Result.Err("could not convert string '" + s + "' to a Float" ); + } + start = 1; + } + var dotCount = 0; + for (var i = start; i < len; ++i) + { + if (Char.isDigit(s[i])) + { + continue; + } + if (s[i] === '.') + { + dotCount += 1; + if (dotCount <= 1) + { + continue; + } + } + return Result.Err("could not convert string '" + s + "' to a Float" ); + } + return Result.Ok(parseFloat(s)); + } + + function toList(str) + { + return List.fromArray(str.split('').map(Utils.chr)); + } + function fromList(chars) + { + return List.toArray(chars).join(''); + } + + return Elm.Native.String.values = { + isEmpty: isEmpty, + cons: F2(cons), + uncons: uncons, + append: F2(append), + concat: concat, + length: length, + map: F2(map), + filter: F2(filter), + reverse: reverse, + foldl: F3(foldl), + foldr: F3(foldr), + + split: F2(split), + join: F2(join), + repeat: F2(repeat), + + slice: F3(slice), + left: F2(left), + right: F2(right), + dropLeft: F2(dropLeft), + dropRight: F2(dropRight), + + pad: F3(pad), + padLeft: F3(padLeft), + padRight: F3(padRight), + + trim: trim, + trimLeft: trimLeft, + trimRight: trimRight, + + words: words, + lines: lines, + + toUpper: toUpper, + toLower: toLower, + + any: F2(any), + all: F2(all), + + contains: F2(contains), + startsWith: F2(startsWith), + endsWith: F2(endsWith), + indexes: F2(indexes), + + toInt: toInt, + toFloat: toFloat, + toList: toList, + fromList: fromList + }; +}; + +Elm.String = Elm.String || {}; +Elm.String.make = function (_elm) { + "use strict"; + _elm.String = _elm.String || {}; + if (_elm.String.values) return _elm.String.values; + var _U = Elm.Native.Utils.make(_elm),$Maybe = Elm.Maybe.make(_elm),$Native$String = Elm.Native.String.make(_elm),$Result = Elm.Result.make(_elm); + var _op = {}; + var fromList = $Native$String.fromList; + var toList = $Native$String.toList; + var toFloat = $Native$String.toFloat; + var toInt = $Native$String.toInt; + var indices = $Native$String.indexes; + var indexes = $Native$String.indexes; + var endsWith = $Native$String.endsWith; + var startsWith = $Native$String.startsWith; + var contains = $Native$String.contains; + var all = $Native$String.all; + var any = $Native$String.any; + var toLower = $Native$String.toLower; + var toUpper = $Native$String.toUpper; + var lines = $Native$String.lines; + var words = $Native$String.words; + var trimRight = $Native$String.trimRight; + var trimLeft = $Native$String.trimLeft; + var trim = $Native$String.trim; + var padRight = $Native$String.padRight; + var padLeft = $Native$String.padLeft; + var pad = $Native$String.pad; + var dropRight = $Native$String.dropRight; + var dropLeft = $Native$String.dropLeft; + var right = $Native$String.right; + var left = $Native$String.left; + var slice = $Native$String.slice; + var repeat = $Native$String.repeat; + var join = $Native$String.join; + var split = $Native$String.split; + var foldr = $Native$String.foldr; + var foldl = $Native$String.foldl; + var reverse = $Native$String.reverse; + var filter = $Native$String.filter; + var map = $Native$String.map; + var length = $Native$String.length; + var concat = $Native$String.concat; + var append = $Native$String.append; + var uncons = $Native$String.uncons; + var cons = $Native$String.cons; + var fromChar = function ($char) { return A2(cons,$char,"");}; + var isEmpty = $Native$String.isEmpty; + return _elm.String.values = {_op: _op + ,isEmpty: isEmpty + ,length: length + ,reverse: reverse + ,repeat: repeat + ,cons: cons + ,uncons: uncons + ,fromChar: fromChar + ,append: append + ,concat: concat + ,split: split + ,join: join + ,words: words + ,lines: lines + ,slice: slice + ,left: left + ,right: right + ,dropLeft: dropLeft + ,dropRight: dropRight + ,contains: contains + ,startsWith: startsWith + ,endsWith: endsWith + ,indexes: indexes + ,indices: indices + ,toInt: toInt + ,toFloat: toFloat + ,toList: toList + ,fromList: fromList + ,toUpper: toUpper + ,toLower: toLower + ,pad: pad + ,padLeft: padLeft + ,padRight: padRight + ,trim: trim + ,trimLeft: trimLeft + ,trimRight: trimRight + ,map: map + ,filter: filter + ,foldl: foldl + ,foldr: foldr + ,any: any + ,all: all}; +}; +Elm.Dict = Elm.Dict || {}; +Elm.Dict.make = function (_elm) { + "use strict"; + _elm.Dict = _elm.Dict || {}; + if (_elm.Dict.values) return _elm.Dict.values; + var _U = Elm.Native.Utils.make(_elm), + $Basics = Elm.Basics.make(_elm), + $List = Elm.List.make(_elm), + $Maybe = Elm.Maybe.make(_elm), + $Native$Debug = Elm.Native.Debug.make(_elm), + $String = Elm.String.make(_elm); + var _op = {}; + var foldr = F3(function (f,acc,t) { + foldr: while (true) { + var _p0 = t; + if (_p0.ctor === "RBEmpty_elm_builtin") { + return acc; + } else { + var _v1 = f,_v2 = A3(f,_p0._1,_p0._2,A3(foldr,f,acc,_p0._4)),_v3 = _p0._3; + f = _v1; + acc = _v2; + t = _v3; + continue foldr; + } + } + }); + var keys = function (dict) { return A3(foldr,F3(function (key,value,keyList) { return A2($List._op["::"],key,keyList);}),_U.list([]),dict);}; + var values = function (dict) { return A3(foldr,F3(function (key,value,valueList) { return A2($List._op["::"],value,valueList);}),_U.list([]),dict);}; + var toList = function (dict) { + return A3(foldr,F3(function (key,value,list) { return A2($List._op["::"],{ctor: "_Tuple2",_0: key,_1: value},list);}),_U.list([]),dict); + }; + var foldl = F3(function (f,acc,dict) { + foldl: while (true) { + var _p1 = dict; + if (_p1.ctor === "RBEmpty_elm_builtin") { + return acc; + } else { + var _v5 = f,_v6 = A3(f,_p1._1,_p1._2,A3(foldl,f,acc,_p1._3)),_v7 = _p1._4; + f = _v5; + acc = _v6; + dict = _v7; + continue foldl; + } + } + }); + var reportRemBug = F4(function (msg,c,lgot,rgot) { + return $Native$Debug.crash($String.concat(_U.list(["Internal red-black tree invariant violated, expected " + ,msg + ," and got " + ,$Basics.toString(c) + ,"/" + ,lgot + ,"/" + ,rgot + ,"\nPlease report this bug to "]))); + }); + var isBBlack = function (dict) { + var _p2 = dict; + _v8_2: do { + if (_p2.ctor === "RBNode_elm_builtin") { + if (_p2._0.ctor === "BBlack") { + return true; + } else { + break _v8_2; + } + } else { + if (_p2._0.ctor === "LBBlack") { + return true; + } else { + break _v8_2; + } + } + } while (false); + return false; + }; + var Same = {ctor: "Same"}; + var Remove = {ctor: "Remove"}; + var Insert = {ctor: "Insert"}; + var sizeHelp = F2(function (n,dict) { + sizeHelp: while (true) { + var _p3 = dict; + if (_p3.ctor === "RBEmpty_elm_builtin") { + return n; + } else { + var _v10 = A2(sizeHelp,n + 1,_p3._4),_v11 = _p3._3; + n = _v10; + dict = _v11; + continue sizeHelp; + } + } + }); + var size = function (dict) { return A2(sizeHelp,0,dict);}; + var get = F2(function (targetKey,dict) { + get: while (true) { + var _p4 = dict; + if (_p4.ctor === "RBEmpty_elm_builtin") { + return $Maybe.Nothing; + } else { + var _p5 = A2($Basics.compare,targetKey,_p4._1); + switch (_p5.ctor) + {case "LT": var _v14 = targetKey,_v15 = _p4._3; + targetKey = _v14; + dict = _v15; + continue get; + case "EQ": return $Maybe.Just(_p4._2); + default: var _v16 = targetKey,_v17 = _p4._4; + targetKey = _v16; + dict = _v17; + continue get;} + } + } + }); + var member = F2(function (key,dict) { var _p6 = A2(get,key,dict);if (_p6.ctor === "Just") { return true;} else { return false;}}); + var maxWithDefault = F3(function (k,v,r) { + maxWithDefault: while (true) { + var _p7 = r; + if (_p7.ctor === "RBEmpty_elm_builtin") { + return {ctor: "_Tuple2",_0: k,_1: v}; + } else { + var _v20 = _p7._1,_v21 = _p7._2,_v22 = _p7._4; + k = _v20; + v = _v21; + r = _v22; + continue maxWithDefault; + } + } + }); + var RBEmpty_elm_builtin = function (a) { return {ctor: "RBEmpty_elm_builtin",_0: a};}; + var RBNode_elm_builtin = F5(function (a,b,c,d,e) { return {ctor: "RBNode_elm_builtin",_0: a,_1: b,_2: c,_3: d,_4: e};}); + var LBBlack = {ctor: "LBBlack"}; + var LBlack = {ctor: "LBlack"}; + var empty = RBEmpty_elm_builtin(LBlack); + var isEmpty = function (dict) { return _U.eq(dict,empty);}; + var map = F2(function (f,dict) { + var _p8 = dict; + if (_p8.ctor === "RBEmpty_elm_builtin") { + return RBEmpty_elm_builtin(LBlack); + } else { + var _p9 = _p8._1; + return A5(RBNode_elm_builtin,_p8._0,_p9,A2(f,_p9,_p8._2),A2(map,f,_p8._3),A2(map,f,_p8._4)); + } + }); + var NBlack = {ctor: "NBlack"}; + var BBlack = {ctor: "BBlack"}; + var Black = {ctor: "Black"}; + var ensureBlackRoot = function (dict) { + var _p10 = dict; + if (_p10.ctor === "RBNode_elm_builtin" && _p10._0.ctor === "Red") { + return A5(RBNode_elm_builtin,Black,_p10._1,_p10._2,_p10._3,_p10._4); + } else { + return dict; + } + }; + var blackish = function (t) { + var _p11 = t; + if (_p11.ctor === "RBNode_elm_builtin") { + var _p12 = _p11._0; + return _U.eq(_p12,Black) || _U.eq(_p12,BBlack); + } else { + return true; + } + }; + var blacken = function (t) { + var _p13 = t; + if (_p13.ctor === "RBEmpty_elm_builtin") { + return RBEmpty_elm_builtin(LBlack); + } else { + return A5(RBNode_elm_builtin,Black,_p13._1,_p13._2,_p13._3,_p13._4); + } + }; + var Red = {ctor: "Red"}; + var moreBlack = function (color) { + var _p14 = color; + switch (_p14.ctor) + {case "Black": return BBlack; + case "Red": return Black; + case "NBlack": return Red; + default: return $Native$Debug.crash("Can\'t make a double black node more black!");} + }; + var lessBlack = function (color) { + var _p15 = color; + switch (_p15.ctor) + {case "BBlack": return Black; + case "Black": return Red; + case "Red": return NBlack; + default: return $Native$Debug.crash("Can\'t make a negative black node less black!");} + }; + var lessBlackTree = function (dict) { + var _p16 = dict; + if (_p16.ctor === "RBNode_elm_builtin") { + return A5(RBNode_elm_builtin,lessBlack(_p16._0),_p16._1,_p16._2,_p16._3,_p16._4); + } else { + return RBEmpty_elm_builtin(LBlack); + } + }; + var balancedTree = function (col) { + return function (xk) { + return function (xv) { + return function (yk) { + return function (yv) { + return function (zk) { + return function (zv) { + return function (a) { + return function (b) { + return function (c) { + return function (d) { + return A5(RBNode_elm_builtin, + lessBlack(col), + yk, + yv, + A5(RBNode_elm_builtin,Black,xk,xv,a,b), + A5(RBNode_elm_builtin,Black,zk,zv,c,d)); + }; + }; + }; + }; + }; + }; + }; + }; + }; + }; + }; + var redden = function (t) { + var _p17 = t; + if (_p17.ctor === "RBEmpty_elm_builtin") { + return $Native$Debug.crash("can\'t make a Leaf red"); + } else { + return A5(RBNode_elm_builtin,Red,_p17._1,_p17._2,_p17._3,_p17._4); + } + }; + var balanceHelp = function (tree) { + var _p18 = tree; + _v31_6: do { + _v31_5: do { + _v31_4: do { + _v31_3: do { + _v31_2: do { + _v31_1: do { + _v31_0: do { + if (_p18.ctor === "RBNode_elm_builtin") { + if (_p18._3.ctor === "RBNode_elm_builtin") { + if (_p18._4.ctor === "RBNode_elm_builtin") { + switch (_p18._3._0.ctor) + {case "Red": switch (_p18._4._0.ctor) + {case "Red": if (_p18._3._3.ctor === "RBNode_elm_builtin" && _p18._3._3._0.ctor === "Red") { + break _v31_0; + } else { + if (_p18._3._4.ctor === "RBNode_elm_builtin" && _p18._3._4._0.ctor === "Red") { + break _v31_1; + } else { + if (_p18._4._3.ctor === "RBNode_elm_builtin" && _p18._4._3._0.ctor === "Red") { + break _v31_2; + } else { + if (_p18._4._4.ctor === "RBNode_elm_builtin" && _p18._4._4._0.ctor === "Red") { + break _v31_3; + } else { + break _v31_6; + } + } + } + } + case "NBlack": if (_p18._3._3.ctor === "RBNode_elm_builtin" && _p18._3._3._0.ctor === "Red") { + break _v31_0; + } else { + if (_p18._3._4.ctor === "RBNode_elm_builtin" && _p18._3._4._0.ctor === "Red") { + break _v31_1; + } else { + if (_p18._0.ctor === "BBlack" && _p18._4._3.ctor === "RBNode_elm_builtin" && _p18._4._3._0.ctor === "Black" && _p18._4._4.ctor === "RBNode_elm_builtin" && _p18._4._4._0.ctor === "Black") + { + break _v31_4; + } else { + break _v31_6; + } + } + } + default: if (_p18._3._3.ctor === "RBNode_elm_builtin" && _p18._3._3._0.ctor === "Red") { + break _v31_0; + } else { + if (_p18._3._4.ctor === "RBNode_elm_builtin" && _p18._3._4._0.ctor === "Red") { + break _v31_1; + } else { + break _v31_6; + } + }} + case "NBlack": switch (_p18._4._0.ctor) + {case "Red": if (_p18._4._3.ctor === "RBNode_elm_builtin" && _p18._4._3._0.ctor === "Red") { + break _v31_2; + } else { + if (_p18._4._4.ctor === "RBNode_elm_builtin" && _p18._4._4._0.ctor === "Red") { + break _v31_3; + } else { + if (_p18._0.ctor === "BBlack" && _p18._3._3.ctor === "RBNode_elm_builtin" && _p18._3._3._0.ctor === "Black" && _p18._3._4.ctor === "RBNode_elm_builtin" && _p18._3._4._0.ctor === "Black") + { + break _v31_5; + } else { + break _v31_6; + } + } + } + case "NBlack": if (_p18._0.ctor === "BBlack") { + if (_p18._4._3.ctor === "RBNode_elm_builtin" && _p18._4._3._0.ctor === "Black" && _p18._4._4.ctor === "RBNode_elm_builtin" && _p18._4._4._0.ctor === "Black") + { + break _v31_4; + } else { + if (_p18._3._3.ctor === "RBNode_elm_builtin" && _p18._3._3._0.ctor === "Black" && _p18._3._4.ctor === "RBNode_elm_builtin" && _p18._3._4._0.ctor === "Black") + { + break _v31_5; + } else { + break _v31_6; + } + } + } else { + break _v31_6; + } + default: + if (_p18._0.ctor === "BBlack" && _p18._3._3.ctor === "RBNode_elm_builtin" && _p18._3._3._0.ctor === "Black" && _p18._3._4.ctor === "RBNode_elm_builtin" && _p18._3._4._0.ctor === "Black") + { + break _v31_5; + } else { + break _v31_6; + }} + default: switch (_p18._4._0.ctor) + {case "Red": if (_p18._4._3.ctor === "RBNode_elm_builtin" && _p18._4._3._0.ctor === "Red") { + break _v31_2; + } else { + if (_p18._4._4.ctor === "RBNode_elm_builtin" && _p18._4._4._0.ctor === "Red") { + break _v31_3; + } else { + break _v31_6; + } + } + case "NBlack": + if (_p18._0.ctor === "BBlack" && _p18._4._3.ctor === "RBNode_elm_builtin" && _p18._4._3._0.ctor === "Black" && _p18._4._4.ctor === "RBNode_elm_builtin" && _p18._4._4._0.ctor === "Black") + { + break _v31_4; + } else { + break _v31_6; + } + default: break _v31_6;}} + } else { + switch (_p18._3._0.ctor) + {case "Red": if (_p18._3._3.ctor === "RBNode_elm_builtin" && _p18._3._3._0.ctor === "Red") { + break _v31_0; + } else { + if (_p18._3._4.ctor === "RBNode_elm_builtin" && _p18._3._4._0.ctor === "Red") { + break _v31_1; + } else { + break _v31_6; + } + } + case "NBlack": + if (_p18._0.ctor === "BBlack" && _p18._3._3.ctor === "RBNode_elm_builtin" && _p18._3._3._0.ctor === "Black" && _p18._3._4.ctor === "RBNode_elm_builtin" && _p18._3._4._0.ctor === "Black") + { + break _v31_5; + } else { + break _v31_6; + } + default: break _v31_6;} + } + } else { + if (_p18._4.ctor === "RBNode_elm_builtin") { + switch (_p18._4._0.ctor) + {case "Red": if (_p18._4._3.ctor === "RBNode_elm_builtin" && _p18._4._3._0.ctor === "Red") { + break _v31_2; + } else { + if (_p18._4._4.ctor === "RBNode_elm_builtin" && _p18._4._4._0.ctor === "Red") { + break _v31_3; + } else { + break _v31_6; + } + } + case "NBlack": + if (_p18._0.ctor === "BBlack" && _p18._4._3.ctor === "RBNode_elm_builtin" && _p18._4._3._0.ctor === "Black" && _p18._4._4.ctor === "RBNode_elm_builtin" && _p18._4._4._0.ctor === "Black") + { + break _v31_4; + } else { + break _v31_6; + } + default: break _v31_6;} + } else { + break _v31_6; + } + } + } else { + break _v31_6; + } + } while (false); + return balancedTree(_p18._0)(_p18._3._3._1)(_p18._3._3._2)(_p18._3._1)(_p18._3._2)(_p18._1)(_p18._2)(_p18._3._3._3)(_p18._3._3._4)(_p18._3._4)(_p18._4); + } while (false); + return balancedTree(_p18._0)(_p18._3._1)(_p18._3._2)(_p18._3._4._1)(_p18._3._4._2)(_p18._1)(_p18._2)(_p18._3._3)(_p18._3._4._3)(_p18._3._4._4)(_p18._4); + } while (false); + return balancedTree(_p18._0)(_p18._1)(_p18._2)(_p18._4._3._1)(_p18._4._3._2)(_p18._4._1)(_p18._4._2)(_p18._3)(_p18._4._3._3)(_p18._4._3._4)(_p18._4._4); + } while (false); + return balancedTree(_p18._0)(_p18._1)(_p18._2)(_p18._4._1)(_p18._4._2)(_p18._4._4._1)(_p18._4._4._2)(_p18._3)(_p18._4._3)(_p18._4._4._3)(_p18._4._4._4); + } while (false); + return A5(RBNode_elm_builtin, + Black, + _p18._4._3._1, + _p18._4._3._2, + A5(RBNode_elm_builtin,Black,_p18._1,_p18._2,_p18._3,_p18._4._3._3), + A5(balance,Black,_p18._4._1,_p18._4._2,_p18._4._3._4,redden(_p18._4._4))); + } while (false); + return A5(RBNode_elm_builtin, + Black, + _p18._3._4._1, + _p18._3._4._2, + A5(balance,Black,_p18._3._1,_p18._3._2,redden(_p18._3._3),_p18._3._4._3), + A5(RBNode_elm_builtin,Black,_p18._1,_p18._2,_p18._3._4._4,_p18._4)); + } while (false); + return tree; + }; + var balance = F5(function (c,k,v,l,r) { var tree = A5(RBNode_elm_builtin,c,k,v,l,r);return blackish(tree) ? balanceHelp(tree) : tree;}); + var bubble = F5(function (c,k,v,l,r) { + return isBBlack(l) || isBBlack(r) ? A5(balance,moreBlack(c),k,v,lessBlackTree(l),lessBlackTree(r)) : A5(RBNode_elm_builtin,c,k,v,l,r); + }); + var removeMax = F5(function (c,k,v,l,r) { + var _p19 = r; + if (_p19.ctor === "RBEmpty_elm_builtin") { + return A3(rem,c,l,r); + } else { + return A5(bubble,c,k,v,l,A5(removeMax,_p19._0,_p19._1,_p19._2,_p19._3,_p19._4)); + } + }); + var rem = F3(function (c,l,r) { + var _p20 = {ctor: "_Tuple2",_0: l,_1: r}; + if (_p20._0.ctor === "RBEmpty_elm_builtin") { + if (_p20._1.ctor === "RBEmpty_elm_builtin") { + var _p21 = c; + switch (_p21.ctor) + {case "Red": return RBEmpty_elm_builtin(LBlack); + case "Black": return RBEmpty_elm_builtin(LBBlack); + default: return $Native$Debug.crash("cannot have bblack or nblack nodes at this point");} + } else { + var _p24 = _p20._1._0; + var _p23 = _p20._0._0; + var _p22 = {ctor: "_Tuple3",_0: c,_1: _p23,_2: _p24}; + if (_p22.ctor === "_Tuple3" && _p22._0.ctor === "Black" && _p22._1.ctor === "LBlack" && _p22._2.ctor === "Red") { + return A5(RBNode_elm_builtin,Black,_p20._1._1,_p20._1._2,_p20._1._3,_p20._1._4); + } else { + return A4(reportRemBug,"Black/LBlack/Red",c,$Basics.toString(_p23),$Basics.toString(_p24)); + } + } + } else { + if (_p20._1.ctor === "RBEmpty_elm_builtin") { + var _p27 = _p20._1._0; + var _p26 = _p20._0._0; + var _p25 = {ctor: "_Tuple3",_0: c,_1: _p26,_2: _p27}; + if (_p25.ctor === "_Tuple3" && _p25._0.ctor === "Black" && _p25._1.ctor === "Red" && _p25._2.ctor === "LBlack") { + return A5(RBNode_elm_builtin,Black,_p20._0._1,_p20._0._2,_p20._0._3,_p20._0._4); + } else { + return A4(reportRemBug,"Black/Red/LBlack",c,$Basics.toString(_p26),$Basics.toString(_p27)); + } + } else { + var _p31 = _p20._0._2; + var _p30 = _p20._0._4; + var _p29 = _p20._0._1; + var l$ = A5(removeMax,_p20._0._0,_p29,_p31,_p20._0._3,_p30); + var _p28 = A3(maxWithDefault,_p29,_p31,_p30); + var k = _p28._0; + var v = _p28._1; + return A5(bubble,c,k,v,l$,r); + } + } + }); + var update = F3(function (k,alter,dict) { + var up = function (dict) { + var _p32 = dict; + if (_p32.ctor === "RBEmpty_elm_builtin") { + var _p33 = alter($Maybe.Nothing); + if (_p33.ctor === "Nothing") { + return {ctor: "_Tuple2",_0: Same,_1: empty}; + } else { + return {ctor: "_Tuple2",_0: Insert,_1: A5(RBNode_elm_builtin,Red,k,_p33._0,empty,empty)}; + } + } else { + var _p44 = _p32._2; + var _p43 = _p32._4; + var _p42 = _p32._3; + var _p41 = _p32._1; + var _p40 = _p32._0; + var _p34 = A2($Basics.compare,k,_p41); + switch (_p34.ctor) + {case "EQ": var _p35 = alter($Maybe.Just(_p44)); + if (_p35.ctor === "Nothing") { + return {ctor: "_Tuple2",_0: Remove,_1: A3(rem,_p40,_p42,_p43)}; + } else { + return {ctor: "_Tuple2",_0: Same,_1: A5(RBNode_elm_builtin,_p40,_p41,_p35._0,_p42,_p43)}; + } + case "LT": var _p36 = up(_p42); + var flag = _p36._0; + var newLeft = _p36._1; + var _p37 = flag; + switch (_p37.ctor) + {case "Same": return {ctor: "_Tuple2",_0: Same,_1: A5(RBNode_elm_builtin,_p40,_p41,_p44,newLeft,_p43)}; + case "Insert": return {ctor: "_Tuple2",_0: Insert,_1: A5(balance,_p40,_p41,_p44,newLeft,_p43)}; + default: return {ctor: "_Tuple2",_0: Remove,_1: A5(bubble,_p40,_p41,_p44,newLeft,_p43)};} + default: var _p38 = up(_p43); + var flag = _p38._0; + var newRight = _p38._1; + var _p39 = flag; + switch (_p39.ctor) + {case "Same": return {ctor: "_Tuple2",_0: Same,_1: A5(RBNode_elm_builtin,_p40,_p41,_p44,_p42,newRight)}; + case "Insert": return {ctor: "_Tuple2",_0: Insert,_1: A5(balance,_p40,_p41,_p44,_p42,newRight)}; + default: return {ctor: "_Tuple2",_0: Remove,_1: A5(bubble,_p40,_p41,_p44,_p42,newRight)};}} + } + }; + var _p45 = up(dict); + var flag = _p45._0; + var updatedDict = _p45._1; + var _p46 = flag; + switch (_p46.ctor) + {case "Same": return updatedDict; + case "Insert": return ensureBlackRoot(updatedDict); + default: return blacken(updatedDict);} + }); + var insert = F3(function (key,value,dict) { return A3(update,key,$Basics.always($Maybe.Just(value)),dict);}); + var singleton = F2(function (key,value) { return A3(insert,key,value,empty);}); + var union = F2(function (t1,t2) { return A3(foldl,insert,t2,t1);}); + var fromList = function (assocs) { + return A3($List.foldl,F2(function (_p47,dict) { var _p48 = _p47;return A3(insert,_p48._0,_p48._1,dict);}),empty,assocs); + }; + var filter = F2(function (predicate,dictionary) { + var add = F3(function (key,value,dict) { return A2(predicate,key,value) ? A3(insert,key,value,dict) : dict;}); + return A3(foldl,add,empty,dictionary); + }); + var intersect = F2(function (t1,t2) { return A2(filter,F2(function (k,_p49) { return A2(member,k,t2);}),t1);}); + var partition = F2(function (predicate,dict) { + var add = F3(function (key,value,_p50) { + var _p51 = _p50; + var _p53 = _p51._1; + var _p52 = _p51._0; + return A2(predicate,key,value) ? {ctor: "_Tuple2",_0: A3(insert,key,value,_p52),_1: _p53} : {ctor: "_Tuple2",_0: _p52,_1: A3(insert,key,value,_p53)}; + }); + return A3(foldl,add,{ctor: "_Tuple2",_0: empty,_1: empty},dict); + }); + var remove = F2(function (key,dict) { return A3(update,key,$Basics.always($Maybe.Nothing),dict);}); + var diff = F2(function (t1,t2) { return A3(foldl,F3(function (k,v,t) { return A2(remove,k,t);}),t1,t2);}); + return _elm.Dict.values = {_op: _op + ,empty: empty + ,singleton: singleton + ,insert: insert + ,update: update + ,isEmpty: isEmpty + ,get: get + ,remove: remove + ,member: member + ,size: size + ,filter: filter + ,partition: partition + ,foldl: foldl + ,foldr: foldr + ,map: map + ,union: union + ,intersect: intersect + ,diff: diff + ,keys: keys + ,values: values + ,toList: toList + ,fromList: fromList}; +}; +Elm.Native.Json = {}; + +Elm.Native.Json.make = function(localRuntime) { + localRuntime.Native = localRuntime.Native || {}; + localRuntime.Native.Json = localRuntime.Native.Json || {}; + if (localRuntime.Native.Json.values) { + return localRuntime.Native.Json.values; + } + + var ElmArray = Elm.Native.Array.make(localRuntime); + var List = Elm.Native.List.make(localRuntime); + var Maybe = Elm.Maybe.make(localRuntime); + var Result = Elm.Result.make(localRuntime); + var Utils = Elm.Native.Utils.make(localRuntime); + + + function crash(expected, actual) { + throw new Error( + 'expecting ' + expected + ' but got ' + JSON.stringify(actual) + ); + } + + + // PRIMITIVE VALUES + + function decodeNull(successValue) { + return function(value) { + if (value === null) { + return successValue; + } + crash('null', value); + }; + } + + + function decodeString(value) { + if (typeof value === 'string' || value instanceof String) { + return value; + } + crash('a String', value); + } + + + function decodeFloat(value) { + if (typeof value === 'number') { + return value; + } + crash('a Float', value); + } + + + function decodeInt(value) { + if (typeof value !== 'number') { + crash('an Int', value); + } + + if (value < 2147483647 && value > -2147483647 && (value | 0) === value) { + return value; + } + + if (isFinite(value) && !(value % 1)) { + return value; + } + + crash('an Int', value); + } + + + function decodeBool(value) { + if (typeof value === 'boolean') { + return value; + } + crash('a Bool', value); + } + + + // ARRAY + + function decodeArray(decoder) { + return function(value) { + if (value instanceof Array) { + var len = value.length; + var array = new Array(len); + for (var i = len; i--; ) { + array[i] = decoder(value[i]); + } + return ElmArray.fromJSArray(array); + } + crash('an Array', value); + }; + } + + + // LIST + + function decodeList(decoder) { + return function(value) { + if (value instanceof Array) { + var len = value.length; + var list = List.Nil; + for (var i = len; i--; ) { + list = List.Cons( decoder(value[i]), list ); + } + return list; + } + crash('a List', value); + }; + } + + + // MAYBE + + function decodeMaybe(decoder) { + return function(value) { + try { + return Maybe.Just(decoder(value)); + } catch(e) { + return Maybe.Nothing; + } + }; + } + + + // FIELDS + + function decodeField(field, decoder) { + return function(value) { + var subValue = value[field]; + if (subValue !== undefined) { + return decoder(subValue); + } + crash("an object with field '" + field + "'", value); + }; + } + + + // OBJECTS + + function decodeKeyValuePairs(decoder) { + return function(value) { + var isObject = + typeof value === 'object' + && value !== null + && !(value instanceof Array); + + if (isObject) { + var keyValuePairs = List.Nil; + for (var key in value) + { + var elmValue = decoder(value[key]); + var pair = Utils.Tuple2(key, elmValue); + keyValuePairs = List.Cons(pair, keyValuePairs); + } + return keyValuePairs; + } + + crash('an object', value); + }; + } + + function decodeObject1(f, d1) { + return function(value) { + return f(d1(value)); + }; + } + + function decodeObject2(f, d1, d2) { + return function(value) { + return A2( f, d1(value), d2(value) ); + }; + } + + function decodeObject3(f, d1, d2, d3) { + return function(value) { + return A3( f, d1(value), d2(value), d3(value) ); + }; + } + + function decodeObject4(f, d1, d2, d3, d4) { + return function(value) { + return A4( f, d1(value), d2(value), d3(value), d4(value) ); + }; + } + + function decodeObject5(f, d1, d2, d3, d4, d5) { + return function(value) { + return A5( f, d1(value), d2(value), d3(value), d4(value), d5(value) ); + }; + } + + function decodeObject6(f, d1, d2, d3, d4, d5, d6) { + return function(value) { + return A6( f, + d1(value), + d2(value), + d3(value), + d4(value), + d5(value), + d6(value) + ); + }; + } + + function decodeObject7(f, d1, d2, d3, d4, d5, d6, d7) { + return function(value) { + return A7( f, + d1(value), + d2(value), + d3(value), + d4(value), + d5(value), + d6(value), + d7(value) + ); + }; + } + + function decodeObject8(f, d1, d2, d3, d4, d5, d6, d7, d8) { + return function(value) { + return A8( f, + d1(value), + d2(value), + d3(value), + d4(value), + d5(value), + d6(value), + d7(value), + d8(value) + ); + }; + } + + + // TUPLES + + function decodeTuple1(f, d1) { + return function(value) { + if ( !(value instanceof Array) || value.length !== 1 ) { + crash('a Tuple of length 1', value); + } + return f( d1(value[0]) ); + }; + } + + function decodeTuple2(f, d1, d2) { + return function(value) { + if ( !(value instanceof Array) || value.length !== 2 ) { + crash('a Tuple of length 2', value); + } + return A2( f, d1(value[0]), d2(value[1]) ); + }; + } + + function decodeTuple3(f, d1, d2, d3) { + return function(value) { + if ( !(value instanceof Array) || value.length !== 3 ) { + crash('a Tuple of length 3', value); + } + return A3( f, d1(value[0]), d2(value[1]), d3(value[2]) ); + }; + } + + + function decodeTuple4(f, d1, d2, d3, d4) { + return function(value) { + if ( !(value instanceof Array) || value.length !== 4 ) { + crash('a Tuple of length 4', value); + } + return A4( f, d1(value[0]), d2(value[1]), d3(value[2]), d4(value[3]) ); + }; + } + + + function decodeTuple5(f, d1, d2, d3, d4, d5) { + return function(value) { + if ( !(value instanceof Array) || value.length !== 5 ) { + crash('a Tuple of length 5', value); + } + return A5( f, + d1(value[0]), + d2(value[1]), + d3(value[2]), + d4(value[3]), + d5(value[4]) + ); + }; + } + + + function decodeTuple6(f, d1, d2, d3, d4, d5, d6) { + return function(value) { + if ( !(value instanceof Array) || value.length !== 6 ) { + crash('a Tuple of length 6', value); + } + return A6( f, + d1(value[0]), + d2(value[1]), + d3(value[2]), + d4(value[3]), + d5(value[4]), + d6(value[5]) + ); + }; + } + + function decodeTuple7(f, d1, d2, d3, d4, d5, d6, d7) { + return function(value) { + if ( !(value instanceof Array) || value.length !== 7 ) { + crash('a Tuple of length 7', value); + } + return A7( f, + d1(value[0]), + d2(value[1]), + d3(value[2]), + d4(value[3]), + d5(value[4]), + d6(value[5]), + d7(value[6]) + ); + }; + } + + + function decodeTuple8(f, d1, d2, d3, d4, d5, d6, d7, d8) { + return function(value) { + if ( !(value instanceof Array) || value.length !== 8 ) { + crash('a Tuple of length 8', value); + } + return A8( f, + d1(value[0]), + d2(value[1]), + d3(value[2]), + d4(value[3]), + d5(value[4]), + d6(value[5]), + d7(value[6]), + d8(value[7]) + ); + }; + } + + + // CUSTOM DECODERS + + function decodeValue(value) { + return value; + } + + function runDecoderValue(decoder, value) { + try { + return Result.Ok(decoder(value)); + } catch(e) { + return Result.Err(e.message); + } + } + + function customDecoder(decoder, callback) { + return function(value) { + var result = callback(decoder(value)); + if (result.ctor === 'Err') { + throw new Error('custom decoder failed: ' + result._0); + } + return result._0; + }; + } + + function andThen(decode, callback) { + return function(value) { + var result = decode(value); + return callback(result)(value); + }; + } + + function fail(msg) { + return function(value) { + throw new Error(msg); + }; + } + + function succeed(successValue) { + return function(value) { + return successValue; + }; + } + + + // ONE OF MANY + + function oneOf(decoders) { + return function(value) { + var errors = []; + var temp = decoders; + while (temp.ctor !== '[]') { + try { + return temp._0(value); + } catch(e) { + errors.push(e.message); + } + temp = temp._1; + } + throw new Error('expecting one of the following:\n ' + errors.join('\n ')); + }; + } + + function get(decoder, value) { + try { + return Result.Ok(decoder(value)); + } catch(e) { + return Result.Err(e.message); + } + } + + + // ENCODE / DECODE + + function runDecoderString(decoder, string) { + try { + return Result.Ok(decoder(JSON.parse(string))); + } catch(e) { + return Result.Err(e.message); + } + } + + function encode(indentLevel, value) { + return JSON.stringify(value, null, indentLevel); + } + + function identity(value) { + return value; + } + + function encodeObject(keyValuePairs) { + var obj = {}; + while (keyValuePairs.ctor !== '[]') { + var pair = keyValuePairs._0; + obj[pair._0] = pair._1; + keyValuePairs = keyValuePairs._1; + } + return obj; + } + + return localRuntime.Native.Json.values = { + encode: F2(encode), + runDecoderString: F2(runDecoderString), + runDecoderValue: F2(runDecoderValue), + + get: F2(get), + oneOf: oneOf, + + decodeNull: decodeNull, + decodeInt: decodeInt, + decodeFloat: decodeFloat, + decodeString: decodeString, + decodeBool: decodeBool, + + decodeMaybe: decodeMaybe, + + decodeList: decodeList, + decodeArray: decodeArray, + + decodeField: F2(decodeField), + + decodeObject1: F2(decodeObject1), + decodeObject2: F3(decodeObject2), + decodeObject3: F4(decodeObject3), + decodeObject4: F5(decodeObject4), + decodeObject5: F6(decodeObject5), + decodeObject6: F7(decodeObject6), + decodeObject7: F8(decodeObject7), + decodeObject8: F9(decodeObject8), + decodeKeyValuePairs: decodeKeyValuePairs, + + decodeTuple1: F2(decodeTuple1), + decodeTuple2: F3(decodeTuple2), + decodeTuple3: F4(decodeTuple3), + decodeTuple4: F5(decodeTuple4), + decodeTuple5: F6(decodeTuple5), + decodeTuple6: F7(decodeTuple6), + decodeTuple7: F8(decodeTuple7), + decodeTuple8: F9(decodeTuple8), + + andThen: F2(andThen), + decodeValue: decodeValue, + customDecoder: F2(customDecoder), + fail: fail, + succeed: succeed, + + identity: identity, + encodeNull: null, + encodeArray: ElmArray.toJSArray, + encodeList: List.toArray, + encodeObject: encodeObject + + }; +}; + +Elm.Json = Elm.Json || {}; +Elm.Json.Encode = Elm.Json.Encode || {}; +Elm.Json.Encode.make = function (_elm) { + "use strict"; + _elm.Json = _elm.Json || {}; + _elm.Json.Encode = _elm.Json.Encode || {}; + if (_elm.Json.Encode.values) return _elm.Json.Encode.values; + var _U = Elm.Native.Utils.make(_elm),$Array = Elm.Array.make(_elm),$Native$Json = Elm.Native.Json.make(_elm); + var _op = {}; + var list = $Native$Json.encodeList; + var array = $Native$Json.encodeArray; + var object = $Native$Json.encodeObject; + var $null = $Native$Json.encodeNull; + var bool = $Native$Json.identity; + var $float = $Native$Json.identity; + var $int = $Native$Json.identity; + var string = $Native$Json.identity; + var encode = $Native$Json.encode; + var Value = {ctor: "Value"}; + return _elm.Json.Encode.values = {_op: _op + ,encode: encode + ,string: string + ,$int: $int + ,$float: $float + ,bool: bool + ,$null: $null + ,list: list + ,array: array + ,object: object}; +}; +Elm.Json = Elm.Json || {}; +Elm.Json.Decode = Elm.Json.Decode || {}; +Elm.Json.Decode.make = function (_elm) { + "use strict"; + _elm.Json = _elm.Json || {}; + _elm.Json.Decode = _elm.Json.Decode || {}; + if (_elm.Json.Decode.values) return _elm.Json.Decode.values; + var _U = Elm.Native.Utils.make(_elm), + $Array = Elm.Array.make(_elm), + $Dict = Elm.Dict.make(_elm), + $Json$Encode = Elm.Json.Encode.make(_elm), + $List = Elm.List.make(_elm), + $Maybe = Elm.Maybe.make(_elm), + $Native$Json = Elm.Native.Json.make(_elm), + $Result = Elm.Result.make(_elm); + var _op = {}; + var tuple8 = $Native$Json.decodeTuple8; + var tuple7 = $Native$Json.decodeTuple7; + var tuple6 = $Native$Json.decodeTuple6; + var tuple5 = $Native$Json.decodeTuple5; + var tuple4 = $Native$Json.decodeTuple4; + var tuple3 = $Native$Json.decodeTuple3; + var tuple2 = $Native$Json.decodeTuple2; + var tuple1 = $Native$Json.decodeTuple1; + var succeed = $Native$Json.succeed; + var fail = $Native$Json.fail; + var andThen = $Native$Json.andThen; + var customDecoder = $Native$Json.customDecoder; + var decodeValue = $Native$Json.runDecoderValue; + var value = $Native$Json.decodeValue; + var maybe = $Native$Json.decodeMaybe; + var $null = $Native$Json.decodeNull; + var array = $Native$Json.decodeArray; + var list = $Native$Json.decodeList; + var bool = $Native$Json.decodeBool; + var $int = $Native$Json.decodeInt; + var $float = $Native$Json.decodeFloat; + var string = $Native$Json.decodeString; + var oneOf = $Native$Json.oneOf; + var keyValuePairs = $Native$Json.decodeKeyValuePairs; + var object8 = $Native$Json.decodeObject8; + var object7 = $Native$Json.decodeObject7; + var object6 = $Native$Json.decodeObject6; + var object5 = $Native$Json.decodeObject5; + var object4 = $Native$Json.decodeObject4; + var object3 = $Native$Json.decodeObject3; + var object2 = $Native$Json.decodeObject2; + var object1 = $Native$Json.decodeObject1; + _op[":="] = $Native$Json.decodeField; + var at = F2(function (fields,decoder) { return A3($List.foldr,F2(function (x,y) { return A2(_op[":="],x,y);}),decoder,fields);}); + var decodeString = $Native$Json.runDecoderString; + var map = $Native$Json.decodeObject1; + var dict = function (decoder) { return A2(map,$Dict.fromList,keyValuePairs(decoder));}; + var Decoder = {ctor: "Decoder"}; + return _elm.Json.Decode.values = {_op: _op + ,decodeString: decodeString + ,decodeValue: decodeValue + ,string: string + ,$int: $int + ,$float: $float + ,bool: bool + ,$null: $null + ,list: list + ,array: array + ,tuple1: tuple1 + ,tuple2: tuple2 + ,tuple3: tuple3 + ,tuple4: tuple4 + ,tuple5: tuple5 + ,tuple6: tuple6 + ,tuple7: tuple7 + ,tuple8: tuple8 + ,at: at + ,object1: object1 + ,object2: object2 + ,object3: object3 + ,object4: object4 + ,object5: object5 + ,object6: object6 + ,object7: object7 + ,object8: object8 + ,keyValuePairs: keyValuePairs + ,dict: dict + ,maybe: maybe + ,oneOf: oneOf + ,map: map + ,fail: fail + ,succeed: succeed + ,andThen: andThen + ,value: value + ,customDecoder: customDecoder}; +}; +Elm.Native = Elm.Native || {}; +Elm.Native.Window = {}; +Elm.Native.Window.make = function make(localRuntime) { + localRuntime.Native = localRuntime.Native || {}; + localRuntime.Native.Window = localRuntime.Native.Window || {}; + if (localRuntime.Native.Window.values) + { + return localRuntime.Native.Window.values; + } + + var NS = Elm.Native.Signal.make(localRuntime); + var Tuple2 = Elm.Native.Utils.make(localRuntime).Tuple2; + + + function getWidth() + { + return localRuntime.node.clientWidth; + } + + + function getHeight() + { + if (localRuntime.isFullscreen()) + { + return window.innerHeight; + } + return localRuntime.node.clientHeight; + } + + + var dimensions = NS.input('Window.dimensions', Tuple2(getWidth(), getHeight())); + + + function resizeIfNeeded() + { + // Do not trigger event if the dimensions have not changed. + // This should be most of the time. + var w = getWidth(); + var h = getHeight(); + if (dimensions.value._0 === w && dimensions.value._1 === h) + { + return; + } + + setTimeout(function() { + // Check again to see if the dimensions have changed. + // It is conceivable that the dimensions have changed + // again while some other event was being processed. + w = getWidth(); + h = getHeight(); + if (dimensions.value._0 === w && dimensions.value._1 === h) + { + return; + } + localRuntime.notify(dimensions.id, Tuple2(w, h)); + }, 0); + } + + + localRuntime.addListener([dimensions.id], window, 'resize', resizeIfNeeded); + + + return localRuntime.Native.Window.values = { + dimensions: dimensions, + resizeIfNeeded: resizeIfNeeded + }; +}; + +Elm.Window = Elm.Window || {}; +Elm.Window.make = function (_elm) { + "use strict"; + _elm.Window = _elm.Window || {}; + if (_elm.Window.values) return _elm.Window.values; + var _U = Elm.Native.Utils.make(_elm),$Basics = Elm.Basics.make(_elm),$Native$Window = Elm.Native.Window.make(_elm),$Signal = Elm.Signal.make(_elm); + var _op = {}; + var dimensions = $Native$Window.dimensions; + var width = A2($Signal.map,$Basics.fst,dimensions); + var height = A2($Signal.map,$Basics.snd,dimensions); + return _elm.Window.values = {_op: _op,dimensions: dimensions,width: width,height: height}; +}; +(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o> 0 + currentItem = indices[currentIndex] + + if (minIndex === maxIndex) { + return currentItem >= left && currentItem <= right + } else if (currentItem < left) { + minIndex = currentIndex + 1 + } else if (currentItem > right) { + maxIndex = currentIndex - 1 + } else { + return true + } + } + + return false; +} + +function ascending(a, b) { + return a > b ? 1 : -1 +} + +},{}],8:[function(require,module,exports){ +var applyProperties = require("./apply-properties") + +var isWidget = require("../vnode/is-widget.js") +var VPatch = require("../vnode/vpatch.js") + +var render = require("./create-element") +var updateWidget = require("./update-widget") + +module.exports = applyPatch + +function applyPatch(vpatch, domNode, renderOptions) { + var type = vpatch.type + var vNode = vpatch.vNode + var patch = vpatch.patch + + switch (type) { + case VPatch.REMOVE: + return removeNode(domNode, vNode) + case VPatch.INSERT: + return insertNode(domNode, patch, renderOptions) + case VPatch.VTEXT: + return stringPatch(domNode, vNode, patch, renderOptions) + case VPatch.WIDGET: + return widgetPatch(domNode, vNode, patch, renderOptions) + case VPatch.VNODE: + return vNodePatch(domNode, vNode, patch, renderOptions) + case VPatch.ORDER: + reorderChildren(domNode, patch) + return domNode + case VPatch.PROPS: + applyProperties(domNode, patch, vNode.properties) + return domNode + case VPatch.THUNK: + return replaceRoot(domNode, + renderOptions.patch(domNode, patch, renderOptions)) + default: + return domNode + } +} + +function removeNode(domNode, vNode) { + var parentNode = domNode.parentNode + + if (parentNode) { + parentNode.removeChild(domNode) + } + + destroyWidget(domNode, vNode); + + return null +} + +function insertNode(parentNode, vNode, renderOptions) { + var newNode = render(vNode, renderOptions) + + if (parentNode) { + parentNode.appendChild(newNode) + } + + return parentNode +} + +function stringPatch(domNode, leftVNode, vText, renderOptions) { + var newNode + + if (domNode.nodeType === 3) { + domNode.replaceData(0, domNode.length, vText.text) + newNode = domNode + } else { + var parentNode = domNode.parentNode + newNode = render(vText, renderOptions) + + if (parentNode && newNode !== domNode) { + parentNode.replaceChild(newNode, domNode) + } + } + + return newNode +} + +function widgetPatch(domNode, leftVNode, widget, renderOptions) { + var updating = updateWidget(leftVNode, widget) + var newNode + + if (updating) { + newNode = widget.update(leftVNode, domNode) || domNode + } else { + newNode = render(widget, renderOptions) + } + + var parentNode = domNode.parentNode + + if (parentNode && newNode !== domNode) { + parentNode.replaceChild(newNode, domNode) + } + + if (!updating) { + destroyWidget(domNode, leftVNode) + } + + return newNode +} + +function vNodePatch(domNode, leftVNode, vNode, renderOptions) { + var parentNode = domNode.parentNode + var newNode = render(vNode, renderOptions) + + if (parentNode && newNode !== domNode) { + parentNode.replaceChild(newNode, domNode) + } + + return newNode +} + +function destroyWidget(domNode, w) { + if (typeof w.destroy === "function" && isWidget(w)) { + w.destroy(domNode) + } +} + +function reorderChildren(domNode, moves) { + var childNodes = domNode.childNodes + var keyMap = {} + var node + var remove + var insert + + for (var i = 0; i < moves.removes.length; i++) { + remove = moves.removes[i] + node = childNodes[remove.from] + if (remove.key) { + keyMap[remove.key] = node + } + domNode.removeChild(node) + } + + var length = childNodes.length + for (var j = 0; j < moves.inserts.length; j++) { + insert = moves.inserts[j] + node = keyMap[insert.key] + // this is the weirdest bug i've ever seen in webkit + domNode.insertBefore(node, insert.to >= length++ ? null : childNodes[insert.to]) + } +} + +function replaceRoot(oldRoot, newRoot) { + if (oldRoot && newRoot && oldRoot !== newRoot && oldRoot.parentNode) { + oldRoot.parentNode.replaceChild(newRoot, oldRoot) + } + + return newRoot; +} + +},{"../vnode/is-widget.js":16,"../vnode/vpatch.js":19,"./apply-properties":5,"./create-element":6,"./update-widget":10}],9:[function(require,module,exports){ +var document = require("global/document") +var isArray = require("x-is-array") + +var domIndex = require("./dom-index") +var patchOp = require("./patch-op") +module.exports = patch + +function patch(rootNode, patches) { + return patchRecursive(rootNode, patches) +} + +function patchRecursive(rootNode, patches, renderOptions) { + var indices = patchIndices(patches) + + if (indices.length === 0) { + return rootNode + } + + var index = domIndex(rootNode, patches.a, indices) + var ownerDocument = rootNode.ownerDocument + + if (!renderOptions) { + renderOptions = { patch: patchRecursive } + if (ownerDocument !== document) { + renderOptions.document = ownerDocument + } + } + + for (var i = 0; i < indices.length; i++) { + var nodeIndex = indices[i] + rootNode = applyPatch(rootNode, + index[nodeIndex], + patches[nodeIndex], + renderOptions) + } + + return rootNode +} + +function applyPatch(rootNode, domNode, patchList, renderOptions) { + if (!domNode) { + return rootNode + } + + var newNode + + if (isArray(patchList)) { + for (var i = 0; i < patchList.length; i++) { + newNode = patchOp(patchList[i], domNode, renderOptions) + + if (domNode === rootNode) { + rootNode = newNode + } + } + } else { + newNode = patchOp(patchList, domNode, renderOptions) + + if (domNode === rootNode) { + rootNode = newNode + } + } + + return rootNode +} + +function patchIndices(patches) { + var indices = [] + + for (var key in patches) { + if (key !== "a") { + indices.push(Number(key)) + } + } + + return indices +} + +},{"./dom-index":7,"./patch-op":8,"global/document":2,"x-is-array":4}],10:[function(require,module,exports){ +var isWidget = require("../vnode/is-widget.js") + +module.exports = updateWidget + +function updateWidget(a, b) { + if (isWidget(a) && isWidget(b)) { + if ("name" in a && "name" in b) { + return a.id === b.id + } else { + return a.init === b.init + } + } + + return false +} + +},{"../vnode/is-widget.js":16}],11:[function(require,module,exports){ +var isVNode = require("./is-vnode") +var isVText = require("./is-vtext") +var isWidget = require("./is-widget") +var isThunk = require("./is-thunk") + +module.exports = handleThunk + +function handleThunk(a, b) { + var renderedA = a + var renderedB = b + + if (isThunk(b)) { + renderedB = renderThunk(b, a) + } + + if (isThunk(a)) { + renderedA = renderThunk(a, null) + } + + return { + a: renderedA, + b: renderedB + } +} + +function renderThunk(thunk, previous) { + var renderedThunk = thunk.vnode + + if (!renderedThunk) { + renderedThunk = thunk.vnode = thunk.render(previous) + } + + if (!(isVNode(renderedThunk) || + isVText(renderedThunk) || + isWidget(renderedThunk))) { + throw new Error("thunk did not return a valid node"); + } + + return renderedThunk +} + +},{"./is-thunk":12,"./is-vnode":14,"./is-vtext":15,"./is-widget":16}],12:[function(require,module,exports){ +module.exports = isThunk + +function isThunk(t) { + return t && t.type === "Thunk" +} + +},{}],13:[function(require,module,exports){ +module.exports = isHook + +function isHook(hook) { + return hook && + (typeof hook.hook === "function" && !hook.hasOwnProperty("hook") || + typeof hook.unhook === "function" && !hook.hasOwnProperty("unhook")) +} + +},{}],14:[function(require,module,exports){ +var version = require("./version") + +module.exports = isVirtualNode + +function isVirtualNode(x) { + return x && x.type === "VirtualNode" && x.version === version +} + +},{"./version":17}],15:[function(require,module,exports){ +var version = require("./version") + +module.exports = isVirtualText + +function isVirtualText(x) { + return x && x.type === "VirtualText" && x.version === version +} + +},{"./version":17}],16:[function(require,module,exports){ +module.exports = isWidget + +function isWidget(w) { + return w && w.type === "Widget" +} + +},{}],17:[function(require,module,exports){ +module.exports = "2" + +},{}],18:[function(require,module,exports){ +var version = require("./version") +var isVNode = require("./is-vnode") +var isWidget = require("./is-widget") +var isThunk = require("./is-thunk") +var isVHook = require("./is-vhook") + +module.exports = VirtualNode + +var noProperties = {} +var noChildren = [] + +function VirtualNode(tagName, properties, children, key, namespace) { + this.tagName = tagName + this.properties = properties || noProperties + this.children = children || noChildren + this.key = key != null ? String(key) : undefined + this.namespace = (typeof namespace === "string") ? namespace : null + + var count = (children && children.length) || 0 + var descendants = 0 + var hasWidgets = false + var hasThunks = false + var descendantHooks = false + var hooks + + for (var propName in properties) { + if (properties.hasOwnProperty(propName)) { + var property = properties[propName] + if (isVHook(property) && property.unhook) { + if (!hooks) { + hooks = {} + } + + hooks[propName] = property + } + } + } + + for (var i = 0; i < count; i++) { + var child = children[i] + if (isVNode(child)) { + descendants += child.count || 0 + + if (!hasWidgets && child.hasWidgets) { + hasWidgets = true + } + + if (!hasThunks && child.hasThunks) { + hasThunks = true + } + + if (!descendantHooks && (child.hooks || child.descendantHooks)) { + descendantHooks = true + } + } else if (!hasWidgets && isWidget(child)) { + if (typeof child.destroy === "function") { + hasWidgets = true + } + } else if (!hasThunks && isThunk(child)) { + hasThunks = true; + } + } + + this.count = count + descendants + this.hasWidgets = hasWidgets + this.hasThunks = hasThunks + this.hooks = hooks + this.descendantHooks = descendantHooks +} + +VirtualNode.prototype.version = version +VirtualNode.prototype.type = "VirtualNode" + +},{"./is-thunk":12,"./is-vhook":13,"./is-vnode":14,"./is-widget":16,"./version":17}],19:[function(require,module,exports){ +var version = require("./version") + +VirtualPatch.NONE = 0 +VirtualPatch.VTEXT = 1 +VirtualPatch.VNODE = 2 +VirtualPatch.WIDGET = 3 +VirtualPatch.PROPS = 4 +VirtualPatch.ORDER = 5 +VirtualPatch.INSERT = 6 +VirtualPatch.REMOVE = 7 +VirtualPatch.THUNK = 8 + +module.exports = VirtualPatch + +function VirtualPatch(type, vNode, patch) { + this.type = Number(type) + this.vNode = vNode + this.patch = patch +} + +VirtualPatch.prototype.version = version +VirtualPatch.prototype.type = "VirtualPatch" + +},{"./version":17}],20:[function(require,module,exports){ +var version = require("./version") + +module.exports = VirtualText + +function VirtualText(text) { + this.text = String(text) +} + +VirtualText.prototype.version = version +VirtualText.prototype.type = "VirtualText" + +},{"./version":17}],21:[function(require,module,exports){ +var isObject = require("is-object") +var isHook = require("../vnode/is-vhook") + +module.exports = diffProps + +function diffProps(a, b) { + var diff + + for (var aKey in a) { + if (!(aKey in b)) { + diff = diff || {} + diff[aKey] = undefined + } + + var aValue = a[aKey] + var bValue = b[aKey] + + if (aValue === bValue) { + continue + } else if (isObject(aValue) && isObject(bValue)) { + if (getPrototype(bValue) !== getPrototype(aValue)) { + diff = diff || {} + diff[aKey] = bValue + } else if (isHook(bValue)) { + diff = diff || {} + diff[aKey] = bValue + } else { + var objectDiff = diffProps(aValue, bValue) + if (objectDiff) { + diff = diff || {} + diff[aKey] = objectDiff + } + } + } else { + diff = diff || {} + diff[aKey] = bValue + } + } + + for (var bKey in b) { + if (!(bKey in a)) { + diff = diff || {} + diff[bKey] = b[bKey] + } + } + + return diff +} + +function getPrototype(value) { + if (Object.getPrototypeOf) { + return Object.getPrototypeOf(value) + } else if (value.__proto__) { + return value.__proto__ + } else if (value.constructor) { + return value.constructor.prototype + } +} + +},{"../vnode/is-vhook":13,"is-object":3}],22:[function(require,module,exports){ +var isArray = require("x-is-array") + +var VPatch = require("../vnode/vpatch") +var isVNode = require("../vnode/is-vnode") +var isVText = require("../vnode/is-vtext") +var isWidget = require("../vnode/is-widget") +var isThunk = require("../vnode/is-thunk") +var handleThunk = require("../vnode/handle-thunk") + +var diffProps = require("./diff-props") + +module.exports = diff + +function diff(a, b) { + var patch = { a: a } + walk(a, b, patch, 0) + return patch +} + +function walk(a, b, patch, index) { + if (a === b) { + return + } + + var apply = patch[index] + var applyClear = false + + if (isThunk(a) || isThunk(b)) { + thunks(a, b, patch, index) + } else if (b == null) { + + // If a is a widget we will add a remove patch for it + // Otherwise any child widgets/hooks must be destroyed. + // This prevents adding two remove patches for a widget. + if (!isWidget(a)) { + clearState(a, patch, index) + apply = patch[index] + } + + apply = appendPatch(apply, new VPatch(VPatch.REMOVE, a, b)) + } else if (isVNode(b)) { + if (isVNode(a)) { + if (a.tagName === b.tagName && + a.namespace === b.namespace && + a.key === b.key) { + var propsPatch = diffProps(a.properties, b.properties) + if (propsPatch) { + apply = appendPatch(apply, + new VPatch(VPatch.PROPS, a, propsPatch)) + } + apply = diffChildren(a, b, patch, apply, index) + } else { + apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b)) + applyClear = true + } + } else { + apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b)) + applyClear = true + } + } else if (isVText(b)) { + if (!isVText(a)) { + apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b)) + applyClear = true + } else if (a.text !== b.text) { + apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b)) + } + } else if (isWidget(b)) { + if (!isWidget(a)) { + applyClear = true + } + + apply = appendPatch(apply, new VPatch(VPatch.WIDGET, a, b)) + } + + if (apply) { + patch[index] = apply + } + + if (applyClear) { + clearState(a, patch, index) + } +} + +function diffChildren(a, b, patch, apply, index) { + var aChildren = a.children + var orderedSet = reorder(aChildren, b.children) + var bChildren = orderedSet.children + + var aLen = aChildren.length + var bLen = bChildren.length + var len = aLen > bLen ? aLen : bLen + + for (var i = 0; i < len; i++) { + var leftNode = aChildren[i] + var rightNode = bChildren[i] + index += 1 + + if (!leftNode) { + if (rightNode) { + // Excess nodes in b need to be added + apply = appendPatch(apply, + new VPatch(VPatch.INSERT, null, rightNode)) + } + } else { + walk(leftNode, rightNode, patch, index) + } + + if (isVNode(leftNode) && leftNode.count) { + index += leftNode.count + } + } + + if (orderedSet.moves) { + // Reorder nodes last + apply = appendPatch(apply, new VPatch( + VPatch.ORDER, + a, + orderedSet.moves + )) + } + + return apply +} + +function clearState(vNode, patch, index) { + // TODO: Make this a single walk, not two + unhook(vNode, patch, index) + destroyWidgets(vNode, patch, index) +} + +// Patch records for all destroyed widgets must be added because we need +// a DOM node reference for the destroy function +function destroyWidgets(vNode, patch, index) { + if (isWidget(vNode)) { + if (typeof vNode.destroy === "function") { + patch[index] = appendPatch( + patch[index], + new VPatch(VPatch.REMOVE, vNode, null) + ) + } + } else if (isVNode(vNode) && (vNode.hasWidgets || vNode.hasThunks)) { + var children = vNode.children + var len = children.length + for (var i = 0; i < len; i++) { + var child = children[i] + index += 1 + + destroyWidgets(child, patch, index) + + if (isVNode(child) && child.count) { + index += child.count + } + } + } else if (isThunk(vNode)) { + thunks(vNode, null, patch, index) + } +} + +// Create a sub-patch for thunks +function thunks(a, b, patch, index) { + var nodes = handleThunk(a, b) + var thunkPatch = diff(nodes.a, nodes.b) + if (hasPatches(thunkPatch)) { + patch[index] = new VPatch(VPatch.THUNK, null, thunkPatch) + } +} + +function hasPatches(patch) { + for (var index in patch) { + if (index !== "a") { + return true + } + } + + return false +} + +// Execute hooks when two nodes are identical +function unhook(vNode, patch, index) { + if (isVNode(vNode)) { + if (vNode.hooks) { + patch[index] = appendPatch( + patch[index], + new VPatch( + VPatch.PROPS, + vNode, + undefinedKeys(vNode.hooks) + ) + ) + } + + if (vNode.descendantHooks || vNode.hasThunks) { + var children = vNode.children + var len = children.length + for (var i = 0; i < len; i++) { + var child = children[i] + index += 1 + + unhook(child, patch, index) + + if (isVNode(child) && child.count) { + index += child.count + } + } + } + } else if (isThunk(vNode)) { + thunks(vNode, null, patch, index) + } +} + +function undefinedKeys(obj) { + var result = {} + + for (var key in obj) { + result[key] = undefined + } + + return result +} + +// List diff, naive left to right reordering +function reorder(aChildren, bChildren) { + // O(M) time, O(M) memory + var bChildIndex = keyIndex(bChildren) + var bKeys = bChildIndex.keys + var bFree = bChildIndex.free + + if (bFree.length === bChildren.length) { + return { + children: bChildren, + moves: null + } + } + + // O(N) time, O(N) memory + var aChildIndex = keyIndex(aChildren) + var aKeys = aChildIndex.keys + var aFree = aChildIndex.free + + if (aFree.length === aChildren.length) { + return { + children: bChildren, + moves: null + } + } + + // O(MAX(N, M)) memory + var newChildren = [] + + var freeIndex = 0 + var freeCount = bFree.length + var deletedItems = 0 + + // Iterate through a and match a node in b + // O(N) time, + for (var i = 0 ; i < aChildren.length; i++) { + var aItem = aChildren[i] + var itemIndex + + if (aItem.key) { + if (bKeys.hasOwnProperty(aItem.key)) { + // Match up the old keys + itemIndex = bKeys[aItem.key] + newChildren.push(bChildren[itemIndex]) + + } else { + // Remove old keyed items + itemIndex = i - deletedItems++ + newChildren.push(null) + } + } else { + // Match the item in a with the next free item in b + if (freeIndex < freeCount) { + itemIndex = bFree[freeIndex++] + newChildren.push(bChildren[itemIndex]) + } else { + // There are no free items in b to match with + // the free items in a, so the extra free nodes + // are deleted. + itemIndex = i - deletedItems++ + newChildren.push(null) + } + } + } + + var lastFreeIndex = freeIndex >= bFree.length ? + bChildren.length : + bFree[freeIndex] + + // Iterate through b and append any new keys + // O(M) time + for (var j = 0; j < bChildren.length; j++) { + var newItem = bChildren[j] + + if (newItem.key) { + if (!aKeys.hasOwnProperty(newItem.key)) { + // Add any new keyed items + // We are adding new items to the end and then sorting them + // in place. In future we should insert new items in place. + newChildren.push(newItem) + } + } else if (j >= lastFreeIndex) { + // Add any leftover non-keyed items + newChildren.push(newItem) + } + } + + var simulate = newChildren.slice() + var simulateIndex = 0 + var removes = [] + var inserts = [] + var simulateItem + + for (var k = 0; k < bChildren.length;) { + var wantedItem = bChildren[k] + simulateItem = simulate[simulateIndex] + + // remove items + while (simulateItem === null && simulate.length) { + removes.push(remove(simulate, simulateIndex, null)) + simulateItem = simulate[simulateIndex] + } + + if (!simulateItem || simulateItem.key !== wantedItem.key) { + // if we need a key in this position... + if (wantedItem.key) { + if (simulateItem && simulateItem.key) { + // if an insert doesn't put this key in place, it needs to move + if (bKeys[simulateItem.key] !== k + 1) { + removes.push(remove(simulate, simulateIndex, simulateItem.key)) + simulateItem = simulate[simulateIndex] + // if the remove didn't put the wanted item in place, we need to insert it + if (!simulateItem || simulateItem.key !== wantedItem.key) { + inserts.push({key: wantedItem.key, to: k}) + } + // items are matching, so skip ahead + else { + simulateIndex++ + } + } + else { + inserts.push({key: wantedItem.key, to: k}) + } + } + else { + inserts.push({key: wantedItem.key, to: k}) + } + k++ + } + // a key in simulate has no matching wanted key, remove it + else if (simulateItem && simulateItem.key) { + removes.push(remove(simulate, simulateIndex, simulateItem.key)) + } + } + else { + simulateIndex++ + k++ + } + } + + // remove all the remaining nodes from simulate + while(simulateIndex < simulate.length) { + simulateItem = simulate[simulateIndex] + removes.push(remove(simulate, simulateIndex, simulateItem && simulateItem.key)) + } + + // If the only moves we have are deletes then we can just + // let the delete patch remove these items. + if (removes.length === deletedItems && !inserts.length) { + return { + children: newChildren, + moves: null + } + } + + return { + children: newChildren, + moves: { + removes: removes, + inserts: inserts + } + } +} + +function remove(arr, index, key) { + arr.splice(index, 1) + + return { + from: index, + key: key + } +} + +function keyIndex(children) { + var keys = {} + var free = [] + var length = children.length + + for (var i = 0; i < length; i++) { + var child = children[i] + + if (child.key) { + keys[child.key] = i + } else { + free.push(i) + } + } + + return { + keys: keys, // A hash of key name to index + free: free, // An array of unkeyed item indices + } +} + +function appendPatch(apply, patch) { + if (apply) { + if (isArray(apply)) { + apply.push(patch) + } else { + apply = [apply, patch] + } + + return apply + } else { + return patch + } +} + +},{"../vnode/handle-thunk":11,"../vnode/is-thunk":12,"../vnode/is-vnode":14,"../vnode/is-vtext":15,"../vnode/is-widget":16,"../vnode/vpatch":19,"./diff-props":21,"x-is-array":4}],23:[function(require,module,exports){ +var VNode = require('virtual-dom/vnode/vnode'); +var VText = require('virtual-dom/vnode/vtext'); +var diff = require('virtual-dom/vtree/diff'); +var patch = require('virtual-dom/vdom/patch'); +var createElement = require('virtual-dom/vdom/create-element'); +var isHook = require("virtual-dom/vnode/is-vhook"); + + +Elm.Native.VirtualDom = {}; +Elm.Native.VirtualDom.make = function(elm) +{ + elm.Native = elm.Native || {}; + elm.Native.VirtualDom = elm.Native.VirtualDom || {}; + if (elm.Native.VirtualDom.values) + { + return elm.Native.VirtualDom.values; + } + + var Element = Elm.Native.Graphics.Element.make(elm); + var Json = Elm.Native.Json.make(elm); + var List = Elm.Native.List.make(elm); + var Signal = Elm.Native.Signal.make(elm); + var Utils = Elm.Native.Utils.make(elm); + + var ATTRIBUTE_KEY = 'UniqueNameThatOthersAreVeryUnlikelyToUse'; + + + + // VIRTUAL DOM NODES + + + function text(string) + { + return new VText(string); + } + + function node(name) + { + return F2(function(propertyList, contents) { + return makeNode(name, propertyList, contents); + }); + } + + + // BUILD VIRTUAL DOME NODES + + + function makeNode(name, propertyList, contents) + { + var props = listToProperties(propertyList); + + var key, namespace; + // support keys + if (props.key !== undefined) + { + key = props.key; + props.key = undefined; + } + + // support namespace + if (props.namespace !== undefined) + { + namespace = props.namespace; + props.namespace = undefined; + } + + // ensure that setting text of an input does not move the cursor + var useSoftSet = + (name === 'input' || name === 'textarea') + && props.value !== undefined + && !isHook(props.value); + + if (useSoftSet) + { + props.value = SoftSetHook(props.value); + } + + return new VNode(name, props, List.toArray(contents), key, namespace); + } + + function listToProperties(list) + { + var object = {}; + while (list.ctor !== '[]') + { + var entry = list._0; + if (entry.key === ATTRIBUTE_KEY) + { + object.attributes = object.attributes || {}; + object.attributes[entry.value.attrKey] = entry.value.attrValue; + } + else + { + object[entry.key] = entry.value; + } + list = list._1; + } + return object; + } + + + + // PROPERTIES AND ATTRIBUTES + + + function property(key, value) + { + return { + key: key, + value: value + }; + } + + function attribute(key, value) + { + return { + key: ATTRIBUTE_KEY, + value: { + attrKey: key, + attrValue: value + } + }; + } + + + + // NAMESPACED ATTRIBUTES + + + function attributeNS(namespace, key, value) + { + return { + key: key, + value: new AttributeHook(namespace, key, value) + }; + } + + function AttributeHook(namespace, key, value) + { + if (!(this instanceof AttributeHook)) + { + return new AttributeHook(namespace, key, value); + } + + this.namespace = namespace; + this.key = key; + this.value = value; + } + + AttributeHook.prototype.hook = function (node, prop, prev) + { + if (prev + && prev.type === 'AttributeHook' + && prev.value === this.value + && prev.namespace === this.namespace) + { + return; + } + + node.setAttributeNS(this.namespace, prop, this.value); + }; + + AttributeHook.prototype.unhook = function (node, prop, next) + { + if (next + && next.type === 'AttributeHook' + && next.namespace === this.namespace) + { + return; + } + + node.removeAttributeNS(this.namespace, this.key); + }; + + AttributeHook.prototype.type = 'AttributeHook'; + + + + // EVENTS + + + function on(name, options, decoder, createMessage) + { + function eventHandler(event) + { + var value = A2(Json.runDecoderValue, decoder, event); + if (value.ctor === 'Ok') + { + if (options.stopPropagation) + { + event.stopPropagation(); + } + if (options.preventDefault) + { + event.preventDefault(); + } + Signal.sendMessage(createMessage(value._0)); + } + } + return property('on' + name, eventHandler); + } + + function SoftSetHook(value) + { + if (!(this instanceof SoftSetHook)) + { + return new SoftSetHook(value); + } + + this.value = value; + } + + SoftSetHook.prototype.hook = function (node, propertyName) + { + if (node[propertyName] !== this.value) + { + node[propertyName] = this.value; + } + }; + + + + // INTEGRATION WITH ELEMENTS + + + function ElementWidget(element) + { + this.element = element; + } + + ElementWidget.prototype.type = "Widget"; + + ElementWidget.prototype.init = function init() + { + return Element.render(this.element); + }; + + ElementWidget.prototype.update = function update(previous, node) + { + return Element.update(node, previous.element, this.element); + }; + + function fromElement(element) + { + return new ElementWidget(element); + } + + function toElement(width, height, html) + { + return A3(Element.newElement, width, height, { + ctor: 'Custom', + type: 'evancz/elm-html', + render: render, + update: update, + model: html + }); + } + + + + // RENDER AND UPDATE + + + function render(model) + { + var element = Element.createNode('div'); + element.appendChild(createElement(model)); + return element; + } + + function update(node, oldModel, newModel) + { + updateAndReplace(node.firstChild, oldModel, newModel); + return node; + } + + function updateAndReplace(node, oldModel, newModel) + { + var patches = diff(oldModel, newModel); + var newNode = patch(node, patches); + return newNode; + } + + + + // LAZINESS + + + function lazyRef(fn, a) + { + function thunk() + { + return fn(a); + } + return new Thunk(fn, [a], thunk); + } + + function lazyRef2(fn, a, b) + { + function thunk() + { + return A2(fn, a, b); + } + return new Thunk(fn, [a,b], thunk); + } + + function lazyRef3(fn, a, b, c) + { + function thunk() + { + return A3(fn, a, b, c); + } + return new Thunk(fn, [a,b,c], thunk); + } + + function Thunk(fn, args, thunk) + { + /* public (used by VirtualDom.js) */ + this.vnode = null; + this.key = undefined; + + /* private */ + this.fn = fn; + this.args = args; + this.thunk = thunk; + } + + Thunk.prototype.type = "Thunk"; + Thunk.prototype.render = renderThunk; + + function shouldUpdate(current, previous) + { + if (current.fn !== previous.fn) + { + return true; + } + + // if it's the same function, we know the number of args must match + var cargs = current.args; + var pargs = previous.args; + + for (var i = cargs.length; i--; ) + { + if (cargs[i] !== pargs[i]) + { + return true; + } + } + + return false; + } + + function renderThunk(previous) + { + if (previous == null || shouldUpdate(this, previous)) + { + return this.thunk(); + } + else + { + return previous.vnode; + } + } + + + return elm.Native.VirtualDom.values = Elm.Native.VirtualDom.values = { + node: node, + text: text, + on: F4(on), + + property: F2(property), + attribute: F2(attribute), + attributeNS: F3(attributeNS), + + lazy: F2(lazyRef), + lazy2: F3(lazyRef2), + lazy3: F4(lazyRef3), + + toElement: F3(toElement), + fromElement: fromElement, + + render: createElement, + updateAndReplace: updateAndReplace + }; +}; + +},{"virtual-dom/vdom/create-element":6,"virtual-dom/vdom/patch":9,"virtual-dom/vnode/is-vhook":13,"virtual-dom/vnode/vnode":18,"virtual-dom/vnode/vtext":20,"virtual-dom/vtree/diff":22}]},{},[23]); + +Elm.VirtualDom = Elm.VirtualDom || {}; +Elm.VirtualDom.make = function (_elm) { + "use strict"; + _elm.VirtualDom = _elm.VirtualDom || {}; + if (_elm.VirtualDom.values) return _elm.VirtualDom.values; + var _U = Elm.Native.Utils.make(_elm), + $Basics = Elm.Basics.make(_elm), + $Debug = Elm.Debug.make(_elm), + $Graphics$Element = Elm.Graphics.Element.make(_elm), + $Json$Decode = Elm.Json.Decode.make(_elm), + $List = Elm.List.make(_elm), + $Maybe = Elm.Maybe.make(_elm), + $Native$VirtualDom = Elm.Native.VirtualDom.make(_elm), + $Result = Elm.Result.make(_elm), + $Signal = Elm.Signal.make(_elm); + var _op = {}; + var lazy3 = $Native$VirtualDom.lazy3; + var lazy2 = $Native$VirtualDom.lazy2; + var lazy = $Native$VirtualDom.lazy; + var defaultOptions = {stopPropagation: false,preventDefault: false}; + var Options = F2(function (a,b) { return {stopPropagation: a,preventDefault: b};}); + var onWithOptions = $Native$VirtualDom.on; + var on = F3(function (eventName,decoder,toMessage) { return A4($Native$VirtualDom.on,eventName,defaultOptions,decoder,toMessage);}); + var attributeNS = $Native$VirtualDom.attributeNS; + var attribute = $Native$VirtualDom.attribute; + var property = $Native$VirtualDom.property; + var Property = {ctor: "Property"}; + var fromElement = $Native$VirtualDom.fromElement; + var toElement = $Native$VirtualDom.toElement; + var text = $Native$VirtualDom.text; + var node = $Native$VirtualDom.node; + var Node = {ctor: "Node"}; + return _elm.VirtualDom.values = {_op: _op + ,text: text + ,node: node + ,toElement: toElement + ,fromElement: fromElement + ,property: property + ,attribute: attribute + ,attributeNS: attributeNS + ,on: on + ,onWithOptions: onWithOptions + ,defaultOptions: defaultOptions + ,lazy: lazy + ,lazy2: lazy2 + ,lazy3: lazy3 + ,Options: Options}; +}; +Elm.Html = Elm.Html || {}; +Elm.Html.make = function (_elm) { + "use strict"; + _elm.Html = _elm.Html || {}; + if (_elm.Html.values) return _elm.Html.values; + var _U = Elm.Native.Utils.make(_elm), + $Basics = Elm.Basics.make(_elm), + $Debug = Elm.Debug.make(_elm), + $Graphics$Element = Elm.Graphics.Element.make(_elm), + $List = Elm.List.make(_elm), + $Maybe = Elm.Maybe.make(_elm), + $Result = Elm.Result.make(_elm), + $Signal = Elm.Signal.make(_elm), + $VirtualDom = Elm.VirtualDom.make(_elm); + var _op = {}; + var fromElement = $VirtualDom.fromElement; + var toElement = $VirtualDom.toElement; + var text = $VirtualDom.text; + var node = $VirtualDom.node; + var body = node("body"); + var section = node("section"); + var nav = node("nav"); + var article = node("article"); + var aside = node("aside"); + var h1 = node("h1"); + var h2 = node("h2"); + var h3 = node("h3"); + var h4 = node("h4"); + var h5 = node("h5"); + var h6 = node("h6"); + var header = node("header"); + var footer = node("footer"); + var address = node("address"); + var main$ = node("main"); + var p = node("p"); + var hr = node("hr"); + var pre = node("pre"); + var blockquote = node("blockquote"); + var ol = node("ol"); + var ul = node("ul"); + var li = node("li"); + var dl = node("dl"); + var dt = node("dt"); + var dd = node("dd"); + var figure = node("figure"); + var figcaption = node("figcaption"); + var div = node("div"); + var a = node("a"); + var em = node("em"); + var strong = node("strong"); + var small = node("small"); + var s = node("s"); + var cite = node("cite"); + var q = node("q"); + var dfn = node("dfn"); + var abbr = node("abbr"); + var time = node("time"); + var code = node("code"); + var $var = node("var"); + var samp = node("samp"); + var kbd = node("kbd"); + var sub = node("sub"); + var sup = node("sup"); + var i = node("i"); + var b = node("b"); + var u = node("u"); + var mark = node("mark"); + var ruby = node("ruby"); + var rt = node("rt"); + var rp = node("rp"); + var bdi = node("bdi"); + var bdo = node("bdo"); + var span = node("span"); + var br = node("br"); + var wbr = node("wbr"); + var ins = node("ins"); + var del = node("del"); + var img = node("img"); + var iframe = node("iframe"); + var embed = node("embed"); + var object = node("object"); + var param = node("param"); + var video = node("video"); + var audio = node("audio"); + var source = node("source"); + var track = node("track"); + var canvas = node("canvas"); + var svg = node("svg"); + var math = node("math"); + var table = node("table"); + var caption = node("caption"); + var colgroup = node("colgroup"); + var col = node("col"); + var tbody = node("tbody"); + var thead = node("thead"); + var tfoot = node("tfoot"); + var tr = node("tr"); + var td = node("td"); + var th = node("th"); + var form = node("form"); + var fieldset = node("fieldset"); + var legend = node("legend"); + var label = node("label"); + var input = node("input"); + var button = node("button"); + var select = node("select"); + var datalist = node("datalist"); + var optgroup = node("optgroup"); + var option = node("option"); + var textarea = node("textarea"); + var keygen = node("keygen"); + var output = node("output"); + var progress = node("progress"); + var meter = node("meter"); + var details = node("details"); + var summary = node("summary"); + var menuitem = node("menuitem"); + var menu = node("menu"); + return _elm.Html.values = {_op: _op + ,node: node + ,text: text + ,toElement: toElement + ,fromElement: fromElement + ,body: body + ,section: section + ,nav: nav + ,article: article + ,aside: aside + ,h1: h1 + ,h2: h2 + ,h3: h3 + ,h4: h4 + ,h5: h5 + ,h6: h6 + ,header: header + ,footer: footer + ,address: address + ,main$: main$ + ,p: p + ,hr: hr + ,pre: pre + ,blockquote: blockquote + ,ol: ol + ,ul: ul + ,li: li + ,dl: dl + ,dt: dt + ,dd: dd + ,figure: figure + ,figcaption: figcaption + ,div: div + ,a: a + ,em: em + ,strong: strong + ,small: small + ,s: s + ,cite: cite + ,q: q + ,dfn: dfn + ,abbr: abbr + ,time: time + ,code: code + ,$var: $var + ,samp: samp + ,kbd: kbd + ,sub: sub + ,sup: sup + ,i: i + ,b: b + ,u: u + ,mark: mark + ,ruby: ruby + ,rt: rt + ,rp: rp + ,bdi: bdi + ,bdo: bdo + ,span: span + ,br: br + ,wbr: wbr + ,ins: ins + ,del: del + ,img: img + ,iframe: iframe + ,embed: embed + ,object: object + ,param: param + ,video: video + ,audio: audio + ,source: source + ,track: track + ,canvas: canvas + ,svg: svg + ,math: math + ,table: table + ,caption: caption + ,colgroup: colgroup + ,col: col + ,tbody: tbody + ,thead: thead + ,tfoot: tfoot + ,tr: tr + ,td: td + ,th: th + ,form: form + ,fieldset: fieldset + ,legend: legend + ,label: label + ,input: input + ,button: button + ,select: select + ,datalist: datalist + ,optgroup: optgroup + ,option: option + ,textarea: textarea + ,keygen: keygen + ,output: output + ,progress: progress + ,meter: meter + ,details: details + ,summary: summary + ,menuitem: menuitem + ,menu: menu}; +}; +Elm.Html = Elm.Html || {}; +Elm.Html.Attributes = Elm.Html.Attributes || {}; +Elm.Html.Attributes.make = function (_elm) { + "use strict"; + _elm.Html = _elm.Html || {}; + _elm.Html.Attributes = _elm.Html.Attributes || {}; + if (_elm.Html.Attributes.values) return _elm.Html.Attributes.values; + var _U = Elm.Native.Utils.make(_elm), + $Basics = Elm.Basics.make(_elm), + $Debug = Elm.Debug.make(_elm), + $Html = Elm.Html.make(_elm), + $Json$Encode = Elm.Json.Encode.make(_elm), + $List = Elm.List.make(_elm), + $Maybe = Elm.Maybe.make(_elm), + $Result = Elm.Result.make(_elm), + $Signal = Elm.Signal.make(_elm), + $String = Elm.String.make(_elm), + $VirtualDom = Elm.VirtualDom.make(_elm); + var _op = {}; + var attribute = $VirtualDom.attribute; + var contextmenu = function (value) { return A2(attribute,"contextmenu",value);}; + var property = $VirtualDom.property; + var stringProperty = F2(function (name,string) { return A2(property,name,$Json$Encode.string(string));}); + var $class = function (name) { return A2(stringProperty,"className",name);}; + var id = function (name) { return A2(stringProperty,"id",name);}; + var title = function (name) { return A2(stringProperty,"title",name);}; + var accesskey = function ($char) { return A2(stringProperty,"accessKey",$String.fromChar($char));}; + var dir = function (value) { return A2(stringProperty,"dir",value);}; + var draggable = function (value) { return A2(stringProperty,"draggable",value);}; + var dropzone = function (value) { return A2(stringProperty,"dropzone",value);}; + var itemprop = function (value) { return A2(stringProperty,"itemprop",value);}; + var lang = function (value) { return A2(stringProperty,"lang",value);}; + var tabindex = function (n) { return A2(stringProperty,"tabIndex",$Basics.toString(n));}; + var charset = function (value) { return A2(stringProperty,"charset",value);}; + var content = function (value) { return A2(stringProperty,"content",value);}; + var httpEquiv = function (value) { return A2(stringProperty,"httpEquiv",value);}; + var language = function (value) { return A2(stringProperty,"language",value);}; + var src = function (value) { return A2(stringProperty,"src",value);}; + var height = function (value) { return A2(stringProperty,"height",$Basics.toString(value));}; + var width = function (value) { return A2(stringProperty,"width",$Basics.toString(value));}; + var alt = function (value) { return A2(stringProperty,"alt",value);}; + var preload = function (value) { return A2(stringProperty,"preload",value);}; + var poster = function (value) { return A2(stringProperty,"poster",value);}; + var kind = function (value) { return A2(stringProperty,"kind",value);}; + var srclang = function (value) { return A2(stringProperty,"srclang",value);}; + var sandbox = function (value) { return A2(stringProperty,"sandbox",value);}; + var srcdoc = function (value) { return A2(stringProperty,"srcdoc",value);}; + var type$ = function (value) { return A2(stringProperty,"type",value);}; + var value = function (value) { return A2(stringProperty,"value",value);}; + var placeholder = function (value) { return A2(stringProperty,"placeholder",value);}; + var accept = function (value) { return A2(stringProperty,"accept",value);}; + var acceptCharset = function (value) { return A2(stringProperty,"acceptCharset",value);}; + var action = function (value) { return A2(stringProperty,"action",value);}; + var autocomplete = function (bool) { return A2(stringProperty,"autocomplete",bool ? "on" : "off");}; + var autosave = function (value) { return A2(stringProperty,"autosave",value);}; + var enctype = function (value) { return A2(stringProperty,"enctype",value);}; + var formaction = function (value) { return A2(stringProperty,"formAction",value);}; + var list = function (value) { return A2(stringProperty,"list",value);}; + var minlength = function (n) { return A2(stringProperty,"minLength",$Basics.toString(n));}; + var maxlength = function (n) { return A2(stringProperty,"maxLength",$Basics.toString(n));}; + var method = function (value) { return A2(stringProperty,"method",value);}; + var name = function (value) { return A2(stringProperty,"name",value);}; + var pattern = function (value) { return A2(stringProperty,"pattern",value);}; + var size = function (n) { return A2(stringProperty,"size",$Basics.toString(n));}; + var $for = function (value) { return A2(stringProperty,"htmlFor",value);}; + var form = function (value) { return A2(stringProperty,"form",value);}; + var max = function (value) { return A2(stringProperty,"max",value);}; + var min = function (value) { return A2(stringProperty,"min",value);}; + var step = function (n) { return A2(stringProperty,"step",n);}; + var cols = function (n) { return A2(stringProperty,"cols",$Basics.toString(n));}; + var rows = function (n) { return A2(stringProperty,"rows",$Basics.toString(n));}; + var wrap = function (value) { return A2(stringProperty,"wrap",value);}; + var usemap = function (value) { return A2(stringProperty,"useMap",value);}; + var shape = function (value) { return A2(stringProperty,"shape",value);}; + var coords = function (value) { return A2(stringProperty,"coords",value);}; + var challenge = function (value) { return A2(stringProperty,"challenge",value);}; + var keytype = function (value) { return A2(stringProperty,"keytype",value);}; + var align = function (value) { return A2(stringProperty,"align",value);}; + var cite = function (value) { return A2(stringProperty,"cite",value);}; + var href = function (value) { return A2(stringProperty,"href",value);}; + var target = function (value) { return A2(stringProperty,"target",value);}; + var downloadAs = function (value) { return A2(stringProperty,"download",value);}; + var hreflang = function (value) { return A2(stringProperty,"hreflang",value);}; + var media = function (value) { return A2(stringProperty,"media",value);}; + var ping = function (value) { return A2(stringProperty,"ping",value);}; + var rel = function (value) { return A2(stringProperty,"rel",value);}; + var datetime = function (value) { return A2(stringProperty,"datetime",value);}; + var pubdate = function (value) { return A2(stringProperty,"pubdate",value);}; + var start = function (n) { return A2(stringProperty,"start",$Basics.toString(n));}; + var colspan = function (n) { return A2(stringProperty,"colSpan",$Basics.toString(n));}; + var headers = function (value) { return A2(stringProperty,"headers",value);}; + var rowspan = function (n) { return A2(stringProperty,"rowSpan",$Basics.toString(n));}; + var scope = function (value) { return A2(stringProperty,"scope",value);}; + var manifest = function (value) { return A2(stringProperty,"manifest",value);}; + var boolProperty = F2(function (name,bool) { return A2(property,name,$Json$Encode.bool(bool));}); + var hidden = function (bool) { return A2(boolProperty,"hidden",bool);}; + var contenteditable = function (bool) { return A2(boolProperty,"contentEditable",bool);}; + var spellcheck = function (bool) { return A2(boolProperty,"spellcheck",bool);}; + var async = function (bool) { return A2(boolProperty,"async",bool);}; + var defer = function (bool) { return A2(boolProperty,"defer",bool);}; + var scoped = function (bool) { return A2(boolProperty,"scoped",bool);}; + var autoplay = function (bool) { return A2(boolProperty,"autoplay",bool);}; + var controls = function (bool) { return A2(boolProperty,"controls",bool);}; + var loop = function (bool) { return A2(boolProperty,"loop",bool);}; + var $default = function (bool) { return A2(boolProperty,"default",bool);}; + var seamless = function (bool) { return A2(boolProperty,"seamless",bool);}; + var checked = function (bool) { return A2(boolProperty,"checked",bool);}; + var selected = function (bool) { return A2(boolProperty,"selected",bool);}; + var autofocus = function (bool) { return A2(boolProperty,"autofocus",bool);}; + var disabled = function (bool) { return A2(boolProperty,"disabled",bool);}; + var multiple = function (bool) { return A2(boolProperty,"multiple",bool);}; + var novalidate = function (bool) { return A2(boolProperty,"noValidate",bool);}; + var readonly = function (bool) { return A2(boolProperty,"readOnly",bool);}; + var required = function (bool) { return A2(boolProperty,"required",bool);}; + var ismap = function (value) { return A2(boolProperty,"isMap",value);}; + var download = function (bool) { return A2(boolProperty,"download",bool);}; + var reversed = function (bool) { return A2(boolProperty,"reversed",bool);}; + var classList = function (list) { return $class(A2($String.join," ",A2($List.map,$Basics.fst,A2($List.filter,$Basics.snd,list))));}; + var style = function (props) { + return A2(property, + "style", + $Json$Encode.object(A2($List.map,function (_p0) { var _p1 = _p0;return {ctor: "_Tuple2",_0: _p1._0,_1: $Json$Encode.string(_p1._1)};},props))); + }; + var key = function (k) { return A2(stringProperty,"key",k);}; + return _elm.Html.Attributes.values = {_op: _op + ,key: key + ,style: style + ,$class: $class + ,classList: classList + ,id: id + ,title: title + ,hidden: hidden + ,type$: type$ + ,value: value + ,checked: checked + ,placeholder: placeholder + ,selected: selected + ,accept: accept + ,acceptCharset: acceptCharset + ,action: action + ,autocomplete: autocomplete + ,autofocus: autofocus + ,autosave: autosave + ,disabled: disabled + ,enctype: enctype + ,formaction: formaction + ,list: list + ,maxlength: maxlength + ,minlength: minlength + ,method: method + ,multiple: multiple + ,name: name + ,novalidate: novalidate + ,pattern: pattern + ,readonly: readonly + ,required: required + ,size: size + ,$for: $for + ,form: form + ,max: max + ,min: min + ,step: step + ,cols: cols + ,rows: rows + ,wrap: wrap + ,href: href + ,target: target + ,download: download + ,downloadAs: downloadAs + ,hreflang: hreflang + ,media: media + ,ping: ping + ,rel: rel + ,ismap: ismap + ,usemap: usemap + ,shape: shape + ,coords: coords + ,src: src + ,height: height + ,width: width + ,alt: alt + ,autoplay: autoplay + ,controls: controls + ,loop: loop + ,preload: preload + ,poster: poster + ,$default: $default + ,kind: kind + ,srclang: srclang + ,sandbox: sandbox + ,seamless: seamless + ,srcdoc: srcdoc + ,reversed: reversed + ,start: start + ,align: align + ,colspan: colspan + ,rowspan: rowspan + ,headers: headers + ,scope: scope + ,async: async + ,charset: charset + ,content: content + ,defer: defer + ,httpEquiv: httpEquiv + ,language: language + ,scoped: scoped + ,accesskey: accesskey + ,contenteditable: contenteditable + ,contextmenu: contextmenu + ,dir: dir + ,draggable: draggable + ,dropzone: dropzone + ,itemprop: itemprop + ,lang: lang + ,spellcheck: spellcheck + ,tabindex: tabindex + ,challenge: challenge + ,keytype: keytype + ,cite: cite + ,datetime: datetime + ,pubdate: pubdate + ,manifest: manifest + ,property: property + ,attribute: attribute}; +}; +Elm.Html = Elm.Html || {}; +Elm.Html.Events = Elm.Html.Events || {}; +Elm.Html.Events.make = function (_elm) { + "use strict"; + _elm.Html = _elm.Html || {}; + _elm.Html.Events = _elm.Html.Events || {}; + if (_elm.Html.Events.values) return _elm.Html.Events.values; + var _U = Elm.Native.Utils.make(_elm), + $Basics = Elm.Basics.make(_elm), + $Debug = Elm.Debug.make(_elm), + $Html = Elm.Html.make(_elm), + $Json$Decode = Elm.Json.Decode.make(_elm), + $List = Elm.List.make(_elm), + $Maybe = Elm.Maybe.make(_elm), + $Result = Elm.Result.make(_elm), + $Signal = Elm.Signal.make(_elm), + $VirtualDom = Elm.VirtualDom.make(_elm); + var _op = {}; + var keyCode = A2($Json$Decode._op[":="],"keyCode",$Json$Decode.$int); + var targetChecked = A2($Json$Decode.at,_U.list(["target","checked"]),$Json$Decode.bool); + var targetValue = A2($Json$Decode.at,_U.list(["target","value"]),$Json$Decode.string); + var defaultOptions = $VirtualDom.defaultOptions; + var Options = F2(function (a,b) { return {stopPropagation: a,preventDefault: b};}); + var onWithOptions = $VirtualDom.onWithOptions; + var on = $VirtualDom.on; + var messageOn = F3(function (name,addr,msg) { return A3(on,name,$Json$Decode.value,function (_p0) { return A2($Signal.message,addr,msg);});}); + var onClick = messageOn("click"); + var onDoubleClick = messageOn("dblclick"); + var onMouseMove = messageOn("mousemove"); + var onMouseDown = messageOn("mousedown"); + var onMouseUp = messageOn("mouseup"); + var onMouseEnter = messageOn("mouseenter"); + var onMouseLeave = messageOn("mouseleave"); + var onMouseOver = messageOn("mouseover"); + var onMouseOut = messageOn("mouseout"); + var onBlur = messageOn("blur"); + var onFocus = messageOn("focus"); + var onSubmit = messageOn("submit"); + var onKey = F3(function (name,addr,handler) { return A3(on,name,keyCode,function (code) { return A2($Signal.message,addr,handler(code));});}); + var onKeyUp = onKey("keyup"); + var onKeyDown = onKey("keydown"); + var onKeyPress = onKey("keypress"); + return _elm.Html.Events.values = {_op: _op + ,onBlur: onBlur + ,onFocus: onFocus + ,onSubmit: onSubmit + ,onKeyUp: onKeyUp + ,onKeyDown: onKeyDown + ,onKeyPress: onKeyPress + ,onClick: onClick + ,onDoubleClick: onDoubleClick + ,onMouseMove: onMouseMove + ,onMouseDown: onMouseDown + ,onMouseUp: onMouseUp + ,onMouseEnter: onMouseEnter + ,onMouseLeave: onMouseLeave + ,onMouseOver: onMouseOver + ,onMouseOut: onMouseOut + ,on: on + ,onWithOptions: onWithOptions + ,defaultOptions: defaultOptions + ,targetValue: targetValue + ,targetChecked: targetChecked + ,keyCode: keyCode + ,Options: Options}; +}; +Elm.Todo = Elm.Todo || {}; +Elm.Todo.make = function (_elm) { + "use strict"; + _elm.Todo = _elm.Todo || {}; + if (_elm.Todo.values) return _elm.Todo.values; + var _U = Elm.Native.Utils.make(_elm), + $Basics = Elm.Basics.make(_elm), + $Debug = Elm.Debug.make(_elm), + $Html = Elm.Html.make(_elm), + $Html$Attributes = Elm.Html.Attributes.make(_elm), + $Html$Events = Elm.Html.Events.make(_elm), + $Json$Decode = Elm.Json.Decode.make(_elm), + $List = Elm.List.make(_elm), + $Maybe = Elm.Maybe.make(_elm), + $Result = Elm.Result.make(_elm), + $Signal = Elm.Signal.make(_elm), + $String = Elm.String.make(_elm); + var _op = {}; + var infoFooter = A2($Html.footer, + _U.list([$Html$Attributes.$class("info")]), + _U.list([A2($Html.p,_U.list([]),_U.list([$Html.text("Double-click to edit a todo")])) + ,A2($Html.p, + _U.list([]), + _U.list([$Html.text("Written by ") + ,A2($Html.a,_U.list([$Html$Attributes.href("https://github.com/evancz")]),_U.list([$Html.text("Evan Czaplicki")]))])) + ,A2($Html.p, + _U.list([]), + _U.list([$Html.text("Part of "),A2($Html.a,_U.list([$Html$Attributes.href("http://todomvc.com")]),_U.list([$Html.text("TodoMVC")]))]))])); + var is13 = function (code) { return _U.eq(code,13) ? $Result.Ok({ctor: "_Tuple0"}) : $Result.Err("not the right key code");}; + var onEnter = F2(function (address,value) { + return A3($Html$Events.on, + "keydown", + A2($Json$Decode.customDecoder,$Html$Events.keyCode,is13), + function (_p0) { + return A2($Signal.message,address,value); + }); + }); + var ChangeVisibility = function (a) { return {ctor: "ChangeVisibility",_0: a};}; + var visibilitySwap = F4(function (address,uri,visibility,actualVisibility) { + return A2($Html.li, + _U.list([A2($Html$Events.onClick,address,ChangeVisibility(visibility))]), + _U.list([A2($Html.a, + _U.list([$Html$Attributes.href(uri),$Html$Attributes.classList(_U.list([{ctor: "_Tuple2",_0: "selected",_1: _U.eq(visibility,actualVisibility)}]))]), + _U.list([$Html.text(visibility)]))])); + }); + var CheckAll = function (a) { return {ctor: "CheckAll",_0: a};}; + var Check = F2(function (a,b) { return {ctor: "Check",_0: a,_1: b};}); + var DeleteComplete = {ctor: "DeleteComplete"}; + var controls = F3(function (address,visibility,tasks) { + var tasksCompleted = $List.length(A2($List.filter,function (_) { return _.completed;},tasks)); + var tasksLeft = $List.length(tasks) - tasksCompleted; + var item_ = _U.eq(tasksLeft,1) ? " item" : " items"; + return A2($Html.footer, + _U.list([$Html$Attributes.$class("footer"),$Html$Attributes.hidden($List.isEmpty(tasks))]), + _U.list([A2($Html.span, + _U.list([$Html$Attributes.$class("todo-count")]), + _U.list([A2($Html.strong,_U.list([]),_U.list([$Html.text($Basics.toString(tasksLeft))])),$Html.text(A2($Basics._op["++"],item_," left"))])) + ,A2($Html.ul, + _U.list([$Html$Attributes.$class("filters")]), + _U.list([A4(visibilitySwap,address,"#/","All",visibility) + ,$Html.text(" ") + ,A4(visibilitySwap,address,"#/active","Active",visibility) + ,$Html.text(" ") + ,A4(visibilitySwap,address,"#/completed","Completed",visibility)])) + ,A2($Html.button, + _U.list([$Html$Attributes.$class("clear-completed") + ,$Html$Attributes.hidden(_U.eq(tasksCompleted,0)) + ,A2($Html$Events.onClick,address,DeleteComplete)]), + _U.list([$Html.text(A2($Basics._op["++"],"Clear completed (",A2($Basics._op["++"],$Basics.toString(tasksCompleted),")")))]))])); + }); + var Delete = function (a) { return {ctor: "Delete",_0: a};}; + var Add = {ctor: "Add"}; + var UpdateTask = F2(function (a,b) { return {ctor: "UpdateTask",_0: a,_1: b};}); + var EditingTask = F2(function (a,b) { return {ctor: "EditingTask",_0: a,_1: b};}); + var todoItem = F2(function (address,todo) { + return A2($Html.li, + _U.list([$Html$Attributes.classList(_U.list([{ctor: "_Tuple2",_0: "completed",_1: todo.completed},{ctor: "_Tuple2",_0: "editing",_1: todo.editing}]))]), + _U.list([A2($Html.div, + _U.list([$Html$Attributes.$class("view")]), + _U.list([A2($Html.input, + _U.list([$Html$Attributes.$class("toggle") + ,$Html$Attributes.type$("checkbox") + ,$Html$Attributes.checked(todo.completed) + ,A2($Html$Events.onClick,address,A2(Check,todo.id,$Basics.not(todo.completed)))]), + _U.list([])) + ,A2($Html.label,_U.list([A2($Html$Events.onDoubleClick,address,A2(EditingTask,todo.id,true))]),_U.list([$Html.text(todo.description)])) + ,A2($Html.button,_U.list([$Html$Attributes.$class("destroy"),A2($Html$Events.onClick,address,Delete(todo.id))]),_U.list([]))])) + ,A2($Html.input, + _U.list([$Html$Attributes.$class("edit") + ,$Html$Attributes.value(todo.description) + ,$Html$Attributes.name("title") + ,$Html$Attributes.id(A2($Basics._op["++"],"todo-",$Basics.toString(todo.id))) + ,A3($Html$Events.on,"input",$Html$Events.targetValue,function (_p1) { return A2($Signal.message,address,A2(UpdateTask,todo.id,_p1));}) + ,A2($Html$Events.onBlur,address,A2(EditingTask,todo.id,false)) + ,A2(onEnter,address,A2(EditingTask,todo.id,false))]), + _U.list([]))])); + }); + var taskList = F3(function (address,visibility,tasks) { + var cssVisibility = $List.isEmpty(tasks) ? "hidden" : "visible"; + var allCompleted = A2($List.all,function (_) { return _.completed;},tasks); + var isVisible = function (todo) { + var _p2 = visibility; + switch (_p2) + {case "Completed": return todo.completed; + case "Active": return $Basics.not(todo.completed); + default: return true;} + }; + return A2($Html.section, + _U.list([$Html$Attributes.$class("main"),$Html$Attributes.style(_U.list([{ctor: "_Tuple2",_0: "visibility",_1: cssVisibility}]))]), + _U.list([A2($Html.input, + _U.list([$Html$Attributes.$class("toggle-all") + ,$Html$Attributes.type$("checkbox") + ,$Html$Attributes.name("toggle") + ,$Html$Attributes.checked(allCompleted) + ,A2($Html$Events.onClick,address,CheckAll($Basics.not(allCompleted)))]), + _U.list([])) + ,A2($Html.label,_U.list([$Html$Attributes.$for("toggle-all")]),_U.list([$Html.text("Mark all as complete")])) + ,A2($Html.ul,_U.list([$Html$Attributes.$class("todo-list")]),A2($List.map,todoItem(address),A2($List.filter,isVisible,tasks)))])); + }); + var UpdateField = function (a) { return {ctor: "UpdateField",_0: a};}; + var taskEntry = F2(function (address,task) { + return A2($Html.header, + _U.list([$Html$Attributes.$class("header")]), + _U.list([A2($Html.h1,_U.list([]),_U.list([$Html.text("todos")])) + ,A2($Html.input, + _U.list([$Html$Attributes.$class("new-todo") + ,$Html$Attributes.placeholder("What needs to be done?") + ,$Html$Attributes.autofocus(true) + ,$Html$Attributes.value(task) + ,$Html$Attributes.name("newTodo") + ,A3($Html$Events.on,"input",$Html$Events.targetValue,function (_p3) { return A2($Signal.message,address,UpdateField(_p3));}) + ,A2(onEnter,address,Add)]), + _U.list([]))])); + }); + var view = F2(function (address,model) { + return A2($Html.div, + _U.list([$Html$Attributes.$class("todomvc-wrapper"),$Html$Attributes.style(_U.list([{ctor: "_Tuple2",_0: "visibility",_1: "hidden"}]))]), + _U.list([A2($Html.section, + _U.list([$Html$Attributes.$class("todoapp")]), + _U.list([A2(taskEntry,address,model.field),A3(taskList,address,model.visibility,model.tasks),A3(controls,address,model.visibility,model.tasks)])) + ,infoFooter])); + }); + var NoOp = {ctor: "NoOp"}; + var actions = $Signal.mailbox(NoOp); + var focus = Elm.Native.Port.make(_elm).outboundSignal("focus", + function (v) { + return v; + }, + function () { + var toSelector = function (act) { + var _p4 = act; + if (_p4.ctor === "EditingTask") { + return A2($Basics._op["++"],"#todo-",$Basics.toString(_p4._0)); + } else { + return ""; + } + }; + var needsFocus = function (act) { var _p5 = act;if (_p5.ctor === "EditingTask") { return _p5._1;} else { return false;}}; + return A2($Signal.map,toSelector,A3($Signal.filter,needsFocus,A2(EditingTask,0,true),actions.signal)); + }()); + var emptyModel = {tasks: _U.list([]),visibility: "All",field: "",uid: 0}; + var newTask = F2(function (desc,id) { return {description: desc,completed: false,editing: false,id: id};}); + var update = F2(function (action,model) { + var _p6 = action; + switch (_p6.ctor) + {case "NoOp": return model; + case "Add": return _U.update(model, + {uid: model.uid + 1 + ,field: "" + ,tasks: $String.isEmpty(model.field) ? model.tasks : A2($Basics._op["++"],model.tasks,_U.list([A2(newTask,model.field,model.uid)]))}); + case "UpdateField": return _U.update(model,{field: _p6._0}); + case "EditingTask": var updateTask = function (t) { return _U.eq(t.id,_p6._0) ? _U.update(t,{editing: _p6._1}) : t;}; + return _U.update(model,{tasks: A2($List.map,updateTask,model.tasks)}); + case "UpdateTask": var updateTask = function (t) { return _U.eq(t.id,_p6._0) ? _U.update(t,{description: _p6._1}) : t;}; + return _U.update(model,{tasks: A2($List.map,updateTask,model.tasks)}); + case "Delete": return _U.update(model,{tasks: A2($List.filter,function (t) { return !_U.eq(t.id,_p6._0);},model.tasks)}); + case "DeleteComplete": return _U.update(model, + {tasks: A2($List.filter,function (_p7) { return $Basics.not(function (_) { return _.completed;}(_p7));},model.tasks)}); + case "Check": var updateTask = function (t) { return _U.eq(t.id,_p6._0) ? _U.update(t,{completed: _p6._1}) : t;}; + return _U.update(model,{tasks: A2($List.map,updateTask,model.tasks)}); + case "CheckAll": var updateTask = function (t) { return _U.update(t,{completed: _p6._0});}; + return _U.update(model,{tasks: A2($List.map,updateTask,model.tasks)}); + default: return _U.update(model,{visibility: _p6._0});} + }); + var model = A3($Signal.foldp,update,emptyModel,actions.signal); + var main = A2($Signal.map,view(actions.address),model); + var Task = F4(function (a,b,c,d) { return {description: a,completed: b,editing: c,id: d};}); + var Model = F4(function (a,b,c,d) { return {tasks: a,field: b,uid: c,visibility: d};}); + return _elm.Todo.values = {_op: _op + ,Model: Model + ,Task: Task + ,newTask: newTask + ,emptyModel: emptyModel + ,NoOp: NoOp + ,UpdateField: UpdateField + ,EditingTask: EditingTask + ,UpdateTask: UpdateTask + ,Add: Add + ,Delete: Delete + ,DeleteComplete: DeleteComplete + ,Check: Check + ,CheckAll: CheckAll + ,ChangeVisibility: ChangeVisibility + ,update: update + ,view: view + ,onEnter: onEnter + ,is13: is13 + ,taskEntry: taskEntry + ,taskList: taskList + ,todoItem: todoItem + ,controls: controls + ,visibilitySwap: visibilitySwap + ,infoFooter: infoFooter + ,main: main + ,model: model + ,actions: actions}; +}; diff --git a/bench/implementations/elm-0.16/index.html b/bench/implementations/elm-0.16/index.html new file mode 100644 index 0000000..c9f689d --- /dev/null +++ b/bench/implementations/elm-0.16/index.html @@ -0,0 +1,26 @@ + + + + + + Elm • TodoMVC + + + + + + + + + + diff --git a/bench/implementations/elm-0.16/style.css b/bench/implementations/elm-0.16/style.css new file mode 100644 index 0000000..fc2e67b --- /dev/null +++ b/bench/implementations/elm-0.16/style.css @@ -0,0 +1,382 @@ +html, +body { + margin: 0; + padding: 0; +} + +.todomvc-wrapper { + visibility: visible !important; +} + +button { + margin: 0; + padding: 0; + border: 0; + background: none; + font-size: 100%; + vertical-align: baseline; + font-family: inherit; + font-weight: inherit; + color: inherit; + -webkit-appearance: none; + appearance: none; + -webkit-font-smoothing: antialiased; + -moz-font-smoothing: antialiased; + font-smoothing: antialiased; +} + +body { + font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif; + line-height: 1.4em; + background: #f5f5f5; + color: #4d4d4d; + min-width: 230px; + max-width: 550px; + margin: 0 auto; + -webkit-font-smoothing: antialiased; + -moz-font-smoothing: antialiased; + font-smoothing: antialiased; + font-weight: 300; +} + +button, +input[type="checkbox"] { + outline: none; +} + +.hidden { + display: none; +} + +.todoapp { + background: #fff; + margin: 130px 0 40px 0; + position: relative; + box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), + 0 25px 50px 0 rgba(0, 0, 0, 0.1); +} + +.todoapp input::-webkit-input-placeholder { + font-style: italic; + font-weight: 300; + color: #e6e6e6; +} + +.todoapp input::-moz-placeholder { + font-style: italic; + font-weight: 300; + color: #e6e6e6; +} + +.todoapp input::input-placeholder { + font-style: italic; + font-weight: 300; + color: #e6e6e6; +} + +.todoapp h1 { + position: absolute; + top: -155px; + width: 100%; + font-size: 100px; + font-weight: 100; + text-align: center; + color: rgba(175, 47, 47, 0.15); + -webkit-text-rendering: optimizeLegibility; + -moz-text-rendering: optimizeLegibility; + text-rendering: optimizeLegibility; +} + +.new-todo, +.edit { + position: relative; + margin: 0; + width: 100%; + font-size: 24px; + font-family: inherit; + font-weight: 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); + box-sizing: border-box; + -webkit-font-smoothing: antialiased; + -moz-font-smoothing: antialiased; + font-smoothing: antialiased; +} + +.new-todo { + padding: 16px 16px 16px 60px; + border: none; + background: rgba(0, 0, 0, 0.003); + box-shadow: inset 0 -2px 1px rgba(0,0,0,0.03); +} + +.main { + position: relative; + z-index: 2; + border-top: 1px solid #e6e6e6; +} + +label[for='toggle-all'] { + display: none; +} + +.toggle-all { + position: absolute; + top: -55px; + left: -12px; + width: 60px; + height: 34px; + text-align: center; + border: none; /* Mobile Safari */ +} + +.toggle-all:before { + content: '❯'; + font-size: 22px; + color: #e6e6e6; + padding: 10px 27px 10px 27px; +} + +.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 solid #ededed; +} + +.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; + appearance: none; +} + +.todo-list li .toggle:after { + content: url('data:image/svg+xml;utf8,'); +} + +.todo-list li .toggle:checked:after { + content: url('data:image/svg+xml;utf8,'); +} + +.todo-list li label { + white-space: pre-line; + word-break: break-all; + padding: 15px 60px 15px 15px; + margin-left: 45px; + display: block; + line-height: 1.2; + transition: color 0.4s; +} + +.todo-list li.completed label { + color: #d9d9d9; + 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: 30px; + color: #cc9a9a; + margin-bottom: 11px; + transition: color 0.2s ease-out; +} + +.todo-list li .destroy:hover { + color: #af5b5e; +} + +.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: 10px 15px; + height: 20px; + text-align: center; + border-top: 1px solid #e6e6e6; +} + +.footer:before { + content: ''; + position: absolute; + right: 0; + bottom: 0; + left: 0; + height: 50px; + overflow: hidden; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), + 0 8px 0 -3px #f6f6f6, + 0 9px 1px -3px rgba(0, 0, 0, 0.2), + 0 16px 0 -6px #f6f6f6, + 0 17px 2px -6px rgba(0, 0, 0, 0.2); +} + +.todo-count { + float: left; + text-align: left; +} + +.todo-count strong { + font-weight: 300; +} + +.filters { + margin: 0; + padding: 0; + list-style: none; + position: absolute; + right: 0; + left: 0; +} + +.filters li { + display: inline; +} + +.filters li a { + color: inherit; + margin: 3px; + padding: 3px 7px; + text-decoration: none; + border: 1px solid transparent; + border-radius: 3px; +} + +.filters li a.selected, +.filters li a:hover { + border-color: rgba(175, 47, 47, 0.1); +} + +.filters li a.selected { + border-color: rgba(175, 47, 47, 0.2); +} + +.clear-completed, +html .clear-completed:active { + float: right; + position: relative; + line-height: 20px; + text-decoration: none; + cursor: pointer; + position: relative; +} + +.clear-completed:hover { + text-decoration: underline; +} + +.info { + margin: 65px auto 0; + color: #bfbfbf; + font-size: 10px; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + text-align: center; +} + +.info p { + line-height: 1; +} + +.info a { + color: inherit; + text-decoration: none; + font-weight: 400; +} + +.info a:hover { + text-decoration: underline; +} + +/* + Hack to remove background from Mobile Safari. + Can't use it globally since it destroys checkboxes in Firefox +*/ +@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 { + -webkit-transform: rotate(90deg); + transform: rotate(90deg); + -webkit-appearance: none; + appearance: none; + } +} + +@media (max-width: 430px) { + .footer { + height: 50px; + } + + .filters { + bottom: 10px; + } +} \ No newline at end of file diff --git a/bench/implementations/elm-0.17-optimized/Todo.elm b/bench/implementations/elm-0.17-optimized/Todo.elm new file mode 100755 index 0000000..a3003d2 --- /dev/null +++ b/bench/implementations/elm-0.17-optimized/Todo.elm @@ -0,0 +1,381 @@ +port module Todo exposing (main) +{-| TodoMVC implemented in Elm, using plain HTML and CSS for rendering. + +This application is broken up into three key parts: + + 1. Model - a full definition of the application's state + 2. Update - a way to step the application state forward + 3. View - a way to visualize our application state with HTML + +This clean division of concerns is a core part of Elm. You can read more about +this in +-} + +import Html exposing (..) +import Html.App as App +import Html.Attributes exposing (..) +import Html.Events exposing (..) +import Html.Keyed as Keyed +import Html.Lazy exposing (lazy, lazy2) +import Json.Decode as Json +import String + + + +main : Program Never +main = + App.program + { init = init + , view = view + , update = update + , subscriptions = \_ -> Sub.none + } + + +port focus : String -> Cmd msg + + + +-- MODEL + + +-- The full application state of our todo app. +type alias Model = + { entries : List Entry + , field : String + , uid : Int + , visibility : String + } + + +type alias Entry = + { description : String + , completed : Bool + , editing : Bool + , id : Int + } + + +emptyModel : Model +emptyModel = + { entries = [] + , visibility = "All" + , field = "" + , uid = 0 + } + + +newEntry : String -> Int -> Entry +newEntry desc id = + { description = desc + , completed = False + , editing = False + , id = id + } + + +init : ( Model, Cmd Msg ) +init = + emptyModel ! [] + + + +-- UPDATE + + +{-| Users of our app can trigger messages by clicking and typing. These +messages are fed into the `update` function as they occur, letting us react +to them. +-} +type Msg + = NoOp + | UpdateField String + | EditingEntry Int Bool + | UpdateEntry Int String + | Add + | Delete Int + | DeleteComplete + | Check Int Bool + | CheckAll Bool + | ChangeVisibility String + + +-- How we update our Model on a given Msg? +update : Msg -> Model -> ( Model, Cmd Msg ) +update msg model = + case msg of + NoOp -> + model ! [] + + Add -> + { model + | uid = model.uid + 1 + , field = "" + , entries = + if String.isEmpty model.field then + model.entries + else + model.entries ++ [newEntry model.field model.uid] + } + ! [] + + UpdateField str -> + { model | field = str } + ! [] + + EditingEntry id isEditing -> + let + updateEntry t = + if t.id == id then { t | editing = isEditing } else t + in + { model | entries = List.map updateEntry model.entries } + ! [ focus ("#todo-" ++ toString id) ] + + UpdateEntry id task -> + let + updateEntry t = + if t.id == id then { t | description = task } else t + in + { model | entries = List.map updateEntry model.entries } + ! [] + + Delete id -> + { model | entries = List.filter (\t -> t.id /= id) model.entries } + ! [] + + DeleteComplete -> + { model | entries = List.filter (not << .completed) model.entries } + ! [] + + Check id isCompleted -> + let + updateEntry t = + if t.id == id then { t | completed = isCompleted } else t + in + { model | entries = List.map updateEntry model.entries } + ! [] + + CheckAll isCompleted -> + let + updateEntry t = + { t | completed = isCompleted } + in + { model | entries = List.map updateEntry model.entries } + ! [] + + ChangeVisibility visibility -> + { model | visibility = visibility } + ! [] + + + +-- VIEW + + +view : Model -> Html Msg +view model = + div + [ class "todomvc-wrapper" + , style [ ("visibility", "hidden") ] + ] + [ section + [ class "todoapp" ] + [ lazy viewInput model.field + , lazy2 viewEntries model.visibility model.entries + , lazy2 viewControls model.visibility model.entries + ] + , infoFooter + ] + + +viewInput : String -> Html Msg +viewInput task = + header + [ class "header" ] + [ h1 [] [ text "todos" ] + , input + [ class "new-todo" + , placeholder "What needs to be done?" + , autofocus True + , value task + , name "newTodo" + , onInput UpdateField + , onEnter Add + ] + [] + ] + + +onEnter : Msg -> Attribute Msg +onEnter msg = + let + tagger code = + if code == 13 then msg else NoOp + in + on "keydown" (Json.map tagger keyCode) + + + +-- VIEW ALL ENTRIES + + +viewEntries : String -> List Entry -> Html Msg +viewEntries visibility entries = + let + isVisible todo = + case visibility of + "Completed" -> todo.completed + "Active" -> not todo.completed + _ -> True + + allCompleted = + List.all .completed entries + + cssVisibility = + if List.isEmpty entries then "hidden" else "visible" + in + section + [ class "main" + , style [ ("visibility", cssVisibility) ] + ] + [ input + [ class "toggle-all" + , type' "checkbox" + , name "toggle" + , checked allCompleted + , onClick (CheckAll (not allCompleted)) + ] + [] + , label + [ for "toggle-all" ] + [ text "Mark all as complete" ] + , Keyed.ul [ class "todo-list" ] <| + List.map viewKeyedEntry (List.filter isVisible entries) + ] + + + +-- VIEW INDIVIDUAL ENTRIES + + +viewKeyedEntry : Entry -> (String, Html Msg) +viewKeyedEntry todo = + ( toString todo.id, lazy viewEntry todo ) + + +viewEntry : Entry -> Html Msg +viewEntry todo = + li + [ classList [ ("completed", todo.completed), ("editing", todo.editing) ] ] + [ div + [ class "view" ] + [ input + [ class "toggle" + , type' "checkbox" + , checked todo.completed + , onClick (Check todo.id (not todo.completed)) + ] + [] + , label + [ onDoubleClick (EditingEntry todo.id True) ] + [ text todo.description ] + , button + [ class "destroy" + , onClick (Delete todo.id) + ] + [] + ] + , input + [ class "edit" + , value todo.description + , name "title" + , id ("todo-" ++ toString todo.id) + , onInput (UpdateEntry todo.id) + , onBlur (EditingEntry todo.id False) + , onEnter (EditingEntry todo.id False) + ] + [] + ] + + + +-- VIEW CONTROLS AND FOOTER + + +viewControls : String -> List Entry -> Html Msg +viewControls visibility entries = + let + entriesCompleted = + List.length (List.filter .completed entries) + + entriesLeft = + List.length entries - entriesCompleted + in + footer + [ class "footer" + , hidden (List.isEmpty entries) + ] + [ lazy viewControlsCount entriesLeft + , lazy viewControlsFilters visibility + , lazy viewControlsClear entriesCompleted + ] + + +viewControlsCount : Int -> Html Msg +viewControlsCount entriesLeft = + let + item_ = + if entriesLeft == 1 then " item" else " items" + in + span + [ class "todo-count" ] + [ strong [] [ text (toString entriesLeft) ] + , text (item_ ++ " left") + ] + + +viewControlsFilters : String -> Html Msg +viewControlsFilters visibility = + ul + [ class "filters" ] + [ visibilitySwap "#/" "All" visibility + , text " " + , visibilitySwap "#/active" "Active" visibility + , text " " + , visibilitySwap "#/completed" "Completed" visibility + ] + + +visibilitySwap : String -> String -> String -> Html Msg +visibilitySwap uri visibility actualVisibility = + li + [ onClick (ChangeVisibility visibility) ] + [ a [ href uri, classList [("selected", visibility == actualVisibility)] ] + [ text visibility ] + ] + + +viewControlsClear : Int -> Html Msg +viewControlsClear entriesCompleted = + button + [ class "clear-completed" + , hidden (entriesCompleted == 0) + , onClick DeleteComplete + ] + [ text ("Clear completed (" ++ toString entriesCompleted ++ ")") + ] + + +infoFooter : Html msg +infoFooter = + footer [ class "info" ] + [ p [] [ text "Double-click to edit a todo" ] + , p [] + [ text "Written by " + , a [ href "https://github.com/evancz" ] [ text "Evan Czaplicki" ] + ] + , p [] + [ text "Part of " + , a [ href "http://todomvc.com" ] [ text "TodoMVC" ] + ] + ] diff --git a/bench/implementations/elm-0.17-optimized/elm-package.json b/bench/implementations/elm-0.17-optimized/elm-package.json new file mode 100644 index 0000000..ea3f7cd --- /dev/null +++ b/bench/implementations/elm-0.17-optimized/elm-package.json @@ -0,0 +1,15 @@ +{ + "version": "1.0.0", + "summary": "TodoMVC created with Elm and elm-html", + "repository": "https://github.com/evancz/elm-todomvc.git", + "license": "BSD3", + "source-directories": [ + "." + ], + "exposed-modules": [], + "dependencies": { + "elm-lang/core": "4.0.0 <= v < 5.0.0", + "elm-lang/html": "1.0.0 <= v < 2.0.0" + }, + "elm-version": "0.17.0 <= v < 0.18.0" +} diff --git a/bench/implementations/elm-0.17-optimized/elm.js b/bench/implementations/elm-0.17-optimized/elm.js new file mode 100755 index 0000000..4c59d9b --- /dev/null +++ b/bench/implementations/elm-0.17-optimized/elm.js @@ -0,0 +1,8282 @@ + +(function() { +'use strict'; + +function F2(fun) +{ + function wrapper(a) { return function(b) { return fun(a,b); }; } + wrapper.arity = 2; + wrapper.func = fun; + return wrapper; +} + +function F3(fun) +{ + function wrapper(a) { + return function(b) { return function(c) { return fun(a, b, c); }; }; + } + wrapper.arity = 3; + wrapper.func = fun; + return wrapper; +} + +function F4(fun) +{ + function wrapper(a) { return function(b) { return function(c) { + return function(d) { return fun(a, b, c, d); }; }; }; + } + wrapper.arity = 4; + wrapper.func = fun; + return wrapper; +} + +function F5(fun) +{ + function wrapper(a) { return function(b) { return function(c) { + return function(d) { return function(e) { return fun(a, b, c, d, e); }; }; }; }; + } + wrapper.arity = 5; + wrapper.func = fun; + return wrapper; +} + +function F6(fun) +{ + function wrapper(a) { return function(b) { return function(c) { + return function(d) { return function(e) { return function(f) { + return fun(a, b, c, d, e, f); }; }; }; }; }; + } + wrapper.arity = 6; + wrapper.func = fun; + return wrapper; +} + +function F7(fun) +{ + function wrapper(a) { return function(b) { return function(c) { + return function(d) { return function(e) { return function(f) { + return function(g) { return fun(a, b, c, d, e, f, g); }; }; }; }; }; }; + } + wrapper.arity = 7; + wrapper.func = fun; + return wrapper; +} + +function F8(fun) +{ + function wrapper(a) { return function(b) { return function(c) { + return function(d) { return function(e) { return function(f) { + return function(g) { return function(h) { + return fun(a, b, c, d, e, f, g, h); }; }; }; }; }; }; }; + } + wrapper.arity = 8; + wrapper.func = fun; + return wrapper; +} + +function F9(fun) +{ + function wrapper(a) { return function(b) { return function(c) { + return function(d) { return function(e) { return function(f) { + return function(g) { return function(h) { return function(i) { + return fun(a, b, c, d, e, f, g, h, i); }; }; }; }; }; }; }; }; + } + wrapper.arity = 9; + wrapper.func = fun; + return wrapper; +} + +function A2(fun, a, b) +{ + return fun.arity === 2 + ? fun.func(a, b) + : fun(a)(b); +} +function A3(fun, a, b, c) +{ + return fun.arity === 3 + ? fun.func(a, b, c) + : fun(a)(b)(c); +} +function A4(fun, a, b, c, d) +{ + return fun.arity === 4 + ? fun.func(a, b, c, d) + : fun(a)(b)(c)(d); +} +function A5(fun, a, b, c, d, e) +{ + return fun.arity === 5 + ? fun.func(a, b, c, d, e) + : fun(a)(b)(c)(d)(e); +} +function A6(fun, a, b, c, d, e, f) +{ + return fun.arity === 6 + ? fun.func(a, b, c, d, e, f) + : fun(a)(b)(c)(d)(e)(f); +} +function A7(fun, a, b, c, d, e, f, g) +{ + return fun.arity === 7 + ? fun.func(a, b, c, d, e, f, g) + : fun(a)(b)(c)(d)(e)(f)(g); +} +function A8(fun, a, b, c, d, e, f, g, h) +{ + return fun.arity === 8 + ? fun.func(a, b, c, d, e, f, g, h) + : fun(a)(b)(c)(d)(e)(f)(g)(h); +} +function A9(fun, a, b, c, d, e, f, g, h, i) +{ + return fun.arity === 9 + ? fun.func(a, b, c, d, e, f, g, h, i) + : fun(a)(b)(c)(d)(e)(f)(g)(h)(i); +} + +//import Native.List // + +var _elm_lang$core$Native_Array = function() { + +// A RRB-Tree has two distinct data types. +// Leaf -> "height" is always 0 +// "table" is an array of elements +// Node -> "height" is always greater than 0 +// "table" is an array of child nodes +// "lengths" is an array of accumulated lengths of the child nodes + +// M is the maximal table size. 32 seems fast. E is the allowed increase +// of search steps when concatting to find an index. Lower values will +// decrease balancing, but will increase search steps. +var M = 32; +var E = 2; + +// An empty array. +var empty = { + ctor: '_Array', + height: 0, + table: [] +}; + + +function get(i, array) +{ + if (i < 0 || i >= length(array)) + { + throw new Error( + 'Index ' + i + ' is out of range. Check the length of ' + + 'your array first or use getMaybe or getWithDefault.'); + } + return unsafeGet(i, array); +} + + +function unsafeGet(i, array) +{ + for (var x = array.height; x > 0; x--) + { + var slot = i >> (x * 5); + while (array.lengths[slot] <= i) + { + slot++; + } + if (slot > 0) + { + i -= array.lengths[slot - 1]; + } + array = array.table[slot]; + } + return array.table[i]; +} + + +// Sets the value at the index i. Only the nodes leading to i will get +// copied and updated. +function set(i, item, array) +{ + if (i < 0 || length(array) <= i) + { + return array; + } + return unsafeSet(i, item, array); +} + + +function unsafeSet(i, item, array) +{ + array = nodeCopy(array); + + if (array.height === 0) + { + array.table[i] = item; + } + else + { + var slot = getSlot(i, array); + if (slot > 0) + { + i -= array.lengths[slot - 1]; + } + array.table[slot] = unsafeSet(i, item, array.table[slot]); + } + return array; +} + + +function initialize(len, f) +{ + if (len <= 0) + { + return empty; + } + var h = Math.floor( Math.log(len) / Math.log(M) ); + return initialize_(f, h, 0, len); +} + +function initialize_(f, h, from, to) +{ + if (h === 0) + { + var table = new Array((to - from) % (M + 1)); + for (var i = 0; i < table.length; i++) + { + table[i] = f(from + i); + } + return { + ctor: '_Array', + height: 0, + table: table + }; + } + + var step = Math.pow(M, h); + var table = new Array(Math.ceil((to - from) / step)); + var lengths = new Array(table.length); + for (var i = 0; i < table.length; i++) + { + table[i] = initialize_(f, h - 1, from + (i * step), Math.min(from + ((i + 1) * step), to)); + lengths[i] = length(table[i]) + (i > 0 ? lengths[i-1] : 0); + } + return { + ctor: '_Array', + height: h, + table: table, + lengths: lengths + }; +} + +function fromList(list) +{ + if (list.ctor === '[]') + { + return empty; + } + + // Allocate M sized blocks (table) and write list elements to it. + var table = new Array(M); + var nodes = []; + var i = 0; + + while (list.ctor !== '[]') + { + table[i] = list._0; + list = list._1; + i++; + + // table is full, so we can push a leaf containing it into the + // next node. + if (i === M) + { + var leaf = { + ctor: '_Array', + height: 0, + table: table + }; + fromListPush(leaf, nodes); + table = new Array(M); + i = 0; + } + } + + // Maybe there is something left on the table. + if (i > 0) + { + var leaf = { + ctor: '_Array', + height: 0, + table: table.splice(0, i) + }; + fromListPush(leaf, nodes); + } + + // Go through all of the nodes and eventually push them into higher nodes. + for (var h = 0; h < nodes.length - 1; h++) + { + if (nodes[h].table.length > 0) + { + fromListPush(nodes[h], nodes); + } + } + + var head = nodes[nodes.length - 1]; + if (head.height > 0 && head.table.length === 1) + { + return head.table[0]; + } + else + { + return head; + } +} + +// Push a node into a higher node as a child. +function fromListPush(toPush, nodes) +{ + var h = toPush.height; + + // Maybe the node on this height does not exist. + if (nodes.length === h) + { + var node = { + ctor: '_Array', + height: h + 1, + table: [], + lengths: [] + }; + nodes.push(node); + } + + nodes[h].table.push(toPush); + var len = length(toPush); + if (nodes[h].lengths.length > 0) + { + len += nodes[h].lengths[nodes[h].lengths.length - 1]; + } + nodes[h].lengths.push(len); + + if (nodes[h].table.length === M) + { + fromListPush(nodes[h], nodes); + nodes[h] = { + ctor: '_Array', + height: h + 1, + table: [], + lengths: [] + }; + } +} + +// Pushes an item via push_ to the bottom right of a tree. +function push(item, a) +{ + var pushed = push_(item, a); + if (pushed !== null) + { + return pushed; + } + + var newTree = create(item, a.height); + return siblise(a, newTree); +} + +// Recursively tries to push an item to the bottom-right most +// tree possible. If there is no space left for the item, +// null will be returned. +function push_(item, a) +{ + // Handle resursion stop at leaf level. + if (a.height === 0) + { + if (a.table.length < M) + { + var newA = { + ctor: '_Array', + height: 0, + table: a.table.slice() + }; + newA.table.push(item); + return newA; + } + else + { + return null; + } + } + + // Recursively push + var pushed = push_(item, botRight(a)); + + // There was space in the bottom right tree, so the slot will + // be updated. + if (pushed !== null) + { + var newA = nodeCopy(a); + newA.table[newA.table.length - 1] = pushed; + newA.lengths[newA.lengths.length - 1]++; + return newA; + } + + // When there was no space left, check if there is space left + // for a new slot with a tree which contains only the item + // at the bottom. + if (a.table.length < M) + { + var newSlot = create(item, a.height - 1); + var newA = nodeCopy(a); + newA.table.push(newSlot); + newA.lengths.push(newA.lengths[newA.lengths.length - 1] + length(newSlot)); + return newA; + } + else + { + return null; + } +} + +// Converts an array into a list of elements. +function toList(a) +{ + return toList_(_elm_lang$core$Native_List.Nil, a); +} + +function toList_(list, a) +{ + for (var i = a.table.length - 1; i >= 0; i--) + { + list = + a.height === 0 + ? _elm_lang$core$Native_List.Cons(a.table[i], list) + : toList_(list, a.table[i]); + } + return list; +} + +// Maps a function over the elements of an array. +function map(f, a) +{ + var newA = { + ctor: '_Array', + height: a.height, + table: new Array(a.table.length) + }; + if (a.height > 0) + { + newA.lengths = a.lengths; + } + for (var i = 0; i < a.table.length; i++) + { + newA.table[i] = + a.height === 0 + ? f(a.table[i]) + : map(f, a.table[i]); + } + return newA; +} + +// Maps a function over the elements with their index as first argument. +function indexedMap(f, a) +{ + return indexedMap_(f, a, 0); +} + +function indexedMap_(f, a, from) +{ + var newA = { + ctor: '_Array', + height: a.height, + table: new Array(a.table.length) + }; + if (a.height > 0) + { + newA.lengths = a.lengths; + } + for (var i = 0; i < a.table.length; i++) + { + newA.table[i] = + a.height === 0 + ? A2(f, from + i, a.table[i]) + : indexedMap_(f, a.table[i], i == 0 ? from : from + a.lengths[i - 1]); + } + return newA; +} + +function foldl(f, b, a) +{ + if (a.height === 0) + { + for (var i = 0; i < a.table.length; i++) + { + b = A2(f, a.table[i], b); + } + } + else + { + for (var i = 0; i < a.table.length; i++) + { + b = foldl(f, b, a.table[i]); + } + } + return b; +} + +function foldr(f, b, a) +{ + if (a.height === 0) + { + for (var i = a.table.length; i--; ) + { + b = A2(f, a.table[i], b); + } + } + else + { + for (var i = a.table.length; i--; ) + { + b = foldr(f, b, a.table[i]); + } + } + return b; +} + +// TODO: currently, it slices the right, then the left. This can be +// optimized. +function slice(from, to, a) +{ + if (from < 0) + { + from += length(a); + } + if (to < 0) + { + to += length(a); + } + return sliceLeft(from, sliceRight(to, a)); +} + +function sliceRight(to, a) +{ + if (to === length(a)) + { + return a; + } + + // Handle leaf level. + if (a.height === 0) + { + var newA = { ctor:'_Array', height:0 }; + newA.table = a.table.slice(0, to); + return newA; + } + + // Slice the right recursively. + var right = getSlot(to, a); + var sliced = sliceRight(to - (right > 0 ? a.lengths[right - 1] : 0), a.table[right]); + + // Maybe the a node is not even needed, as sliced contains the whole slice. + if (right === 0) + { + return sliced; + } + + // Create new node. + var newA = { + ctor: '_Array', + height: a.height, + table: a.table.slice(0, right), + lengths: a.lengths.slice(0, right) + }; + if (sliced.table.length > 0) + { + newA.table[right] = sliced; + newA.lengths[right] = length(sliced) + (right > 0 ? newA.lengths[right - 1] : 0); + } + return newA; +} + +function sliceLeft(from, a) +{ + if (from === 0) + { + return a; + } + + // Handle leaf level. + if (a.height === 0) + { + var newA = { ctor:'_Array', height:0 }; + newA.table = a.table.slice(from, a.table.length + 1); + return newA; + } + + // Slice the left recursively. + var left = getSlot(from, a); + var sliced = sliceLeft(from - (left > 0 ? a.lengths[left - 1] : 0), a.table[left]); + + // Maybe the a node is not even needed, as sliced contains the whole slice. + if (left === a.table.length - 1) + { + return sliced; + } + + // Create new node. + var newA = { + ctor: '_Array', + height: a.height, + table: a.table.slice(left, a.table.length + 1), + lengths: new Array(a.table.length - left) + }; + newA.table[0] = sliced; + var len = 0; + for (var i = 0; i < newA.table.length; i++) + { + len += length(newA.table[i]); + newA.lengths[i] = len; + } + + return newA; +} + +// Appends two trees. +function append(a,b) +{ + if (a.table.length === 0) + { + return b; + } + if (b.table.length === 0) + { + return a; + } + + var c = append_(a, b); + + // Check if both nodes can be crunshed together. + if (c[0].table.length + c[1].table.length <= M) + { + if (c[0].table.length === 0) + { + return c[1]; + } + if (c[1].table.length === 0) + { + return c[0]; + } + + // Adjust .table and .lengths + c[0].table = c[0].table.concat(c[1].table); + if (c[0].height > 0) + { + var len = length(c[0]); + for (var i = 0; i < c[1].lengths.length; i++) + { + c[1].lengths[i] += len; + } + c[0].lengths = c[0].lengths.concat(c[1].lengths); + } + + return c[0]; + } + + if (c[0].height > 0) + { + var toRemove = calcToRemove(a, b); + if (toRemove > E) + { + c = shuffle(c[0], c[1], toRemove); + } + } + + return siblise(c[0], c[1]); +} + +// Returns an array of two nodes; right and left. One node _may_ be empty. +function append_(a, b) +{ + if (a.height === 0 && b.height === 0) + { + return [a, b]; + } + + if (a.height !== 1 || b.height !== 1) + { + if (a.height === b.height) + { + a = nodeCopy(a); + b = nodeCopy(b); + var appended = append_(botRight(a), botLeft(b)); + + insertRight(a, appended[1]); + insertLeft(b, appended[0]); + } + else if (a.height > b.height) + { + a = nodeCopy(a); + var appended = append_(botRight(a), b); + + insertRight(a, appended[0]); + b = parentise(appended[1], appended[1].height + 1); + } + else + { + b = nodeCopy(b); + var appended = append_(a, botLeft(b)); + + var left = appended[0].table.length === 0 ? 0 : 1; + var right = left === 0 ? 1 : 0; + insertLeft(b, appended[left]); + a = parentise(appended[right], appended[right].height + 1); + } + } + + // Check if balancing is needed and return based on that. + if (a.table.length === 0 || b.table.length === 0) + { + return [a, b]; + } + + var toRemove = calcToRemove(a, b); + if (toRemove <= E) + { + return [a, b]; + } + return shuffle(a, b, toRemove); +} + +// Helperfunctions for append_. Replaces a child node at the side of the parent. +function insertRight(parent, node) +{ + var index = parent.table.length - 1; + parent.table[index] = node; + parent.lengths[index] = length(node); + parent.lengths[index] += index > 0 ? parent.lengths[index - 1] : 0; +} + +function insertLeft(parent, node) +{ + if (node.table.length > 0) + { + parent.table[0] = node; + parent.lengths[0] = length(node); + + var len = length(parent.table[0]); + for (var i = 1; i < parent.lengths.length; i++) + { + len += length(parent.table[i]); + parent.lengths[i] = len; + } + } + else + { + parent.table.shift(); + for (var i = 1; i < parent.lengths.length; i++) + { + parent.lengths[i] = parent.lengths[i] - parent.lengths[0]; + } + parent.lengths.shift(); + } +} + +// Returns the extra search steps for E. Refer to the paper. +function calcToRemove(a, b) +{ + var subLengths = 0; + for (var i = 0; i < a.table.length; i++) + { + subLengths += a.table[i].table.length; + } + for (var i = 0; i < b.table.length; i++) + { + subLengths += b.table[i].table.length; + } + + var toRemove = a.table.length + b.table.length; + return toRemove - (Math.floor((subLengths - 1) / M) + 1); +} + +// get2, set2 and saveSlot are helpers for accessing elements over two arrays. +function get2(a, b, index) +{ + return index < a.length + ? a[index] + : b[index - a.length]; +} + +function set2(a, b, index, value) +{ + if (index < a.length) + { + a[index] = value; + } + else + { + b[index - a.length] = value; + } +} + +function saveSlot(a, b, index, slot) +{ + set2(a.table, b.table, index, slot); + + var l = (index === 0 || index === a.lengths.length) + ? 0 + : get2(a.lengths, a.lengths, index - 1); + + set2(a.lengths, b.lengths, index, l + length(slot)); +} + +// Creates a node or leaf with a given length at their arrays for perfomance. +// Is only used by shuffle. +function createNode(h, length) +{ + if (length < 0) + { + length = 0; + } + var a = { + ctor: '_Array', + height: h, + table: new Array(length) + }; + if (h > 0) + { + a.lengths = new Array(length); + } + return a; +} + +// Returns an array of two balanced nodes. +function shuffle(a, b, toRemove) +{ + var newA = createNode(a.height, Math.min(M, a.table.length + b.table.length - toRemove)); + var newB = createNode(a.height, newA.table.length - (a.table.length + b.table.length - toRemove)); + + // Skip the slots with size M. More precise: copy the slot references + // to the new node + var read = 0; + while (get2(a.table, b.table, read).table.length % M === 0) + { + set2(newA.table, newB.table, read, get2(a.table, b.table, read)); + set2(newA.lengths, newB.lengths, read, get2(a.lengths, b.lengths, read)); + read++; + } + + // Pulling items from left to right, caching in a slot before writing + // it into the new nodes. + var write = read; + var slot = new createNode(a.height - 1, 0); + var from = 0; + + // If the current slot is still containing data, then there will be at + // least one more write, so we do not break this loop yet. + while (read - write - (slot.table.length > 0 ? 1 : 0) < toRemove) + { + // Find out the max possible items for copying. + var source = get2(a.table, b.table, read); + var to = Math.min(M - slot.table.length, source.table.length); + + // Copy and adjust size table. + slot.table = slot.table.concat(source.table.slice(from, to)); + if (slot.height > 0) + { + var len = slot.lengths.length; + for (var i = len; i < len + to - from; i++) + { + slot.lengths[i] = length(slot.table[i]); + slot.lengths[i] += (i > 0 ? slot.lengths[i - 1] : 0); + } + } + + from += to; + + // Only proceed to next slots[i] if the current one was + // fully copied. + if (source.table.length <= to) + { + read++; from = 0; + } + + // Only create a new slot if the current one is filled up. + if (slot.table.length === M) + { + saveSlot(newA, newB, write, slot); + slot = createNode(a.height - 1, 0); + write++; + } + } + + // Cleanup after the loop. Copy the last slot into the new nodes. + if (slot.table.length > 0) + { + saveSlot(newA, newB, write, slot); + write++; + } + + // Shift the untouched slots to the left + while (read < a.table.length + b.table.length ) + { + saveSlot(newA, newB, write, get2(a.table, b.table, read)); + read++; + write++; + } + + return [newA, newB]; +} + +// Navigation functions +function botRight(a) +{ + return a.table[a.table.length - 1]; +} +function botLeft(a) +{ + return a.table[0]; +} + +// Copies a node for updating. Note that you should not use this if +// only updating only one of "table" or "lengths" for performance reasons. +function nodeCopy(a) +{ + var newA = { + ctor: '_Array', + height: a.height, + table: a.table.slice() + }; + if (a.height > 0) + { + newA.lengths = a.lengths.slice(); + } + return newA; +} + +// Returns how many items are in the tree. +function length(array) +{ + if (array.height === 0) + { + return array.table.length; + } + else + { + return array.lengths[array.lengths.length - 1]; + } +} + +// Calculates in which slot of "table" the item probably is, then +// find the exact slot via forward searching in "lengths". Returns the index. +function getSlot(i, a) +{ + var slot = i >> (5 * a.height); + while (a.lengths[slot] <= i) + { + slot++; + } + return slot; +} + +// Recursively creates a tree with a given height containing +// only the given item. +function create(item, h) +{ + if (h === 0) + { + return { + ctor: '_Array', + height: 0, + table: [item] + }; + } + return { + ctor: '_Array', + height: h, + table: [create(item, h - 1)], + lengths: [1] + }; +} + +// Recursively creates a tree that contains the given tree. +function parentise(tree, h) +{ + if (h === tree.height) + { + return tree; + } + + return { + ctor: '_Array', + height: h, + table: [parentise(tree, h - 1)], + lengths: [length(tree)] + }; +} + +// Emphasizes blood brotherhood beneath two trees. +function siblise(a, b) +{ + return { + ctor: '_Array', + height: a.height + 1, + table: [a, b], + lengths: [length(a), length(a) + length(b)] + }; +} + +function toJSArray(a) +{ + var jsArray = new Array(length(a)); + toJSArray_(jsArray, 0, a); + return jsArray; +} + +function toJSArray_(jsArray, i, a) +{ + for (var t = 0; t < a.table.length; t++) + { + if (a.height === 0) + { + jsArray[i + t] = a.table[t]; + } + else + { + var inc = t === 0 ? 0 : a.lengths[t - 1]; + toJSArray_(jsArray, i + inc, a.table[t]); + } + } +} + +function fromJSArray(jsArray) +{ + if (jsArray.length === 0) + { + return empty; + } + var h = Math.floor(Math.log(jsArray.length) / Math.log(M)); + return fromJSArray_(jsArray, h, 0, jsArray.length); +} + +function fromJSArray_(jsArray, h, from, to) +{ + if (h === 0) + { + return { + ctor: '_Array', + height: 0, + table: jsArray.slice(from, to) + }; + } + + var step = Math.pow(M, h); + var table = new Array(Math.ceil((to - from) / step)); + var lengths = new Array(table.length); + for (var i = 0; i < table.length; i++) + { + table[i] = fromJSArray_(jsArray, h - 1, from + (i * step), Math.min(from + ((i + 1) * step), to)); + lengths[i] = length(table[i]) + (i > 0 ? lengths[i - 1] : 0); + } + return { + ctor: '_Array', + height: h, + table: table, + lengths: lengths + }; +} + +return { + empty: empty, + fromList: fromList, + toList: toList, + initialize: F2(initialize), + append: F2(append), + push: F2(push), + slice: F3(slice), + get: F2(get), + set: F3(set), + map: F2(map), + indexedMap: F2(indexedMap), + foldl: F3(foldl), + foldr: F3(foldr), + length: length, + + toJSArray: toJSArray, + fromJSArray: fromJSArray +}; + +}(); +//import Native.Utils // + +var _elm_lang$core$Native_Basics = function() { + +function div(a, b) +{ + return (a / b) | 0; +} +function rem(a, b) +{ + return a % b; +} +function mod(a, b) +{ + if (b === 0) + { + throw new Error('Cannot perform mod 0. Division by zero error.'); + } + var r = a % b; + var m = a === 0 ? 0 : (b > 0 ? (a >= 0 ? r : r + b) : -mod(-a, -b)); + + return m === b ? 0 : m; +} +function logBase(base, n) +{ + return Math.log(n) / Math.log(base); +} +function negate(n) +{ + return -n; +} +function abs(n) +{ + return n < 0 ? -n : n; +} + +function min(a, b) +{ + return _elm_lang$core$Native_Utils.cmp(a, b) < 0 ? a : b; +} +function max(a, b) +{ + return _elm_lang$core$Native_Utils.cmp(a, b) > 0 ? a : b; +} +function clamp(lo, hi, n) +{ + return _elm_lang$core$Native_Utils.cmp(n, lo) < 0 + ? lo + : _elm_lang$core$Native_Utils.cmp(n, hi) > 0 + ? hi + : n; +} + +var ord = ['LT', 'EQ', 'GT']; + +function compare(x, y) +{ + return { ctor: ord[_elm_lang$core$Native_Utils.cmp(x, y) + 1] }; +} + +function xor(a, b) +{ + return a !== b; +} +function not(b) +{ + return !b; +} +function isInfinite(n) +{ + return n === Infinity || n === -Infinity; +} + +function truncate(n) +{ + return n | 0; +} + +function degrees(d) +{ + return d * Math.PI / 180; +} +function turns(t) +{ + return 2 * Math.PI * t; +} +function fromPolar(point) +{ + var r = point._0; + var t = point._1; + return _elm_lang$core$Native_Utils.Tuple2(r * Math.cos(t), r * Math.sin(t)); +} +function toPolar(point) +{ + var x = point._0; + var y = point._1; + return _elm_lang$core$Native_Utils.Tuple2(Math.sqrt(x * x + y * y), Math.atan2(y, x)); +} + +return { + div: F2(div), + rem: F2(rem), + mod: F2(mod), + + pi: Math.PI, + e: Math.E, + cos: Math.cos, + sin: Math.sin, + tan: Math.tan, + acos: Math.acos, + asin: Math.asin, + atan: Math.atan, + atan2: F2(Math.atan2), + + degrees: degrees, + turns: turns, + fromPolar: fromPolar, + toPolar: toPolar, + + sqrt: Math.sqrt, + logBase: F2(logBase), + negate: negate, + abs: abs, + min: F2(min), + max: F2(max), + clamp: F3(clamp), + compare: F2(compare), + + xor: F2(xor), + not: not, + + truncate: truncate, + ceiling: Math.ceil, + floor: Math.floor, + round: Math.round, + toFloat: function(x) { return x; }, + isNaN: isNaN, + isInfinite: isInfinite +}; + +}(); +//import // + +var _elm_lang$core$Native_Utils = function() { + +// COMPARISONS + +function eq(rootX, rootY) +{ + var stack = [{ x: rootX, y: rootY }]; + while (stack.length > 0) + { + var front = stack.pop(); + var x = front.x; + var y = front.y; + if (x === y) + { + continue; + } + if (typeof x === 'object') + { + var c = 0; + for (var key in x) + { + ++c; + if (!(key in y)) + { + return false; + } + if (key === 'ctor') + { + continue; + } + stack.push({ x: x[key], y: y[key] }); + } + if ('ctor' in x) + { + stack.push({ x: x.ctor, y: y.ctor}); + } + if (c !== Object.keys(y).length) + { + return false; + } + } + else if (typeof x === 'function') + { + throw new Error('Equality error: general function equality is ' + + 'undecidable, and therefore, unsupported'); + } + else + { + return false; + } + } + return true; +} + +// Code in Generate/JavaScript.hs, Basics.js, and List.js depends on +// the particular integer values assigned to LT, EQ, and GT. + +var LT = -1, EQ = 0, GT = 1; + +function cmp(x, y) +{ + var ord; + if (typeof x !== 'object') + { + return x === y ? EQ : x < y ? LT : GT; + } + else if (x instanceof String) + { + var a = x.valueOf(); + var b = y.valueOf(); + return a === b + ? EQ + : a < b + ? LT + : GT; + } + else if (x.ctor === '::' || x.ctor === '[]') + { + while (true) + { + if (x.ctor === '[]' && y.ctor === '[]') + { + return EQ; + } + if (x.ctor !== y.ctor) + { + return x.ctor === '[]' ? LT : GT; + } + ord = cmp(x._0, y._0); + if (ord !== EQ) + { + return ord; + } + x = x._1; + y = y._1; + } + } + else if (x.ctor.slice(0, 6) === '_Tuple') + { + var n = x.ctor.slice(6) - 0; + var err = 'cannot compare tuples with more than 6 elements.'; + if (n === 0) return EQ; + if (n >= 1) { ord = cmp(x._0, y._0); if (ord !== EQ) return ord; + if (n >= 2) { ord = cmp(x._1, y._1); if (ord !== EQ) return ord; + if (n >= 3) { ord = cmp(x._2, y._2); if (ord !== EQ) return ord; + if (n >= 4) { ord = cmp(x._3, y._3); if (ord !== EQ) return ord; + if (n >= 5) { ord = cmp(x._4, y._4); if (ord !== EQ) return ord; + if (n >= 6) { ord = cmp(x._5, y._5); if (ord !== EQ) return ord; + if (n >= 7) throw new Error('Comparison error: ' + err); } } } } } } + return EQ; + } + else + { + throw new Error('Comparison error: comparison is only defined on ints, ' + + 'floats, times, chars, strings, lists of comparable values, ' + + 'and tuples of comparable values.'); + } +} + + +// COMMON VALUES + +var Tuple0 = { + ctor: '_Tuple0' +}; + +function Tuple2(x, y) +{ + return { + ctor: '_Tuple2', + _0: x, + _1: y + }; +} + +function chr(c) +{ + return new String(c); +} + + +// GUID + +var count = 0; +function guid(_) +{ + return count++; +} + + +// RECORDS + +function update(oldRecord, updatedFields) +{ + var newRecord = {}; + for (var key in oldRecord) + { + var value = (key in updatedFields) ? updatedFields[key] : oldRecord[key]; + newRecord[key] = value; + } + return newRecord; +} + + +//// LIST STUFF //// + +var Nil = { ctor: '[]' }; + +function Cons(hd, tl) +{ + return { + ctor: '::', + _0: hd, + _1: tl + }; +} + +function append(xs, ys) +{ + // append Strings + if (typeof xs === 'string') + { + return xs + ys; + } + + // append Lists + if (xs.ctor === '[]') + { + return ys; + } + var root = Cons(xs._0, Nil); + var curr = root; + xs = xs._1; + while (xs.ctor !== '[]') + { + curr._1 = Cons(xs._0, Nil); + xs = xs._1; + curr = curr._1; + } + curr._1 = ys; + return root; +} + + +// CRASHES + +function crash(moduleName, region) +{ + return function(message) { + throw new Error( + 'Ran into a `Debug.crash` in module `' + moduleName + '` ' + regionToString(region) + '\n' + + 'The message provided by the code author is:\n\n ' + + message + ); + }; +} + +function crashCase(moduleName, region, value) +{ + return function(message) { + throw new Error( + 'Ran into a `Debug.crash` in module `' + moduleName + '`\n\n' + + 'This was caused by the `case` expression ' + regionToString(region) + '.\n' + + 'One of the branches ended with a crash and the following value got through:\n\n ' + toString(value) + '\n\n' + + 'The message provided by the code author is:\n\n ' + + message + ); + }; +} + +function regionToString(region) +{ + if (region.start.line == region.end.line) + { + return 'on line ' + region.start.line; + } + return 'between lines ' + region.start.line + ' and ' + region.end.line; +} + + +// TO STRING + +function toString(v) +{ + var type = typeof v; + if (type === 'function') + { + var name = v.func ? v.func.name : v.name; + return ''; + } + + if (type === 'boolean') + { + return v ? 'True' : 'False'; + } + + if (type === 'number') + { + return v + ''; + } + + if (v instanceof String) + { + return '\'' + addSlashes(v, true) + '\''; + } + + if (type === 'string') + { + return '"' + addSlashes(v, false) + '"'; + } + + if (v === null) + { + return 'null'; + } + + if (type === 'object' && 'ctor' in v) + { + var ctorStarter = v.ctor.substring(0, 5); + + if (ctorStarter === '_Tupl') + { + var output = []; + for (var k in v) + { + if (k === 'ctor') continue; + output.push(toString(v[k])); + } + return '(' + output.join(',') + ')'; + } + + if (ctorStarter === '_Task') + { + return '' + } + + if (v.ctor === '_Array') + { + var list = _elm_lang$core$Array$toList(v); + return 'Array.fromList ' + toString(list); + } + + if (v.ctor === '') + { + return ''; + } + + if (v.ctor === '_Process') + { + return ''; + } + + if (v.ctor === '::') + { + var output = '[' + toString(v._0); + v = v._1; + while (v.ctor === '::') + { + output += ',' + toString(v._0); + v = v._1; + } + return output + ']'; + } + + if (v.ctor === '[]') + { + return '[]'; + } + + if (v.ctor === 'RBNode_elm_builtin' || v.ctor === 'RBEmpty_elm_builtin' || v.ctor === 'Set_elm_builtin') + { + var name, list; + if (v.ctor === 'Set_elm_builtin') + { + name = 'Set'; + list = A2( + _elm_lang$core$List$map, + function(x) {return x._0; }, + _elm_lang$core$Dict$toList(v._0) + ); + } + else + { + name = 'Dict'; + list = _elm_lang$core$Dict$toList(v); + } + return name + '.fromList ' + toString(list); + } + + var output = ''; + for (var i in v) + { + if (i === 'ctor') continue; + var str = toString(v[i]); + var c0 = str[0]; + var parenless = c0 === '{' || c0 === '(' || c0 === '<' || c0 === '"' || str.indexOf(' ') < 0; + output += ' ' + (parenless ? str : '(' + str + ')'); + } + return v.ctor + output; + } + + if (type === 'object') + { + var output = []; + for (var k in v) + { + output.push(k + ' = ' + toString(v[k])); + } + if (output.length === 0) + { + return '{}'; + } + return '{ ' + output.join(', ') + ' }'; + } + + return ''; +} + +function addSlashes(str, isChar) +{ + var s = str.replace(/\\/g, '\\\\') + .replace(/\n/g, '\\n') + .replace(/\t/g, '\\t') + .replace(/\r/g, '\\r') + .replace(/\v/g, '\\v') + .replace(/\0/g, '\\0'); + if (isChar) + { + return s.replace(/\'/g, '\\\''); + } + else + { + return s.replace(/\"/g, '\\"'); + } +} + + +return { + eq: eq, + cmp: cmp, + Tuple0: Tuple0, + Tuple2: Tuple2, + chr: chr, + update: update, + guid: guid, + + append: F2(append), + + crash: crash, + crashCase: crashCase, + + toString: toString +}; + +}(); +var _elm_lang$core$Basics$uncurry = F2( + function (f, _p0) { + var _p1 = _p0; + return A2(f, _p1._0, _p1._1); + }); +var _elm_lang$core$Basics$curry = F3( + function (f, a, b) { + return f( + {ctor: '_Tuple2', _0: a, _1: b}); + }); +var _elm_lang$core$Basics$flip = F3( + function (f, b, a) { + return A2(f, a, b); + }); +var _elm_lang$core$Basics$snd = function (_p2) { + var _p3 = _p2; + return _p3._1; +}; +var _elm_lang$core$Basics$fst = function (_p4) { + var _p5 = _p4; + return _p5._0; +}; +var _elm_lang$core$Basics$always = F2( + function (a, _p6) { + return a; + }); +var _elm_lang$core$Basics$identity = function (x) { + return x; +}; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['<|'] = F2( + function (f, x) { + return f(x); + }); +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['|>'] = F2( + function (x, f) { + return f(x); + }); +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['>>'] = F3( + function (f, g, x) { + return g( + f(x)); + }); +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['<<'] = F3( + function (g, f, x) { + return g( + f(x)); + }); +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['++'] = _elm_lang$core$Native_Utils.append; +var _elm_lang$core$Basics$toString = _elm_lang$core$Native_Utils.toString; +var _elm_lang$core$Basics$isInfinite = _elm_lang$core$Native_Basics.isInfinite; +var _elm_lang$core$Basics$isNaN = _elm_lang$core$Native_Basics.isNaN; +var _elm_lang$core$Basics$toFloat = _elm_lang$core$Native_Basics.toFloat; +var _elm_lang$core$Basics$ceiling = _elm_lang$core$Native_Basics.ceiling; +var _elm_lang$core$Basics$floor = _elm_lang$core$Native_Basics.floor; +var _elm_lang$core$Basics$truncate = _elm_lang$core$Native_Basics.truncate; +var _elm_lang$core$Basics$round = _elm_lang$core$Native_Basics.round; +var _elm_lang$core$Basics$not = _elm_lang$core$Native_Basics.not; +var _elm_lang$core$Basics$xor = _elm_lang$core$Native_Basics.xor; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['||'] = _elm_lang$core$Native_Basics.or; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['&&'] = _elm_lang$core$Native_Basics.and; +var _elm_lang$core$Basics$max = _elm_lang$core$Native_Basics.max; +var _elm_lang$core$Basics$min = _elm_lang$core$Native_Basics.min; +var _elm_lang$core$Basics$compare = _elm_lang$core$Native_Basics.compare; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['>='] = _elm_lang$core$Native_Basics.ge; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['<='] = _elm_lang$core$Native_Basics.le; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['>'] = _elm_lang$core$Native_Basics.gt; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['<'] = _elm_lang$core$Native_Basics.lt; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['/='] = _elm_lang$core$Native_Basics.neq; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['=='] = _elm_lang$core$Native_Basics.eq; +var _elm_lang$core$Basics$e = _elm_lang$core$Native_Basics.e; +var _elm_lang$core$Basics$pi = _elm_lang$core$Native_Basics.pi; +var _elm_lang$core$Basics$clamp = _elm_lang$core$Native_Basics.clamp; +var _elm_lang$core$Basics$logBase = _elm_lang$core$Native_Basics.logBase; +var _elm_lang$core$Basics$abs = _elm_lang$core$Native_Basics.abs; +var _elm_lang$core$Basics$negate = _elm_lang$core$Native_Basics.negate; +var _elm_lang$core$Basics$sqrt = _elm_lang$core$Native_Basics.sqrt; +var _elm_lang$core$Basics$atan2 = _elm_lang$core$Native_Basics.atan2; +var _elm_lang$core$Basics$atan = _elm_lang$core$Native_Basics.atan; +var _elm_lang$core$Basics$asin = _elm_lang$core$Native_Basics.asin; +var _elm_lang$core$Basics$acos = _elm_lang$core$Native_Basics.acos; +var _elm_lang$core$Basics$tan = _elm_lang$core$Native_Basics.tan; +var _elm_lang$core$Basics$sin = _elm_lang$core$Native_Basics.sin; +var _elm_lang$core$Basics$cos = _elm_lang$core$Native_Basics.cos; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['^'] = _elm_lang$core$Native_Basics.exp; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['%'] = _elm_lang$core$Native_Basics.mod; +var _elm_lang$core$Basics$rem = _elm_lang$core$Native_Basics.rem; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['//'] = _elm_lang$core$Native_Basics.div; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['/'] = _elm_lang$core$Native_Basics.floatDiv; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['*'] = _elm_lang$core$Native_Basics.mul; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['-'] = _elm_lang$core$Native_Basics.sub; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['+'] = _elm_lang$core$Native_Basics.add; +var _elm_lang$core$Basics$toPolar = _elm_lang$core$Native_Basics.toPolar; +var _elm_lang$core$Basics$fromPolar = _elm_lang$core$Native_Basics.fromPolar; +var _elm_lang$core$Basics$turns = _elm_lang$core$Native_Basics.turns; +var _elm_lang$core$Basics$degrees = _elm_lang$core$Native_Basics.degrees; +var _elm_lang$core$Basics$radians = function (t) { + return t; +}; +var _elm_lang$core$Basics$GT = {ctor: 'GT'}; +var _elm_lang$core$Basics$EQ = {ctor: 'EQ'}; +var _elm_lang$core$Basics$LT = {ctor: 'LT'}; +var _elm_lang$core$Basics$Never = function (a) { + return {ctor: 'Never', _0: a}; +}; + +var _elm_lang$core$Maybe$withDefault = F2( + function ($default, maybe) { + var _p0 = maybe; + if (_p0.ctor === 'Just') { + return _p0._0; + } else { + return $default; + } + }); +var _elm_lang$core$Maybe$Nothing = {ctor: 'Nothing'}; +var _elm_lang$core$Maybe$oneOf = function (maybes) { + oneOf: + while (true) { + var _p1 = maybes; + if (_p1.ctor === '[]') { + return _elm_lang$core$Maybe$Nothing; + } else { + var _p3 = _p1._0; + var _p2 = _p3; + if (_p2.ctor === 'Nothing') { + var _v3 = _p1._1; + maybes = _v3; + continue oneOf; + } else { + return _p3; + } + } + } +}; +var _elm_lang$core$Maybe$andThen = F2( + function (maybeValue, callback) { + var _p4 = maybeValue; + if (_p4.ctor === 'Just') { + return callback(_p4._0); + } else { + return _elm_lang$core$Maybe$Nothing; + } + }); +var _elm_lang$core$Maybe$Just = function (a) { + return {ctor: 'Just', _0: a}; +}; +var _elm_lang$core$Maybe$map = F2( + function (f, maybe) { + var _p5 = maybe; + if (_p5.ctor === 'Just') { + return _elm_lang$core$Maybe$Just( + f(_p5._0)); + } else { + return _elm_lang$core$Maybe$Nothing; + } + }); +var _elm_lang$core$Maybe$map2 = F3( + function (func, ma, mb) { + var _p6 = {ctor: '_Tuple2', _0: ma, _1: mb}; + if (((_p6.ctor === '_Tuple2') && (_p6._0.ctor === 'Just')) && (_p6._1.ctor === 'Just')) { + return _elm_lang$core$Maybe$Just( + A2(func, _p6._0._0, _p6._1._0)); + } else { + return _elm_lang$core$Maybe$Nothing; + } + }); +var _elm_lang$core$Maybe$map3 = F4( + function (func, ma, mb, mc) { + var _p7 = {ctor: '_Tuple3', _0: ma, _1: mb, _2: mc}; + if ((((_p7.ctor === '_Tuple3') && (_p7._0.ctor === 'Just')) && (_p7._1.ctor === 'Just')) && (_p7._2.ctor === 'Just')) { + return _elm_lang$core$Maybe$Just( + A3(func, _p7._0._0, _p7._1._0, _p7._2._0)); + } else { + return _elm_lang$core$Maybe$Nothing; + } + }); +var _elm_lang$core$Maybe$map4 = F5( + function (func, ma, mb, mc, md) { + var _p8 = {ctor: '_Tuple4', _0: ma, _1: mb, _2: mc, _3: md}; + if (((((_p8.ctor === '_Tuple4') && (_p8._0.ctor === 'Just')) && (_p8._1.ctor === 'Just')) && (_p8._2.ctor === 'Just')) && (_p8._3.ctor === 'Just')) { + return _elm_lang$core$Maybe$Just( + A4(func, _p8._0._0, _p8._1._0, _p8._2._0, _p8._3._0)); + } else { + return _elm_lang$core$Maybe$Nothing; + } + }); +var _elm_lang$core$Maybe$map5 = F6( + function (func, ma, mb, mc, md, me) { + var _p9 = {ctor: '_Tuple5', _0: ma, _1: mb, _2: mc, _3: md, _4: me}; + if ((((((_p9.ctor === '_Tuple5') && (_p9._0.ctor === 'Just')) && (_p9._1.ctor === 'Just')) && (_p9._2.ctor === 'Just')) && (_p9._3.ctor === 'Just')) && (_p9._4.ctor === 'Just')) { + return _elm_lang$core$Maybe$Just( + A5(func, _p9._0._0, _p9._1._0, _p9._2._0, _p9._3._0, _p9._4._0)); + } else { + return _elm_lang$core$Maybe$Nothing; + } + }); + +//import Native.Utils // + +var _elm_lang$core$Native_List = function() { + +var Nil = { ctor: '[]' }; + +function Cons(hd, tl) +{ + return { ctor: '::', _0: hd, _1: tl }; +} + +function fromArray(arr) +{ + var out = Nil; + for (var i = arr.length; i--; ) + { + out = Cons(arr[i], out); + } + return out; +} + +function toArray(xs) +{ + var out = []; + while (xs.ctor !== '[]') + { + out.push(xs._0); + xs = xs._1; + } + return out; +} + + +function range(lo, hi) +{ + var list = Nil; + if (lo <= hi) + { + do + { + list = Cons(hi, list); + } + while (hi-- > lo); + } + return list; +} + +function foldr(f, b, xs) +{ + var arr = toArray(xs); + var acc = b; + for (var i = arr.length; i--; ) + { + acc = A2(f, arr[i], acc); + } + return acc; +} + +function map2(f, xs, ys) +{ + var arr = []; + while (xs.ctor !== '[]' && ys.ctor !== '[]') + { + arr.push(A2(f, xs._0, ys._0)); + xs = xs._1; + ys = ys._1; + } + return fromArray(arr); +} + +function map3(f, xs, ys, zs) +{ + var arr = []; + while (xs.ctor !== '[]' && ys.ctor !== '[]' && zs.ctor !== '[]') + { + arr.push(A3(f, xs._0, ys._0, zs._0)); + xs = xs._1; + ys = ys._1; + zs = zs._1; + } + return fromArray(arr); +} + +function map4(f, ws, xs, ys, zs) +{ + var arr = []; + while ( ws.ctor !== '[]' + && xs.ctor !== '[]' + && ys.ctor !== '[]' + && zs.ctor !== '[]') + { + arr.push(A4(f, ws._0, xs._0, ys._0, zs._0)); + ws = ws._1; + xs = xs._1; + ys = ys._1; + zs = zs._1; + } + return fromArray(arr); +} + +function map5(f, vs, ws, xs, ys, zs) +{ + var arr = []; + while ( vs.ctor !== '[]' + && ws.ctor !== '[]' + && xs.ctor !== '[]' + && ys.ctor !== '[]' + && zs.ctor !== '[]') + { + arr.push(A5(f, vs._0, ws._0, xs._0, ys._0, zs._0)); + vs = vs._1; + ws = ws._1; + xs = xs._1; + ys = ys._1; + zs = zs._1; + } + return fromArray(arr); +} + +function sortBy(f, xs) +{ + return fromArray(toArray(xs).sort(function(a, b) { + return _elm_lang$core$Native_Utils.cmp(f(a), f(b)); + })); +} + +function sortWith(f, xs) +{ + return fromArray(toArray(xs).sort(function(a, b) { + var ord = f(a)(b).ctor; + return ord === 'EQ' ? 0 : ord === 'LT' ? -1 : 1; + })); +} + +return { + Nil: Nil, + Cons: Cons, + cons: F2(Cons), + toArray: toArray, + fromArray: fromArray, + range: range, + + foldr: F3(foldr), + + map2: F3(map2), + map3: F4(map3), + map4: F5(map4), + map5: F6(map5), + sortBy: F2(sortBy), + sortWith: F2(sortWith) +}; + +}(); +var _elm_lang$core$List$sortWith = _elm_lang$core$Native_List.sortWith; +var _elm_lang$core$List$sortBy = _elm_lang$core$Native_List.sortBy; +var _elm_lang$core$List$sort = function (xs) { + return A2(_elm_lang$core$List$sortBy, _elm_lang$core$Basics$identity, xs); +}; +var _elm_lang$core$List$drop = F2( + function (n, list) { + drop: + while (true) { + if (_elm_lang$core$Native_Utils.cmp(n, 0) < 1) { + return list; + } else { + var _p0 = list; + if (_p0.ctor === '[]') { + return list; + } else { + var _v1 = n - 1, + _v2 = _p0._1; + n = _v1; + list = _v2; + continue drop; + } + } + } + }); +var _elm_lang$core$List$map5 = _elm_lang$core$Native_List.map5; +var _elm_lang$core$List$map4 = _elm_lang$core$Native_List.map4; +var _elm_lang$core$List$map3 = _elm_lang$core$Native_List.map3; +var _elm_lang$core$List$map2 = _elm_lang$core$Native_List.map2; +var _elm_lang$core$List$any = F2( + function (isOkay, list) { + any: + while (true) { + var _p1 = list; + if (_p1.ctor === '[]') { + return false; + } else { + if (isOkay(_p1._0)) { + return true; + } else { + var _v4 = isOkay, + _v5 = _p1._1; + isOkay = _v4; + list = _v5; + continue any; + } + } + } + }); +var _elm_lang$core$List$all = F2( + function (isOkay, list) { + return _elm_lang$core$Basics$not( + A2( + _elm_lang$core$List$any, + function (_p2) { + return _elm_lang$core$Basics$not( + isOkay(_p2)); + }, + list)); + }); +var _elm_lang$core$List$foldr = _elm_lang$core$Native_List.foldr; +var _elm_lang$core$List$foldl = F3( + function (func, acc, list) { + foldl: + while (true) { + var _p3 = list; + if (_p3.ctor === '[]') { + return acc; + } else { + var _v7 = func, + _v8 = A2(func, _p3._0, acc), + _v9 = _p3._1; + func = _v7; + acc = _v8; + list = _v9; + continue foldl; + } + } + }); +var _elm_lang$core$List$length = function (xs) { + return A3( + _elm_lang$core$List$foldl, + F2( + function (_p4, i) { + return i + 1; + }), + 0, + xs); +}; +var _elm_lang$core$List$sum = function (numbers) { + return A3( + _elm_lang$core$List$foldl, + F2( + function (x, y) { + return x + y; + }), + 0, + numbers); +}; +var _elm_lang$core$List$product = function (numbers) { + return A3( + _elm_lang$core$List$foldl, + F2( + function (x, y) { + return x * y; + }), + 1, + numbers); +}; +var _elm_lang$core$List$maximum = function (list) { + var _p5 = list; + if (_p5.ctor === '::') { + return _elm_lang$core$Maybe$Just( + A3(_elm_lang$core$List$foldl, _elm_lang$core$Basics$max, _p5._0, _p5._1)); + } else { + return _elm_lang$core$Maybe$Nothing; + } +}; +var _elm_lang$core$List$minimum = function (list) { + var _p6 = list; + if (_p6.ctor === '::') { + return _elm_lang$core$Maybe$Just( + A3(_elm_lang$core$List$foldl, _elm_lang$core$Basics$min, _p6._0, _p6._1)); + } else { + return _elm_lang$core$Maybe$Nothing; + } +}; +var _elm_lang$core$List$indexedMap = F2( + function (f, xs) { + return A3( + _elm_lang$core$List$map2, + f, + _elm_lang$core$Native_List.range( + 0, + _elm_lang$core$List$length(xs) - 1), + xs); + }); +var _elm_lang$core$List$member = F2( + function (x, xs) { + return A2( + _elm_lang$core$List$any, + function (a) { + return _elm_lang$core$Native_Utils.eq(a, x); + }, + xs); + }); +var _elm_lang$core$List$isEmpty = function (xs) { + var _p7 = xs; + if (_p7.ctor === '[]') { + return true; + } else { + return false; + } +}; +var _elm_lang$core$List$tail = function (list) { + var _p8 = list; + if (_p8.ctor === '::') { + return _elm_lang$core$Maybe$Just(_p8._1); + } else { + return _elm_lang$core$Maybe$Nothing; + } +}; +var _elm_lang$core$List$head = function (list) { + var _p9 = list; + if (_p9.ctor === '::') { + return _elm_lang$core$Maybe$Just(_p9._0); + } else { + return _elm_lang$core$Maybe$Nothing; + } +}; +var _elm_lang$core$List_ops = _elm_lang$core$List_ops || {}; +_elm_lang$core$List_ops['::'] = _elm_lang$core$Native_List.cons; +var _elm_lang$core$List$map = F2( + function (f, xs) { + return A3( + _elm_lang$core$List$foldr, + F2( + function (x, acc) { + return A2( + _elm_lang$core$List_ops['::'], + f(x), + acc); + }), + _elm_lang$core$Native_List.fromArray( + []), + xs); + }); +var _elm_lang$core$List$filter = F2( + function (pred, xs) { + var conditionalCons = F2( + function (x, xs$) { + return pred(x) ? A2(_elm_lang$core$List_ops['::'], x, xs$) : xs$; + }); + return A3( + _elm_lang$core$List$foldr, + conditionalCons, + _elm_lang$core$Native_List.fromArray( + []), + xs); + }); +var _elm_lang$core$List$maybeCons = F3( + function (f, mx, xs) { + var _p10 = f(mx); + if (_p10.ctor === 'Just') { + return A2(_elm_lang$core$List_ops['::'], _p10._0, xs); + } else { + return xs; + } + }); +var _elm_lang$core$List$filterMap = F2( + function (f, xs) { + return A3( + _elm_lang$core$List$foldr, + _elm_lang$core$List$maybeCons(f), + _elm_lang$core$Native_List.fromArray( + []), + xs); + }); +var _elm_lang$core$List$reverse = function (list) { + return A3( + _elm_lang$core$List$foldl, + F2( + function (x, y) { + return A2(_elm_lang$core$List_ops['::'], x, y); + }), + _elm_lang$core$Native_List.fromArray( + []), + list); +}; +var _elm_lang$core$List$scanl = F3( + function (f, b, xs) { + var scan1 = F2( + function (x, accAcc) { + var _p11 = accAcc; + if (_p11.ctor === '::') { + return A2( + _elm_lang$core$List_ops['::'], + A2(f, x, _p11._0), + accAcc); + } else { + return _elm_lang$core$Native_List.fromArray( + []); + } + }); + return _elm_lang$core$List$reverse( + A3( + _elm_lang$core$List$foldl, + scan1, + _elm_lang$core$Native_List.fromArray( + [b]), + xs)); + }); +var _elm_lang$core$List$append = F2( + function (xs, ys) { + var _p12 = ys; + if (_p12.ctor === '[]') { + return xs; + } else { + return A3( + _elm_lang$core$List$foldr, + F2( + function (x, y) { + return A2(_elm_lang$core$List_ops['::'], x, y); + }), + ys, + xs); + } + }); +var _elm_lang$core$List$concat = function (lists) { + return A3( + _elm_lang$core$List$foldr, + _elm_lang$core$List$append, + _elm_lang$core$Native_List.fromArray( + []), + lists); +}; +var _elm_lang$core$List$concatMap = F2( + function (f, list) { + return _elm_lang$core$List$concat( + A2(_elm_lang$core$List$map, f, list)); + }); +var _elm_lang$core$List$partition = F2( + function (pred, list) { + var step = F2( + function (x, _p13) { + var _p14 = _p13; + var _p16 = _p14._0; + var _p15 = _p14._1; + return pred(x) ? { + ctor: '_Tuple2', + _0: A2(_elm_lang$core$List_ops['::'], x, _p16), + _1: _p15 + } : { + ctor: '_Tuple2', + _0: _p16, + _1: A2(_elm_lang$core$List_ops['::'], x, _p15) + }; + }); + return A3( + _elm_lang$core$List$foldr, + step, + { + ctor: '_Tuple2', + _0: _elm_lang$core$Native_List.fromArray( + []), + _1: _elm_lang$core$Native_List.fromArray( + []) + }, + list); + }); +var _elm_lang$core$List$unzip = function (pairs) { + var step = F2( + function (_p18, _p17) { + var _p19 = _p18; + var _p20 = _p17; + return { + ctor: '_Tuple2', + _0: A2(_elm_lang$core$List_ops['::'], _p19._0, _p20._0), + _1: A2(_elm_lang$core$List_ops['::'], _p19._1, _p20._1) + }; + }); + return A3( + _elm_lang$core$List$foldr, + step, + { + ctor: '_Tuple2', + _0: _elm_lang$core$Native_List.fromArray( + []), + _1: _elm_lang$core$Native_List.fromArray( + []) + }, + pairs); +}; +var _elm_lang$core$List$intersperse = F2( + function (sep, xs) { + var _p21 = xs; + if (_p21.ctor === '[]') { + return _elm_lang$core$Native_List.fromArray( + []); + } else { + var step = F2( + function (x, rest) { + return A2( + _elm_lang$core$List_ops['::'], + sep, + A2(_elm_lang$core$List_ops['::'], x, rest)); + }); + var spersed = A3( + _elm_lang$core$List$foldr, + step, + _elm_lang$core$Native_List.fromArray( + []), + _p21._1); + return A2(_elm_lang$core$List_ops['::'], _p21._0, spersed); + } + }); +var _elm_lang$core$List$take = F2( + function (n, list) { + if (_elm_lang$core$Native_Utils.cmp(n, 0) < 1) { + return _elm_lang$core$Native_List.fromArray( + []); + } else { + var _p22 = list; + if (_p22.ctor === '[]') { + return list; + } else { + return A2( + _elm_lang$core$List_ops['::'], + _p22._0, + A2(_elm_lang$core$List$take, n - 1, _p22._1)); + } + } + }); +var _elm_lang$core$List$repeatHelp = F3( + function (result, n, value) { + repeatHelp: + while (true) { + if (_elm_lang$core$Native_Utils.cmp(n, 0) < 1) { + return result; + } else { + var _v23 = A2(_elm_lang$core$List_ops['::'], value, result), + _v24 = n - 1, + _v25 = value; + result = _v23; + n = _v24; + value = _v25; + continue repeatHelp; + } + } + }); +var _elm_lang$core$List$repeat = F2( + function (n, value) { + return A3( + _elm_lang$core$List$repeatHelp, + _elm_lang$core$Native_List.fromArray( + []), + n, + value); + }); + +var _elm_lang$core$Array$append = _elm_lang$core$Native_Array.append; +var _elm_lang$core$Array$length = _elm_lang$core$Native_Array.length; +var _elm_lang$core$Array$isEmpty = function (array) { + return _elm_lang$core$Native_Utils.eq( + _elm_lang$core$Array$length(array), + 0); +}; +var _elm_lang$core$Array$slice = _elm_lang$core$Native_Array.slice; +var _elm_lang$core$Array$set = _elm_lang$core$Native_Array.set; +var _elm_lang$core$Array$get = F2( + function (i, array) { + return ((_elm_lang$core$Native_Utils.cmp(0, i) < 1) && (_elm_lang$core$Native_Utils.cmp( + i, + _elm_lang$core$Native_Array.length(array)) < 0)) ? _elm_lang$core$Maybe$Just( + A2(_elm_lang$core$Native_Array.get, i, array)) : _elm_lang$core$Maybe$Nothing; + }); +var _elm_lang$core$Array$push = _elm_lang$core$Native_Array.push; +var _elm_lang$core$Array$empty = _elm_lang$core$Native_Array.empty; +var _elm_lang$core$Array$filter = F2( + function (isOkay, arr) { + var update = F2( + function (x, xs) { + return isOkay(x) ? A2(_elm_lang$core$Native_Array.push, x, xs) : xs; + }); + return A3(_elm_lang$core$Native_Array.foldl, update, _elm_lang$core$Native_Array.empty, arr); + }); +var _elm_lang$core$Array$foldr = _elm_lang$core$Native_Array.foldr; +var _elm_lang$core$Array$foldl = _elm_lang$core$Native_Array.foldl; +var _elm_lang$core$Array$indexedMap = _elm_lang$core$Native_Array.indexedMap; +var _elm_lang$core$Array$map = _elm_lang$core$Native_Array.map; +var _elm_lang$core$Array$toIndexedList = function (array) { + return A3( + _elm_lang$core$List$map2, + F2( + function (v0, v1) { + return {ctor: '_Tuple2', _0: v0, _1: v1}; + }), + _elm_lang$core$Native_List.range( + 0, + _elm_lang$core$Native_Array.length(array) - 1), + _elm_lang$core$Native_Array.toList(array)); +}; +var _elm_lang$core$Array$toList = _elm_lang$core$Native_Array.toList; +var _elm_lang$core$Array$fromList = _elm_lang$core$Native_Array.fromList; +var _elm_lang$core$Array$initialize = _elm_lang$core$Native_Array.initialize; +var _elm_lang$core$Array$repeat = F2( + function (n, e) { + return A2( + _elm_lang$core$Array$initialize, + n, + _elm_lang$core$Basics$always(e)); + }); +var _elm_lang$core$Array$Array = {ctor: 'Array'}; + +//import Native.Utils // + +var _elm_lang$core$Native_Char = function() { + +return { + fromCode: function(c) { return _elm_lang$core$Native_Utils.chr(String.fromCharCode(c)); }, + toCode: function(c) { return c.charCodeAt(0); }, + toUpper: function(c) { return _elm_lang$core$Native_Utils.chr(c.toUpperCase()); }, + toLower: function(c) { return _elm_lang$core$Native_Utils.chr(c.toLowerCase()); }, + toLocaleUpper: function(c) { return _elm_lang$core$Native_Utils.chr(c.toLocaleUpperCase()); }, + toLocaleLower: function(c) { return _elm_lang$core$Native_Utils.chr(c.toLocaleLowerCase()); } +}; + +}(); +var _elm_lang$core$Char$fromCode = _elm_lang$core$Native_Char.fromCode; +var _elm_lang$core$Char$toCode = _elm_lang$core$Native_Char.toCode; +var _elm_lang$core$Char$toLocaleLower = _elm_lang$core$Native_Char.toLocaleLower; +var _elm_lang$core$Char$toLocaleUpper = _elm_lang$core$Native_Char.toLocaleUpper; +var _elm_lang$core$Char$toLower = _elm_lang$core$Native_Char.toLower; +var _elm_lang$core$Char$toUpper = _elm_lang$core$Native_Char.toUpper; +var _elm_lang$core$Char$isBetween = F3( + function (low, high, $char) { + var code = _elm_lang$core$Char$toCode($char); + return (_elm_lang$core$Native_Utils.cmp( + code, + _elm_lang$core$Char$toCode(low)) > -1) && (_elm_lang$core$Native_Utils.cmp( + code, + _elm_lang$core$Char$toCode(high)) < 1); + }); +var _elm_lang$core$Char$isUpper = A2( + _elm_lang$core$Char$isBetween, + _elm_lang$core$Native_Utils.chr('A'), + _elm_lang$core$Native_Utils.chr('Z')); +var _elm_lang$core$Char$isLower = A2( + _elm_lang$core$Char$isBetween, + _elm_lang$core$Native_Utils.chr('a'), + _elm_lang$core$Native_Utils.chr('z')); +var _elm_lang$core$Char$isDigit = A2( + _elm_lang$core$Char$isBetween, + _elm_lang$core$Native_Utils.chr('0'), + _elm_lang$core$Native_Utils.chr('9')); +var _elm_lang$core$Char$isOctDigit = A2( + _elm_lang$core$Char$isBetween, + _elm_lang$core$Native_Utils.chr('0'), + _elm_lang$core$Native_Utils.chr('7')); +var _elm_lang$core$Char$isHexDigit = function ($char) { + return _elm_lang$core$Char$isDigit($char) || (A3( + _elm_lang$core$Char$isBetween, + _elm_lang$core$Native_Utils.chr('a'), + _elm_lang$core$Native_Utils.chr('f'), + $char) || A3( + _elm_lang$core$Char$isBetween, + _elm_lang$core$Native_Utils.chr('A'), + _elm_lang$core$Native_Utils.chr('F'), + $char)); +}; + +//import Native.Utils // + +var _elm_lang$core$Native_Scheduler = function() { + +var MAX_STEPS = 10000; + + +// TASKS + +function succeed(value) +{ + return { + ctor: '_Task_succeed', + value: value + }; +} + +function fail(error) +{ + return { + ctor: '_Task_fail', + value: error + }; +} + +function nativeBinding(callback) +{ + return { + ctor: '_Task_nativeBinding', + callback: callback, + cancel: null + }; +} + +function andThen(task, callback) +{ + return { + ctor: '_Task_andThen', + task: task, + callback: callback + }; +} + +function onError(task, callback) +{ + return { + ctor: '_Task_onError', + task: task, + callback: callback + }; +} + +function receive(callback) +{ + return { + ctor: '_Task_receive', + callback: callback + }; +} + + +// PROCESSES + +function rawSpawn(task) +{ + var process = { + ctor: '_Process', + id: _elm_lang$core$Native_Utils.guid(), + root: task, + stack: null, + mailbox: [] + }; + + enqueue(process); + + return process; +} + +function spawn(task) +{ + return nativeBinding(function(callback) { + var process = rawSpawn(task); + callback(succeed(process)); + }); +} + +function rawSend(process, msg) +{ + process.mailbox.push(msg); + enqueue(process); +} + +function send(process, msg) +{ + return nativeBinding(function(callback) { + rawSend(process, msg); + callback(succeed(_elm_lang$core$Native_Utils.Tuple0)); + }); +} + +function kill(process) +{ + return nativeBinding(function(callback) { + var root = process.root; + if (root.ctor === '_Task_nativeBinding' && root.cancel) + { + root.cancel(); + } + + process.root = null; + + callback(succeed(_elm_lang$core$Native_Utils.Tuple0)); + }); +} + +function sleep(time) +{ + return nativeBinding(function(callback) { + var id = setTimeout(function() { + callback(succeed(_elm_lang$core$Native_Utils.Tuple0)); + }, time); + + return function() { clearTimeout(id); }; + }); +} + + +// STEP PROCESSES + +function step(numSteps, process) +{ + while (numSteps < MAX_STEPS) + { + var ctor = process.root.ctor; + + if (ctor === '_Task_succeed') + { + while (process.stack && process.stack.ctor === '_Task_onError') + { + process.stack = process.stack.rest; + } + if (process.stack === null) + { + break; + } + process.root = process.stack.callback(process.root.value); + process.stack = process.stack.rest; + ++numSteps; + continue; + } + + if (ctor === '_Task_fail') + { + while (process.stack && process.stack.ctor === '_Task_andThen') + { + process.stack = process.stack.rest; + } + if (process.stack === null) + { + break; + } + process.root = process.stack.callback(process.root.value); + process.stack = process.stack.rest; + ++numSteps; + continue; + } + + if (ctor === '_Task_andThen') + { + process.stack = { + ctor: '_Task_andThen', + callback: process.root.callback, + rest: process.stack + }; + process.root = process.root.task; + ++numSteps; + continue; + } + + if (ctor === '_Task_onError') + { + process.stack = { + ctor: '_Task_onError', + callback: process.root.callback, + rest: process.stack + }; + process.root = process.root.task; + ++numSteps; + continue; + } + + if (ctor === '_Task_nativeBinding') + { + process.root.cancel = process.root.callback(function(newRoot) { + process.root = newRoot; + enqueue(process); + }); + + break; + } + + if (ctor === '_Task_receive') + { + var mailbox = process.mailbox; + if (mailbox.length === 0) + { + break; + } + + process.root = process.root.callback(mailbox.shift()); + ++numSteps; + continue; + } + + throw new Error(ctor); + } + + if (numSteps < MAX_STEPS) + { + return numSteps + 1; + } + enqueue(process); + + return numSteps; +} + + +// WORK QUEUE + +var working = false; +var workQueue = []; + +function enqueue(process) +{ + workQueue.push(process); + + if (!working) + { + setTimeout(work, 0); + working = true; + } +} + +function work() +{ + var numSteps = 0; + var process; + while (numSteps < MAX_STEPS && (process = workQueue.shift())) + { + numSteps = step(numSteps, process); + } + if (!process) + { + working = false; + return; + } + setTimeout(work, 0); +} + + +return { + succeed: succeed, + fail: fail, + nativeBinding: nativeBinding, + andThen: F2(andThen), + onError: F2(onError), + receive: receive, + + spawn: spawn, + kill: kill, + sleep: sleep, + send: F2(send), + + rawSpawn: rawSpawn, + rawSend: rawSend +}; + +}(); +//import // + +var _elm_lang$core$Native_Platform = function() { + + +// PROGRAMS + +function addPublicModule(object, name, main) +{ + var init = main ? makeEmbed(name, main) : mainIsUndefined(name); + + object['worker'] = function worker(flags) + { + return init(undefined, flags, false); + } + + object['embed'] = function embed(domNode, flags) + { + return init(domNode, flags, true); + } + + object['fullscreen'] = function fullscreen(flags) + { + return init(document.body, flags, true); + }; +} + + +// PROGRAM FAIL + +function mainIsUndefined(name) +{ + return function(domNode) + { + var message = 'Cannot initialize module `' + name + + '` because it has no `main` value!\nWhat should I show on screen?'; + domNode.innerHTML = errorHtml(message); + throw new Error(message); + }; +} + +function errorHtml(message) +{ + return '
' + + '

Oops! Something went wrong when starting your Elm program.

' + + '
' + message + '
' + + '
'; +} + + +// PROGRAM SUCCESS + +function makeEmbed(moduleName, main) +{ + return function embed(rootDomNode, flags, withRenderer) + { + try + { + var program = mainToProgram(moduleName, main); + if (!withRenderer) + { + program.renderer = dummyRenderer; + } + return makeEmbedHelp(moduleName, program, rootDomNode, flags); + } + catch (e) + { + rootDomNode.innerHTML = errorHtml(e.message); + throw e; + } + }; +} + +function dummyRenderer() +{ + return { update: function() {} }; +} + + +// MAIN TO PROGRAM + +function mainToProgram(moduleName, wrappedMain) +{ + var main = wrappedMain.main; + + if (typeof main.init === 'undefined') + { + var emptyBag = batch(_elm_lang$core$Native_List.Nil); + var noChange = _elm_lang$core$Native_Utils.Tuple2( + _elm_lang$core$Native_Utils.Tuple0, + emptyBag + ); + + return _elm_lang$virtual_dom$VirtualDom$programWithFlags({ + init: function() { return noChange; }, + view: function() { return main; }, + update: F2(function() { return noChange; }), + subscriptions: function () { return emptyBag; } + }); + } + + var flags = wrappedMain.flags; + var init = flags + ? initWithFlags(moduleName, main.init, flags) + : initWithoutFlags(moduleName, main.init); + + return _elm_lang$virtual_dom$VirtualDom$programWithFlags({ + init: init, + view: main.view, + update: main.update, + subscriptions: main.subscriptions, + }); +} + +function initWithoutFlags(moduleName, realInit) +{ + return function init(flags) + { + if (typeof flags !== 'undefined') + { + throw new Error( + 'You are giving module `' + moduleName + '` an argument in JavaScript.\n' + + 'This module does not take arguments though! You probably need to change the\n' + + 'initialization code to something like `Elm.' + moduleName + '.fullscreen()`' + ); + } + return realInit(); + }; +} + +function initWithFlags(moduleName, realInit, flagDecoder) +{ + return function init(flags) + { + var result = A2(_elm_lang$core$Native_Json.run, flagDecoder, flags); + if (result.ctor === 'Err') + { + throw new Error( + 'You are trying to initialize module `' + moduleName + '` with an unexpected argument.\n' + + 'When trying to convert it to a usable Elm value, I run into this problem:\n\n' + + result._0 + ); + } + return realInit(result._0); + }; +} + + +// SETUP RUNTIME SYSTEM + +function makeEmbedHelp(moduleName, program, rootDomNode, flags) +{ + var init = program.init; + var update = program.update; + var subscriptions = program.subscriptions; + var view = program.view; + var makeRenderer = program.renderer; + + // ambient state + var managers = {}; + var renderer; + + // init and update state in main process + var initApp = _elm_lang$core$Native_Scheduler.nativeBinding(function(callback) { + var results = init(flags); + var model = results._0; + renderer = makeRenderer(rootDomNode, enqueue, view(model)); + var cmds = results._1; + var subs = subscriptions(model); + dispatchEffects(managers, cmds, subs); + callback(_elm_lang$core$Native_Scheduler.succeed(model)); + }); + + function onMessage(msg, model) + { + return _elm_lang$core$Native_Scheduler.nativeBinding(function(callback) { + var results = A2(update, msg, model); + model = results._0; + renderer.update(view(model)); + var cmds = results._1; + var subs = subscriptions(model); + dispatchEffects(managers, cmds, subs); + callback(_elm_lang$core$Native_Scheduler.succeed(model)); + }); + } + + var mainProcess = spawnLoop(initApp, onMessage); + + function enqueue(msg) + { + _elm_lang$core$Native_Scheduler.rawSend(mainProcess, msg); + } + + var ports = setupEffects(managers, enqueue); + + return ports ? { ports: ports } : {}; +} + + +// EFFECT MANAGERS + +var effectManagers = {}; + +function setupEffects(managers, callback) +{ + var ports; + + // setup all necessary effect managers + for (var key in effectManagers) + { + var manager = effectManagers[key]; + + if (manager.isForeign) + { + ports = ports || {}; + ports[key] = manager.tag === 'cmd' + ? setupOutgoingPort(key) + : setupIncomingPort(key, callback); + } + + managers[key] = makeManager(manager, callback); + } + + return ports; +} + +function makeManager(info, callback) +{ + var router = { + main: callback, + self: undefined + }; + + var tag = info.tag; + var onEffects = info.onEffects; + var onSelfMsg = info.onSelfMsg; + + function onMessage(msg, state) + { + if (msg.ctor === 'self') + { + return A3(onSelfMsg, router, msg._0, state); + } + + var fx = msg._0; + switch (tag) + { + case 'cmd': + return A3(onEffects, router, fx.cmds, state); + + case 'sub': + return A3(onEffects, router, fx.subs, state); + + case 'fx': + return A4(onEffects, router, fx.cmds, fx.subs, state); + } + } + + var process = spawnLoop(info.init, onMessage); + router.self = process; + return process; +} + +function sendToApp(router, msg) +{ + return _elm_lang$core$Native_Scheduler.nativeBinding(function(callback) + { + router.main(msg); + callback(_elm_lang$core$Native_Scheduler.succeed(_elm_lang$core$Native_Utils.Tuple0)); + }); +} + +function sendToSelf(router, msg) +{ + return A2(_elm_lang$core$Native_Scheduler.send, router.self, { + ctor: 'self', + _0: msg + }); +} + + +// HELPER for STATEFUL LOOPS + +function spawnLoop(init, onMessage) +{ + var andThen = _elm_lang$core$Native_Scheduler.andThen; + + function loop(state) + { + var handleMsg = _elm_lang$core$Native_Scheduler.receive(function(msg) { + return onMessage(msg, state); + }); + return A2(andThen, handleMsg, loop); + } + + var task = A2(andThen, init, loop); + + return _elm_lang$core$Native_Scheduler.rawSpawn(task); +} + + +// BAGS + +function leaf(home) +{ + return function(value) + { + return { + type: 'leaf', + home: home, + value: value + }; + }; +} + +function batch(list) +{ + return { + type: 'node', + branches: list + }; +} + +function map(tagger, bag) +{ + return { + type: 'map', + tagger: tagger, + tree: bag + } +} + + +// PIPE BAGS INTO EFFECT MANAGERS + +function dispatchEffects(managers, cmdBag, subBag) +{ + var effectsDict = {}; + gatherEffects(true, cmdBag, effectsDict, null); + gatherEffects(false, subBag, effectsDict, null); + + for (var home in managers) + { + var fx = home in effectsDict + ? effectsDict[home] + : { + cmds: _elm_lang$core$Native_List.Nil, + subs: _elm_lang$core$Native_List.Nil + }; + + _elm_lang$core$Native_Scheduler.rawSend(managers[home], { ctor: 'fx', _0: fx }); + } +} + +function gatherEffects(isCmd, bag, effectsDict, taggers) +{ + switch (bag.type) + { + case 'leaf': + var home = bag.home; + var effect = toEffect(isCmd, home, taggers, bag.value); + effectsDict[home] = insert(isCmd, effect, effectsDict[home]); + return; + + case 'node': + var list = bag.branches; + while (list.ctor !== '[]') + { + gatherEffects(isCmd, list._0, effectsDict, taggers); + list = list._1; + } + return; + + case 'map': + gatherEffects(isCmd, bag.tree, effectsDict, { + tagger: bag.tagger, + rest: taggers + }); + return; + } +} + +function toEffect(isCmd, home, taggers, value) +{ + function applyTaggers(x) + { + var temp = taggers; + while (temp) + { + x = temp.tagger(x); + temp = temp.rest; + } + return x; + } + + var map = isCmd + ? effectManagers[home].cmdMap + : effectManagers[home].subMap; + + return A2(map, applyTaggers, value) +} + +function insert(isCmd, newEffect, effects) +{ + effects = effects || { + cmds: _elm_lang$core$Native_List.Nil, + subs: _elm_lang$core$Native_List.Nil + }; + if (isCmd) + { + effects.cmds = _elm_lang$core$Native_List.Cons(newEffect, effects.cmds); + return effects; + } + effects.subs = _elm_lang$core$Native_List.Cons(newEffect, effects.subs); + return effects; +} + + +// PORTS + +function checkPortName(name) +{ + if (name in effectManagers) + { + throw new Error('There can only be one port named `' + name + '`, but your program has multiple.'); + } +} + + +// OUTGOING PORTS + +function outgoingPort(name, converter) +{ + checkPortName(name); + effectManagers[name] = { + tag: 'cmd', + cmdMap: outgoingPortMap, + converter: converter, + isForeign: true + }; + return leaf(name); +} + +var outgoingPortMap = F2(function cmdMap(tagger, value) { + return value; +}); + +function setupOutgoingPort(name) +{ + var subs = []; + var converter = effectManagers[name].converter; + + // CREATE MANAGER + + var init = _elm_lang$core$Native_Scheduler.succeed(null); + + function onEffects(router, cmdList, state) + { + while (cmdList.ctor !== '[]') + { + var value = converter(cmdList._0); + for (var i = 0; i < subs.length; i++) + { + subs[i](value); + } + cmdList = cmdList._1; + } + return init; + } + + effectManagers[name].init = init; + effectManagers[name].onEffects = F3(onEffects); + + // PUBLIC API + + function subscribe(callback) + { + subs.push(callback); + } + + function unsubscribe(callback) + { + var index = subs.indexOf(callback); + if (index >= 0) + { + subs.splice(index, 1); + } + } + + return { + subscribe: subscribe, + unsubscribe: unsubscribe + }; +} + + +// INCOMING PORTS + +function incomingPort(name, converter) +{ + checkPortName(name); + effectManagers[name] = { + tag: 'sub', + subMap: incomingPortMap, + converter: converter, + isForeign: true + }; + return leaf(name); +} + +var incomingPortMap = F2(function subMap(tagger, finalTagger) +{ + return function(value) + { + return tagger(finalTagger(value)); + }; +}); + +function setupIncomingPort(name, callback) +{ + var subs = _elm_lang$core$Native_List.Nil; + var converter = effectManagers[name].converter; + + // CREATE MANAGER + + var init = _elm_lang$core$Native_Scheduler.succeed(null); + + function onEffects(router, subList, state) + { + subs = subList; + return init; + } + + effectManagers[name].init = init; + effectManagers[name].onEffects = F3(onEffects); + + // PUBLIC API + + function send(value) + { + var result = A2(_elm_lang$core$Json_Decode$decodeValue, converter, value); + if (result.ctor === 'Err') + { + throw new Error('Trying to send an unexpected type of value through port `' + name + '`:\n' + result._0); + } + + var value = result._0; + var temp = subs; + while (temp.ctor !== '[]') + { + callback(temp._0(value)); + temp = temp._1; + } + } + + return { send: send }; +} + +return { + // routers + sendToApp: F2(sendToApp), + sendToSelf: F2(sendToSelf), + + // global setup + mainToProgram: mainToProgram, + effectManagers: effectManagers, + outgoingPort: outgoingPort, + incomingPort: incomingPort, + addPublicModule: addPublicModule, + + // effect bags + leaf: leaf, + batch: batch, + map: F2(map) +}; + +}(); +var _elm_lang$core$Platform$hack = _elm_lang$core$Native_Scheduler.succeed; +var _elm_lang$core$Platform$sendToSelf = _elm_lang$core$Native_Platform.sendToSelf; +var _elm_lang$core$Platform$sendToApp = _elm_lang$core$Native_Platform.sendToApp; +var _elm_lang$core$Platform$Program = {ctor: 'Program'}; +var _elm_lang$core$Platform$Task = {ctor: 'Task'}; +var _elm_lang$core$Platform$ProcessId = {ctor: 'ProcessId'}; +var _elm_lang$core$Platform$Router = {ctor: 'Router'}; + +var _elm_lang$core$Platform_Cmd$batch = _elm_lang$core$Native_Platform.batch; +var _elm_lang$core$Platform_Cmd$none = _elm_lang$core$Platform_Cmd$batch( + _elm_lang$core$Native_List.fromArray( + [])); +var _elm_lang$core$Platform_Cmd_ops = _elm_lang$core$Platform_Cmd_ops || {}; +_elm_lang$core$Platform_Cmd_ops['!'] = F2( + function (model, commands) { + return { + ctor: '_Tuple2', + _0: model, + _1: _elm_lang$core$Platform_Cmd$batch(commands) + }; + }); +var _elm_lang$core$Platform_Cmd$map = _elm_lang$core$Native_Platform.map; +var _elm_lang$core$Platform_Cmd$Cmd = {ctor: 'Cmd'}; + +var _elm_lang$core$Result$toMaybe = function (result) { + var _p0 = result; + if (_p0.ctor === 'Ok') { + return _elm_lang$core$Maybe$Just(_p0._0); + } else { + return _elm_lang$core$Maybe$Nothing; + } +}; +var _elm_lang$core$Result$withDefault = F2( + function (def, result) { + var _p1 = result; + if (_p1.ctor === 'Ok') { + return _p1._0; + } else { + return def; + } + }); +var _elm_lang$core$Result$Err = function (a) { + return {ctor: 'Err', _0: a}; +}; +var _elm_lang$core$Result$andThen = F2( + function (result, callback) { + var _p2 = result; + if (_p2.ctor === 'Ok') { + return callback(_p2._0); + } else { + return _elm_lang$core$Result$Err(_p2._0); + } + }); +var _elm_lang$core$Result$Ok = function (a) { + return {ctor: 'Ok', _0: a}; +}; +var _elm_lang$core$Result$map = F2( + function (func, ra) { + var _p3 = ra; + if (_p3.ctor === 'Ok') { + return _elm_lang$core$Result$Ok( + func(_p3._0)); + } else { + return _elm_lang$core$Result$Err(_p3._0); + } + }); +var _elm_lang$core$Result$map2 = F3( + function (func, ra, rb) { + var _p4 = {ctor: '_Tuple2', _0: ra, _1: rb}; + if (_p4._0.ctor === 'Ok') { + if (_p4._1.ctor === 'Ok') { + return _elm_lang$core$Result$Ok( + A2(func, _p4._0._0, _p4._1._0)); + } else { + return _elm_lang$core$Result$Err(_p4._1._0); + } + } else { + return _elm_lang$core$Result$Err(_p4._0._0); + } + }); +var _elm_lang$core$Result$map3 = F4( + function (func, ra, rb, rc) { + var _p5 = {ctor: '_Tuple3', _0: ra, _1: rb, _2: rc}; + if (_p5._0.ctor === 'Ok') { + if (_p5._1.ctor === 'Ok') { + if (_p5._2.ctor === 'Ok') { + return _elm_lang$core$Result$Ok( + A3(func, _p5._0._0, _p5._1._0, _p5._2._0)); + } else { + return _elm_lang$core$Result$Err(_p5._2._0); + } + } else { + return _elm_lang$core$Result$Err(_p5._1._0); + } + } else { + return _elm_lang$core$Result$Err(_p5._0._0); + } + }); +var _elm_lang$core$Result$map4 = F5( + function (func, ra, rb, rc, rd) { + var _p6 = {ctor: '_Tuple4', _0: ra, _1: rb, _2: rc, _3: rd}; + if (_p6._0.ctor === 'Ok') { + if (_p6._1.ctor === 'Ok') { + if (_p6._2.ctor === 'Ok') { + if (_p6._3.ctor === 'Ok') { + return _elm_lang$core$Result$Ok( + A4(func, _p6._0._0, _p6._1._0, _p6._2._0, _p6._3._0)); + } else { + return _elm_lang$core$Result$Err(_p6._3._0); + } + } else { + return _elm_lang$core$Result$Err(_p6._2._0); + } + } else { + return _elm_lang$core$Result$Err(_p6._1._0); + } + } else { + return _elm_lang$core$Result$Err(_p6._0._0); + } + }); +var _elm_lang$core$Result$map5 = F6( + function (func, ra, rb, rc, rd, re) { + var _p7 = {ctor: '_Tuple5', _0: ra, _1: rb, _2: rc, _3: rd, _4: re}; + if (_p7._0.ctor === 'Ok') { + if (_p7._1.ctor === 'Ok') { + if (_p7._2.ctor === 'Ok') { + if (_p7._3.ctor === 'Ok') { + if (_p7._4.ctor === 'Ok') { + return _elm_lang$core$Result$Ok( + A5(func, _p7._0._0, _p7._1._0, _p7._2._0, _p7._3._0, _p7._4._0)); + } else { + return _elm_lang$core$Result$Err(_p7._4._0); + } + } else { + return _elm_lang$core$Result$Err(_p7._3._0); + } + } else { + return _elm_lang$core$Result$Err(_p7._2._0); + } + } else { + return _elm_lang$core$Result$Err(_p7._1._0); + } + } else { + return _elm_lang$core$Result$Err(_p7._0._0); + } + }); +var _elm_lang$core$Result$formatError = F2( + function (f, result) { + var _p8 = result; + if (_p8.ctor === 'Ok') { + return _elm_lang$core$Result$Ok(_p8._0); + } else { + return _elm_lang$core$Result$Err( + f(_p8._0)); + } + }); +var _elm_lang$core$Result$fromMaybe = F2( + function (err, maybe) { + var _p9 = maybe; + if (_p9.ctor === 'Just') { + return _elm_lang$core$Result$Ok(_p9._0); + } else { + return _elm_lang$core$Result$Err(err); + } + }); + +//import Native.Utils // + +var _elm_lang$core$Native_Debug = function() { + +function log(tag, value) +{ + var msg = tag + ': ' + _elm_lang$core$Native_Utils.toString(value); + var process = process || {}; + if (process.stdout) + { + process.stdout.write(msg); + } + else + { + console.log(msg); + } + return value; +} + +function crash(message) +{ + throw new Error(message); +} + +return { + crash: crash, + log: F2(log) +}; + +}(); +//import Maybe, Native.List, Native.Utils, Result // + +var _elm_lang$core$Native_String = function() { + +function isEmpty(str) +{ + return str.length === 0; +} +function cons(chr, str) +{ + return chr + str; +} +function uncons(str) +{ + var hd = str[0]; + if (hd) + { + return _elm_lang$core$Maybe$Just(_elm_lang$core$Native_Utils.Tuple2(_elm_lang$core$Native_Utils.chr(hd), str.slice(1))); + } + return _elm_lang$core$Maybe$Nothing; +} +function append(a, b) +{ + return a + b; +} +function concat(strs) +{ + return _elm_lang$core$Native_List.toArray(strs).join(''); +} +function length(str) +{ + return str.length; +} +function map(f, str) +{ + var out = str.split(''); + for (var i = out.length; i--; ) + { + out[i] = f(_elm_lang$core$Native_Utils.chr(out[i])); + } + return out.join(''); +} +function filter(pred, str) +{ + return str.split('').map(_elm_lang$core$Native_Utils.chr).filter(pred).join(''); +} +function reverse(str) +{ + return str.split('').reverse().join(''); +} +function foldl(f, b, str) +{ + var len = str.length; + for (var i = 0; i < len; ++i) + { + b = A2(f, _elm_lang$core$Native_Utils.chr(str[i]), b); + } + return b; +} +function foldr(f, b, str) +{ + for (var i = str.length; i--; ) + { + b = A2(f, _elm_lang$core$Native_Utils.chr(str[i]), b); + } + return b; +} +function split(sep, str) +{ + return _elm_lang$core$Native_List.fromArray(str.split(sep)); +} +function join(sep, strs) +{ + return _elm_lang$core$Native_List.toArray(strs).join(sep); +} +function repeat(n, str) +{ + var result = ''; + while (n > 0) + { + if (n & 1) + { + result += str; + } + n >>= 1, str += str; + } + return result; +} +function slice(start, end, str) +{ + return str.slice(start, end); +} +function left(n, str) +{ + return n < 1 ? '' : str.slice(0, n); +} +function right(n, str) +{ + return n < 1 ? '' : str.slice(-n); +} +function dropLeft(n, str) +{ + return n < 1 ? str : str.slice(n); +} +function dropRight(n, str) +{ + return n < 1 ? str : str.slice(0, -n); +} +function pad(n, chr, str) +{ + var half = (n - str.length) / 2; + return repeat(Math.ceil(half), chr) + str + repeat(half | 0, chr); +} +function padRight(n, chr, str) +{ + return str + repeat(n - str.length, chr); +} +function padLeft(n, chr, str) +{ + return repeat(n - str.length, chr) + str; +} + +function trim(str) +{ + return str.trim(); +} +function trimLeft(str) +{ + return str.replace(/^\s+/, ''); +} +function trimRight(str) +{ + return str.replace(/\s+$/, ''); +} + +function words(str) +{ + return _elm_lang$core$Native_List.fromArray(str.trim().split(/\s+/g)); +} +function lines(str) +{ + return _elm_lang$core$Native_List.fromArray(str.split(/\r\n|\r|\n/g)); +} + +function toUpper(str) +{ + return str.toUpperCase(); +} +function toLower(str) +{ + return str.toLowerCase(); +} + +function any(pred, str) +{ + for (var i = str.length; i--; ) + { + if (pred(_elm_lang$core$Native_Utils.chr(str[i]))) + { + return true; + } + } + return false; +} +function all(pred, str) +{ + for (var i = str.length; i--; ) + { + if (!pred(_elm_lang$core$Native_Utils.chr(str[i]))) + { + return false; + } + } + return true; +} + +function contains(sub, str) +{ + return str.indexOf(sub) > -1; +} +function startsWith(sub, str) +{ + return str.indexOf(sub) === 0; +} +function endsWith(sub, str) +{ + return str.length >= sub.length && + str.lastIndexOf(sub) === str.length - sub.length; +} +function indexes(sub, str) +{ + var subLen = sub.length; + var i = 0; + var is = []; + while ((i = str.indexOf(sub, i)) > -1) + { + is.push(i); + i = i + subLen; + } + return _elm_lang$core$Native_List.fromArray(is); +} + +function toInt(s) +{ + var len = s.length; + if (len === 0) + { + return _elm_lang$core$Result$Err("could not convert string '" + s + "' to an Int" ); + } + var start = 0; + if (s[0] === '-') + { + if (len === 1) + { + return _elm_lang$core$Result$Err("could not convert string '" + s + "' to an Int" ); + } + start = 1; + } + for (var i = start; i < len; ++i) + { + var c = s[i]; + if (c < '0' || '9' < c) + { + return _elm_lang$core$Result$Err("could not convert string '" + s + "' to an Int" ); + } + } + return _elm_lang$core$Result$Ok(parseInt(s, 10)); +} + +function toFloat(s) +{ + var len = s.length; + if (len === 0) + { + return _elm_lang$core$Result$Err("could not convert string '" + s + "' to a Float" ); + } + var start = 0; + if (s[0] === '-') + { + if (len === 1) + { + return _elm_lang$core$Result$Err("could not convert string '" + s + "' to a Float" ); + } + start = 1; + } + var dotCount = 0; + for (var i = start; i < len; ++i) + { + var c = s[i]; + if ('0' <= c && c <= '9') + { + continue; + } + if (c === '.') + { + dotCount += 1; + if (dotCount <= 1) + { + continue; + } + } + return _elm_lang$core$Result$Err("could not convert string '" + s + "' to a Float" ); + } + return _elm_lang$core$Result$Ok(parseFloat(s)); +} + +function toList(str) +{ + return _elm_lang$core$Native_List.fromArray(str.split('').map(_elm_lang$core$Native_Utils.chr)); +} +function fromList(chars) +{ + return _elm_lang$core$Native_List.toArray(chars).join(''); +} + +return { + isEmpty: isEmpty, + cons: F2(cons), + uncons: uncons, + append: F2(append), + concat: concat, + length: length, + map: F2(map), + filter: F2(filter), + reverse: reverse, + foldl: F3(foldl), + foldr: F3(foldr), + + split: F2(split), + join: F2(join), + repeat: F2(repeat), + + slice: F3(slice), + left: F2(left), + right: F2(right), + dropLeft: F2(dropLeft), + dropRight: F2(dropRight), + + pad: F3(pad), + padLeft: F3(padLeft), + padRight: F3(padRight), + + trim: trim, + trimLeft: trimLeft, + trimRight: trimRight, + + words: words, + lines: lines, + + toUpper: toUpper, + toLower: toLower, + + any: F2(any), + all: F2(all), + + contains: F2(contains), + startsWith: F2(startsWith), + endsWith: F2(endsWith), + indexes: F2(indexes), + + toInt: toInt, + toFloat: toFloat, + toList: toList, + fromList: fromList +}; + +}(); +var _elm_lang$core$String$fromList = _elm_lang$core$Native_String.fromList; +var _elm_lang$core$String$toList = _elm_lang$core$Native_String.toList; +var _elm_lang$core$String$toFloat = _elm_lang$core$Native_String.toFloat; +var _elm_lang$core$String$toInt = _elm_lang$core$Native_String.toInt; +var _elm_lang$core$String$indices = _elm_lang$core$Native_String.indexes; +var _elm_lang$core$String$indexes = _elm_lang$core$Native_String.indexes; +var _elm_lang$core$String$endsWith = _elm_lang$core$Native_String.endsWith; +var _elm_lang$core$String$startsWith = _elm_lang$core$Native_String.startsWith; +var _elm_lang$core$String$contains = _elm_lang$core$Native_String.contains; +var _elm_lang$core$String$all = _elm_lang$core$Native_String.all; +var _elm_lang$core$String$any = _elm_lang$core$Native_String.any; +var _elm_lang$core$String$toLower = _elm_lang$core$Native_String.toLower; +var _elm_lang$core$String$toUpper = _elm_lang$core$Native_String.toUpper; +var _elm_lang$core$String$lines = _elm_lang$core$Native_String.lines; +var _elm_lang$core$String$words = _elm_lang$core$Native_String.words; +var _elm_lang$core$String$trimRight = _elm_lang$core$Native_String.trimRight; +var _elm_lang$core$String$trimLeft = _elm_lang$core$Native_String.trimLeft; +var _elm_lang$core$String$trim = _elm_lang$core$Native_String.trim; +var _elm_lang$core$String$padRight = _elm_lang$core$Native_String.padRight; +var _elm_lang$core$String$padLeft = _elm_lang$core$Native_String.padLeft; +var _elm_lang$core$String$pad = _elm_lang$core$Native_String.pad; +var _elm_lang$core$String$dropRight = _elm_lang$core$Native_String.dropRight; +var _elm_lang$core$String$dropLeft = _elm_lang$core$Native_String.dropLeft; +var _elm_lang$core$String$right = _elm_lang$core$Native_String.right; +var _elm_lang$core$String$left = _elm_lang$core$Native_String.left; +var _elm_lang$core$String$slice = _elm_lang$core$Native_String.slice; +var _elm_lang$core$String$repeat = _elm_lang$core$Native_String.repeat; +var _elm_lang$core$String$join = _elm_lang$core$Native_String.join; +var _elm_lang$core$String$split = _elm_lang$core$Native_String.split; +var _elm_lang$core$String$foldr = _elm_lang$core$Native_String.foldr; +var _elm_lang$core$String$foldl = _elm_lang$core$Native_String.foldl; +var _elm_lang$core$String$reverse = _elm_lang$core$Native_String.reverse; +var _elm_lang$core$String$filter = _elm_lang$core$Native_String.filter; +var _elm_lang$core$String$map = _elm_lang$core$Native_String.map; +var _elm_lang$core$String$length = _elm_lang$core$Native_String.length; +var _elm_lang$core$String$concat = _elm_lang$core$Native_String.concat; +var _elm_lang$core$String$append = _elm_lang$core$Native_String.append; +var _elm_lang$core$String$uncons = _elm_lang$core$Native_String.uncons; +var _elm_lang$core$String$cons = _elm_lang$core$Native_String.cons; +var _elm_lang$core$String$fromChar = function ($char) { + return A2(_elm_lang$core$String$cons, $char, ''); +}; +var _elm_lang$core$String$isEmpty = _elm_lang$core$Native_String.isEmpty; + +var _elm_lang$core$Dict$foldr = F3( + function (f, acc, t) { + foldr: + while (true) { + var _p0 = t; + if (_p0.ctor === 'RBEmpty_elm_builtin') { + return acc; + } else { + var _v1 = f, + _v2 = A3( + f, + _p0._1, + _p0._2, + A3(_elm_lang$core$Dict$foldr, f, acc, _p0._4)), + _v3 = _p0._3; + f = _v1; + acc = _v2; + t = _v3; + continue foldr; + } + } + }); +var _elm_lang$core$Dict$keys = function (dict) { + return A3( + _elm_lang$core$Dict$foldr, + F3( + function (key, value, keyList) { + return A2(_elm_lang$core$List_ops['::'], key, keyList); + }), + _elm_lang$core$Native_List.fromArray( + []), + dict); +}; +var _elm_lang$core$Dict$values = function (dict) { + return A3( + _elm_lang$core$Dict$foldr, + F3( + function (key, value, valueList) { + return A2(_elm_lang$core$List_ops['::'], value, valueList); + }), + _elm_lang$core$Native_List.fromArray( + []), + dict); +}; +var _elm_lang$core$Dict$toList = function (dict) { + return A3( + _elm_lang$core$Dict$foldr, + F3( + function (key, value, list) { + return A2( + _elm_lang$core$List_ops['::'], + {ctor: '_Tuple2', _0: key, _1: value}, + list); + }), + _elm_lang$core$Native_List.fromArray( + []), + dict); +}; +var _elm_lang$core$Dict$foldl = F3( + function (f, acc, dict) { + foldl: + while (true) { + var _p1 = dict; + if (_p1.ctor === 'RBEmpty_elm_builtin') { + return acc; + } else { + var _v5 = f, + _v6 = A3( + f, + _p1._1, + _p1._2, + A3(_elm_lang$core$Dict$foldl, f, acc, _p1._3)), + _v7 = _p1._4; + f = _v5; + acc = _v6; + dict = _v7; + continue foldl; + } + } + }); +var _elm_lang$core$Dict$merge = F6( + function (leftStep, bothStep, rightStep, leftDict, rightDict, initialResult) { + var stepState = F3( + function (rKey, rValue, _p2) { + var _p3 = _p2; + var _p9 = _p3._1; + var _p8 = _p3._0; + var _p4 = _p8; + if (_p4.ctor === '[]') { + return { + ctor: '_Tuple2', + _0: _p8, + _1: A3(rightStep, rKey, rValue, _p9) + }; + } else { + var _p7 = _p4._1; + var _p6 = _p4._0._1; + var _p5 = _p4._0._0; + return (_elm_lang$core$Native_Utils.cmp(_p5, rKey) < 0) ? { + ctor: '_Tuple2', + _0: _p7, + _1: A3(leftStep, _p5, _p6, _p9) + } : ((_elm_lang$core$Native_Utils.cmp(_p5, rKey) > 0) ? { + ctor: '_Tuple2', + _0: _p8, + _1: A3(rightStep, rKey, rValue, _p9) + } : { + ctor: '_Tuple2', + _0: _p7, + _1: A4(bothStep, _p5, _p6, rValue, _p9) + }); + } + }); + var _p10 = A3( + _elm_lang$core$Dict$foldl, + stepState, + { + ctor: '_Tuple2', + _0: _elm_lang$core$Dict$toList(leftDict), + _1: initialResult + }, + rightDict); + var leftovers = _p10._0; + var intermediateResult = _p10._1; + return A3( + _elm_lang$core$List$foldl, + F2( + function (_p11, result) { + var _p12 = _p11; + return A3(leftStep, _p12._0, _p12._1, result); + }), + intermediateResult, + leftovers); + }); +var _elm_lang$core$Dict$reportRemBug = F4( + function (msg, c, lgot, rgot) { + return _elm_lang$core$Native_Debug.crash( + _elm_lang$core$String$concat( + _elm_lang$core$Native_List.fromArray( + [ + 'Internal red-black tree invariant violated, expected ', + msg, + ' and got ', + _elm_lang$core$Basics$toString(c), + '/', + lgot, + '/', + rgot, + '\nPlease report this bug to ' + ]))); + }); +var _elm_lang$core$Dict$isBBlack = function (dict) { + var _p13 = dict; + _v11_2: + do { + if (_p13.ctor === 'RBNode_elm_builtin') { + if (_p13._0.ctor === 'BBlack') { + return true; + } else { + break _v11_2; + } + } else { + if (_p13._0.ctor === 'LBBlack') { + return true; + } else { + break _v11_2; + } + } + } while(false); + return false; +}; +var _elm_lang$core$Dict$sizeHelp = F2( + function (n, dict) { + sizeHelp: + while (true) { + var _p14 = dict; + if (_p14.ctor === 'RBEmpty_elm_builtin') { + return n; + } else { + var _v13 = A2(_elm_lang$core$Dict$sizeHelp, n + 1, _p14._4), + _v14 = _p14._3; + n = _v13; + dict = _v14; + continue sizeHelp; + } + } + }); +var _elm_lang$core$Dict$size = function (dict) { + return A2(_elm_lang$core$Dict$sizeHelp, 0, dict); +}; +var _elm_lang$core$Dict$get = F2( + function (targetKey, dict) { + get: + while (true) { + var _p15 = dict; + if (_p15.ctor === 'RBEmpty_elm_builtin') { + return _elm_lang$core$Maybe$Nothing; + } else { + var _p16 = A2(_elm_lang$core$Basics$compare, targetKey, _p15._1); + switch (_p16.ctor) { + case 'LT': + var _v17 = targetKey, + _v18 = _p15._3; + targetKey = _v17; + dict = _v18; + continue get; + case 'EQ': + return _elm_lang$core$Maybe$Just(_p15._2); + default: + var _v19 = targetKey, + _v20 = _p15._4; + targetKey = _v19; + dict = _v20; + continue get; + } + } + } + }); +var _elm_lang$core$Dict$member = F2( + function (key, dict) { + var _p17 = A2(_elm_lang$core$Dict$get, key, dict); + if (_p17.ctor === 'Just') { + return true; + } else { + return false; + } + }); +var _elm_lang$core$Dict$maxWithDefault = F3( + function (k, v, r) { + maxWithDefault: + while (true) { + var _p18 = r; + if (_p18.ctor === 'RBEmpty_elm_builtin') { + return {ctor: '_Tuple2', _0: k, _1: v}; + } else { + var _v23 = _p18._1, + _v24 = _p18._2, + _v25 = _p18._4; + k = _v23; + v = _v24; + r = _v25; + continue maxWithDefault; + } + } + }); +var _elm_lang$core$Dict$NBlack = {ctor: 'NBlack'}; +var _elm_lang$core$Dict$BBlack = {ctor: 'BBlack'}; +var _elm_lang$core$Dict$Black = {ctor: 'Black'}; +var _elm_lang$core$Dict$blackish = function (t) { + var _p19 = t; + if (_p19.ctor === 'RBNode_elm_builtin') { + var _p20 = _p19._0; + return _elm_lang$core$Native_Utils.eq(_p20, _elm_lang$core$Dict$Black) || _elm_lang$core$Native_Utils.eq(_p20, _elm_lang$core$Dict$BBlack); + } else { + return true; + } +}; +var _elm_lang$core$Dict$Red = {ctor: 'Red'}; +var _elm_lang$core$Dict$moreBlack = function (color) { + var _p21 = color; + switch (_p21.ctor) { + case 'Black': + return _elm_lang$core$Dict$BBlack; + case 'Red': + return _elm_lang$core$Dict$Black; + case 'NBlack': + return _elm_lang$core$Dict$Red; + default: + return _elm_lang$core$Native_Debug.crash('Can\'t make a double black node more black!'); + } +}; +var _elm_lang$core$Dict$lessBlack = function (color) { + var _p22 = color; + switch (_p22.ctor) { + case 'BBlack': + return _elm_lang$core$Dict$Black; + case 'Black': + return _elm_lang$core$Dict$Red; + case 'Red': + return _elm_lang$core$Dict$NBlack; + default: + return _elm_lang$core$Native_Debug.crash('Can\'t make a negative black node less black!'); + } +}; +var _elm_lang$core$Dict$LBBlack = {ctor: 'LBBlack'}; +var _elm_lang$core$Dict$LBlack = {ctor: 'LBlack'}; +var _elm_lang$core$Dict$RBEmpty_elm_builtin = function (a) { + return {ctor: 'RBEmpty_elm_builtin', _0: a}; +}; +var _elm_lang$core$Dict$empty = _elm_lang$core$Dict$RBEmpty_elm_builtin(_elm_lang$core$Dict$LBlack); +var _elm_lang$core$Dict$isEmpty = function (dict) { + return _elm_lang$core$Native_Utils.eq(dict, _elm_lang$core$Dict$empty); +}; +var _elm_lang$core$Dict$RBNode_elm_builtin = F5( + function (a, b, c, d, e) { + return {ctor: 'RBNode_elm_builtin', _0: a, _1: b, _2: c, _3: d, _4: e}; + }); +var _elm_lang$core$Dict$ensureBlackRoot = function (dict) { + var _p23 = dict; + if ((_p23.ctor === 'RBNode_elm_builtin') && (_p23._0.ctor === 'Red')) { + return A5(_elm_lang$core$Dict$RBNode_elm_builtin, _elm_lang$core$Dict$Black, _p23._1, _p23._2, _p23._3, _p23._4); + } else { + return dict; + } +}; +var _elm_lang$core$Dict$lessBlackTree = function (dict) { + var _p24 = dict; + if (_p24.ctor === 'RBNode_elm_builtin') { + return A5( + _elm_lang$core$Dict$RBNode_elm_builtin, + _elm_lang$core$Dict$lessBlack(_p24._0), + _p24._1, + _p24._2, + _p24._3, + _p24._4); + } else { + return _elm_lang$core$Dict$RBEmpty_elm_builtin(_elm_lang$core$Dict$LBlack); + } +}; +var _elm_lang$core$Dict$balancedTree = function (col) { + return function (xk) { + return function (xv) { + return function (yk) { + return function (yv) { + return function (zk) { + return function (zv) { + return function (a) { + return function (b) { + return function (c) { + return function (d) { + return A5( + _elm_lang$core$Dict$RBNode_elm_builtin, + _elm_lang$core$Dict$lessBlack(col), + yk, + yv, + A5(_elm_lang$core$Dict$RBNode_elm_builtin, _elm_lang$core$Dict$Black, xk, xv, a, b), + A5(_elm_lang$core$Dict$RBNode_elm_builtin, _elm_lang$core$Dict$Black, zk, zv, c, d)); + }; + }; + }; + }; + }; + }; + }; + }; + }; + }; +}; +var _elm_lang$core$Dict$blacken = function (t) { + var _p25 = t; + if (_p25.ctor === 'RBEmpty_elm_builtin') { + return _elm_lang$core$Dict$RBEmpty_elm_builtin(_elm_lang$core$Dict$LBlack); + } else { + return A5(_elm_lang$core$Dict$RBNode_elm_builtin, _elm_lang$core$Dict$Black, _p25._1, _p25._2, _p25._3, _p25._4); + } +}; +var _elm_lang$core$Dict$redden = function (t) { + var _p26 = t; + if (_p26.ctor === 'RBEmpty_elm_builtin') { + return _elm_lang$core$Native_Debug.crash('can\'t make a Leaf red'); + } else { + return A5(_elm_lang$core$Dict$RBNode_elm_builtin, _elm_lang$core$Dict$Red, _p26._1, _p26._2, _p26._3, _p26._4); + } +}; +var _elm_lang$core$Dict$balanceHelp = function (tree) { + var _p27 = tree; + _v33_6: + do { + _v33_5: + do { + _v33_4: + do { + _v33_3: + do { + _v33_2: + do { + _v33_1: + do { + _v33_0: + do { + if (_p27.ctor === 'RBNode_elm_builtin') { + if (_p27._3.ctor === 'RBNode_elm_builtin') { + if (_p27._4.ctor === 'RBNode_elm_builtin') { + switch (_p27._3._0.ctor) { + case 'Red': + switch (_p27._4._0.ctor) { + case 'Red': + if ((_p27._3._3.ctor === 'RBNode_elm_builtin') && (_p27._3._3._0.ctor === 'Red')) { + break _v33_0; + } else { + if ((_p27._3._4.ctor === 'RBNode_elm_builtin') && (_p27._3._4._0.ctor === 'Red')) { + break _v33_1; + } else { + if ((_p27._4._3.ctor === 'RBNode_elm_builtin') && (_p27._4._3._0.ctor === 'Red')) { + break _v33_2; + } else { + if ((_p27._4._4.ctor === 'RBNode_elm_builtin') && (_p27._4._4._0.ctor === 'Red')) { + break _v33_3; + } else { + break _v33_6; + } + } + } + } + case 'NBlack': + if ((_p27._3._3.ctor === 'RBNode_elm_builtin') && (_p27._3._3._0.ctor === 'Red')) { + break _v33_0; + } else { + if ((_p27._3._4.ctor === 'RBNode_elm_builtin') && (_p27._3._4._0.ctor === 'Red')) { + break _v33_1; + } else { + if (((((_p27._0.ctor === 'BBlack') && (_p27._4._3.ctor === 'RBNode_elm_builtin')) && (_p27._4._3._0.ctor === 'Black')) && (_p27._4._4.ctor === 'RBNode_elm_builtin')) && (_p27._4._4._0.ctor === 'Black')) { + break _v33_4; + } else { + break _v33_6; + } + } + } + default: + if ((_p27._3._3.ctor === 'RBNode_elm_builtin') && (_p27._3._3._0.ctor === 'Red')) { + break _v33_0; + } else { + if ((_p27._3._4.ctor === 'RBNode_elm_builtin') && (_p27._3._4._0.ctor === 'Red')) { + break _v33_1; + } else { + break _v33_6; + } + } + } + case 'NBlack': + switch (_p27._4._0.ctor) { + case 'Red': + if ((_p27._4._3.ctor === 'RBNode_elm_builtin') && (_p27._4._3._0.ctor === 'Red')) { + break _v33_2; + } else { + if ((_p27._4._4.ctor === 'RBNode_elm_builtin') && (_p27._4._4._0.ctor === 'Red')) { + break _v33_3; + } else { + if (((((_p27._0.ctor === 'BBlack') && (_p27._3._3.ctor === 'RBNode_elm_builtin')) && (_p27._3._3._0.ctor === 'Black')) && (_p27._3._4.ctor === 'RBNode_elm_builtin')) && (_p27._3._4._0.ctor === 'Black')) { + break _v33_5; + } else { + break _v33_6; + } + } + } + case 'NBlack': + if (_p27._0.ctor === 'BBlack') { + if ((((_p27._4._3.ctor === 'RBNode_elm_builtin') && (_p27._4._3._0.ctor === 'Black')) && (_p27._4._4.ctor === 'RBNode_elm_builtin')) && (_p27._4._4._0.ctor === 'Black')) { + break _v33_4; + } else { + if ((((_p27._3._3.ctor === 'RBNode_elm_builtin') && (_p27._3._3._0.ctor === 'Black')) && (_p27._3._4.ctor === 'RBNode_elm_builtin')) && (_p27._3._4._0.ctor === 'Black')) { + break _v33_5; + } else { + break _v33_6; + } + } + } else { + break _v33_6; + } + default: + if (((((_p27._0.ctor === 'BBlack') && (_p27._3._3.ctor === 'RBNode_elm_builtin')) && (_p27._3._3._0.ctor === 'Black')) && (_p27._3._4.ctor === 'RBNode_elm_builtin')) && (_p27._3._4._0.ctor === 'Black')) { + break _v33_5; + } else { + break _v33_6; + } + } + default: + switch (_p27._4._0.ctor) { + case 'Red': + if ((_p27._4._3.ctor === 'RBNode_elm_builtin') && (_p27._4._3._0.ctor === 'Red')) { + break _v33_2; + } else { + if ((_p27._4._4.ctor === 'RBNode_elm_builtin') && (_p27._4._4._0.ctor === 'Red')) { + break _v33_3; + } else { + break _v33_6; + } + } + case 'NBlack': + if (((((_p27._0.ctor === 'BBlack') && (_p27._4._3.ctor === 'RBNode_elm_builtin')) && (_p27._4._3._0.ctor === 'Black')) && (_p27._4._4.ctor === 'RBNode_elm_builtin')) && (_p27._4._4._0.ctor === 'Black')) { + break _v33_4; + } else { + break _v33_6; + } + default: + break _v33_6; + } + } + } else { + switch (_p27._3._0.ctor) { + case 'Red': + if ((_p27._3._3.ctor === 'RBNode_elm_builtin') && (_p27._3._3._0.ctor === 'Red')) { + break _v33_0; + } else { + if ((_p27._3._4.ctor === 'RBNode_elm_builtin') && (_p27._3._4._0.ctor === 'Red')) { + break _v33_1; + } else { + break _v33_6; + } + } + case 'NBlack': + if (((((_p27._0.ctor === 'BBlack') && (_p27._3._3.ctor === 'RBNode_elm_builtin')) && (_p27._3._3._0.ctor === 'Black')) && (_p27._3._4.ctor === 'RBNode_elm_builtin')) && (_p27._3._4._0.ctor === 'Black')) { + break _v33_5; + } else { + break _v33_6; + } + default: + break _v33_6; + } + } + } else { + if (_p27._4.ctor === 'RBNode_elm_builtin') { + switch (_p27._4._0.ctor) { + case 'Red': + if ((_p27._4._3.ctor === 'RBNode_elm_builtin') && (_p27._4._3._0.ctor === 'Red')) { + break _v33_2; + } else { + if ((_p27._4._4.ctor === 'RBNode_elm_builtin') && (_p27._4._4._0.ctor === 'Red')) { + break _v33_3; + } else { + break _v33_6; + } + } + case 'NBlack': + if (((((_p27._0.ctor === 'BBlack') && (_p27._4._3.ctor === 'RBNode_elm_builtin')) && (_p27._4._3._0.ctor === 'Black')) && (_p27._4._4.ctor === 'RBNode_elm_builtin')) && (_p27._4._4._0.ctor === 'Black')) { + break _v33_4; + } else { + break _v33_6; + } + default: + break _v33_6; + } + } else { + break _v33_6; + } + } + } else { + break _v33_6; + } + } while(false); + return _elm_lang$core$Dict$balancedTree(_p27._0)(_p27._3._3._1)(_p27._3._3._2)(_p27._3._1)(_p27._3._2)(_p27._1)(_p27._2)(_p27._3._3._3)(_p27._3._3._4)(_p27._3._4)(_p27._4); + } while(false); + return _elm_lang$core$Dict$balancedTree(_p27._0)(_p27._3._1)(_p27._3._2)(_p27._3._4._1)(_p27._3._4._2)(_p27._1)(_p27._2)(_p27._3._3)(_p27._3._4._3)(_p27._3._4._4)(_p27._4); + } while(false); + return _elm_lang$core$Dict$balancedTree(_p27._0)(_p27._1)(_p27._2)(_p27._4._3._1)(_p27._4._3._2)(_p27._4._1)(_p27._4._2)(_p27._3)(_p27._4._3._3)(_p27._4._3._4)(_p27._4._4); + } while(false); + return _elm_lang$core$Dict$balancedTree(_p27._0)(_p27._1)(_p27._2)(_p27._4._1)(_p27._4._2)(_p27._4._4._1)(_p27._4._4._2)(_p27._3)(_p27._4._3)(_p27._4._4._3)(_p27._4._4._4); + } while(false); + return A5( + _elm_lang$core$Dict$RBNode_elm_builtin, + _elm_lang$core$Dict$Black, + _p27._4._3._1, + _p27._4._3._2, + A5(_elm_lang$core$Dict$RBNode_elm_builtin, _elm_lang$core$Dict$Black, _p27._1, _p27._2, _p27._3, _p27._4._3._3), + A5( + _elm_lang$core$Dict$balance, + _elm_lang$core$Dict$Black, + _p27._4._1, + _p27._4._2, + _p27._4._3._4, + _elm_lang$core$Dict$redden(_p27._4._4))); + } while(false); + return A5( + _elm_lang$core$Dict$RBNode_elm_builtin, + _elm_lang$core$Dict$Black, + _p27._3._4._1, + _p27._3._4._2, + A5( + _elm_lang$core$Dict$balance, + _elm_lang$core$Dict$Black, + _p27._3._1, + _p27._3._2, + _elm_lang$core$Dict$redden(_p27._3._3), + _p27._3._4._3), + A5(_elm_lang$core$Dict$RBNode_elm_builtin, _elm_lang$core$Dict$Black, _p27._1, _p27._2, _p27._3._4._4, _p27._4)); + } while(false); + return tree; +}; +var _elm_lang$core$Dict$balance = F5( + function (c, k, v, l, r) { + var tree = A5(_elm_lang$core$Dict$RBNode_elm_builtin, c, k, v, l, r); + return _elm_lang$core$Dict$blackish(tree) ? _elm_lang$core$Dict$balanceHelp(tree) : tree; + }); +var _elm_lang$core$Dict$bubble = F5( + function (c, k, v, l, r) { + return (_elm_lang$core$Dict$isBBlack(l) || _elm_lang$core$Dict$isBBlack(r)) ? A5( + _elm_lang$core$Dict$balance, + _elm_lang$core$Dict$moreBlack(c), + k, + v, + _elm_lang$core$Dict$lessBlackTree(l), + _elm_lang$core$Dict$lessBlackTree(r)) : A5(_elm_lang$core$Dict$RBNode_elm_builtin, c, k, v, l, r); + }); +var _elm_lang$core$Dict$removeMax = F5( + function (c, k, v, l, r) { + var _p28 = r; + if (_p28.ctor === 'RBEmpty_elm_builtin') { + return A3(_elm_lang$core$Dict$rem, c, l, r); + } else { + return A5( + _elm_lang$core$Dict$bubble, + c, + k, + v, + l, + A5(_elm_lang$core$Dict$removeMax, _p28._0, _p28._1, _p28._2, _p28._3, _p28._4)); + } + }); +var _elm_lang$core$Dict$rem = F3( + function (c, l, r) { + var _p29 = {ctor: '_Tuple2', _0: l, _1: r}; + if (_p29._0.ctor === 'RBEmpty_elm_builtin') { + if (_p29._1.ctor === 'RBEmpty_elm_builtin') { + var _p30 = c; + switch (_p30.ctor) { + case 'Red': + return _elm_lang$core$Dict$RBEmpty_elm_builtin(_elm_lang$core$Dict$LBlack); + case 'Black': + return _elm_lang$core$Dict$RBEmpty_elm_builtin(_elm_lang$core$Dict$LBBlack); + default: + return _elm_lang$core$Native_Debug.crash('cannot have bblack or nblack nodes at this point'); + } + } else { + var _p33 = _p29._1._0; + var _p32 = _p29._0._0; + var _p31 = {ctor: '_Tuple3', _0: c, _1: _p32, _2: _p33}; + if ((((_p31.ctor === '_Tuple3') && (_p31._0.ctor === 'Black')) && (_p31._1.ctor === 'LBlack')) && (_p31._2.ctor === 'Red')) { + return A5(_elm_lang$core$Dict$RBNode_elm_builtin, _elm_lang$core$Dict$Black, _p29._1._1, _p29._1._2, _p29._1._3, _p29._1._4); + } else { + return A4( + _elm_lang$core$Dict$reportRemBug, + 'Black/LBlack/Red', + c, + _elm_lang$core$Basics$toString(_p32), + _elm_lang$core$Basics$toString(_p33)); + } + } + } else { + if (_p29._1.ctor === 'RBEmpty_elm_builtin') { + var _p36 = _p29._1._0; + var _p35 = _p29._0._0; + var _p34 = {ctor: '_Tuple3', _0: c, _1: _p35, _2: _p36}; + if ((((_p34.ctor === '_Tuple3') && (_p34._0.ctor === 'Black')) && (_p34._1.ctor === 'Red')) && (_p34._2.ctor === 'LBlack')) { + return A5(_elm_lang$core$Dict$RBNode_elm_builtin, _elm_lang$core$Dict$Black, _p29._0._1, _p29._0._2, _p29._0._3, _p29._0._4); + } else { + return A4( + _elm_lang$core$Dict$reportRemBug, + 'Black/Red/LBlack', + c, + _elm_lang$core$Basics$toString(_p35), + _elm_lang$core$Basics$toString(_p36)); + } + } else { + var _p40 = _p29._0._2; + var _p39 = _p29._0._4; + var _p38 = _p29._0._1; + var l$ = A5(_elm_lang$core$Dict$removeMax, _p29._0._0, _p38, _p40, _p29._0._3, _p39); + var _p37 = A3(_elm_lang$core$Dict$maxWithDefault, _p38, _p40, _p39); + var k = _p37._0; + var v = _p37._1; + return A5(_elm_lang$core$Dict$bubble, c, k, v, l$, r); + } + } + }); +var _elm_lang$core$Dict$map = F2( + function (f, dict) { + var _p41 = dict; + if (_p41.ctor === 'RBEmpty_elm_builtin') { + return _elm_lang$core$Dict$RBEmpty_elm_builtin(_elm_lang$core$Dict$LBlack); + } else { + var _p42 = _p41._1; + return A5( + _elm_lang$core$Dict$RBNode_elm_builtin, + _p41._0, + _p42, + A2(f, _p42, _p41._2), + A2(_elm_lang$core$Dict$map, f, _p41._3), + A2(_elm_lang$core$Dict$map, f, _p41._4)); + } + }); +var _elm_lang$core$Dict$Same = {ctor: 'Same'}; +var _elm_lang$core$Dict$Remove = {ctor: 'Remove'}; +var _elm_lang$core$Dict$Insert = {ctor: 'Insert'}; +var _elm_lang$core$Dict$update = F3( + function (k, alter, dict) { + var up = function (dict) { + var _p43 = dict; + if (_p43.ctor === 'RBEmpty_elm_builtin') { + var _p44 = alter(_elm_lang$core$Maybe$Nothing); + if (_p44.ctor === 'Nothing') { + return {ctor: '_Tuple2', _0: _elm_lang$core$Dict$Same, _1: _elm_lang$core$Dict$empty}; + } else { + return { + ctor: '_Tuple2', + _0: _elm_lang$core$Dict$Insert, + _1: A5(_elm_lang$core$Dict$RBNode_elm_builtin, _elm_lang$core$Dict$Red, k, _p44._0, _elm_lang$core$Dict$empty, _elm_lang$core$Dict$empty) + }; + } + } else { + var _p55 = _p43._2; + var _p54 = _p43._4; + var _p53 = _p43._3; + var _p52 = _p43._1; + var _p51 = _p43._0; + var _p45 = A2(_elm_lang$core$Basics$compare, k, _p52); + switch (_p45.ctor) { + case 'EQ': + var _p46 = alter( + _elm_lang$core$Maybe$Just(_p55)); + if (_p46.ctor === 'Nothing') { + return { + ctor: '_Tuple2', + _0: _elm_lang$core$Dict$Remove, + _1: A3(_elm_lang$core$Dict$rem, _p51, _p53, _p54) + }; + } else { + return { + ctor: '_Tuple2', + _0: _elm_lang$core$Dict$Same, + _1: A5(_elm_lang$core$Dict$RBNode_elm_builtin, _p51, _p52, _p46._0, _p53, _p54) + }; + } + case 'LT': + var _p47 = up(_p53); + var flag = _p47._0; + var newLeft = _p47._1; + var _p48 = flag; + switch (_p48.ctor) { + case 'Same': + return { + ctor: '_Tuple2', + _0: _elm_lang$core$Dict$Same, + _1: A5(_elm_lang$core$Dict$RBNode_elm_builtin, _p51, _p52, _p55, newLeft, _p54) + }; + case 'Insert': + return { + ctor: '_Tuple2', + _0: _elm_lang$core$Dict$Insert, + _1: A5(_elm_lang$core$Dict$balance, _p51, _p52, _p55, newLeft, _p54) + }; + default: + return { + ctor: '_Tuple2', + _0: _elm_lang$core$Dict$Remove, + _1: A5(_elm_lang$core$Dict$bubble, _p51, _p52, _p55, newLeft, _p54) + }; + } + default: + var _p49 = up(_p54); + var flag = _p49._0; + var newRight = _p49._1; + var _p50 = flag; + switch (_p50.ctor) { + case 'Same': + return { + ctor: '_Tuple2', + _0: _elm_lang$core$Dict$Same, + _1: A5(_elm_lang$core$Dict$RBNode_elm_builtin, _p51, _p52, _p55, _p53, newRight) + }; + case 'Insert': + return { + ctor: '_Tuple2', + _0: _elm_lang$core$Dict$Insert, + _1: A5(_elm_lang$core$Dict$balance, _p51, _p52, _p55, _p53, newRight) + }; + default: + return { + ctor: '_Tuple2', + _0: _elm_lang$core$Dict$Remove, + _1: A5(_elm_lang$core$Dict$bubble, _p51, _p52, _p55, _p53, newRight) + }; + } + } + } + }; + var _p56 = up(dict); + var flag = _p56._0; + var updatedDict = _p56._1; + var _p57 = flag; + switch (_p57.ctor) { + case 'Same': + return updatedDict; + case 'Insert': + return _elm_lang$core$Dict$ensureBlackRoot(updatedDict); + default: + return _elm_lang$core$Dict$blacken(updatedDict); + } + }); +var _elm_lang$core$Dict$insert = F3( + function (key, value, dict) { + return A3( + _elm_lang$core$Dict$update, + key, + _elm_lang$core$Basics$always( + _elm_lang$core$Maybe$Just(value)), + dict); + }); +var _elm_lang$core$Dict$singleton = F2( + function (key, value) { + return A3(_elm_lang$core$Dict$insert, key, value, _elm_lang$core$Dict$empty); + }); +var _elm_lang$core$Dict$union = F2( + function (t1, t2) { + return A3(_elm_lang$core$Dict$foldl, _elm_lang$core$Dict$insert, t2, t1); + }); +var _elm_lang$core$Dict$filter = F2( + function (predicate, dictionary) { + var add = F3( + function (key, value, dict) { + return A2(predicate, key, value) ? A3(_elm_lang$core$Dict$insert, key, value, dict) : dict; + }); + return A3(_elm_lang$core$Dict$foldl, add, _elm_lang$core$Dict$empty, dictionary); + }); +var _elm_lang$core$Dict$intersect = F2( + function (t1, t2) { + return A2( + _elm_lang$core$Dict$filter, + F2( + function (k, _p58) { + return A2(_elm_lang$core$Dict$member, k, t2); + }), + t1); + }); +var _elm_lang$core$Dict$partition = F2( + function (predicate, dict) { + var add = F3( + function (key, value, _p59) { + var _p60 = _p59; + var _p62 = _p60._1; + var _p61 = _p60._0; + return A2(predicate, key, value) ? { + ctor: '_Tuple2', + _0: A3(_elm_lang$core$Dict$insert, key, value, _p61), + _1: _p62 + } : { + ctor: '_Tuple2', + _0: _p61, + _1: A3(_elm_lang$core$Dict$insert, key, value, _p62) + }; + }); + return A3( + _elm_lang$core$Dict$foldl, + add, + {ctor: '_Tuple2', _0: _elm_lang$core$Dict$empty, _1: _elm_lang$core$Dict$empty}, + dict); + }); +var _elm_lang$core$Dict$fromList = function (assocs) { + return A3( + _elm_lang$core$List$foldl, + F2( + function (_p63, dict) { + var _p64 = _p63; + return A3(_elm_lang$core$Dict$insert, _p64._0, _p64._1, dict); + }), + _elm_lang$core$Dict$empty, + assocs); +}; +var _elm_lang$core$Dict$remove = F2( + function (key, dict) { + return A3( + _elm_lang$core$Dict$update, + key, + _elm_lang$core$Basics$always(_elm_lang$core$Maybe$Nothing), + dict); + }); +var _elm_lang$core$Dict$diff = F2( + function (t1, t2) { + return A3( + _elm_lang$core$Dict$foldl, + F3( + function (k, v, t) { + return A2(_elm_lang$core$Dict$remove, k, t); + }), + t1, + t2); + }); + +var _elm_lang$core$Platform_Sub$batch = _elm_lang$core$Native_Platform.batch; +var _elm_lang$core$Platform_Sub$none = _elm_lang$core$Platform_Sub$batch( + _elm_lang$core$Native_List.fromArray( + [])); +var _elm_lang$core$Platform_Sub$map = _elm_lang$core$Native_Platform.map; +var _elm_lang$core$Platform_Sub$Sub = {ctor: 'Sub'}; + +var _elm_lang$core$Debug$crash = _elm_lang$core$Native_Debug.crash; +var _elm_lang$core$Debug$log = _elm_lang$core$Native_Debug.log; + +//import Maybe, Native.Array, Native.List, Native.Utils, Result // + +var _elm_lang$core$Native_Json = function() { + + +// CORE DECODERS + +function succeed(msg) +{ + return { + ctor: '', + tag: 'succeed', + msg: msg + }; +} + +function fail(msg) +{ + return { + ctor: '', + tag: 'fail', + msg: msg + }; +} + +function decodePrimitive(tag) +{ + return { + ctor: '', + tag: tag + }; +} + +function decodeContainer(tag, decoder) +{ + return { + ctor: '', + tag: tag, + decoder: decoder + }; +} + +function decodeNull(value) +{ + return { + ctor: '', + tag: 'null', + value: value + }; +} + +function decodeField(field, decoder) +{ + return { + ctor: '', + tag: 'field', + field: field, + decoder: decoder + }; +} + +function decodeKeyValuePairs(decoder) +{ + return { + ctor: '', + tag: 'key-value', + decoder: decoder + }; +} + +function decodeObject(f, decoders) +{ + return { + ctor: '', + tag: 'map-many', + func: f, + decoders: decoders + }; +} + +function decodeTuple(f, decoders) +{ + return { + ctor: '', + tag: 'tuple', + func: f, + decoders: decoders + }; +} + +function andThen(decoder, callback) +{ + return { + ctor: '', + tag: 'andThen', + decoder: decoder, + callback: callback + }; +} + +function customAndThen(decoder, callback) +{ + return { + ctor: '', + tag: 'customAndThen', + decoder: decoder, + callback: callback + }; +} + +function oneOf(decoders) +{ + return { + ctor: '', + tag: 'oneOf', + decoders: decoders + }; +} + + +// DECODING OBJECTS + +function decodeObject1(f, d1) +{ + return decodeObject(f, [d1]); +} + +function decodeObject2(f, d1, d2) +{ + return decodeObject(f, [d1, d2]); +} + +function decodeObject3(f, d1, d2, d3) +{ + return decodeObject(f, [d1, d2, d3]); +} + +function decodeObject4(f, d1, d2, d3, d4) +{ + return decodeObject(f, [d1, d2, d3, d4]); +} + +function decodeObject5(f, d1, d2, d3, d4, d5) +{ + return decodeObject(f, [d1, d2, d3, d4, d5]); +} + +function decodeObject6(f, d1, d2, d3, d4, d5, d6) +{ + return decodeObject(f, [d1, d2, d3, d4, d5, d6]); +} + +function decodeObject7(f, d1, d2, d3, d4, d5, d6, d7) +{ + return decodeObject(f, [d1, d2, d3, d4, d5, d6, d7]); +} + +function decodeObject8(f, d1, d2, d3, d4, d5, d6, d7, d8) +{ + return decodeObject(f, [d1, d2, d3, d4, d5, d6, d7, d8]); +} + + +// DECODING TUPLES + +function decodeTuple1(f, d1) +{ + return decodeTuple(f, [d1]); +} + +function decodeTuple2(f, d1, d2) +{ + return decodeTuple(f, [d1, d2]); +} + +function decodeTuple3(f, d1, d2, d3) +{ + return decodeTuple(f, [d1, d2, d3]); +} + +function decodeTuple4(f, d1, d2, d3, d4) +{ + return decodeTuple(f, [d1, d2, d3, d4]); +} + +function decodeTuple5(f, d1, d2, d3, d4, d5) +{ + return decodeTuple(f, [d1, d2, d3, d4, d5]); +} + +function decodeTuple6(f, d1, d2, d3, d4, d5, d6) +{ + return decodeTuple(f, [d1, d2, d3, d4, d5, d6]); +} + +function decodeTuple7(f, d1, d2, d3, d4, d5, d6, d7) +{ + return decodeTuple(f, [d1, d2, d3, d4, d5, d6, d7]); +} + +function decodeTuple8(f, d1, d2, d3, d4, d5, d6, d7, d8) +{ + return decodeTuple(f, [d1, d2, d3, d4, d5, d6, d7, d8]); +} + + +// DECODE HELPERS + +function ok(value) +{ + return { tag: 'ok', value: value }; +} + +function badPrimitive(type, value) +{ + return { tag: 'primitive', type: type, value: value }; +} + +function badIndex(index, nestedProblems) +{ + return { tag: 'index', index: index, rest: nestedProblems }; +} + +function badField(field, nestedProblems) +{ + return { tag: 'field', field: field, rest: nestedProblems }; +} + +function badOneOf(problems) +{ + return { tag: 'oneOf', problems: problems }; +} + +function bad(msg) +{ + return { tag: 'fail', msg: msg }; +} + +function badToString(problem) +{ + var context = '_'; + while (problem) + { + switch (problem.tag) + { + case 'primitive': + return 'Expecting ' + problem.type + + (context === '_' ? '' : ' at ' + context) + + ' but instead got: ' + jsToString(problem.value); + + case 'index': + context += '[' + problem.index + ']'; + problem = problem.rest; + break; + + case 'field': + context += '.' + problem.field; + problem = problem.rest; + break; + + case 'oneOf': + var problems = problem.problems; + for (var i = 0; i < problems.length; i++) + { + problems[i] = badToString(problems[i]); + } + return 'I ran into the following problems' + + (context === '_' ? '' : ' at ' + context) + + ':\n\n' + problems.join('\n'); + + case 'fail': + return 'I ran into a `fail` decoder' + + (context === '_' ? '' : ' at ' + context) + + ': ' + problem.msg; + } + } +} + +function jsToString(value) +{ + return value === undefined + ? 'undefined' + : JSON.stringify(value); +} + + +// DECODE + +function runOnString(decoder, string) +{ + var json; + try + { + json = JSON.parse(string); + } + catch (e) + { + return _elm_lang$core$Result$Err('Given an invalid JSON: ' + e.message); + } + return run(decoder, json); +} + +function run(decoder, value) +{ + var result = runHelp(decoder, value); + return (result.tag === 'ok') + ? _elm_lang$core$Result$Ok(result.value) + : _elm_lang$core$Result$Err(badToString(result)); +} + +function runHelp(decoder, value) +{ + switch (decoder.tag) + { + case 'bool': + return (typeof value === 'boolean') + ? ok(value) + : badPrimitive('a Bool', value); + + case 'int': + if (typeof value !== 'number') { + return badPrimitive('an Int', value); + } + + if (-2147483647 < value && value < 2147483647 && (value | 0) === value) { + return ok(value); + } + + if (isFinite(value) && !(value % 1)) { + return ok(value); + } + + return badPrimitive('an Int', value); + + case 'float': + return (typeof value === 'number') + ? ok(value) + : badPrimitive('a Float', value); + + case 'string': + return (typeof value === 'string') + ? ok(value) + : (value instanceof String) + ? ok(value + '') + : badPrimitive('a String', value); + + case 'null': + return (value === null) + ? ok(decoder.value) + : badPrimitive('null', value); + + case 'value': + return ok(value); + + case 'list': + if (!(value instanceof Array)) + { + return badPrimitive('a List', value); + } + + var list = _elm_lang$core$Native_List.Nil; + for (var i = value.length; i--; ) + { + var result = runHelp(decoder.decoder, value[i]); + if (result.tag !== 'ok') + { + return badIndex(i, result) + } + list = _elm_lang$core$Native_List.Cons(result.value, list); + } + return ok(list); + + case 'array': + if (!(value instanceof Array)) + { + return badPrimitive('an Array', value); + } + + var len = value.length; + var array = new Array(len); + for (var i = len; i--; ) + { + var result = runHelp(decoder.decoder, value[i]); + if (result.tag !== 'ok') + { + return badIndex(i, result); + } + array[i] = result.value; + } + return ok(_elm_lang$core$Native_Array.fromJSArray(array)); + + case 'maybe': + var result = runHelp(decoder.decoder, value); + return (result.tag === 'ok') + ? ok(_elm_lang$core$Maybe$Just(result.value)) + : ok(_elm_lang$core$Maybe$Nothing); + + case 'field': + var field = decoder.field; + if (typeof value !== 'object' || value === null || !(field in value)) + { + return badPrimitive('an object with a field named `' + field + '`', value); + } + + var result = runHelp(decoder.decoder, value[field]); + return (result.tag === 'ok') + ? result + : badField(field, result); + + case 'key-value': + if (typeof value !== 'object' || value === null || value instanceof Array) + { + return badPrimitive('an object', value); + } + + var keyValuePairs = _elm_lang$core$Native_List.Nil; + for (var key in value) + { + var result = runHelp(decoder.decoder, value[key]); + if (result.tag !== 'ok') + { + return badField(key, result); + } + var pair = _elm_lang$core$Native_Utils.Tuple2(key, result.value); + keyValuePairs = _elm_lang$core$Native_List.Cons(pair, keyValuePairs); + } + return ok(keyValuePairs); + + case 'map-many': + var answer = decoder.func; + var decoders = decoder.decoders; + for (var i = 0; i < decoders.length; i++) + { + var result = runHelp(decoders[i], value); + if (result.tag !== 'ok') + { + return result; + } + answer = answer(result.value); + } + return ok(answer); + + case 'tuple': + var decoders = decoder.decoders; + var len = decoders.length; + + if ( !(value instanceof Array) || value.length !== len ) + { + return badPrimitive('a Tuple with ' + len + ' entries', value); + } + + var answer = decoder.func; + for (var i = 0; i < len; i++) + { + var result = runHelp(decoders[i], value[i]); + if (result.tag !== 'ok') + { + return badIndex(i, result); + } + answer = answer(result.value); + } + return ok(answer); + + case 'customAndThen': + var result = runHelp(decoder.decoder, value); + if (result.tag !== 'ok') + { + return result; + } + var realResult = decoder.callback(result.value); + if (realResult.ctor === 'Err') + { + return badPrimitive('something custom', value); + } + return ok(realResult._0); + + case 'andThen': + var result = runHelp(decoder.decoder, value); + return (result.tag !== 'ok') + ? result + : runHelp(decoder.callback(result.value), value); + + case 'oneOf': + var errors = []; + var temp = decoder.decoders; + while (temp.ctor !== '[]') + { + var result = runHelp(temp._0, value); + + if (result.tag === 'ok') + { + return result; + } + + errors.push(result); + + temp = temp._1; + } + return badOneOf(errors); + + case 'fail': + return bad(decoder.msg); + + case 'succeed': + return ok(decoder.msg); + } +} + + +// EQUALITY + +function equality(a, b) +{ + if (a === b) + { + return true; + } + + if (a.tag !== b.tag) + { + return false; + } + + switch (a.tag) + { + case 'succeed': + case 'fail': + return a.msg === b.msg; + + case 'bool': + case 'int': + case 'float': + case 'string': + case 'value': + return true; + + case 'null': + return a.value === b.value; + + case 'list': + case 'array': + case 'maybe': + case 'key-value': + return equality(a.decoder, b.decoder); + + case 'field': + return a.field === b.field && equality(a.decoder, b.decoder); + + case 'map-many': + case 'tuple': + if (a.func !== b.func) + { + return false; + } + return listEquality(a.decoders, b.decoders); + + case 'andThen': + case 'customAndThen': + return a.callback === b.callback && equality(a.decoder, b.decoder); + + case 'oneOf': + return listEquality(a.decoders, b.decoders); + } +} + +function listEquality(aDecoders, bDecoders) +{ + var len = aDecoders.length; + if (len !== bDecoders.length) + { + return false; + } + for (var i = 0; i < len; i++) + { + if (!equality(aDecoders[i], bDecoders[i])) + { + return false; + } + } + return true; +} + + +// ENCODE + +function encode(indentLevel, value) +{ + return JSON.stringify(value, null, indentLevel); +} + +function identity(value) +{ + return value; +} + +function encodeObject(keyValuePairs) +{ + var obj = {}; + while (keyValuePairs.ctor !== '[]') + { + var pair = keyValuePairs._0; + obj[pair._0] = pair._1; + keyValuePairs = keyValuePairs._1; + } + return obj; +} + +return { + encode: F2(encode), + runOnString: F2(runOnString), + run: F2(run), + + decodeNull: decodeNull, + decodePrimitive: decodePrimitive, + decodeContainer: F2(decodeContainer), + + decodeField: F2(decodeField), + + decodeObject1: F2(decodeObject1), + decodeObject2: F3(decodeObject2), + decodeObject3: F4(decodeObject3), + decodeObject4: F5(decodeObject4), + decodeObject5: F6(decodeObject5), + decodeObject6: F7(decodeObject6), + decodeObject7: F8(decodeObject7), + decodeObject8: F9(decodeObject8), + decodeKeyValuePairs: decodeKeyValuePairs, + + decodeTuple1: F2(decodeTuple1), + decodeTuple2: F3(decodeTuple2), + decodeTuple3: F4(decodeTuple3), + decodeTuple4: F5(decodeTuple4), + decodeTuple5: F6(decodeTuple5), + decodeTuple6: F7(decodeTuple6), + decodeTuple7: F8(decodeTuple7), + decodeTuple8: F9(decodeTuple8), + + andThen: F2(andThen), + customAndThen: F2(customAndThen), + fail: fail, + succeed: succeed, + oneOf: oneOf, + + identity: identity, + encodeNull: null, + encodeArray: _elm_lang$core$Native_Array.toJSArray, + encodeList: _elm_lang$core$Native_List.toArray, + encodeObject: encodeObject, + + equality: equality +}; + +}(); + +var _elm_lang$core$Json_Encode$list = _elm_lang$core$Native_Json.encodeList; +var _elm_lang$core$Json_Encode$array = _elm_lang$core$Native_Json.encodeArray; +var _elm_lang$core$Json_Encode$object = _elm_lang$core$Native_Json.encodeObject; +var _elm_lang$core$Json_Encode$null = _elm_lang$core$Native_Json.encodeNull; +var _elm_lang$core$Json_Encode$bool = _elm_lang$core$Native_Json.identity; +var _elm_lang$core$Json_Encode$float = _elm_lang$core$Native_Json.identity; +var _elm_lang$core$Json_Encode$int = _elm_lang$core$Native_Json.identity; +var _elm_lang$core$Json_Encode$string = _elm_lang$core$Native_Json.identity; +var _elm_lang$core$Json_Encode$encode = _elm_lang$core$Native_Json.encode; +var _elm_lang$core$Json_Encode$Value = {ctor: 'Value'}; + +var _elm_lang$core$Json_Decode$tuple8 = _elm_lang$core$Native_Json.decodeTuple8; +var _elm_lang$core$Json_Decode$tuple7 = _elm_lang$core$Native_Json.decodeTuple7; +var _elm_lang$core$Json_Decode$tuple6 = _elm_lang$core$Native_Json.decodeTuple6; +var _elm_lang$core$Json_Decode$tuple5 = _elm_lang$core$Native_Json.decodeTuple5; +var _elm_lang$core$Json_Decode$tuple4 = _elm_lang$core$Native_Json.decodeTuple4; +var _elm_lang$core$Json_Decode$tuple3 = _elm_lang$core$Native_Json.decodeTuple3; +var _elm_lang$core$Json_Decode$tuple2 = _elm_lang$core$Native_Json.decodeTuple2; +var _elm_lang$core$Json_Decode$tuple1 = _elm_lang$core$Native_Json.decodeTuple1; +var _elm_lang$core$Json_Decode$succeed = _elm_lang$core$Native_Json.succeed; +var _elm_lang$core$Json_Decode$fail = _elm_lang$core$Native_Json.fail; +var _elm_lang$core$Json_Decode$andThen = _elm_lang$core$Native_Json.andThen; +var _elm_lang$core$Json_Decode$customDecoder = _elm_lang$core$Native_Json.customAndThen; +var _elm_lang$core$Json_Decode$decodeValue = _elm_lang$core$Native_Json.run; +var _elm_lang$core$Json_Decode$value = _elm_lang$core$Native_Json.decodePrimitive('value'); +var _elm_lang$core$Json_Decode$maybe = function (decoder) { + return A2(_elm_lang$core$Native_Json.decodeContainer, 'maybe', decoder); +}; +var _elm_lang$core$Json_Decode$null = _elm_lang$core$Native_Json.decodeNull; +var _elm_lang$core$Json_Decode$array = function (decoder) { + return A2(_elm_lang$core$Native_Json.decodeContainer, 'array', decoder); +}; +var _elm_lang$core$Json_Decode$list = function (decoder) { + return A2(_elm_lang$core$Native_Json.decodeContainer, 'list', decoder); +}; +var _elm_lang$core$Json_Decode$bool = _elm_lang$core$Native_Json.decodePrimitive('bool'); +var _elm_lang$core$Json_Decode$int = _elm_lang$core$Native_Json.decodePrimitive('int'); +var _elm_lang$core$Json_Decode$float = _elm_lang$core$Native_Json.decodePrimitive('float'); +var _elm_lang$core$Json_Decode$string = _elm_lang$core$Native_Json.decodePrimitive('string'); +var _elm_lang$core$Json_Decode$oneOf = _elm_lang$core$Native_Json.oneOf; +var _elm_lang$core$Json_Decode$keyValuePairs = _elm_lang$core$Native_Json.decodeKeyValuePairs; +var _elm_lang$core$Json_Decode$object8 = _elm_lang$core$Native_Json.decodeObject8; +var _elm_lang$core$Json_Decode$object7 = _elm_lang$core$Native_Json.decodeObject7; +var _elm_lang$core$Json_Decode$object6 = _elm_lang$core$Native_Json.decodeObject6; +var _elm_lang$core$Json_Decode$object5 = _elm_lang$core$Native_Json.decodeObject5; +var _elm_lang$core$Json_Decode$object4 = _elm_lang$core$Native_Json.decodeObject4; +var _elm_lang$core$Json_Decode$object3 = _elm_lang$core$Native_Json.decodeObject3; +var _elm_lang$core$Json_Decode$object2 = _elm_lang$core$Native_Json.decodeObject2; +var _elm_lang$core$Json_Decode$object1 = _elm_lang$core$Native_Json.decodeObject1; +var _elm_lang$core$Json_Decode_ops = _elm_lang$core$Json_Decode_ops || {}; +_elm_lang$core$Json_Decode_ops[':='] = _elm_lang$core$Native_Json.decodeField; +var _elm_lang$core$Json_Decode$at = F2( + function (fields, decoder) { + return A3( + _elm_lang$core$List$foldr, + F2( + function (x, y) { + return A2(_elm_lang$core$Json_Decode_ops[':='], x, y); + }), + decoder, + fields); + }); +var _elm_lang$core$Json_Decode$decodeString = _elm_lang$core$Native_Json.runOnString; +var _elm_lang$core$Json_Decode$map = _elm_lang$core$Native_Json.decodeObject1; +var _elm_lang$core$Json_Decode$dict = function (decoder) { + return A2( + _elm_lang$core$Json_Decode$map, + _elm_lang$core$Dict$fromList, + _elm_lang$core$Json_Decode$keyValuePairs(decoder)); +}; +var _elm_lang$core$Json_Decode$Decoder = {ctor: 'Decoder'}; + +//import Native.Json // + +var _elm_lang$virtual_dom$Native_VirtualDom = function() { + +var STYLE_KEY = 'STYLE'; +var EVENT_KEY = 'EVENT'; +var ATTR_KEY = 'ATTR'; +var ATTR_NS_KEY = 'ATTR_NS'; + + + +//////////// VIRTUAL DOM NODES //////////// + + +function text(string) +{ + return { + type: 'text', + text: string + }; +} + + +function node(tag) +{ + return F2(function(factList, kidList) { + return nodeHelp(tag, factList, kidList); + }); +} + + +function nodeHelp(tag, factList, kidList) +{ + var organized = organizeFacts(factList); + var namespace = organized.namespace; + var facts = organized.facts; + + var children = []; + var descendantsCount = 0; + while (kidList.ctor !== '[]') + { + var kid = kidList._0; + descendantsCount += (kid.descendantsCount || 0); + children.push(kid); + kidList = kidList._1; + } + descendantsCount += children.length; + + return { + type: 'node', + tag: tag, + facts: facts, + children: children, + namespace: namespace, + descendantsCount: descendantsCount + }; +} + + +function keyedNode(tag, factList, kidList) +{ + var organized = organizeFacts(factList); + var namespace = organized.namespace; + var facts = organized.facts; + + var children = []; + var descendantsCount = 0; + while (kidList.ctor !== '[]') + { + var kid = kidList._0; + descendantsCount += (kid._1.descendantsCount || 0); + children.push(kid); + kidList = kidList._1; + } + descendantsCount += children.length; + + return { + type: 'keyed-node', + tag: tag, + facts: facts, + children: children, + namespace: namespace, + descendantsCount: descendantsCount + }; +} + + +function custom(factList, model, impl) +{ + var facts = organizeFacts(factList).facts; + + return { + type: 'custom', + facts: facts, + model: model, + impl: impl + }; +} + + +function map(tagger, node) +{ + return { + type: 'tagger', + tagger: tagger, + node: node, + descendantsCount: 1 + (node.descendantsCount || 0) + }; +} + + +function thunk(func, args, thunk) +{ + return { + type: 'thunk', + func: func, + args: args, + thunk: thunk, + node: undefined + }; +} + +function lazy(fn, a) +{ + return thunk(fn, [a], function() { + return fn(a); + }); +} + +function lazy2(fn, a, b) +{ + return thunk(fn, [a,b], function() { + return A2(fn, a, b); + }); +} + +function lazy3(fn, a, b, c) +{ + return thunk(fn, [a,b,c], function() { + return A3(fn, a, b, c); + }); +} + + + +// FACTS + + +function organizeFacts(factList) +{ + var namespace, facts = {}; + + while (factList.ctor !== '[]') + { + var entry = factList._0; + var key = entry.key; + + if (key === ATTR_KEY || key === ATTR_NS_KEY || key === EVENT_KEY) + { + var subFacts = facts[key] || {}; + subFacts[entry.realKey] = entry.value; + facts[key] = subFacts; + } + else if (key === STYLE_KEY) + { + var styles = facts[key] || {}; + var styleList = entry.value; + while (styleList.ctor !== '[]') + { + var style = styleList._0; + styles[style._0] = style._1; + styleList = styleList._1; + } + facts[key] = styles; + } + else if (key === 'namespace') + { + namespace = entry.value; + } + else + { + facts[key] = entry.value; + } + factList = factList._1; + } + + return { + facts: facts, + namespace: namespace + }; +} + + + +//////////// PROPERTIES AND ATTRIBUTES //////////// + + +function style(value) +{ + return { + key: STYLE_KEY, + value: value + }; +} + + +function property(key, value) +{ + return { + key: key, + value: value + }; +} + + +function attribute(key, value) +{ + return { + key: ATTR_KEY, + realKey: key, + value: value + }; +} + + +function attributeNS(namespace, key, value) +{ + return { + key: ATTR_NS_KEY, + realKey: key, + value: { + value: value, + namespace: namespace + } + }; +} + + +function on(name, options, decoder) +{ + return { + key: EVENT_KEY, + realKey: name, + value: { + options: options, + decoder: decoder + } + }; +} + + +function equalEvents(a, b) +{ + if (!a.options === b.options) + { + if (a.stopPropagation !== b.stopPropagation || a.preventDefault !== b.preventDefault) + { + return false; + } + } + return _elm_lang$core$Native_Json.equality(a.decoder, b.decoder); +} + + + +//////////// RENDERER //////////// + + +function renderer(parent, tagger, initialVirtualNode) +{ + var eventNode = { tagger: tagger, parent: undefined }; + + var domNode = render(initialVirtualNode, eventNode); + parent.appendChild(domNode); + + var state = 'NO_REQUEST'; + var currentVirtualNode = initialVirtualNode; + var nextVirtualNode = initialVirtualNode; + + function registerVirtualNode(nextVirtualNode) + { + var patches = diff(currentVirtualNode, nextVirtualNode); + domNode = applyPatches(domNode, currentVirtualNode, patches, eventNode); + currentVirtualNode = nextVirtualNode; + } + + return { update: registerVirtualNode }; +} + + +var rAF = + typeof requestAnimationFrame !== 'undefined' + ? requestAnimationFrame + : function(cb) { setTimeout(cb, 1000 / 60); }; + + + +//////////// RENDER //////////// + + +function render(vNode, eventNode) +{ + switch (vNode.type) + { + case 'thunk': + if (!vNode.node) + { + vNode.node = vNode.thunk(); + } + return render(vNode.node, eventNode); + + case 'tagger': + var subNode = vNode.node; + var tagger = vNode.tagger; + + while (subNode.type === 'tagger') + { + typeof tagger !== 'object' + ? tagger = [tagger, subNode.tagger] + : tagger.push(subNode.tagger); + + subNode = subNode.node; + } + + var subEventRoot = { + tagger: tagger, + parent: eventNode + }; + + var domNode = render(subNode, subEventRoot); + domNode.elm_event_node_ref = subEventRoot; + return domNode; + + case 'text': + return document.createTextNode(vNode.text); + + case 'node': + var domNode = vNode.namespace + ? document.createElementNS(vNode.namespace, vNode.tag) + : document.createElement(vNode.tag); + + applyFacts(domNode, eventNode, vNode.facts); + + var children = vNode.children; + + for (var i = 0; i < children.length; i++) + { + domNode.appendChild(render(children[i], eventNode)); + } + + return domNode; + + case 'keyed-node': + var domNode = vNode.namespace + ? document.createElementNS(vNode.namespace, vNode.tag) + : document.createElement(vNode.tag); + + applyFacts(domNode, eventNode, vNode.facts); + + var children = vNode.children; + + for (var i = 0; i < children.length; i++) + { + domNode.appendChild(render(children[i]._1, eventNode)); + } + + return domNode; + + case 'custom': + var domNode = vNode.impl.render(vNode.model); + applyFacts(domNode, eventNode, vNode.facts); + return domNode; + } +} + + + +//////////// APPLY FACTS //////////// + + +function applyFacts(domNode, eventNode, facts) +{ + for (var key in facts) + { + var value = facts[key]; + + switch (key) + { + case STYLE_KEY: + applyStyles(domNode, value); + break; + + case EVENT_KEY: + applyEvents(domNode, eventNode, value); + break; + + case ATTR_KEY: + applyAttrs(domNode, value); + break; + + case ATTR_NS_KEY: + applyAttrsNS(domNode, value); + break; + + case 'value': + if (domNode[key] !== value) + { + domNode[key] = value; + } + break; + + default: + domNode[key] = value; + break; + } + } +} + +function applyStyles(domNode, styles) +{ + var domNodeStyle = domNode.style; + + for (var key in styles) + { + domNodeStyle[key] = styles[key]; + } +} + +function applyEvents(domNode, eventNode, events) +{ + var allHandlers = domNode.elm_handlers || {}; + + for (var key in events) + { + var handler = allHandlers[key]; + var value = events[key]; + + if (typeof value === 'undefined') + { + domNode.removeEventListener(key, handler); + allHandlers[key] = undefined; + } + else if (typeof handler === 'undefined') + { + var handler = makeEventHandler(eventNode, value); + domNode.addEventListener(key, handler); + allHandlers[key] = handler; + } + else + { + handler.info = value; + } + } + + domNode.elm_handlers = allHandlers; +} + +function makeEventHandler(eventNode, info) +{ + function eventHandler(event) + { + var info = eventHandler.info; + + var value = A2(_elm_lang$core$Native_Json.run, info.decoder, event); + + if (value.ctor === 'Ok') + { + var options = info.options; + if (options.stopPropagation) + { + event.stopPropagation(); + } + if (options.preventDefault) + { + event.preventDefault(); + } + + var message = value._0; + + var currentEventNode = eventNode; + while (currentEventNode) + { + var tagger = currentEventNode.tagger; + if (typeof tagger === 'function') + { + message = tagger(message); + } + else + { + for (var i = tagger.length; i--; ) + { + message = tagger[i](message); + } + } + currentEventNode = currentEventNode.parent; + } + } + }; + + eventHandler.info = info; + + return eventHandler; +} + +function applyAttrs(domNode, attrs) +{ + for (var key in attrs) + { + var value = attrs[key]; + if (typeof value === 'undefined') + { + domNode.removeAttribute(key); + } + else + { + domNode.setAttribute(key, value); + } + } +} + +function applyAttrsNS(domNode, nsAttrs) +{ + for (var key in nsAttrs) + { + var pair = nsAttrs[key]; + var namespace = pair.namespace; + var value = pair.value; + + if (typeof value === 'undefined') + { + domNode.removeAttributeNS(namespace, key); + } + else + { + domNode.setAttributeNS(namespace, key, value); + } + } +} + + + +//////////// DIFF //////////// + + +function diff(a, b) +{ + var patches = []; + diffHelp(a, b, patches, 0); + return patches; +} + + +function makePatch(type, index, data) +{ + return { + index: index, + type: type, + data: data, + domNode: undefined, + eventNode: undefined + }; +} + + +function diffHelp(a, b, patches, index) +{ + if (a === b) + { + return; + } + + var aType = a.type; + var bType = b.type; + + // Bail if you run into different types of nodes. Implies that the + // structure has changed significantly and it's not worth a diff. + if (aType !== bType) + { + patches.push(makePatch('p-redraw', index, b)); + return; + } + + // Now we know that both nodes are the same type. + switch (bType) + { + case 'thunk': + var aArgs = a.args; + var bArgs = b.args; + var i = aArgs.length; + var same = a.func === b.func && i === bArgs.length; + while (same && i--) + { + same = aArgs[i] === bArgs[i]; + } + if (same) + { + b.node = a.node; + return; + } + b.node = b.thunk(); + var subPatches = []; + diffHelp(a.node, b.node, subPatches, 0); + if (subPatches.length > 0) + { + patches.push(makePatch('p-thunk', index, subPatches)); + } + return; + + case 'tagger': + // gather nested taggers + var aTaggers = a.tagger; + var bTaggers = b.tagger; + var nesting = false; + + var aSubNode = a.node; + while (aSubNode.type === 'tagger') + { + nesting = true; + + typeof aTaggers !== 'object' + ? aTaggers = [aTaggers, aSubNode.tagger] + : aTaggers.push(aSubNode.tagger); + + aSubNode = aSubNode.node; + } + + var bSubNode = b.node; + while (bSubNode.type === 'tagger') + { + nesting = true; + + typeof bTaggers !== 'object' + ? bTaggers = [bTaggers, bSubNode.tagger] + : bTaggers.push(bSubNode.tagger); + + bSubNode = bSubNode.node; + } + + // Just bail if different numbers of taggers. This implies the + // structure of the virtual DOM has changed. + if (nesting && aTaggers.length !== bTaggers.length) + { + patches.push(makePatch('p-redraw', index, b)); + return; + } + + // check if taggers are "the same" + if (nesting ? !pairwiseRefEqual(aTaggers, bTaggers) : aTaggers !== bTaggers) + { + patches.push(makePatch('p-tagger', index, bTaggers)); + } + + // diff everything below the taggers + diffHelp(aSubNode, bSubNode, patches, index + 1); + return; + + case 'text': + if (a.text !== b.text) + { + patches.push(makePatch('p-text', index, b.text)); + return; + } + + return; + + case 'node': + // Bail if obvious indicators have changed. Implies more serious + // structural changes such that it's not worth it to diff. + if (a.tag !== b.tag || a.namespace !== b.namespace) + { + patches.push(makePatch('p-redraw', index, b)); + return; + } + + var factsDiff = diffFacts(a.facts, b.facts); + + if (typeof factsDiff !== 'undefined') + { + patches.push(makePatch('p-facts', index, factsDiff)); + } + + diffChildren(a, b, patches, index); + return; + + case 'keyed-node': + // Bail if obvious indicators have changed. Implies more serious + // structural changes such that it's not worth it to diff. + if (a.tag !== b.tag || a.namespace !== b.namespace) + { + patches.push(makePatch('p-redraw', index, b)); + return; + } + + var factsDiff = diffFacts(a.facts, b.facts); + + if (typeof factsDiff !== 'undefined') + { + patches.push(makePatch('p-facts', index, factsDiff)); + } + + diffKeyedChildren(a, b, patches, index); + return; + + case 'custom': + if (a.impl !== b.impl) + { + patches.push(makePatch('p-redraw', index, b)); + return; + } + + var factsDiff = diffFacts(a.facts, b.facts); + if (typeof factsDiff !== 'undefined') + { + patches.push(makePatch('p-facts', index, factsDiff)); + } + + var patch = b.impl.diff(a,b); + if (patch) + { + patches.push(makePatch('p-custom', index, patch)); + return; + } + + return; + } +} + + +// assumes the incoming arrays are the same length +function pairwiseRefEqual(as, bs) +{ + for (var i = 0; i < as.length; i++) + { + if (as[i] !== bs[i]) + { + return false; + } + } + + return true; +} + + +// TODO Instead of creating a new diff object, it's possible to just test if +// there *is* a diff. During the actual patch, do the diff again and make the +// modifications directly. This way, there's no new allocations. Worth it? +function diffFacts(a, b, category) +{ + var diff; + + // look for changes and removals + for (var aKey in a) + { + if (aKey === STYLE_KEY || aKey === EVENT_KEY || aKey === ATTR_KEY || aKey === ATTR_NS_KEY) + { + var subDiff = diffFacts(a[aKey], b[aKey] || {}, aKey); + if (subDiff) + { + diff = diff || {}; + diff[aKey] = subDiff; + } + continue; + } + + // remove if not in the new facts + if (!(aKey in b)) + { + diff = diff || {}; + diff[aKey] = + (typeof category === 'undefined') + ? (typeof a[aKey] === 'string' ? '' : null) + : + (category === STYLE_KEY) + ? '' + : + (category === EVENT_KEY || category === ATTR_KEY) + ? undefined + : + { namespace: a[aKey].namespace, value: undefined }; + + continue; + } + + var aValue = a[aKey]; + var bValue = b[aKey]; + + // reference equal, so don't worry about it + if (aValue === bValue && aKey !== 'value' + || category === EVENT_KEY && equalEvents(aValue, bValue)) + { + continue; + } + + diff = diff || {}; + diff[aKey] = bValue; + } + + // add new stuff + for (var bKey in b) + { + if (!(bKey in a)) + { + diff = diff || {}; + diff[bKey] = b[bKey]; + } + } + + return diff; +} + + +function diffChildren(aParent, bParent, patches, rootIndex) +{ + var aChildren = aParent.children; + var bChildren = bParent.children; + + var aLen = aChildren.length; + var bLen = bChildren.length; + + // FIGURE OUT IF THERE ARE INSERTS OR REMOVALS + + if (aLen > bLen) + { + patches.push(makePatch('p-remove-last', rootIndex, aLen - bLen)); + } + else if (aLen < bLen) + { + patches.push(makePatch('p-append', rootIndex, bChildren.slice(aLen))); + } + + // PAIRWISE DIFF EVERYTHING ELSE + + var index = rootIndex; + var minLen = aLen < bLen ? aLen : bLen; + for (var i = 0; i < minLen; i++) + { + index++; + var aChild = aChildren[i]; + diffHelp(aChild, bChildren[i], patches, index); + index += aChild.descendantsCount || 0; + } +} + + + +//////////// KEYED DIFF //////////// + + +function diffKeyedChildren(aParent, bParent, patches, rootIndex) +{ + var localPatches = []; + + var changes = {}; // Dict String Entry + var inserts = []; // Array { index : Int, entry : Entry } + // type Entry = { tag : String, vnode : VNode, index : Int, data : _ } + + var aChildren = aParent.children; + var bChildren = bParent.children; + var aLen = aChildren.length; + var bLen = bChildren.length; + var aIndex = 0; + var bIndex = 0; + + var index = rootIndex; + + while (aIndex < aLen && bIndex < bLen) + { + var a = aChildren[aIndex]; + var b = bChildren[bIndex]; + + var aKey = a._0; + var bKey = b._0; + var aNode = a._1; + var bNode = b._1; + + // check if keys match + + if (aKey === bKey) + { + index++; + diffHelp(aNode, bNode, localPatches, index); + index += aNode.descendantsCount || 0; + + aIndex++; + bIndex++; + continue; + } + + // look ahead 1 to detect insertions and removals. + + var aLookAhead = aIndex + 1 < aLen; + var bLookAhead = bIndex + 1 < bLen; + + if (aLookAhead) + { + var aNext = aChildren[aIndex + 1]; + var aNextKey = aNext._0; + var aNextNode = aNext._1; + var oldMatch = bKey === aNextKey; + } + + if (bLookAhead) + { + var bNext = bChildren[bIndex + 1]; + var bNextKey = bNext._0; + var bNextNode = bNext._1; + var newMatch = aKey === bNextKey; + } + + + // swap a and b + if (aLookAhead && bLookAhead && newMatch && oldMatch) + { + index++; + diffHelp(aNode, bNextNode, localPatches, index); + insertNode(changes, localPatches, aKey, bNode, bIndex, inserts); + index += aNode.descendantsCount || 0; + + index++; + removeNode(changes, localPatches, aKey, aNextNode, index); + index += aNextNode.descendantsCount || 0; + + aIndex += 2; + bIndex += 2; + continue; + } + + // insert b + if (bLookAhead && newMatch) + { + index++; + insertNode(changes, localPatches, bKey, bNode, bIndex, inserts); + diffHelp(aNode, bNextNode, localPatches, index); + index += aNode.descendantsCount || 0; + + aIndex += 1; + bIndex += 2; + continue; + } + + // remove a + if (aLookAhead && oldMatch) + { + index++; + removeNode(changes, localPatches, aKey, aNode, index); + index += aNode.descendantsCount || 0; + + index++; + diffHelp(aNextNode, bNode, localPatches, index); + index += aNextNode.descendantsCount || 0; + + aIndex += 2; + bIndex += 1; + continue; + } + + // remove a, insert b + if (aLookAhead && bLookAhead && aNextKey === bNextKey) + { + index++; + removeNode(changes, localPatches, aKey, aNode, index); + insertNode(changes, localPatches, bKey, bNode, bIndex, inserts); + index += aNode.descendantsCount || 0; + + index++; + diffHelp(aNextNode, bNextNode, localPatches, index); + index += aNextNode.descendantsCount || 0; + + aIndex += 2; + bIndex += 2; + continue; + } + + break; + } + + // eat up any remaining nodes with removeNode and insertNode + + while (aIndex < aLen) + { + index++; + var a = aChildren[aIndex]; + var aNode = a._1; + removeNode(changes, localPatches, a._0, aNode, index); + index += aNode.descendantsCount || 0; + aIndex++; + } + + var endInserts; + while (bIndex < bLen) + { + endInserts = endInserts || []; + var b = bChildren[bIndex]; + insertNode(changes, localPatches, b._0, b._1, undefined, endInserts); + bIndex++; + } + + if (localPatches.length > 0 || inserts.length > 0 || typeof endInserts !== 'undefined') + { + patches.push(makePatch('p-reorder', rootIndex, { + patches: localPatches, + inserts: inserts, + endInserts: endInserts + })); + } +} + + + +//////////// CHANGES FROM KEYED DIFF //////////// + + +var POSTFIX = '_elmW6BL'; + + +function insertNode(changes, localPatches, key, vnode, bIndex, inserts) +{ + var entry = changes[key]; + + // never seen this key before + if (typeof entry === 'undefined') + { + entry = { + tag: 'insert', + vnode: vnode, + index: bIndex, + data: undefined + }; + + inserts.push({ index: bIndex, entry: entry }); + changes[key] = entry; + + return; + } + + // this key was removed earlier, a match! + if (entry.tag === 'remove') + { + inserts.push({ index: bIndex, entry: entry }); + + entry.tag = 'move'; + var subPatches = []; + diffHelp(entry.vnode, vnode, subPatches, entry.index); + entry.index = bIndex; + entry.data.data = { + patches: subPatches, + entry: entry + }; + + return; + } + + // this key has already been inserted or moved, a duplicate! + insertNode(changes, localPatches, key + POSTFIX, vnode, bIndex, inserts); +} + + +function removeNode(changes, localPatches, key, vnode, index) +{ + var entry = changes[key]; + + // never seen this key before + if (typeof entry === 'undefined') + { + var patch = makePatch('p-remove', index, undefined); + localPatches.push(patch); + + changes[key] = { + tag: 'remove', + vnode: vnode, + index: index, + data: patch + }; + + return; + } + + // this key was inserted earlier, a match! + if (entry.tag === 'insert') + { + entry.tag = 'move'; + var subPatches = []; + diffHelp(vnode, entry.vnode, subPatches, index); + + var patch = makePatch('p-remove', index, { + patches: subPatches, + entry: entry + }); + localPatches.push(patch); + + return; + } + + // this key has already been removed or moved, a duplicate! + removeNode(changes, localPatches, key + POSTFIX, vnode, index); +} + + + +//////////// ADD DOM NODES //////////// +// +// Each DOM node has an "index" assigned in order of traversal. It is important +// to minimize our crawl over the actual DOM, so these indexes (along with the +// descendantsCount of virtual nodes) let us skip touching entire subtrees of +// the DOM if we know there are no patches there. + + +function addDomNodes(domNode, vNode, patches, eventNode) +{ + addDomNodesHelp(domNode, vNode, patches, 0, 0, vNode.descendantsCount, eventNode); +} + + +// assumes `patches` is non-empty and indexes increase monotonically. +function addDomNodesHelp(domNode, vNode, patches, i, low, high, eventNode) +{ + var patch = patches[i]; + var index = patch.index; + + while (index === low) + { + var patchType = patch.type; + + if (patchType === 'p-thunk') + { + addDomNodes(domNode, vNode.node, patch.data, eventNode); + } + else if (patchType === 'p-reorder') + { + patch.domNode = domNode; + patch.eventNode = eventNode; + + var subPatches = patch.data.patches; + if (subPatches.length > 0) + { + addDomNodesHelp(domNode, vNode, subPatches, 0, low, high, eventNode); + } + } + else if (patchType === 'p-remove') + { + patch.domNode = domNode; + patch.eventNode = eventNode; + + var data = patch.data; + if (typeof data !== 'undefined') + { + data.entry.data = domNode; + var subPatches = data.patches; + if (subPatches.length > 0) + { + addDomNodesHelp(domNode, vNode, subPatches, 0, low, high, eventNode); + } + } + } + else + { + patch.domNode = domNode; + patch.eventNode = eventNode; + } + + i++; + + if (!(patch = patches[i]) || (index = patch.index) > high) + { + return i; + } + } + + switch (vNode.type) + { + case 'tagger': + var subNode = vNode.node; + + while (subNode.type === "tagger") + { + subNode = subNode.node; + } + + return addDomNodesHelp(domNode, subNode, patches, i, low + 1, high, domNode.elm_event_node_ref); + + case 'node': + var vChildren = vNode.children; + var childNodes = domNode.childNodes; + for (var j = 0; j < vChildren.length; j++) + { + low++; + var vChild = vChildren[j]; + var nextLow = low + (vChild.descendantsCount || 0); + if (low <= index && index <= nextLow) + { + i = addDomNodesHelp(childNodes[j], vChild, patches, i, low, nextLow, eventNode); + if (!(patch = patches[i]) || (index = patch.index) > high) + { + return i; + } + } + low = nextLow; + } + return i; + + case 'keyed-node': + var vChildren = vNode.children; + var childNodes = domNode.childNodes; + for (var j = 0; j < vChildren.length; j++) + { + low++; + var vChild = vChildren[j]._1; + var nextLow = low + (vChild.descendantsCount || 0); + if (low <= index && index <= nextLow) + { + i = addDomNodesHelp(childNodes[j], vChild, patches, i, low, nextLow, eventNode); + if (!(patch = patches[i]) || (index = patch.index) > high) + { + return i; + } + } + low = nextLow; + } + return i; + + case 'text': + case 'thunk': + throw new Error('should never traverse `text` or `thunk` nodes like this'); + } +} + + + +//////////// APPLY PATCHES //////////// + + +function applyPatches(rootDomNode, oldVirtualNode, patches, eventNode) +{ + if (patches.length === 0) + { + return rootDomNode; + } + + addDomNodes(rootDomNode, oldVirtualNode, patches, eventNode); + return applyPatchesHelp(rootDomNode, patches); +} + +function applyPatchesHelp(rootDomNode, patches) +{ + for (var i = 0; i < patches.length; i++) + { + var patch = patches[i]; + var localDomNode = patch.domNode + var newNode = applyPatch(localDomNode, patch); + if (localDomNode === rootDomNode) + { + rootDomNode = newNode; + } + } + return rootDomNode; +} + +function applyPatch(domNode, patch) +{ + switch (patch.type) + { + case 'p-redraw': + return redraw(domNode, patch.data, patch.eventNode); + + case 'p-facts': + applyFacts(domNode, patch.eventNode, patch.data); + return domNode; + + case 'p-text': + domNode.replaceData(0, domNode.length, patch.data); + return domNode; + + case 'p-thunk': + return applyPatchesHelp(domNode, patch.data); + + case 'p-tagger': + domNode.elm_event_node_ref.tagger = patch.data; + return domNode; + + case 'p-remove-last': + var i = patch.data; + while (i--) + { + domNode.removeChild(domNode.lastChild); + } + return domNode; + + case 'p-append': + var newNodes = patch.data; + for (var i = 0; i < newNodes.length; i++) + { + domNode.appendChild(render(newNodes[i], patch.eventNode)); + } + return domNode; + + case 'p-remove': + var data = patch.data; + if (typeof data === 'undefined') + { + domNode.parentNode.removeChild(domNode); + return domNode; + } + var entry = data.entry; + if (typeof entry.index !== 'undefined') + { + domNode.parentNode.removeChild(domNode); + } + entry.data = applyPatchesHelp(domNode, data.patches); + return domNode; + + case 'p-reorder': + var data = patch.data; + + // end inserts + var endInserts = data.endInserts; + var end; + if (typeof endInserts !== 'undefined') + { + if (endInserts.length === 1) + { + var insert = endInserts[0]; + var entry = insert.entry; + var end = entry.tag === 'move' + ? entry.data + : render(entry.vnode, patch.eventNode); + } + else + { + end = document.createDocumentFragment(); + for (var i = 0; i < endInserts.length; i++) + { + var insert = endInserts[i]; + var entry = insert.entry; + var node = entry.tag === 'move' + ? entry.data + : render(entry.vnode, patch.eventNode); + end.appendChild(node); + } + } + } + + // removals + domNode = applyPatchesHelp(domNode, data.patches); + + // inserts + var inserts = data.inserts; + for (var i = 0; i < inserts.length; i++) + { + var insert = inserts[i]; + var entry = insert.entry; + var node = entry.tag === 'move' + ? entry.data + : render(entry.vnode, patch.eventNode); + domNode.insertBefore(node, domNode.childNodes[insert.index]); + } + + if (typeof end !== 'undefined') + { + domNode.appendChild(end); + } + + return domNode; + + case 'p-custom': + var impl = patch.data; + return impl.applyPatch(domNode, impl.data); + + default: + throw new Error('Ran into an unknown patch!'); + } +} + + +function redraw(domNode, vNode, eventNode) +{ + var parentNode = domNode.parentNode; + var newNode = render(vNode, eventNode); + + if (typeof newNode.elm_event_node_ref === 'undefined') + { + newNode.elm_event_node_ref = domNode.elm_event_node_ref; + } + + if (parentNode && newNode !== domNode) + { + parentNode.replaceChild(newNode, domNode); + } + return newNode; +} + + + +//////////// PROGRAMS //////////// + + +function programWithFlags(details) +{ + return { + init: details.init, + update: details.update, + subscriptions: details.subscriptions, + view: details.view, + renderer: renderer + }; +} + + +return { + node: node, + text: text, + + custom: custom, + + map: F2(map), + + on: F3(on), + style: style, + property: F2(property), + attribute: F2(attribute), + attributeNS: F3(attributeNS), + + lazy: F2(lazy), + lazy2: F3(lazy2), + lazy3: F4(lazy3), + keyedNode: F3(keyedNode), + + programWithFlags: programWithFlags +}; + +}(); +var _elm_lang$virtual_dom$VirtualDom$programWithFlags = _elm_lang$virtual_dom$Native_VirtualDom.programWithFlags; +var _elm_lang$virtual_dom$VirtualDom$keyedNode = _elm_lang$virtual_dom$Native_VirtualDom.keyedNode; +var _elm_lang$virtual_dom$VirtualDom$lazy3 = _elm_lang$virtual_dom$Native_VirtualDom.lazy3; +var _elm_lang$virtual_dom$VirtualDom$lazy2 = _elm_lang$virtual_dom$Native_VirtualDom.lazy2; +var _elm_lang$virtual_dom$VirtualDom$lazy = _elm_lang$virtual_dom$Native_VirtualDom.lazy; +var _elm_lang$virtual_dom$VirtualDom$defaultOptions = {stopPropagation: false, preventDefault: false}; +var _elm_lang$virtual_dom$VirtualDom$onWithOptions = _elm_lang$virtual_dom$Native_VirtualDom.on; +var _elm_lang$virtual_dom$VirtualDom$on = F2( + function (eventName, decoder) { + return A3(_elm_lang$virtual_dom$VirtualDom$onWithOptions, eventName, _elm_lang$virtual_dom$VirtualDom$defaultOptions, decoder); + }); +var _elm_lang$virtual_dom$VirtualDom$style = _elm_lang$virtual_dom$Native_VirtualDom.style; +var _elm_lang$virtual_dom$VirtualDom$attributeNS = _elm_lang$virtual_dom$Native_VirtualDom.attributeNS; +var _elm_lang$virtual_dom$VirtualDom$attribute = _elm_lang$virtual_dom$Native_VirtualDom.attribute; +var _elm_lang$virtual_dom$VirtualDom$property = _elm_lang$virtual_dom$Native_VirtualDom.property; +var _elm_lang$virtual_dom$VirtualDom$map = _elm_lang$virtual_dom$Native_VirtualDom.map; +var _elm_lang$virtual_dom$VirtualDom$text = _elm_lang$virtual_dom$Native_VirtualDom.text; +var _elm_lang$virtual_dom$VirtualDom$node = _elm_lang$virtual_dom$Native_VirtualDom.node; +var _elm_lang$virtual_dom$VirtualDom$Options = F2( + function (a, b) { + return {stopPropagation: a, preventDefault: b}; + }); +var _elm_lang$virtual_dom$VirtualDom$Node = {ctor: 'Node'}; +var _elm_lang$virtual_dom$VirtualDom$Property = {ctor: 'Property'}; + +var _elm_lang$html$Html$text = _elm_lang$virtual_dom$VirtualDom$text; +var _elm_lang$html$Html$node = _elm_lang$virtual_dom$VirtualDom$node; +var _elm_lang$html$Html$body = _elm_lang$html$Html$node('body'); +var _elm_lang$html$Html$section = _elm_lang$html$Html$node('section'); +var _elm_lang$html$Html$nav = _elm_lang$html$Html$node('nav'); +var _elm_lang$html$Html$article = _elm_lang$html$Html$node('article'); +var _elm_lang$html$Html$aside = _elm_lang$html$Html$node('aside'); +var _elm_lang$html$Html$h1 = _elm_lang$html$Html$node('h1'); +var _elm_lang$html$Html$h2 = _elm_lang$html$Html$node('h2'); +var _elm_lang$html$Html$h3 = _elm_lang$html$Html$node('h3'); +var _elm_lang$html$Html$h4 = _elm_lang$html$Html$node('h4'); +var _elm_lang$html$Html$h5 = _elm_lang$html$Html$node('h5'); +var _elm_lang$html$Html$h6 = _elm_lang$html$Html$node('h6'); +var _elm_lang$html$Html$header = _elm_lang$html$Html$node('header'); +var _elm_lang$html$Html$footer = _elm_lang$html$Html$node('footer'); +var _elm_lang$html$Html$address = _elm_lang$html$Html$node('address'); +var _elm_lang$html$Html$main$ = _elm_lang$html$Html$node('main'); +var _elm_lang$html$Html$p = _elm_lang$html$Html$node('p'); +var _elm_lang$html$Html$hr = _elm_lang$html$Html$node('hr'); +var _elm_lang$html$Html$pre = _elm_lang$html$Html$node('pre'); +var _elm_lang$html$Html$blockquote = _elm_lang$html$Html$node('blockquote'); +var _elm_lang$html$Html$ol = _elm_lang$html$Html$node('ol'); +var _elm_lang$html$Html$ul = _elm_lang$html$Html$node('ul'); +var _elm_lang$html$Html$li = _elm_lang$html$Html$node('li'); +var _elm_lang$html$Html$dl = _elm_lang$html$Html$node('dl'); +var _elm_lang$html$Html$dt = _elm_lang$html$Html$node('dt'); +var _elm_lang$html$Html$dd = _elm_lang$html$Html$node('dd'); +var _elm_lang$html$Html$figure = _elm_lang$html$Html$node('figure'); +var _elm_lang$html$Html$figcaption = _elm_lang$html$Html$node('figcaption'); +var _elm_lang$html$Html$div = _elm_lang$html$Html$node('div'); +var _elm_lang$html$Html$a = _elm_lang$html$Html$node('a'); +var _elm_lang$html$Html$em = _elm_lang$html$Html$node('em'); +var _elm_lang$html$Html$strong = _elm_lang$html$Html$node('strong'); +var _elm_lang$html$Html$small = _elm_lang$html$Html$node('small'); +var _elm_lang$html$Html$s = _elm_lang$html$Html$node('s'); +var _elm_lang$html$Html$cite = _elm_lang$html$Html$node('cite'); +var _elm_lang$html$Html$q = _elm_lang$html$Html$node('q'); +var _elm_lang$html$Html$dfn = _elm_lang$html$Html$node('dfn'); +var _elm_lang$html$Html$abbr = _elm_lang$html$Html$node('abbr'); +var _elm_lang$html$Html$time = _elm_lang$html$Html$node('time'); +var _elm_lang$html$Html$code = _elm_lang$html$Html$node('code'); +var _elm_lang$html$Html$var = _elm_lang$html$Html$node('var'); +var _elm_lang$html$Html$samp = _elm_lang$html$Html$node('samp'); +var _elm_lang$html$Html$kbd = _elm_lang$html$Html$node('kbd'); +var _elm_lang$html$Html$sub = _elm_lang$html$Html$node('sub'); +var _elm_lang$html$Html$sup = _elm_lang$html$Html$node('sup'); +var _elm_lang$html$Html$i = _elm_lang$html$Html$node('i'); +var _elm_lang$html$Html$b = _elm_lang$html$Html$node('b'); +var _elm_lang$html$Html$u = _elm_lang$html$Html$node('u'); +var _elm_lang$html$Html$mark = _elm_lang$html$Html$node('mark'); +var _elm_lang$html$Html$ruby = _elm_lang$html$Html$node('ruby'); +var _elm_lang$html$Html$rt = _elm_lang$html$Html$node('rt'); +var _elm_lang$html$Html$rp = _elm_lang$html$Html$node('rp'); +var _elm_lang$html$Html$bdi = _elm_lang$html$Html$node('bdi'); +var _elm_lang$html$Html$bdo = _elm_lang$html$Html$node('bdo'); +var _elm_lang$html$Html$span = _elm_lang$html$Html$node('span'); +var _elm_lang$html$Html$br = _elm_lang$html$Html$node('br'); +var _elm_lang$html$Html$wbr = _elm_lang$html$Html$node('wbr'); +var _elm_lang$html$Html$ins = _elm_lang$html$Html$node('ins'); +var _elm_lang$html$Html$del = _elm_lang$html$Html$node('del'); +var _elm_lang$html$Html$img = _elm_lang$html$Html$node('img'); +var _elm_lang$html$Html$iframe = _elm_lang$html$Html$node('iframe'); +var _elm_lang$html$Html$embed = _elm_lang$html$Html$node('embed'); +var _elm_lang$html$Html$object = _elm_lang$html$Html$node('object'); +var _elm_lang$html$Html$param = _elm_lang$html$Html$node('param'); +var _elm_lang$html$Html$video = _elm_lang$html$Html$node('video'); +var _elm_lang$html$Html$audio = _elm_lang$html$Html$node('audio'); +var _elm_lang$html$Html$source = _elm_lang$html$Html$node('source'); +var _elm_lang$html$Html$track = _elm_lang$html$Html$node('track'); +var _elm_lang$html$Html$canvas = _elm_lang$html$Html$node('canvas'); +var _elm_lang$html$Html$svg = _elm_lang$html$Html$node('svg'); +var _elm_lang$html$Html$math = _elm_lang$html$Html$node('math'); +var _elm_lang$html$Html$table = _elm_lang$html$Html$node('table'); +var _elm_lang$html$Html$caption = _elm_lang$html$Html$node('caption'); +var _elm_lang$html$Html$colgroup = _elm_lang$html$Html$node('colgroup'); +var _elm_lang$html$Html$col = _elm_lang$html$Html$node('col'); +var _elm_lang$html$Html$tbody = _elm_lang$html$Html$node('tbody'); +var _elm_lang$html$Html$thead = _elm_lang$html$Html$node('thead'); +var _elm_lang$html$Html$tfoot = _elm_lang$html$Html$node('tfoot'); +var _elm_lang$html$Html$tr = _elm_lang$html$Html$node('tr'); +var _elm_lang$html$Html$td = _elm_lang$html$Html$node('td'); +var _elm_lang$html$Html$th = _elm_lang$html$Html$node('th'); +var _elm_lang$html$Html$form = _elm_lang$html$Html$node('form'); +var _elm_lang$html$Html$fieldset = _elm_lang$html$Html$node('fieldset'); +var _elm_lang$html$Html$legend = _elm_lang$html$Html$node('legend'); +var _elm_lang$html$Html$label = _elm_lang$html$Html$node('label'); +var _elm_lang$html$Html$input = _elm_lang$html$Html$node('input'); +var _elm_lang$html$Html$button = _elm_lang$html$Html$node('button'); +var _elm_lang$html$Html$select = _elm_lang$html$Html$node('select'); +var _elm_lang$html$Html$datalist = _elm_lang$html$Html$node('datalist'); +var _elm_lang$html$Html$optgroup = _elm_lang$html$Html$node('optgroup'); +var _elm_lang$html$Html$option = _elm_lang$html$Html$node('option'); +var _elm_lang$html$Html$textarea = _elm_lang$html$Html$node('textarea'); +var _elm_lang$html$Html$keygen = _elm_lang$html$Html$node('keygen'); +var _elm_lang$html$Html$output = _elm_lang$html$Html$node('output'); +var _elm_lang$html$Html$progress = _elm_lang$html$Html$node('progress'); +var _elm_lang$html$Html$meter = _elm_lang$html$Html$node('meter'); +var _elm_lang$html$Html$details = _elm_lang$html$Html$node('details'); +var _elm_lang$html$Html$summary = _elm_lang$html$Html$node('summary'); +var _elm_lang$html$Html$menuitem = _elm_lang$html$Html$node('menuitem'); +var _elm_lang$html$Html$menu = _elm_lang$html$Html$node('menu'); + +var _elm_lang$html$Html_App$programWithFlags = _elm_lang$virtual_dom$VirtualDom$programWithFlags; +var _elm_lang$html$Html_App$program = function (app) { + return _elm_lang$html$Html_App$programWithFlags( + _elm_lang$core$Native_Utils.update( + app, + { + init: function (_p0) { + return app.init; + } + })); +}; +var _elm_lang$html$Html_App$beginnerProgram = function (_p1) { + var _p2 = _p1; + return _elm_lang$html$Html_App$programWithFlags( + { + init: function (_p3) { + return A2( + _elm_lang$core$Platform_Cmd_ops['!'], + _p2.model, + _elm_lang$core$Native_List.fromArray( + [])); + }, + update: F2( + function (msg, model) { + return A2( + _elm_lang$core$Platform_Cmd_ops['!'], + A2(_p2.update, msg, model), + _elm_lang$core$Native_List.fromArray( + [])); + }), + view: _p2.view, + subscriptions: function (_p4) { + return _elm_lang$core$Platform_Sub$none; + } + }); +}; +var _elm_lang$html$Html_App$map = _elm_lang$virtual_dom$VirtualDom$map; + +var _elm_lang$html$Html_Attributes$attribute = _elm_lang$virtual_dom$VirtualDom$attribute; +var _elm_lang$html$Html_Attributes$contextmenu = function (value) { + return A2(_elm_lang$html$Html_Attributes$attribute, 'contextmenu', value); +}; +var _elm_lang$html$Html_Attributes$draggable = function (value) { + return A2(_elm_lang$html$Html_Attributes$attribute, 'draggable', value); +}; +var _elm_lang$html$Html_Attributes$list = function (value) { + return A2(_elm_lang$html$Html_Attributes$attribute, 'list', value); +}; +var _elm_lang$html$Html_Attributes$maxlength = function (n) { + return A2( + _elm_lang$html$Html_Attributes$attribute, + 'maxlength', + _elm_lang$core$Basics$toString(n)); +}; +var _elm_lang$html$Html_Attributes$datetime = function (value) { + return A2(_elm_lang$html$Html_Attributes$attribute, 'datetime', value); +}; +var _elm_lang$html$Html_Attributes$pubdate = function (value) { + return A2(_elm_lang$html$Html_Attributes$attribute, 'pubdate', value); +}; +var _elm_lang$html$Html_Attributes$colspan = function (n) { + return A2( + _elm_lang$html$Html_Attributes$attribute, + 'colspan', + _elm_lang$core$Basics$toString(n)); +}; +var _elm_lang$html$Html_Attributes$rowspan = function (n) { + return A2( + _elm_lang$html$Html_Attributes$attribute, + 'rowspan', + _elm_lang$core$Basics$toString(n)); +}; +var _elm_lang$html$Html_Attributes$property = _elm_lang$virtual_dom$VirtualDom$property; +var _elm_lang$html$Html_Attributes$stringProperty = F2( + function (name, string) { + return A2( + _elm_lang$html$Html_Attributes$property, + name, + _elm_lang$core$Json_Encode$string(string)); + }); +var _elm_lang$html$Html_Attributes$class = function (name) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'className', name); +}; +var _elm_lang$html$Html_Attributes$id = function (name) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'id', name); +}; +var _elm_lang$html$Html_Attributes$title = function (name) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'title', name); +}; +var _elm_lang$html$Html_Attributes$accesskey = function ($char) { + return A2( + _elm_lang$html$Html_Attributes$stringProperty, + 'accessKey', + _elm_lang$core$String$fromChar($char)); +}; +var _elm_lang$html$Html_Attributes$dir = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'dir', value); +}; +var _elm_lang$html$Html_Attributes$dropzone = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'dropzone', value); +}; +var _elm_lang$html$Html_Attributes$itemprop = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'itemprop', value); +}; +var _elm_lang$html$Html_Attributes$lang = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'lang', value); +}; +var _elm_lang$html$Html_Attributes$tabindex = function (n) { + return A2( + _elm_lang$html$Html_Attributes$stringProperty, + 'tabIndex', + _elm_lang$core$Basics$toString(n)); +}; +var _elm_lang$html$Html_Attributes$charset = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'charset', value); +}; +var _elm_lang$html$Html_Attributes$content = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'content', value); +}; +var _elm_lang$html$Html_Attributes$httpEquiv = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'httpEquiv', value); +}; +var _elm_lang$html$Html_Attributes$language = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'language', value); +}; +var _elm_lang$html$Html_Attributes$src = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'src', value); +}; +var _elm_lang$html$Html_Attributes$height = function (value) { + return A2( + _elm_lang$html$Html_Attributes$stringProperty, + 'height', + _elm_lang$core$Basics$toString(value)); +}; +var _elm_lang$html$Html_Attributes$width = function (value) { + return A2( + _elm_lang$html$Html_Attributes$stringProperty, + 'width', + _elm_lang$core$Basics$toString(value)); +}; +var _elm_lang$html$Html_Attributes$alt = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'alt', value); +}; +var _elm_lang$html$Html_Attributes$preload = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'preload', value); +}; +var _elm_lang$html$Html_Attributes$poster = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'poster', value); +}; +var _elm_lang$html$Html_Attributes$kind = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'kind', value); +}; +var _elm_lang$html$Html_Attributes$srclang = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'srclang', value); +}; +var _elm_lang$html$Html_Attributes$sandbox = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'sandbox', value); +}; +var _elm_lang$html$Html_Attributes$srcdoc = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'srcdoc', value); +}; +var _elm_lang$html$Html_Attributes$type$ = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'type', value); +}; +var _elm_lang$html$Html_Attributes$value = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'value', value); +}; +var _elm_lang$html$Html_Attributes$defaultValue = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'defaultValue', value); +}; +var _elm_lang$html$Html_Attributes$placeholder = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'placeholder', value); +}; +var _elm_lang$html$Html_Attributes$accept = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'accept', value); +}; +var _elm_lang$html$Html_Attributes$acceptCharset = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'acceptCharset', value); +}; +var _elm_lang$html$Html_Attributes$action = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'action', value); +}; +var _elm_lang$html$Html_Attributes$autocomplete = function (bool) { + return A2( + _elm_lang$html$Html_Attributes$stringProperty, + 'autocomplete', + bool ? 'on' : 'off'); +}; +var _elm_lang$html$Html_Attributes$autosave = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'autosave', value); +}; +var _elm_lang$html$Html_Attributes$enctype = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'enctype', value); +}; +var _elm_lang$html$Html_Attributes$formaction = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'formAction', value); +}; +var _elm_lang$html$Html_Attributes$minlength = function (n) { + return A2( + _elm_lang$html$Html_Attributes$stringProperty, + 'minLength', + _elm_lang$core$Basics$toString(n)); +}; +var _elm_lang$html$Html_Attributes$method = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'method', value); +}; +var _elm_lang$html$Html_Attributes$name = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'name', value); +}; +var _elm_lang$html$Html_Attributes$pattern = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'pattern', value); +}; +var _elm_lang$html$Html_Attributes$size = function (n) { + return A2( + _elm_lang$html$Html_Attributes$stringProperty, + 'size', + _elm_lang$core$Basics$toString(n)); +}; +var _elm_lang$html$Html_Attributes$for = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'htmlFor', value); +}; +var _elm_lang$html$Html_Attributes$form = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'form', value); +}; +var _elm_lang$html$Html_Attributes$max = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'max', value); +}; +var _elm_lang$html$Html_Attributes$min = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'min', value); +}; +var _elm_lang$html$Html_Attributes$step = function (n) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'step', n); +}; +var _elm_lang$html$Html_Attributes$cols = function (n) { + return A2( + _elm_lang$html$Html_Attributes$stringProperty, + 'cols', + _elm_lang$core$Basics$toString(n)); +}; +var _elm_lang$html$Html_Attributes$rows = function (n) { + return A2( + _elm_lang$html$Html_Attributes$stringProperty, + 'rows', + _elm_lang$core$Basics$toString(n)); +}; +var _elm_lang$html$Html_Attributes$wrap = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'wrap', value); +}; +var _elm_lang$html$Html_Attributes$usemap = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'useMap', value); +}; +var _elm_lang$html$Html_Attributes$shape = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'shape', value); +}; +var _elm_lang$html$Html_Attributes$coords = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'coords', value); +}; +var _elm_lang$html$Html_Attributes$challenge = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'challenge', value); +}; +var _elm_lang$html$Html_Attributes$keytype = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'keytype', value); +}; +var _elm_lang$html$Html_Attributes$align = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'align', value); +}; +var _elm_lang$html$Html_Attributes$cite = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'cite', value); +}; +var _elm_lang$html$Html_Attributes$href = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'href', value); +}; +var _elm_lang$html$Html_Attributes$target = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'target', value); +}; +var _elm_lang$html$Html_Attributes$downloadAs = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'download', value); +}; +var _elm_lang$html$Html_Attributes$hreflang = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'hreflang', value); +}; +var _elm_lang$html$Html_Attributes$media = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'media', value); +}; +var _elm_lang$html$Html_Attributes$ping = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'ping', value); +}; +var _elm_lang$html$Html_Attributes$rel = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'rel', value); +}; +var _elm_lang$html$Html_Attributes$start = function (n) { + return A2( + _elm_lang$html$Html_Attributes$stringProperty, + 'start', + _elm_lang$core$Basics$toString(n)); +}; +var _elm_lang$html$Html_Attributes$headers = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'headers', value); +}; +var _elm_lang$html$Html_Attributes$scope = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'scope', value); +}; +var _elm_lang$html$Html_Attributes$manifest = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'manifest', value); +}; +var _elm_lang$html$Html_Attributes$boolProperty = F2( + function (name, bool) { + return A2( + _elm_lang$html$Html_Attributes$property, + name, + _elm_lang$core$Json_Encode$bool(bool)); + }); +var _elm_lang$html$Html_Attributes$hidden = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'hidden', bool); +}; +var _elm_lang$html$Html_Attributes$contenteditable = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'contentEditable', bool); +}; +var _elm_lang$html$Html_Attributes$spellcheck = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'spellcheck', bool); +}; +var _elm_lang$html$Html_Attributes$async = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'async', bool); +}; +var _elm_lang$html$Html_Attributes$defer = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'defer', bool); +}; +var _elm_lang$html$Html_Attributes$scoped = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'scoped', bool); +}; +var _elm_lang$html$Html_Attributes$autoplay = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'autoplay', bool); +}; +var _elm_lang$html$Html_Attributes$controls = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'controls', bool); +}; +var _elm_lang$html$Html_Attributes$loop = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'loop', bool); +}; +var _elm_lang$html$Html_Attributes$default = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'default', bool); +}; +var _elm_lang$html$Html_Attributes$seamless = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'seamless', bool); +}; +var _elm_lang$html$Html_Attributes$checked = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'checked', bool); +}; +var _elm_lang$html$Html_Attributes$selected = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'selected', bool); +}; +var _elm_lang$html$Html_Attributes$autofocus = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'autofocus', bool); +}; +var _elm_lang$html$Html_Attributes$disabled = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'disabled', bool); +}; +var _elm_lang$html$Html_Attributes$multiple = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'multiple', bool); +}; +var _elm_lang$html$Html_Attributes$novalidate = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'noValidate', bool); +}; +var _elm_lang$html$Html_Attributes$readonly = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'readOnly', bool); +}; +var _elm_lang$html$Html_Attributes$required = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'required', bool); +}; +var _elm_lang$html$Html_Attributes$ismap = function (value) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'isMap', value); +}; +var _elm_lang$html$Html_Attributes$download = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'download', bool); +}; +var _elm_lang$html$Html_Attributes$reversed = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'reversed', bool); +}; +var _elm_lang$html$Html_Attributes$classList = function (list) { + return _elm_lang$html$Html_Attributes$class( + A2( + _elm_lang$core$String$join, + ' ', + A2( + _elm_lang$core$List$map, + _elm_lang$core$Basics$fst, + A2(_elm_lang$core$List$filter, _elm_lang$core$Basics$snd, list)))); +}; +var _elm_lang$html$Html_Attributes$style = _elm_lang$virtual_dom$VirtualDom$style; + +var _elm_lang$html$Html_Events$keyCode = A2(_elm_lang$core$Json_Decode_ops[':='], 'keyCode', _elm_lang$core$Json_Decode$int); +var _elm_lang$html$Html_Events$targetChecked = A2( + _elm_lang$core$Json_Decode$at, + _elm_lang$core$Native_List.fromArray( + ['target', 'checked']), + _elm_lang$core$Json_Decode$bool); +var _elm_lang$html$Html_Events$targetValue = A2( + _elm_lang$core$Json_Decode$at, + _elm_lang$core$Native_List.fromArray( + ['target', 'value']), + _elm_lang$core$Json_Decode$string); +var _elm_lang$html$Html_Events$defaultOptions = _elm_lang$virtual_dom$VirtualDom$defaultOptions; +var _elm_lang$html$Html_Events$onWithOptions = _elm_lang$virtual_dom$VirtualDom$onWithOptions; +var _elm_lang$html$Html_Events$on = _elm_lang$virtual_dom$VirtualDom$on; +var _elm_lang$html$Html_Events$onFocus = function (msg) { + return A2( + _elm_lang$html$Html_Events$on, + 'focus', + _elm_lang$core$Json_Decode$succeed(msg)); +}; +var _elm_lang$html$Html_Events$onBlur = function (msg) { + return A2( + _elm_lang$html$Html_Events$on, + 'blur', + _elm_lang$core$Json_Decode$succeed(msg)); +}; +var _elm_lang$html$Html_Events$onSubmitOptions = _elm_lang$core$Native_Utils.update( + _elm_lang$html$Html_Events$defaultOptions, + {preventDefault: true}); +var _elm_lang$html$Html_Events$onSubmit = function (msg) { + return A3( + _elm_lang$html$Html_Events$onWithOptions, + 'submit', + _elm_lang$html$Html_Events$onSubmitOptions, + _elm_lang$core$Json_Decode$succeed(msg)); +}; +var _elm_lang$html$Html_Events$onCheck = function (tagger) { + return A2( + _elm_lang$html$Html_Events$on, + 'change', + A2(_elm_lang$core$Json_Decode$map, tagger, _elm_lang$html$Html_Events$targetChecked)); +}; +var _elm_lang$html$Html_Events$onInput = function (tagger) { + return A2( + _elm_lang$html$Html_Events$on, + 'input', + A2(_elm_lang$core$Json_Decode$map, tagger, _elm_lang$html$Html_Events$targetValue)); +}; +var _elm_lang$html$Html_Events$onMouseOut = function (msg) { + return A2( + _elm_lang$html$Html_Events$on, + 'mouseout', + _elm_lang$core$Json_Decode$succeed(msg)); +}; +var _elm_lang$html$Html_Events$onMouseOver = function (msg) { + return A2( + _elm_lang$html$Html_Events$on, + 'mouseover', + _elm_lang$core$Json_Decode$succeed(msg)); +}; +var _elm_lang$html$Html_Events$onMouseLeave = function (msg) { + return A2( + _elm_lang$html$Html_Events$on, + 'mouseleave', + _elm_lang$core$Json_Decode$succeed(msg)); +}; +var _elm_lang$html$Html_Events$onMouseEnter = function (msg) { + return A2( + _elm_lang$html$Html_Events$on, + 'mouseenter', + _elm_lang$core$Json_Decode$succeed(msg)); +}; +var _elm_lang$html$Html_Events$onMouseUp = function (msg) { + return A2( + _elm_lang$html$Html_Events$on, + 'mouseup', + _elm_lang$core$Json_Decode$succeed(msg)); +}; +var _elm_lang$html$Html_Events$onMouseDown = function (msg) { + return A2( + _elm_lang$html$Html_Events$on, + 'mousedown', + _elm_lang$core$Json_Decode$succeed(msg)); +}; +var _elm_lang$html$Html_Events$onDoubleClick = function (msg) { + return A2( + _elm_lang$html$Html_Events$on, + 'dblclick', + _elm_lang$core$Json_Decode$succeed(msg)); +}; +var _elm_lang$html$Html_Events$onClick = function (msg) { + return A2( + _elm_lang$html$Html_Events$on, + 'click', + _elm_lang$core$Json_Decode$succeed(msg)); +}; +var _elm_lang$html$Html_Events$Options = F2( + function (a, b) { + return {stopPropagation: a, preventDefault: b}; + }); + +var _elm_lang$html$Html_Keyed$node = _elm_lang$virtual_dom$VirtualDom$keyedNode; +var _elm_lang$html$Html_Keyed$ol = _elm_lang$html$Html_Keyed$node('ol'); +var _elm_lang$html$Html_Keyed$ul = _elm_lang$html$Html_Keyed$node('ul'); + +var _elm_lang$html$Html_Lazy$lazy3 = _elm_lang$virtual_dom$VirtualDom$lazy3; +var _elm_lang$html$Html_Lazy$lazy2 = _elm_lang$virtual_dom$VirtualDom$lazy2; +var _elm_lang$html$Html_Lazy$lazy = _elm_lang$virtual_dom$VirtualDom$lazy; + +var _evancz$elm_todomvc$Todo$infoFooter = A2( + _elm_lang$html$Html$footer, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$class('info') + ]), + _elm_lang$core$Native_List.fromArray( + [ + A2( + _elm_lang$html$Html$p, + _elm_lang$core$Native_List.fromArray( + []), + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html$text('Double-click to edit a todo') + ])), + A2( + _elm_lang$html$Html$p, + _elm_lang$core$Native_List.fromArray( + []), + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html$text('Written by '), + A2( + _elm_lang$html$Html$a, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$href('https://github.com/evancz') + ]), + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html$text('Evan Czaplicki') + ])) + ])), + A2( + _elm_lang$html$Html$p, + _elm_lang$core$Native_List.fromArray( + []), + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html$text('Part of '), + A2( + _elm_lang$html$Html$a, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$href('http://todomvc.com') + ]), + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html$text('TodoMVC') + ])) + ])) + ])); +var _evancz$elm_todomvc$Todo$viewControlsCount = function (entriesLeft) { + var item_ = _elm_lang$core$Native_Utils.eq(entriesLeft, 1) ? ' item' : ' items'; + return A2( + _elm_lang$html$Html$span, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$class('todo-count') + ]), + _elm_lang$core$Native_List.fromArray( + [ + A2( + _elm_lang$html$Html$strong, + _elm_lang$core$Native_List.fromArray( + []), + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html$text( + _elm_lang$core$Basics$toString(entriesLeft)) + ])), + _elm_lang$html$Html$text( + A2(_elm_lang$core$Basics_ops['++'], item_, ' left')) + ])); +}; +var _evancz$elm_todomvc$Todo$newEntry = F2( + function (desc, id) { + return {description: desc, completed: false, editing: false, id: id}; + }); +var _evancz$elm_todomvc$Todo$emptyModel = { + entries: _elm_lang$core$Native_List.fromArray( + []), + visibility: 'All', + field: '', + uid: 0 +}; +var _evancz$elm_todomvc$Todo$init = A2( + _elm_lang$core$Platform_Cmd_ops['!'], + _evancz$elm_todomvc$Todo$emptyModel, + _elm_lang$core$Native_List.fromArray( + [])); +var _evancz$elm_todomvc$Todo$focus = _elm_lang$core$Native_Platform.outgoingPort( + 'focus', + function (v) { + return v; + }); +var _evancz$elm_todomvc$Todo$update = F2( + function (msg, model) { + var _p0 = msg; + switch (_p0.ctor) { + case 'NoOp': + return A2( + _elm_lang$core$Platform_Cmd_ops['!'], + model, + _elm_lang$core$Native_List.fromArray( + [])); + case 'Add': + return A2( + _elm_lang$core$Platform_Cmd_ops['!'], + _elm_lang$core$Native_Utils.update( + model, + { + uid: model.uid + 1, + field: '', + entries: _elm_lang$core$String$isEmpty(model.field) ? model.entries : A2( + _elm_lang$core$Basics_ops['++'], + model.entries, + _elm_lang$core$Native_List.fromArray( + [ + A2(_evancz$elm_todomvc$Todo$newEntry, model.field, model.uid) + ])) + }), + _elm_lang$core$Native_List.fromArray( + [])); + case 'UpdateField': + return A2( + _elm_lang$core$Platform_Cmd_ops['!'], + _elm_lang$core$Native_Utils.update( + model, + {field: _p0._0}), + _elm_lang$core$Native_List.fromArray( + [])); + case 'EditingEntry': + var _p1 = _p0._0; + var updateEntry = function (t) { + return _elm_lang$core$Native_Utils.eq(t.id, _p1) ? _elm_lang$core$Native_Utils.update( + t, + {editing: _p0._1}) : t; + }; + return A2( + _elm_lang$core$Platform_Cmd_ops['!'], + _elm_lang$core$Native_Utils.update( + model, + { + entries: A2(_elm_lang$core$List$map, updateEntry, model.entries) + }), + _elm_lang$core$Native_List.fromArray( + [ + _evancz$elm_todomvc$Todo$focus( + A2( + _elm_lang$core$Basics_ops['++'], + '#todo-', + _elm_lang$core$Basics$toString(_p1))) + ])); + case 'UpdateEntry': + var updateEntry = function (t) { + return _elm_lang$core$Native_Utils.eq(t.id, _p0._0) ? _elm_lang$core$Native_Utils.update( + t, + {description: _p0._1}) : t; + }; + return A2( + _elm_lang$core$Platform_Cmd_ops['!'], + _elm_lang$core$Native_Utils.update( + model, + { + entries: A2(_elm_lang$core$List$map, updateEntry, model.entries) + }), + _elm_lang$core$Native_List.fromArray( + [])); + case 'Delete': + return A2( + _elm_lang$core$Platform_Cmd_ops['!'], + _elm_lang$core$Native_Utils.update( + model, + { + entries: A2( + _elm_lang$core$List$filter, + function (t) { + return !_elm_lang$core$Native_Utils.eq(t.id, _p0._0); + }, + model.entries) + }), + _elm_lang$core$Native_List.fromArray( + [])); + case 'DeleteComplete': + return A2( + _elm_lang$core$Platform_Cmd_ops['!'], + _elm_lang$core$Native_Utils.update( + model, + { + entries: A2( + _elm_lang$core$List$filter, + function (_p2) { + return _elm_lang$core$Basics$not( + function (_) { + return _.completed; + }(_p2)); + }, + model.entries) + }), + _elm_lang$core$Native_List.fromArray( + [])); + case 'Check': + var updateEntry = function (t) { + return _elm_lang$core$Native_Utils.eq(t.id, _p0._0) ? _elm_lang$core$Native_Utils.update( + t, + {completed: _p0._1}) : t; + }; + return A2( + _elm_lang$core$Platform_Cmd_ops['!'], + _elm_lang$core$Native_Utils.update( + model, + { + entries: A2(_elm_lang$core$List$map, updateEntry, model.entries) + }), + _elm_lang$core$Native_List.fromArray( + [])); + case 'CheckAll': + var updateEntry = function (t) { + return _elm_lang$core$Native_Utils.update( + t, + {completed: _p0._0}); + }; + return A2( + _elm_lang$core$Platform_Cmd_ops['!'], + _elm_lang$core$Native_Utils.update( + model, + { + entries: A2(_elm_lang$core$List$map, updateEntry, model.entries) + }), + _elm_lang$core$Native_List.fromArray( + [])); + default: + return A2( + _elm_lang$core$Platform_Cmd_ops['!'], + _elm_lang$core$Native_Utils.update( + model, + {visibility: _p0._0}), + _elm_lang$core$Native_List.fromArray( + [])); + } + }); +var _evancz$elm_todomvc$Todo$Model = F4( + function (a, b, c, d) { + return {entries: a, field: b, uid: c, visibility: d}; + }); +var _evancz$elm_todomvc$Todo$Entry = F4( + function (a, b, c, d) { + return {description: a, completed: b, editing: c, id: d}; + }); +var _evancz$elm_todomvc$Todo$ChangeVisibility = function (a) { + return {ctor: 'ChangeVisibility', _0: a}; +}; +var _evancz$elm_todomvc$Todo$visibilitySwap = F3( + function (uri, visibility, actualVisibility) { + return A2( + _elm_lang$html$Html$li, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Events$onClick( + _evancz$elm_todomvc$Todo$ChangeVisibility(visibility)) + ]), + _elm_lang$core$Native_List.fromArray( + [ + A2( + _elm_lang$html$Html$a, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$href(uri), + _elm_lang$html$Html_Attributes$classList( + _elm_lang$core$Native_List.fromArray( + [ + { + ctor: '_Tuple2', + _0: 'selected', + _1: _elm_lang$core$Native_Utils.eq(visibility, actualVisibility) + } + ])) + ]), + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html$text(visibility) + ])) + ])); + }); +var _evancz$elm_todomvc$Todo$viewControlsFilters = function (visibility) { + return A2( + _elm_lang$html$Html$ul, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$class('filters') + ]), + _elm_lang$core$Native_List.fromArray( + [ + A3(_evancz$elm_todomvc$Todo$visibilitySwap, '#/', 'All', visibility), + _elm_lang$html$Html$text(' '), + A3(_evancz$elm_todomvc$Todo$visibilitySwap, '#/active', 'Active', visibility), + _elm_lang$html$Html$text(' '), + A3(_evancz$elm_todomvc$Todo$visibilitySwap, '#/completed', 'Completed', visibility) + ])); +}; +var _evancz$elm_todomvc$Todo$CheckAll = function (a) { + return {ctor: 'CheckAll', _0: a}; +}; +var _evancz$elm_todomvc$Todo$Check = F2( + function (a, b) { + return {ctor: 'Check', _0: a, _1: b}; + }); +var _evancz$elm_todomvc$Todo$DeleteComplete = {ctor: 'DeleteComplete'}; +var _evancz$elm_todomvc$Todo$viewControlsClear = function (entriesCompleted) { + return A2( + _elm_lang$html$Html$button, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$class('clear-completed'), + _elm_lang$html$Html_Attributes$hidden( + _elm_lang$core$Native_Utils.eq(entriesCompleted, 0)), + _elm_lang$html$Html_Events$onClick(_evancz$elm_todomvc$Todo$DeleteComplete) + ]), + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html$text( + A2( + _elm_lang$core$Basics_ops['++'], + 'Clear completed (', + A2( + _elm_lang$core$Basics_ops['++'], + _elm_lang$core$Basics$toString(entriesCompleted), + ')'))) + ])); +}; +var _evancz$elm_todomvc$Todo$viewControls = F2( + function (visibility, entries) { + var entriesCompleted = _elm_lang$core$List$length( + A2( + _elm_lang$core$List$filter, + function (_) { + return _.completed; + }, + entries)); + var entriesLeft = _elm_lang$core$List$length(entries) - entriesCompleted; + return A2( + _elm_lang$html$Html$footer, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$class('footer'), + _elm_lang$html$Html_Attributes$hidden( + _elm_lang$core$List$isEmpty(entries)) + ]), + _elm_lang$core$Native_List.fromArray( + [ + A2(_elm_lang$html$Html_Lazy$lazy, _evancz$elm_todomvc$Todo$viewControlsCount, entriesLeft), + A2(_elm_lang$html$Html_Lazy$lazy, _evancz$elm_todomvc$Todo$viewControlsFilters, visibility), + A2(_elm_lang$html$Html_Lazy$lazy, _evancz$elm_todomvc$Todo$viewControlsClear, entriesCompleted) + ])); + }); +var _evancz$elm_todomvc$Todo$Delete = function (a) { + return {ctor: 'Delete', _0: a}; +}; +var _evancz$elm_todomvc$Todo$Add = {ctor: 'Add'}; +var _evancz$elm_todomvc$Todo$UpdateEntry = F2( + function (a, b) { + return {ctor: 'UpdateEntry', _0: a, _1: b}; + }); +var _evancz$elm_todomvc$Todo$EditingEntry = F2( + function (a, b) { + return {ctor: 'EditingEntry', _0: a, _1: b}; + }); +var _evancz$elm_todomvc$Todo$UpdateField = function (a) { + return {ctor: 'UpdateField', _0: a}; +}; +var _evancz$elm_todomvc$Todo$NoOp = {ctor: 'NoOp'}; +var _evancz$elm_todomvc$Todo$onEnter = function (msg) { + var tagger = function (code) { + return _elm_lang$core$Native_Utils.eq(code, 13) ? msg : _evancz$elm_todomvc$Todo$NoOp; + }; + return A2( + _elm_lang$html$Html_Events$on, + 'keydown', + A2(_elm_lang$core$Json_Decode$map, tagger, _elm_lang$html$Html_Events$keyCode)); +}; +var _evancz$elm_todomvc$Todo$viewInput = function (task) { + return A2( + _elm_lang$html$Html$header, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$class('header') + ]), + _elm_lang$core$Native_List.fromArray( + [ + A2( + _elm_lang$html$Html$h1, + _elm_lang$core$Native_List.fromArray( + []), + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html$text('todos') + ])), + A2( + _elm_lang$html$Html$input, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$class('new-todo'), + _elm_lang$html$Html_Attributes$placeholder('What needs to be done?'), + _elm_lang$html$Html_Attributes$autofocus(true), + _elm_lang$html$Html_Attributes$value(task), + _elm_lang$html$Html_Attributes$name('newTodo'), + _elm_lang$html$Html_Events$onInput(_evancz$elm_todomvc$Todo$UpdateField), + _evancz$elm_todomvc$Todo$onEnter(_evancz$elm_todomvc$Todo$Add) + ]), + _elm_lang$core$Native_List.fromArray( + [])) + ])); +}; +var _evancz$elm_todomvc$Todo$viewEntry = function (todo) { + return A2( + _elm_lang$html$Html$li, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$classList( + _elm_lang$core$Native_List.fromArray( + [ + {ctor: '_Tuple2', _0: 'completed', _1: todo.completed}, + {ctor: '_Tuple2', _0: 'editing', _1: todo.editing} + ])) + ]), + _elm_lang$core$Native_List.fromArray( + [ + A2( + _elm_lang$html$Html$div, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$class('view') + ]), + _elm_lang$core$Native_List.fromArray( + [ + A2( + _elm_lang$html$Html$input, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$class('toggle'), + _elm_lang$html$Html_Attributes$type$('checkbox'), + _elm_lang$html$Html_Attributes$checked(todo.completed), + _elm_lang$html$Html_Events$onClick( + A2( + _evancz$elm_todomvc$Todo$Check, + todo.id, + _elm_lang$core$Basics$not(todo.completed))) + ]), + _elm_lang$core$Native_List.fromArray( + [])), + A2( + _elm_lang$html$Html$label, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Events$onDoubleClick( + A2(_evancz$elm_todomvc$Todo$EditingEntry, todo.id, true)) + ]), + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html$text(todo.description) + ])), + A2( + _elm_lang$html$Html$button, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$class('destroy'), + _elm_lang$html$Html_Events$onClick( + _evancz$elm_todomvc$Todo$Delete(todo.id)) + ]), + _elm_lang$core$Native_List.fromArray( + [])) + ])), + A2( + _elm_lang$html$Html$input, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$class('edit'), + _elm_lang$html$Html_Attributes$value(todo.description), + _elm_lang$html$Html_Attributes$name('title'), + _elm_lang$html$Html_Attributes$id( + A2( + _elm_lang$core$Basics_ops['++'], + 'todo-', + _elm_lang$core$Basics$toString(todo.id))), + _elm_lang$html$Html_Events$onInput( + _evancz$elm_todomvc$Todo$UpdateEntry(todo.id)), + _elm_lang$html$Html_Events$onBlur( + A2(_evancz$elm_todomvc$Todo$EditingEntry, todo.id, false)), + _evancz$elm_todomvc$Todo$onEnter( + A2(_evancz$elm_todomvc$Todo$EditingEntry, todo.id, false)) + ]), + _elm_lang$core$Native_List.fromArray( + [])) + ])); +}; +var _evancz$elm_todomvc$Todo$viewKeyedEntry = function (todo) { + return { + ctor: '_Tuple2', + _0: _elm_lang$core$Basics$toString(todo.id), + _1: A2(_elm_lang$html$Html_Lazy$lazy, _evancz$elm_todomvc$Todo$viewEntry, todo) + }; +}; +var _evancz$elm_todomvc$Todo$viewEntries = F2( + function (visibility, entries) { + var cssVisibility = _elm_lang$core$List$isEmpty(entries) ? 'hidden' : 'visible'; + var allCompleted = A2( + _elm_lang$core$List$all, + function (_) { + return _.completed; + }, + entries); + var isVisible = function (todo) { + var _p3 = visibility; + switch (_p3) { + case 'Completed': + return todo.completed; + case 'Active': + return _elm_lang$core$Basics$not(todo.completed); + default: + return true; + } + }; + return A2( + _elm_lang$html$Html$section, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$class('main'), + _elm_lang$html$Html_Attributes$style( + _elm_lang$core$Native_List.fromArray( + [ + {ctor: '_Tuple2', _0: 'visibility', _1: cssVisibility} + ])) + ]), + _elm_lang$core$Native_List.fromArray( + [ + A2( + _elm_lang$html$Html$input, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$class('toggle-all'), + _elm_lang$html$Html_Attributes$type$('checkbox'), + _elm_lang$html$Html_Attributes$name('toggle'), + _elm_lang$html$Html_Attributes$checked(allCompleted), + _elm_lang$html$Html_Events$onClick( + _evancz$elm_todomvc$Todo$CheckAll( + _elm_lang$core$Basics$not(allCompleted))) + ]), + _elm_lang$core$Native_List.fromArray( + [])), + A2( + _elm_lang$html$Html$label, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$for('toggle-all') + ]), + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html$text('Mark all as complete') + ])), + A2( + _elm_lang$html$Html_Keyed$ul, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$class('todo-list') + ]), + A2( + _elm_lang$core$List$map, + _evancz$elm_todomvc$Todo$viewKeyedEntry, + A2(_elm_lang$core$List$filter, isVisible, entries))) + ])); + }); +var _evancz$elm_todomvc$Todo$view = function (model) { + return A2( + _elm_lang$html$Html$div, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$class('todomvc-wrapper'), + _elm_lang$html$Html_Attributes$style( + _elm_lang$core$Native_List.fromArray( + [ + {ctor: '_Tuple2', _0: 'visibility', _1: 'hidden'} + ])) + ]), + _elm_lang$core$Native_List.fromArray( + [ + A2( + _elm_lang$html$Html$section, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$class('todoapp') + ]), + _elm_lang$core$Native_List.fromArray( + [ + A2(_elm_lang$html$Html_Lazy$lazy, _evancz$elm_todomvc$Todo$viewInput, model.field), + A3(_elm_lang$html$Html_Lazy$lazy2, _evancz$elm_todomvc$Todo$viewEntries, model.visibility, model.entries), + A3(_elm_lang$html$Html_Lazy$lazy2, _evancz$elm_todomvc$Todo$viewControls, model.visibility, model.entries) + ])), + _evancz$elm_todomvc$Todo$infoFooter + ])); +}; +var _evancz$elm_todomvc$Todo$main = { + main: _elm_lang$html$Html_App$program( + { + init: _evancz$elm_todomvc$Todo$init, + view: _evancz$elm_todomvc$Todo$view, + update: _evancz$elm_todomvc$Todo$update, + subscriptions: function (_p4) { + return _elm_lang$core$Platform_Sub$none; + } + }) +}; + +var Elm = {}; +Elm['Todo'] = Elm['Todo'] || {}; +_elm_lang$core$Native_Platform.addPublicModule(Elm['Todo'], 'Todo', typeof _evancz$elm_todomvc$Todo$main === 'undefined' ? null : _evancz$elm_todomvc$Todo$main); + +if (typeof define === "function" && define['amd']) +{ + define([], function() { return Elm; }); + return; +} + +if (typeof module === "object") +{ + module['exports'] = Elm; + return; +} + +var globalElm = this['Elm']; +if (typeof globalElm === "undefined") +{ + this['Elm'] = Elm; + return; +} + +for (var publicModule in Elm) +{ + if (publicModule in globalElm) + { + throw new Error('There are two Elm modules called `' + publicModule + '` on this page! Rename one of them.'); + } + globalElm[publicModule] = Elm[publicModule]; +} + +}).call(this); + diff --git a/bench/implementations/elm-0.17-optimized/index.html b/bench/implementations/elm-0.17-optimized/index.html new file mode 100644 index 0000000..dcb938e --- /dev/null +++ b/bench/implementations/elm-0.17-optimized/index.html @@ -0,0 +1,29 @@ + + + + + + Elm • TodoMVC + + + + + + + + + + diff --git a/bench/implementations/elm-0.17-optimized/style.css b/bench/implementations/elm-0.17-optimized/style.css new file mode 100644 index 0000000..fc2e67b --- /dev/null +++ b/bench/implementations/elm-0.17-optimized/style.css @@ -0,0 +1,382 @@ +html, +body { + margin: 0; + padding: 0; +} + +.todomvc-wrapper { + visibility: visible !important; +} + +button { + margin: 0; + padding: 0; + border: 0; + background: none; + font-size: 100%; + vertical-align: baseline; + font-family: inherit; + font-weight: inherit; + color: inherit; + -webkit-appearance: none; + appearance: none; + -webkit-font-smoothing: antialiased; + -moz-font-smoothing: antialiased; + font-smoothing: antialiased; +} + +body { + font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif; + line-height: 1.4em; + background: #f5f5f5; + color: #4d4d4d; + min-width: 230px; + max-width: 550px; + margin: 0 auto; + -webkit-font-smoothing: antialiased; + -moz-font-smoothing: antialiased; + font-smoothing: antialiased; + font-weight: 300; +} + +button, +input[type="checkbox"] { + outline: none; +} + +.hidden { + display: none; +} + +.todoapp { + background: #fff; + margin: 130px 0 40px 0; + position: relative; + box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), + 0 25px 50px 0 rgba(0, 0, 0, 0.1); +} + +.todoapp input::-webkit-input-placeholder { + font-style: italic; + font-weight: 300; + color: #e6e6e6; +} + +.todoapp input::-moz-placeholder { + font-style: italic; + font-weight: 300; + color: #e6e6e6; +} + +.todoapp input::input-placeholder { + font-style: italic; + font-weight: 300; + color: #e6e6e6; +} + +.todoapp h1 { + position: absolute; + top: -155px; + width: 100%; + font-size: 100px; + font-weight: 100; + text-align: center; + color: rgba(175, 47, 47, 0.15); + -webkit-text-rendering: optimizeLegibility; + -moz-text-rendering: optimizeLegibility; + text-rendering: optimizeLegibility; +} + +.new-todo, +.edit { + position: relative; + margin: 0; + width: 100%; + font-size: 24px; + font-family: inherit; + font-weight: 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); + box-sizing: border-box; + -webkit-font-smoothing: antialiased; + -moz-font-smoothing: antialiased; + font-smoothing: antialiased; +} + +.new-todo { + padding: 16px 16px 16px 60px; + border: none; + background: rgba(0, 0, 0, 0.003); + box-shadow: inset 0 -2px 1px rgba(0,0,0,0.03); +} + +.main { + position: relative; + z-index: 2; + border-top: 1px solid #e6e6e6; +} + +label[for='toggle-all'] { + display: none; +} + +.toggle-all { + position: absolute; + top: -55px; + left: -12px; + width: 60px; + height: 34px; + text-align: center; + border: none; /* Mobile Safari */ +} + +.toggle-all:before { + content: '❯'; + font-size: 22px; + color: #e6e6e6; + padding: 10px 27px 10px 27px; +} + +.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 solid #ededed; +} + +.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; + appearance: none; +} + +.todo-list li .toggle:after { + content: url('data:image/svg+xml;utf8,'); +} + +.todo-list li .toggle:checked:after { + content: url('data:image/svg+xml;utf8,'); +} + +.todo-list li label { + white-space: pre-line; + word-break: break-all; + padding: 15px 60px 15px 15px; + margin-left: 45px; + display: block; + line-height: 1.2; + transition: color 0.4s; +} + +.todo-list li.completed label { + color: #d9d9d9; + 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: 30px; + color: #cc9a9a; + margin-bottom: 11px; + transition: color 0.2s ease-out; +} + +.todo-list li .destroy:hover { + color: #af5b5e; +} + +.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: 10px 15px; + height: 20px; + text-align: center; + border-top: 1px solid #e6e6e6; +} + +.footer:before { + content: ''; + position: absolute; + right: 0; + bottom: 0; + left: 0; + height: 50px; + overflow: hidden; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), + 0 8px 0 -3px #f6f6f6, + 0 9px 1px -3px rgba(0, 0, 0, 0.2), + 0 16px 0 -6px #f6f6f6, + 0 17px 2px -6px rgba(0, 0, 0, 0.2); +} + +.todo-count { + float: left; + text-align: left; +} + +.todo-count strong { + font-weight: 300; +} + +.filters { + margin: 0; + padding: 0; + list-style: none; + position: absolute; + right: 0; + left: 0; +} + +.filters li { + display: inline; +} + +.filters li a { + color: inherit; + margin: 3px; + padding: 3px 7px; + text-decoration: none; + border: 1px solid transparent; + border-radius: 3px; +} + +.filters li a.selected, +.filters li a:hover { + border-color: rgba(175, 47, 47, 0.1); +} + +.filters li a.selected { + border-color: rgba(175, 47, 47, 0.2); +} + +.clear-completed, +html .clear-completed:active { + float: right; + position: relative; + line-height: 20px; + text-decoration: none; + cursor: pointer; + position: relative; +} + +.clear-completed:hover { + text-decoration: underline; +} + +.info { + margin: 65px auto 0; + color: #bfbfbf; + font-size: 10px; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + text-align: center; +} + +.info p { + line-height: 1; +} + +.info a { + color: inherit; + text-decoration: none; + font-weight: 400; +} + +.info a:hover { + text-decoration: underline; +} + +/* + Hack to remove background from Mobile Safari. + Can't use it globally since it destroys checkboxes in Firefox +*/ +@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 { + -webkit-transform: rotate(90deg); + transform: rotate(90deg); + -webkit-appearance: none; + appearance: none; + } +} + +@media (max-width: 430px) { + .footer { + height: 50px; + } + + .filters { + bottom: 10px; + } +} \ No newline at end of file diff --git a/bench/implementations/elm-0.17/Todo.elm b/bench/implementations/elm-0.17/Todo.elm new file mode 100644 index 0000000..0c23278 --- /dev/null +++ b/bench/implementations/elm-0.17/Todo.elm @@ -0,0 +1,374 @@ +port module Todo exposing (main) +{-| TodoMVC implemented in Elm, using plain HTML and CSS for rendering. + +This application is broken up into three key parts: + + 1. Model - a full definition of the application's state + 2. Update - a way to step the application state forward + 3. View - a way to visualize our application state with HTML + +This clean division of concerns is a core part of Elm. You can read more about +this in +-} + +import Html exposing (..) +import Html.App as App +import Html.Attributes exposing (..) +import Html.Events exposing (..) +import Json.Decode as Json +import String + + + +main : Program Never +main = + App.program + { init = init + , view = view + , update = update + , subscriptions = \_ -> Sub.none + } + + +port focus : String -> Cmd msg + + + +-- MODEL + + +-- The full application state of our todo app. +type alias Model = + { entries : List Entry + , field : String + , uid : Int + , visibility : String + } + + +type alias Entry = + { description : String + , completed : Bool + , editing : Bool + , id : Int + } + + +emptyModel : Model +emptyModel = + { entries = [] + , visibility = "All" + , field = "" + , uid = 0 + } + + +newEntry : String -> Int -> Entry +newEntry desc id = + { description = desc + , completed = False + , editing = False + , id = id + } + + +init : ( Model, Cmd Msg ) +init = + emptyModel ! [] + + + +-- UPDATE + + +{-| Users of our app can trigger messages by clicking and typing. These +messages are fed into the `update` function as they occur, letting us react +to them. +-} +type Msg + = NoOp + | UpdateField String + | EditingEntry Int Bool + | UpdateEntry Int String + | Add + | Delete Int + | DeleteComplete + | Check Int Bool + | CheckAll Bool + | ChangeVisibility String + + +-- How we update our Model on a given Msg? +update : Msg -> Model -> ( Model, Cmd Msg ) +update msg model = + case msg of + NoOp -> + model ! [] + + Add -> + { model + | uid = model.uid + 1 + , field = "" + , entries = + if String.isEmpty model.field then + model.entries + else + model.entries ++ [newEntry model.field model.uid] + } + ! [] + + UpdateField str -> + { model | field = str } + ! [] + + EditingEntry id isEditing -> + let + updateEntry t = + if t.id == id then { t | editing = isEditing } else t + in + { model | entries = List.map updateEntry model.entries } + ! [ focus ("#todo-" ++ toString id) ] + + UpdateEntry id task -> + let + updateEntry t = + if t.id == id then { t | description = task } else t + in + { model | entries = List.map updateEntry model.entries } + ! [] + + Delete id -> + { model | entries = List.filter (\t -> t.id /= id) model.entries } + ! [] + + DeleteComplete -> + { model | entries = List.filter (not << .completed) model.entries } + ! [] + + Check id isCompleted -> + let + updateEntry t = + if t.id == id then { t | completed = isCompleted } else t + in + { model | entries = List.map updateEntry model.entries } + ! [] + + CheckAll isCompleted -> + let + updateEntry t = + { t | completed = isCompleted } + in + { model | entries = List.map updateEntry model.entries } + ! [] + + ChangeVisibility visibility -> + { model | visibility = visibility } + ! [] + + + +-- VIEW + + +view : Model -> Html Msg +view model = + div + [ class "todomvc-wrapper" + , style [ ("visibility", "hidden") ] + ] + [ section + [ class "todoapp" ] + [ viewInput model.field + , viewEntries model.visibility model.entries + , viewControls model.visibility model.entries + ] + , infoFooter + ] + + +viewInput : String -> Html Msg +viewInput task = + header + [ class "header" ] + [ h1 [] [ text "todos" ] + , input + [ class "new-todo" + , placeholder "What needs to be done?" + , autofocus True + , value task + , name "newTodo" + , onInput UpdateField + , onEnter Add + ] + [] + ] + + +onEnter : Msg -> Attribute Msg +onEnter msg = + let + tagger code = + if code == 13 then msg else NoOp + in + on "keydown" (Json.map tagger keyCode) + + + +-- VIEW ALL ENTRIES + + +viewEntries : String -> List Entry -> Html Msg +viewEntries visibility entries = + let + isVisible todo = + case visibility of + "Completed" -> todo.completed + "Active" -> not todo.completed + _ -> True + + allCompleted = + List.all .completed entries + + cssVisibility = + if List.isEmpty entries then "hidden" else "visible" + in + section + [ class "main" + , style [ ("visibility", cssVisibility) ] + ] + [ input + [ class "toggle-all" + , type' "checkbox" + , name "toggle" + , checked allCompleted + , onClick (CheckAll (not allCompleted)) + ] + [] + , label + [ for "toggle-all" ] + [ text "Mark all as complete" ] + , ul [ class "todo-list" ] <| + List.map viewEntry (List.filter isVisible entries) + ] + + + +-- VIEW INDIVIDUAL ENTRIES + + +viewEntry : Entry -> Html Msg +viewEntry todo = + li + [ classList [ ("completed", todo.completed), ("editing", todo.editing) ] ] + [ div + [ class "view" ] + [ input + [ class "toggle" + , type' "checkbox" + , checked todo.completed + , onClick (Check todo.id (not todo.completed)) + ] + [] + , label + [ onDoubleClick (EditingEntry todo.id True) ] + [ text todo.description ] + , button + [ class "destroy" + , onClick (Delete todo.id) + ] + [] + ] + , input + [ class "edit" + , value todo.description + , name "title" + , id ("todo-" ++ toString todo.id) + , onInput (UpdateEntry todo.id) + , onBlur (EditingEntry todo.id False) + , onEnter (EditingEntry todo.id False) + ] + [] + ] + + + +-- VIEW CONTROLS AND FOOTER + + +viewControls : String -> List Entry -> Html Msg +viewControls visibility entries = + let + entriesCompleted = + List.length (List.filter .completed entries) + + entriesLeft = + List.length entries - entriesCompleted + in + footer + [ class "footer" + , hidden (List.isEmpty entries) + ] + [ viewControlsCount entriesLeft + , viewControlsFilters visibility + , viewControlsClear entriesCompleted + ] + + +viewControlsCount : Int -> Html Msg +viewControlsCount entriesLeft = + let + item_ = + if entriesLeft == 1 then " item" else " items" + in + span + [ class "todo-count" ] + [ strong [] [ text (toString entriesLeft) ] + , text (item_ ++ " left") + ] + + +viewControlsFilters : String -> Html Msg +viewControlsFilters visibility = + ul + [ class "filters" ] + [ visibilitySwap "#/" "All" visibility + , text " " + , visibilitySwap "#/active" "Active" visibility + , text " " + , visibilitySwap "#/completed" "Completed" visibility + ] + + +visibilitySwap : String -> String -> String -> Html Msg +visibilitySwap uri visibility actualVisibility = + li + [ onClick (ChangeVisibility visibility) ] + [ a [ href uri, classList [("selected", visibility == actualVisibility)] ] + [ text visibility ] + ] + + +viewControlsClear : Int -> Html Msg +viewControlsClear entriesCompleted = + button + [ class "clear-completed" + , hidden (entriesCompleted == 0) + , onClick DeleteComplete + ] + [ text ("Clear completed (" ++ toString entriesCompleted ++ ")") + ] + + +infoFooter : Html msg +infoFooter = + footer [ class "info" ] + [ p [] [ text "Double-click to edit a todo" ] + , p [] + [ text "Written by " + , a [ href "https://github.com/evancz" ] [ text "Evan Czaplicki" ] + ] + , p [] + [ text "Part of " + , a [ href "http://todomvc.com" ] [ text "TodoMVC" ] + ] + ] diff --git a/bench/implementations/elm-0.17/elm-package.json b/bench/implementations/elm-0.17/elm-package.json new file mode 100644 index 0000000..ea3f7cd --- /dev/null +++ b/bench/implementations/elm-0.17/elm-package.json @@ -0,0 +1,15 @@ +{ + "version": "1.0.0", + "summary": "TodoMVC created with Elm and elm-html", + "repository": "https://github.com/evancz/elm-todomvc.git", + "license": "BSD3", + "source-directories": [ + "." + ], + "exposed-modules": [], + "dependencies": { + "elm-lang/core": "4.0.0 <= v < 5.0.0", + "elm-lang/html": "1.0.0 <= v < 2.0.0" + }, + "elm-version": "0.17.0 <= v < 0.18.0" +} diff --git a/bench/implementations/elm-0.17/elm.js b/bench/implementations/elm-0.17/elm.js new file mode 100644 index 0000000..1f33f8a --- /dev/null +++ b/bench/implementations/elm-0.17/elm.js @@ -0,0 +1,8512 @@ + +(function() { +'use strict'; + +function F2(fun) +{ + function wrapper(a) { return function(b) { return fun(a,b); }; } + wrapper.arity = 2; + wrapper.func = fun; + return wrapper; +} + +function F3(fun) +{ + function wrapper(a) { + return function(b) { return function(c) { return fun(a, b, c); }; }; + } + wrapper.arity = 3; + wrapper.func = fun; + return wrapper; +} + +function F4(fun) +{ + function wrapper(a) { return function(b) { return function(c) { + return function(d) { return fun(a, b, c, d); }; }; }; + } + wrapper.arity = 4; + wrapper.func = fun; + return wrapper; +} + +function F5(fun) +{ + function wrapper(a) { return function(b) { return function(c) { + return function(d) { return function(e) { return fun(a, b, c, d, e); }; }; }; }; + } + wrapper.arity = 5; + wrapper.func = fun; + return wrapper; +} + +function F6(fun) +{ + function wrapper(a) { return function(b) { return function(c) { + return function(d) { return function(e) { return function(f) { + return fun(a, b, c, d, e, f); }; }; }; }; }; + } + wrapper.arity = 6; + wrapper.func = fun; + return wrapper; +} + +function F7(fun) +{ + function wrapper(a) { return function(b) { return function(c) { + return function(d) { return function(e) { return function(f) { + return function(g) { return fun(a, b, c, d, e, f, g); }; }; }; }; }; }; + } + wrapper.arity = 7; + wrapper.func = fun; + return wrapper; +} + +function F8(fun) +{ + function wrapper(a) { return function(b) { return function(c) { + return function(d) { return function(e) { return function(f) { + return function(g) { return function(h) { + return fun(a, b, c, d, e, f, g, h); }; }; }; }; }; }; }; + } + wrapper.arity = 8; + wrapper.func = fun; + return wrapper; +} + +function F9(fun) +{ + function wrapper(a) { return function(b) { return function(c) { + return function(d) { return function(e) { return function(f) { + return function(g) { return function(h) { return function(i) { + return fun(a, b, c, d, e, f, g, h, i); }; }; }; }; }; }; }; }; + } + wrapper.arity = 9; + wrapper.func = fun; + return wrapper; +} + +function A2(fun, a, b) +{ + return fun.arity === 2 + ? fun.func(a, b) + : fun(a)(b); +} +function A3(fun, a, b, c) +{ + return fun.arity === 3 + ? fun.func(a, b, c) + : fun(a)(b)(c); +} +function A4(fun, a, b, c, d) +{ + return fun.arity === 4 + ? fun.func(a, b, c, d) + : fun(a)(b)(c)(d); +} +function A5(fun, a, b, c, d, e) +{ + return fun.arity === 5 + ? fun.func(a, b, c, d, e) + : fun(a)(b)(c)(d)(e); +} +function A6(fun, a, b, c, d, e, f) +{ + return fun.arity === 6 + ? fun.func(a, b, c, d, e, f) + : fun(a)(b)(c)(d)(e)(f); +} +function A7(fun, a, b, c, d, e, f, g) +{ + return fun.arity === 7 + ? fun.func(a, b, c, d, e, f, g) + : fun(a)(b)(c)(d)(e)(f)(g); +} +function A8(fun, a, b, c, d, e, f, g, h) +{ + return fun.arity === 8 + ? fun.func(a, b, c, d, e, f, g, h) + : fun(a)(b)(c)(d)(e)(f)(g)(h); +} +function A9(fun, a, b, c, d, e, f, g, h, i) +{ + return fun.arity === 9 + ? fun.func(a, b, c, d, e, f, g, h, i) + : fun(a)(b)(c)(d)(e)(f)(g)(h)(i); +} + +//import Native.List // + +var _elm_lang$core$Native_Array = function() { + +// A RRB-Tree has two distinct data types. +// Leaf -> "height" is always 0 +// "table" is an array of elements +// Node -> "height" is always greater than 0 +// "table" is an array of child nodes +// "lengths" is an array of accumulated lengths of the child nodes + +// M is the maximal table size. 32 seems fast. E is the allowed increase +// of search steps when concatting to find an index. Lower values will +// decrease balancing, but will increase search steps. +var M = 32; +var E = 2; + +// An empty array. +var empty = { + ctor: '_Array', + height: 0, + table: [] +}; + + +function get(i, array) +{ + if (i < 0 || i >= length(array)) + { + throw new Error( + 'Index ' + i + ' is out of range. Check the length of ' + + 'your array first or use getMaybe or getWithDefault.'); + } + return unsafeGet(i, array); +} + + +function unsafeGet(i, array) +{ + for (var x = array.height; x > 0; x--) + { + var slot = i >> (x * 5); + while (array.lengths[slot] <= i) + { + slot++; + } + if (slot > 0) + { + i -= array.lengths[slot - 1]; + } + array = array.table[slot]; + } + return array.table[i]; +} + + +// Sets the value at the index i. Only the nodes leading to i will get +// copied and updated. +function set(i, item, array) +{ + if (i < 0 || length(array) <= i) + { + return array; + } + return unsafeSet(i, item, array); +} + + +function unsafeSet(i, item, array) +{ + array = nodeCopy(array); + + if (array.height === 0) + { + array.table[i] = item; + } + else + { + var slot = getSlot(i, array); + if (slot > 0) + { + i -= array.lengths[slot - 1]; + } + array.table[slot] = unsafeSet(i, item, array.table[slot]); + } + return array; +} + + +function initialize(len, f) +{ + if (len <= 0) + { + return empty; + } + var h = Math.floor( Math.log(len) / Math.log(M) ); + return initialize_(f, h, 0, len); +} + +function initialize_(f, h, from, to) +{ + if (h === 0) + { + var table = new Array((to - from) % (M + 1)); + for (var i = 0; i < table.length; i++) + { + table[i] = f(from + i); + } + return { + ctor: '_Array', + height: 0, + table: table + }; + } + + var step = Math.pow(M, h); + var table = new Array(Math.ceil((to - from) / step)); + var lengths = new Array(table.length); + for (var i = 0; i < table.length; i++) + { + table[i] = initialize_(f, h - 1, from + (i * step), Math.min(from + ((i + 1) * step), to)); + lengths[i] = length(table[i]) + (i > 0 ? lengths[i-1] : 0); + } + return { + ctor: '_Array', + height: h, + table: table, + lengths: lengths + }; +} + +function fromList(list) +{ + if (list.ctor === '[]') + { + return empty; + } + + // Allocate M sized blocks (table) and write list elements to it. + var table = new Array(M); + var nodes = []; + var i = 0; + + while (list.ctor !== '[]') + { + table[i] = list._0; + list = list._1; + i++; + + // table is full, so we can push a leaf containing it into the + // next node. + if (i === M) + { + var leaf = { + ctor: '_Array', + height: 0, + table: table + }; + fromListPush(leaf, nodes); + table = new Array(M); + i = 0; + } + } + + // Maybe there is something left on the table. + if (i > 0) + { + var leaf = { + ctor: '_Array', + height: 0, + table: table.splice(0, i) + }; + fromListPush(leaf, nodes); + } + + // Go through all of the nodes and eventually push them into higher nodes. + for (var h = 0; h < nodes.length - 1; h++) + { + if (nodes[h].table.length > 0) + { + fromListPush(nodes[h], nodes); + } + } + + var head = nodes[nodes.length - 1]; + if (head.height > 0 && head.table.length === 1) + { + return head.table[0]; + } + else + { + return head; + } +} + +// Push a node into a higher node as a child. +function fromListPush(toPush, nodes) +{ + var h = toPush.height; + + // Maybe the node on this height does not exist. + if (nodes.length === h) + { + var node = { + ctor: '_Array', + height: h + 1, + table: [], + lengths: [] + }; + nodes.push(node); + } + + nodes[h].table.push(toPush); + var len = length(toPush); + if (nodes[h].lengths.length > 0) + { + len += nodes[h].lengths[nodes[h].lengths.length - 1]; + } + nodes[h].lengths.push(len); + + if (nodes[h].table.length === M) + { + fromListPush(nodes[h], nodes); + nodes[h] = { + ctor: '_Array', + height: h + 1, + table: [], + lengths: [] + }; + } +} + +// Pushes an item via push_ to the bottom right of a tree. +function push(item, a) +{ + var pushed = push_(item, a); + if (pushed !== null) + { + return pushed; + } + + var newTree = create(item, a.height); + return siblise(a, newTree); +} + +// Recursively tries to push an item to the bottom-right most +// tree possible. If there is no space left for the item, +// null will be returned. +function push_(item, a) +{ + // Handle resursion stop at leaf level. + if (a.height === 0) + { + if (a.table.length < M) + { + var newA = { + ctor: '_Array', + height: 0, + table: a.table.slice() + }; + newA.table.push(item); + return newA; + } + else + { + return null; + } + } + + // Recursively push + var pushed = push_(item, botRight(a)); + + // There was space in the bottom right tree, so the slot will + // be updated. + if (pushed !== null) + { + var newA = nodeCopy(a); + newA.table[newA.table.length - 1] = pushed; + newA.lengths[newA.lengths.length - 1]++; + return newA; + } + + // When there was no space left, check if there is space left + // for a new slot with a tree which contains only the item + // at the bottom. + if (a.table.length < M) + { + var newSlot = create(item, a.height - 1); + var newA = nodeCopy(a); + newA.table.push(newSlot); + newA.lengths.push(newA.lengths[newA.lengths.length - 1] + length(newSlot)); + return newA; + } + else + { + return null; + } +} + +// Converts an array into a list of elements. +function toList(a) +{ + return toList_(_elm_lang$core$Native_List.Nil, a); +} + +function toList_(list, a) +{ + for (var i = a.table.length - 1; i >= 0; i--) + { + list = + a.height === 0 + ? _elm_lang$core$Native_List.Cons(a.table[i], list) + : toList_(list, a.table[i]); + } + return list; +} + +// Maps a function over the elements of an array. +function map(f, a) +{ + var newA = { + ctor: '_Array', + height: a.height, + table: new Array(a.table.length) + }; + if (a.height > 0) + { + newA.lengths = a.lengths; + } + for (var i = 0; i < a.table.length; i++) + { + newA.table[i] = + a.height === 0 + ? f(a.table[i]) + : map(f, a.table[i]); + } + return newA; +} + +// Maps a function over the elements with their index as first argument. +function indexedMap(f, a) +{ + return indexedMap_(f, a, 0); +} + +function indexedMap_(f, a, from) +{ + var newA = { + ctor: '_Array', + height: a.height, + table: new Array(a.table.length) + }; + if (a.height > 0) + { + newA.lengths = a.lengths; + } + for (var i = 0; i < a.table.length; i++) + { + newA.table[i] = + a.height === 0 + ? A2(f, from + i, a.table[i]) + : indexedMap_(f, a.table[i], i == 0 ? from : from + a.lengths[i - 1]); + } + return newA; +} + +function foldl(f, b, a) +{ + if (a.height === 0) + { + for (var i = 0; i < a.table.length; i++) + { + b = A2(f, a.table[i], b); + } + } + else + { + for (var i = 0; i < a.table.length; i++) + { + b = foldl(f, b, a.table[i]); + } + } + return b; +} + +function foldr(f, b, a) +{ + if (a.height === 0) + { + for (var i = a.table.length; i--; ) + { + b = A2(f, a.table[i], b); + } + } + else + { + for (var i = a.table.length; i--; ) + { + b = foldr(f, b, a.table[i]); + } + } + return b; +} + +// TODO: currently, it slices the right, then the left. This can be +// optimized. +function slice(from, to, a) +{ + if (from < 0) + { + from += length(a); + } + if (to < 0) + { + to += length(a); + } + return sliceLeft(from, sliceRight(to, a)); +} + +function sliceRight(to, a) +{ + if (to === length(a)) + { + return a; + } + + // Handle leaf level. + if (a.height === 0) + { + var newA = { ctor:'_Array', height:0 }; + newA.table = a.table.slice(0, to); + return newA; + } + + // Slice the right recursively. + var right = getSlot(to, a); + var sliced = sliceRight(to - (right > 0 ? a.lengths[right - 1] : 0), a.table[right]); + + // Maybe the a node is not even needed, as sliced contains the whole slice. + if (right === 0) + { + return sliced; + } + + // Create new node. + var newA = { + ctor: '_Array', + height: a.height, + table: a.table.slice(0, right), + lengths: a.lengths.slice(0, right) + }; + if (sliced.table.length > 0) + { + newA.table[right] = sliced; + newA.lengths[right] = length(sliced) + (right > 0 ? newA.lengths[right - 1] : 0); + } + return newA; +} + +function sliceLeft(from, a) +{ + if (from === 0) + { + return a; + } + + // Handle leaf level. + if (a.height === 0) + { + var newA = { ctor:'_Array', height:0 }; + newA.table = a.table.slice(from, a.table.length + 1); + return newA; + } + + // Slice the left recursively. + var left = getSlot(from, a); + var sliced = sliceLeft(from - (left > 0 ? a.lengths[left - 1] : 0), a.table[left]); + + // Maybe the a node is not even needed, as sliced contains the whole slice. + if (left === a.table.length - 1) + { + return sliced; + } + + // Create new node. + var newA = { + ctor: '_Array', + height: a.height, + table: a.table.slice(left, a.table.length + 1), + lengths: new Array(a.table.length - left) + }; + newA.table[0] = sliced; + var len = 0; + for (var i = 0; i < newA.table.length; i++) + { + len += length(newA.table[i]); + newA.lengths[i] = len; + } + + return newA; +} + +// Appends two trees. +function append(a,b) +{ + if (a.table.length === 0) + { + return b; + } + if (b.table.length === 0) + { + return a; + } + + var c = append_(a, b); + + // Check if both nodes can be crunshed together. + if (c[0].table.length + c[1].table.length <= M) + { + if (c[0].table.length === 0) + { + return c[1]; + } + if (c[1].table.length === 0) + { + return c[0]; + } + + // Adjust .table and .lengths + c[0].table = c[0].table.concat(c[1].table); + if (c[0].height > 0) + { + var len = length(c[0]); + for (var i = 0; i < c[1].lengths.length; i++) + { + c[1].lengths[i] += len; + } + c[0].lengths = c[0].lengths.concat(c[1].lengths); + } + + return c[0]; + } + + if (c[0].height > 0) + { + var toRemove = calcToRemove(a, b); + if (toRemove > E) + { + c = shuffle(c[0], c[1], toRemove); + } + } + + return siblise(c[0], c[1]); +} + +// Returns an array of two nodes; right and left. One node _may_ be empty. +function append_(a, b) +{ + if (a.height === 0 && b.height === 0) + { + return [a, b]; + } + + if (a.height !== 1 || b.height !== 1) + { + if (a.height === b.height) + { + a = nodeCopy(a); + b = nodeCopy(b); + var appended = append_(botRight(a), botLeft(b)); + + insertRight(a, appended[1]); + insertLeft(b, appended[0]); + } + else if (a.height > b.height) + { + a = nodeCopy(a); + var appended = append_(botRight(a), b); + + insertRight(a, appended[0]); + b = parentise(appended[1], appended[1].height + 1); + } + else + { + b = nodeCopy(b); + var appended = append_(a, botLeft(b)); + + var left = appended[0].table.length === 0 ? 0 : 1; + var right = left === 0 ? 1 : 0; + insertLeft(b, appended[left]); + a = parentise(appended[right], appended[right].height + 1); + } + } + + // Check if balancing is needed and return based on that. + if (a.table.length === 0 || b.table.length === 0) + { + return [a, b]; + } + + var toRemove = calcToRemove(a, b); + if (toRemove <= E) + { + return [a, b]; + } + return shuffle(a, b, toRemove); +} + +// Helperfunctions for append_. Replaces a child node at the side of the parent. +function insertRight(parent, node) +{ + var index = parent.table.length - 1; + parent.table[index] = node; + parent.lengths[index] = length(node); + parent.lengths[index] += index > 0 ? parent.lengths[index - 1] : 0; +} + +function insertLeft(parent, node) +{ + if (node.table.length > 0) + { + parent.table[0] = node; + parent.lengths[0] = length(node); + + var len = length(parent.table[0]); + for (var i = 1; i < parent.lengths.length; i++) + { + len += length(parent.table[i]); + parent.lengths[i] = len; + } + } + else + { + parent.table.shift(); + for (var i = 1; i < parent.lengths.length; i++) + { + parent.lengths[i] = parent.lengths[i] - parent.lengths[0]; + } + parent.lengths.shift(); + } +} + +// Returns the extra search steps for E. Refer to the paper. +function calcToRemove(a, b) +{ + var subLengths = 0; + for (var i = 0; i < a.table.length; i++) + { + subLengths += a.table[i].table.length; + } + for (var i = 0; i < b.table.length; i++) + { + subLengths += b.table[i].table.length; + } + + var toRemove = a.table.length + b.table.length; + return toRemove - (Math.floor((subLengths - 1) / M) + 1); +} + +// get2, set2 and saveSlot are helpers for accessing elements over two arrays. +function get2(a, b, index) +{ + return index < a.length + ? a[index] + : b[index - a.length]; +} + +function set2(a, b, index, value) +{ + if (index < a.length) + { + a[index] = value; + } + else + { + b[index - a.length] = value; + } +} + +function saveSlot(a, b, index, slot) +{ + set2(a.table, b.table, index, slot); + + var l = (index === 0 || index === a.lengths.length) + ? 0 + : get2(a.lengths, a.lengths, index - 1); + + set2(a.lengths, b.lengths, index, l + length(slot)); +} + +// Creates a node or leaf with a given length at their arrays for perfomance. +// Is only used by shuffle. +function createNode(h, length) +{ + if (length < 0) + { + length = 0; + } + var a = { + ctor: '_Array', + height: h, + table: new Array(length) + }; + if (h > 0) + { + a.lengths = new Array(length); + } + return a; +} + +// Returns an array of two balanced nodes. +function shuffle(a, b, toRemove) +{ + var newA = createNode(a.height, Math.min(M, a.table.length + b.table.length - toRemove)); + var newB = createNode(a.height, newA.table.length - (a.table.length + b.table.length - toRemove)); + + // Skip the slots with size M. More precise: copy the slot references + // to the new node + var read = 0; + while (get2(a.table, b.table, read).table.length % M === 0) + { + set2(newA.table, newB.table, read, get2(a.table, b.table, read)); + set2(newA.lengths, newB.lengths, read, get2(a.lengths, b.lengths, read)); + read++; + } + + // Pulling items from left to right, caching in a slot before writing + // it into the new nodes. + var write = read; + var slot = new createNode(a.height - 1, 0); + var from = 0; + + // If the current slot is still containing data, then there will be at + // least one more write, so we do not break this loop yet. + while (read - write - (slot.table.length > 0 ? 1 : 0) < toRemove) + { + // Find out the max possible items for copying. + var source = get2(a.table, b.table, read); + var to = Math.min(M - slot.table.length, source.table.length); + + // Copy and adjust size table. + slot.table = slot.table.concat(source.table.slice(from, to)); + if (slot.height > 0) + { + var len = slot.lengths.length; + for (var i = len; i < len + to - from; i++) + { + slot.lengths[i] = length(slot.table[i]); + slot.lengths[i] += (i > 0 ? slot.lengths[i - 1] : 0); + } + } + + from += to; + + // Only proceed to next slots[i] if the current one was + // fully copied. + if (source.table.length <= to) + { + read++; from = 0; + } + + // Only create a new slot if the current one is filled up. + if (slot.table.length === M) + { + saveSlot(newA, newB, write, slot); + slot = createNode(a.height - 1, 0); + write++; + } + } + + // Cleanup after the loop. Copy the last slot into the new nodes. + if (slot.table.length > 0) + { + saveSlot(newA, newB, write, slot); + write++; + } + + // Shift the untouched slots to the left + while (read < a.table.length + b.table.length ) + { + saveSlot(newA, newB, write, get2(a.table, b.table, read)); + read++; + write++; + } + + return [newA, newB]; +} + +// Navigation functions +function botRight(a) +{ + return a.table[a.table.length - 1]; +} +function botLeft(a) +{ + return a.table[0]; +} + +// Copies a node for updating. Note that you should not use this if +// only updating only one of "table" or "lengths" for performance reasons. +function nodeCopy(a) +{ + var newA = { + ctor: '_Array', + height: a.height, + table: a.table.slice() + }; + if (a.height > 0) + { + newA.lengths = a.lengths.slice(); + } + return newA; +} + +// Returns how many items are in the tree. +function length(array) +{ + if (array.height === 0) + { + return array.table.length; + } + else + { + return array.lengths[array.lengths.length - 1]; + } +} + +// Calculates in which slot of "table" the item probably is, then +// find the exact slot via forward searching in "lengths". Returns the index. +function getSlot(i, a) +{ + var slot = i >> (5 * a.height); + while (a.lengths[slot] <= i) + { + slot++; + } + return slot; +} + +// Recursively creates a tree with a given height containing +// only the given item. +function create(item, h) +{ + if (h === 0) + { + return { + ctor: '_Array', + height: 0, + table: [item] + }; + } + return { + ctor: '_Array', + height: h, + table: [create(item, h - 1)], + lengths: [1] + }; +} + +// Recursively creates a tree that contains the given tree. +function parentise(tree, h) +{ + if (h === tree.height) + { + return tree; + } + + return { + ctor: '_Array', + height: h, + table: [parentise(tree, h - 1)], + lengths: [length(tree)] + }; +} + +// Emphasizes blood brotherhood beneath two trees. +function siblise(a, b) +{ + return { + ctor: '_Array', + height: a.height + 1, + table: [a, b], + lengths: [length(a), length(a) + length(b)] + }; +} + +function toJSArray(a) +{ + var jsArray = new Array(length(a)); + toJSArray_(jsArray, 0, a); + return jsArray; +} + +function toJSArray_(jsArray, i, a) +{ + for (var t = 0; t < a.table.length; t++) + { + if (a.height === 0) + { + jsArray[i + t] = a.table[t]; + } + else + { + var inc = t === 0 ? 0 : a.lengths[t - 1]; + toJSArray_(jsArray, i + inc, a.table[t]); + } + } +} + +function fromJSArray(jsArray) +{ + if (jsArray.length === 0) + { + return empty; + } + var h = Math.floor(Math.log(jsArray.length) / Math.log(M)); + return fromJSArray_(jsArray, h, 0, jsArray.length); +} + +function fromJSArray_(jsArray, h, from, to) +{ + if (h === 0) + { + return { + ctor: '_Array', + height: 0, + table: jsArray.slice(from, to) + }; + } + + var step = Math.pow(M, h); + var table = new Array(Math.ceil((to - from) / step)); + var lengths = new Array(table.length); + for (var i = 0; i < table.length; i++) + { + table[i] = fromJSArray_(jsArray, h - 1, from + (i * step), Math.min(from + ((i + 1) * step), to)); + lengths[i] = length(table[i]) + (i > 0 ? lengths[i - 1] : 0); + } + return { + ctor: '_Array', + height: h, + table: table, + lengths: lengths + }; +} + +return { + empty: empty, + fromList: fromList, + toList: toList, + initialize: F2(initialize), + append: F2(append), + push: F2(push), + slice: F3(slice), + get: F2(get), + set: F3(set), + map: F2(map), + indexedMap: F2(indexedMap), + foldl: F3(foldl), + foldr: F3(foldr), + length: length, + + toJSArray: toJSArray, + fromJSArray: fromJSArray +}; + +}(); +//import Native.Utils // + +var _elm_lang$core$Native_Basics = function() { + +function div(a, b) +{ + return (a / b) | 0; +} +function rem(a, b) +{ + return a % b; +} +function mod(a, b) +{ + if (b === 0) + { + throw new Error('Cannot perform mod 0. Division by zero error.'); + } + var r = a % b; + var m = a === 0 ? 0 : (b > 0 ? (a >= 0 ? r : r + b) : -mod(-a, -b)); + + return m === b ? 0 : m; +} +function logBase(base, n) +{ + return Math.log(n) / Math.log(base); +} +function negate(n) +{ + return -n; +} +function abs(n) +{ + return n < 0 ? -n : n; +} + +function min(a, b) +{ + return _elm_lang$core$Native_Utils.cmp(a, b) < 0 ? a : b; +} +function max(a, b) +{ + return _elm_lang$core$Native_Utils.cmp(a, b) > 0 ? a : b; +} +function clamp(lo, hi, n) +{ + return _elm_lang$core$Native_Utils.cmp(n, lo) < 0 + ? lo + : _elm_lang$core$Native_Utils.cmp(n, hi) > 0 + ? hi + : n; +} + +var ord = ['LT', 'EQ', 'GT']; + +function compare(x, y) +{ + return { ctor: ord[_elm_lang$core$Native_Utils.cmp(x, y) + 1] }; +} + +function xor(a, b) +{ + return a !== b; +} +function not(b) +{ + return !b; +} +function isInfinite(n) +{ + return n === Infinity || n === -Infinity; +} + +function truncate(n) +{ + return n | 0; +} + +function degrees(d) +{ + return d * Math.PI / 180; +} +function turns(t) +{ + return 2 * Math.PI * t; +} +function fromPolar(point) +{ + var r = point._0; + var t = point._1; + return _elm_lang$core$Native_Utils.Tuple2(r * Math.cos(t), r * Math.sin(t)); +} +function toPolar(point) +{ + var x = point._0; + var y = point._1; + return _elm_lang$core$Native_Utils.Tuple2(Math.sqrt(x * x + y * y), Math.atan2(y, x)); +} + +return { + div: F2(div), + rem: F2(rem), + mod: F2(mod), + + pi: Math.PI, + e: Math.E, + cos: Math.cos, + sin: Math.sin, + tan: Math.tan, + acos: Math.acos, + asin: Math.asin, + atan: Math.atan, + atan2: F2(Math.atan2), + + degrees: degrees, + turns: turns, + fromPolar: fromPolar, + toPolar: toPolar, + + sqrt: Math.sqrt, + logBase: F2(logBase), + negate: negate, + abs: abs, + min: F2(min), + max: F2(max), + clamp: F3(clamp), + compare: F2(compare), + + xor: F2(xor), + not: not, + + truncate: truncate, + ceiling: Math.ceil, + floor: Math.floor, + round: Math.round, + toFloat: function(x) { return x; }, + isNaN: isNaN, + isInfinite: isInfinite +}; + +}(); +//import // + +var _elm_lang$core$Native_Utils = function() { + +// COMPARISONS + +function eq(x, y) +{ + var stack = []; + var isEqual = eqHelp(x, y, 0, stack); + var pair; + while (isEqual && (pair = stack.pop())) + { + isEqual = eqHelp(pair.x, pair.y, 0, stack); + } + return isEqual; +} + + +function eqHelp(x, y, depth, stack) +{ + if (depth > 100) + { + stack.push({ x: x, y: y }); + return true; + } + + if (x === y) + { + return true; + } + + if (typeof x !== 'object') + { + if (typeof x === 'function') + { + throw new Error( + 'Trying to use `(==)` on functions. There is no way to know if functions are "the same" in the Elm sense.' + + ' Read more about this at http://package.elm-lang.org/packages/elm-lang/core/latest/Basics#==' + + ' which describes why it is this way and what the better version will look like.' + ); + } + return false; + } + + if (x === null || y === null) + { + return false + } + + if (x instanceof Date) + { + return x.getTime() === y.getTime(); + } + + if (!('ctor' in x)) + { + for (var key in x) + { + if (!eqHelp(x[key], y[key], depth + 1, stack)) + { + return false; + } + } + return true; + } + + // convert Dicts and Sets to lists + if (x.ctor === 'RBNode_elm_builtin' || x.ctor === 'RBEmpty_elm_builtin') + { + x = _elm_lang$core$Dict$toList(x); + y = _elm_lang$core$Dict$toList(y); + } + if (x.ctor === 'Set_elm_builtin') + { + x = _elm_lang$core$Set$toList(x); + y = _elm_lang$core$Set$toList(y); + } + + // check if lists are equal without recursion + if (x.ctor === '::') + { + var a = x; + var b = y; + while (a.ctor === '::' && b.ctor === '::') + { + if (!eqHelp(a._0, b._0, depth + 1, stack)) + { + return false; + } + a = a._1; + b = b._1; + } + return a.ctor === b.ctor; + } + + // check if Arrays are equal + if (x.ctor === '_Array') + { + var xs = _elm_lang$core$Native_Array.toJSArray(x); + var ys = _elm_lang$core$Native_Array.toJSArray(y); + if (xs.length !== ys.length) + { + return false; + } + for (var i = 0; i < xs.length; i++) + { + if (!eqHelp(xs[i], ys[i], depth + 1, stack)) + { + return false; + } + } + return true; + } + + if (!eqHelp(x.ctor, y.ctor, depth + 1, stack)) + { + return false; + } + + for (var key in x) + { + if (!eqHelp(x[key], y[key], depth + 1, stack)) + { + return false; + } + } + return true; +} + +// Code in Generate/JavaScript.hs, Basics.js, and List.js depends on +// the particular integer values assigned to LT, EQ, and GT. + +var LT = -1, EQ = 0, GT = 1; + +function cmp(x, y) +{ + if (typeof x !== 'object') + { + return x === y ? EQ : x < y ? LT : GT; + } + + if (x instanceof String) + { + var a = x.valueOf(); + var b = y.valueOf(); + return a === b ? EQ : a < b ? LT : GT; + } + + if (x.ctor === '::' || x.ctor === '[]') + { + while (x.ctor === '::' && y.ctor === '::') + { + var ord = cmp(x._0, y._0); + if (ord !== EQ) + { + return ord; + } + x = x._1; + y = y._1; + } + return x.ctor === y.ctor ? EQ : x.ctor === '[]' ? LT : GT; + } + + if (x.ctor.slice(0, 6) === '_Tuple') + { + var ord; + var n = x.ctor.slice(6) - 0; + var err = 'cannot compare tuples with more than 6 elements.'; + if (n === 0) return EQ; + if (n >= 1) { ord = cmp(x._0, y._0); if (ord !== EQ) return ord; + if (n >= 2) { ord = cmp(x._1, y._1); if (ord !== EQ) return ord; + if (n >= 3) { ord = cmp(x._2, y._2); if (ord !== EQ) return ord; + if (n >= 4) { ord = cmp(x._3, y._3); if (ord !== EQ) return ord; + if (n >= 5) { ord = cmp(x._4, y._4); if (ord !== EQ) return ord; + if (n >= 6) { ord = cmp(x._5, y._5); if (ord !== EQ) return ord; + if (n >= 7) throw new Error('Comparison error: ' + err); } } } } } } + return EQ; + } + + throw new Error( + 'Comparison error: comparison is only defined on ints, ' + + 'floats, times, chars, strings, lists of comparable values, ' + + 'and tuples of comparable values.' + ); +} + + +// COMMON VALUES + +var Tuple0 = { + ctor: '_Tuple0' +}; + +function Tuple2(x, y) +{ + return { + ctor: '_Tuple2', + _0: x, + _1: y + }; +} + +function chr(c) +{ + return new String(c); +} + + +// GUID + +var count = 0; +function guid(_) +{ + return count++; +} + + +// RECORDS + +function update(oldRecord, updatedFields) +{ + var newRecord = {}; + for (var key in oldRecord) + { + var value = (key in updatedFields) ? updatedFields[key] : oldRecord[key]; + newRecord[key] = value; + } + return newRecord; +} + + +//// LIST STUFF //// + +var Nil = { ctor: '[]' }; + +function Cons(hd, tl) +{ + return { + ctor: '::', + _0: hd, + _1: tl + }; +} + +function append(xs, ys) +{ + // append Strings + if (typeof xs === 'string') + { + return xs + ys; + } + + // append Lists + if (xs.ctor === '[]') + { + return ys; + } + var root = Cons(xs._0, Nil); + var curr = root; + xs = xs._1; + while (xs.ctor !== '[]') + { + curr._1 = Cons(xs._0, Nil); + xs = xs._1; + curr = curr._1; + } + curr._1 = ys; + return root; +} + + +// CRASHES + +function crash(moduleName, region) +{ + return function(message) { + throw new Error( + 'Ran into a `Debug.crash` in module `' + moduleName + '` ' + regionToString(region) + '\n' + + 'The message provided by the code author is:\n\n ' + + message + ); + }; +} + +function crashCase(moduleName, region, value) +{ + return function(message) { + throw new Error( + 'Ran into a `Debug.crash` in module `' + moduleName + '`\n\n' + + 'This was caused by the `case` expression ' + regionToString(region) + '.\n' + + 'One of the branches ended with a crash and the following value got through:\n\n ' + toString(value) + '\n\n' + + 'The message provided by the code author is:\n\n ' + + message + ); + }; +} + +function regionToString(region) +{ + if (region.start.line == region.end.line) + { + return 'on line ' + region.start.line; + } + return 'between lines ' + region.start.line + ' and ' + region.end.line; +} + + +// TO STRING + +function toString(v) +{ + var type = typeof v; + if (type === 'function') + { + var name = v.func ? v.func.name : v.name; + return ''; + } + + if (type === 'boolean') + { + return v ? 'True' : 'False'; + } + + if (type === 'number') + { + return v + ''; + } + + if (v instanceof String) + { + return '\'' + addSlashes(v, true) + '\''; + } + + if (type === 'string') + { + return '"' + addSlashes(v, false) + '"'; + } + + if (v === null) + { + return 'null'; + } + + if (type === 'object' && 'ctor' in v) + { + var ctorStarter = v.ctor.substring(0, 5); + + if (ctorStarter === '_Tupl') + { + var output = []; + for (var k in v) + { + if (k === 'ctor') continue; + output.push(toString(v[k])); + } + return '(' + output.join(',') + ')'; + } + + if (ctorStarter === '_Task') + { + return '' + } + + if (v.ctor === '_Array') + { + var list = _elm_lang$core$Array$toList(v); + return 'Array.fromList ' + toString(list); + } + + if (v.ctor === '') + { + return ''; + } + + if (v.ctor === '_Process') + { + return ''; + } + + if (v.ctor === '::') + { + var output = '[' + toString(v._0); + v = v._1; + while (v.ctor === '::') + { + output += ',' + toString(v._0); + v = v._1; + } + return output + ']'; + } + + if (v.ctor === '[]') + { + return '[]'; + } + + if (v.ctor === 'Set_elm_builtin') + { + return 'Set.fromList ' + toString(_elm_lang$core$Set$toList(v)); + } + + if (v.ctor === 'RBNode_elm_builtin' || v.ctor === 'RBEmpty_elm_builtin') + { + return 'Dict.fromList ' + toString(_elm_lang$core$Dict$toList(v)); + } + + var output = ''; + for (var i in v) + { + if (i === 'ctor') continue; + var str = toString(v[i]); + var c0 = str[0]; + var parenless = c0 === '{' || c0 === '(' || c0 === '<' || c0 === '"' || str.indexOf(' ') < 0; + output += ' ' + (parenless ? str : '(' + str + ')'); + } + return v.ctor + output; + } + + if (type === 'object') + { + if (v instanceof Date) + { + return '<' + v.toString() + '>'; + } + + if (v.elm_web_socket) + { + return ''; + } + + var output = []; + for (var k in v) + { + output.push(k + ' = ' + toString(v[k])); + } + if (output.length === 0) + { + return '{}'; + } + return '{ ' + output.join(', ') + ' }'; + } + + return ''; +} + +function addSlashes(str, isChar) +{ + var s = str.replace(/\\/g, '\\\\') + .replace(/\n/g, '\\n') + .replace(/\t/g, '\\t') + .replace(/\r/g, '\\r') + .replace(/\v/g, '\\v') + .replace(/\0/g, '\\0'); + if (isChar) + { + return s.replace(/\'/g, '\\\''); + } + else + { + return s.replace(/\"/g, '\\"'); + } +} + + +return { + eq: eq, + cmp: cmp, + Tuple0: Tuple0, + Tuple2: Tuple2, + chr: chr, + update: update, + guid: guid, + + append: F2(append), + + crash: crash, + crashCase: crashCase, + + toString: toString +}; + +}(); +var _elm_lang$core$Basics$uncurry = F2( + function (f, _p0) { + var _p1 = _p0; + return A2(f, _p1._0, _p1._1); + }); +var _elm_lang$core$Basics$curry = F3( + function (f, a, b) { + return f( + {ctor: '_Tuple2', _0: a, _1: b}); + }); +var _elm_lang$core$Basics$flip = F3( + function (f, b, a) { + return A2(f, a, b); + }); +var _elm_lang$core$Basics$snd = function (_p2) { + var _p3 = _p2; + return _p3._1; +}; +var _elm_lang$core$Basics$fst = function (_p4) { + var _p5 = _p4; + return _p5._0; +}; +var _elm_lang$core$Basics$always = F2( + function (a, _p6) { + return a; + }); +var _elm_lang$core$Basics$identity = function (x) { + return x; +}; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['<|'] = F2( + function (f, x) { + return f(x); + }); +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['|>'] = F2( + function (x, f) { + return f(x); + }); +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['>>'] = F3( + function (f, g, x) { + return g( + f(x)); + }); +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['<<'] = F3( + function (g, f, x) { + return g( + f(x)); + }); +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['++'] = _elm_lang$core$Native_Utils.append; +var _elm_lang$core$Basics$toString = _elm_lang$core$Native_Utils.toString; +var _elm_lang$core$Basics$isInfinite = _elm_lang$core$Native_Basics.isInfinite; +var _elm_lang$core$Basics$isNaN = _elm_lang$core$Native_Basics.isNaN; +var _elm_lang$core$Basics$toFloat = _elm_lang$core$Native_Basics.toFloat; +var _elm_lang$core$Basics$ceiling = _elm_lang$core$Native_Basics.ceiling; +var _elm_lang$core$Basics$floor = _elm_lang$core$Native_Basics.floor; +var _elm_lang$core$Basics$truncate = _elm_lang$core$Native_Basics.truncate; +var _elm_lang$core$Basics$round = _elm_lang$core$Native_Basics.round; +var _elm_lang$core$Basics$not = _elm_lang$core$Native_Basics.not; +var _elm_lang$core$Basics$xor = _elm_lang$core$Native_Basics.xor; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['||'] = _elm_lang$core$Native_Basics.or; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['&&'] = _elm_lang$core$Native_Basics.and; +var _elm_lang$core$Basics$max = _elm_lang$core$Native_Basics.max; +var _elm_lang$core$Basics$min = _elm_lang$core$Native_Basics.min; +var _elm_lang$core$Basics$compare = _elm_lang$core$Native_Basics.compare; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['>='] = _elm_lang$core$Native_Basics.ge; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['<='] = _elm_lang$core$Native_Basics.le; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['>'] = _elm_lang$core$Native_Basics.gt; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['<'] = _elm_lang$core$Native_Basics.lt; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['/='] = _elm_lang$core$Native_Basics.neq; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['=='] = _elm_lang$core$Native_Basics.eq; +var _elm_lang$core$Basics$e = _elm_lang$core$Native_Basics.e; +var _elm_lang$core$Basics$pi = _elm_lang$core$Native_Basics.pi; +var _elm_lang$core$Basics$clamp = _elm_lang$core$Native_Basics.clamp; +var _elm_lang$core$Basics$logBase = _elm_lang$core$Native_Basics.logBase; +var _elm_lang$core$Basics$abs = _elm_lang$core$Native_Basics.abs; +var _elm_lang$core$Basics$negate = _elm_lang$core$Native_Basics.negate; +var _elm_lang$core$Basics$sqrt = _elm_lang$core$Native_Basics.sqrt; +var _elm_lang$core$Basics$atan2 = _elm_lang$core$Native_Basics.atan2; +var _elm_lang$core$Basics$atan = _elm_lang$core$Native_Basics.atan; +var _elm_lang$core$Basics$asin = _elm_lang$core$Native_Basics.asin; +var _elm_lang$core$Basics$acos = _elm_lang$core$Native_Basics.acos; +var _elm_lang$core$Basics$tan = _elm_lang$core$Native_Basics.tan; +var _elm_lang$core$Basics$sin = _elm_lang$core$Native_Basics.sin; +var _elm_lang$core$Basics$cos = _elm_lang$core$Native_Basics.cos; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['^'] = _elm_lang$core$Native_Basics.exp; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['%'] = _elm_lang$core$Native_Basics.mod; +var _elm_lang$core$Basics$rem = _elm_lang$core$Native_Basics.rem; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['//'] = _elm_lang$core$Native_Basics.div; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['/'] = _elm_lang$core$Native_Basics.floatDiv; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['*'] = _elm_lang$core$Native_Basics.mul; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['-'] = _elm_lang$core$Native_Basics.sub; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['+'] = _elm_lang$core$Native_Basics.add; +var _elm_lang$core$Basics$toPolar = _elm_lang$core$Native_Basics.toPolar; +var _elm_lang$core$Basics$fromPolar = _elm_lang$core$Native_Basics.fromPolar; +var _elm_lang$core$Basics$turns = _elm_lang$core$Native_Basics.turns; +var _elm_lang$core$Basics$degrees = _elm_lang$core$Native_Basics.degrees; +var _elm_lang$core$Basics$radians = function (t) { + return t; +}; +var _elm_lang$core$Basics$GT = {ctor: 'GT'}; +var _elm_lang$core$Basics$EQ = {ctor: 'EQ'}; +var _elm_lang$core$Basics$LT = {ctor: 'LT'}; +var _elm_lang$core$Basics$Never = function (a) { + return {ctor: 'Never', _0: a}; +}; + +var _elm_lang$core$Maybe$withDefault = F2( + function ($default, maybe) { + var _p0 = maybe; + if (_p0.ctor === 'Just') { + return _p0._0; + } else { + return $default; + } + }); +var _elm_lang$core$Maybe$Nothing = {ctor: 'Nothing'}; +var _elm_lang$core$Maybe$oneOf = function (maybes) { + oneOf: + while (true) { + var _p1 = maybes; + if (_p1.ctor === '[]') { + return _elm_lang$core$Maybe$Nothing; + } else { + var _p3 = _p1._0; + var _p2 = _p3; + if (_p2.ctor === 'Nothing') { + var _v3 = _p1._1; + maybes = _v3; + continue oneOf; + } else { + return _p3; + } + } + } +}; +var _elm_lang$core$Maybe$andThen = F2( + function (maybeValue, callback) { + var _p4 = maybeValue; + if (_p4.ctor === 'Just') { + return callback(_p4._0); + } else { + return _elm_lang$core$Maybe$Nothing; + } + }); +var _elm_lang$core$Maybe$Just = function (a) { + return {ctor: 'Just', _0: a}; +}; +var _elm_lang$core$Maybe$map = F2( + function (f, maybe) { + var _p5 = maybe; + if (_p5.ctor === 'Just') { + return _elm_lang$core$Maybe$Just( + f(_p5._0)); + } else { + return _elm_lang$core$Maybe$Nothing; + } + }); +var _elm_lang$core$Maybe$map2 = F3( + function (func, ma, mb) { + var _p6 = {ctor: '_Tuple2', _0: ma, _1: mb}; + if (((_p6.ctor === '_Tuple2') && (_p6._0.ctor === 'Just')) && (_p6._1.ctor === 'Just')) { + return _elm_lang$core$Maybe$Just( + A2(func, _p6._0._0, _p6._1._0)); + } else { + return _elm_lang$core$Maybe$Nothing; + } + }); +var _elm_lang$core$Maybe$map3 = F4( + function (func, ma, mb, mc) { + var _p7 = {ctor: '_Tuple3', _0: ma, _1: mb, _2: mc}; + if ((((_p7.ctor === '_Tuple3') && (_p7._0.ctor === 'Just')) && (_p7._1.ctor === 'Just')) && (_p7._2.ctor === 'Just')) { + return _elm_lang$core$Maybe$Just( + A3(func, _p7._0._0, _p7._1._0, _p7._2._0)); + } else { + return _elm_lang$core$Maybe$Nothing; + } + }); +var _elm_lang$core$Maybe$map4 = F5( + function (func, ma, mb, mc, md) { + var _p8 = {ctor: '_Tuple4', _0: ma, _1: mb, _2: mc, _3: md}; + if (((((_p8.ctor === '_Tuple4') && (_p8._0.ctor === 'Just')) && (_p8._1.ctor === 'Just')) && (_p8._2.ctor === 'Just')) && (_p8._3.ctor === 'Just')) { + return _elm_lang$core$Maybe$Just( + A4(func, _p8._0._0, _p8._1._0, _p8._2._0, _p8._3._0)); + } else { + return _elm_lang$core$Maybe$Nothing; + } + }); +var _elm_lang$core$Maybe$map5 = F6( + function (func, ma, mb, mc, md, me) { + var _p9 = {ctor: '_Tuple5', _0: ma, _1: mb, _2: mc, _3: md, _4: me}; + if ((((((_p9.ctor === '_Tuple5') && (_p9._0.ctor === 'Just')) && (_p9._1.ctor === 'Just')) && (_p9._2.ctor === 'Just')) && (_p9._3.ctor === 'Just')) && (_p9._4.ctor === 'Just')) { + return _elm_lang$core$Maybe$Just( + A5(func, _p9._0._0, _p9._1._0, _p9._2._0, _p9._3._0, _p9._4._0)); + } else { + return _elm_lang$core$Maybe$Nothing; + } + }); + +//import Native.Utils // + +var _elm_lang$core$Native_List = function() { + +var Nil = { ctor: '[]' }; + +function Cons(hd, tl) +{ + return { ctor: '::', _0: hd, _1: tl }; +} + +function fromArray(arr) +{ + var out = Nil; + for (var i = arr.length; i--; ) + { + out = Cons(arr[i], out); + } + return out; +} + +function toArray(xs) +{ + var out = []; + while (xs.ctor !== '[]') + { + out.push(xs._0); + xs = xs._1; + } + return out; +} + + +function range(lo, hi) +{ + var list = Nil; + if (lo <= hi) + { + do + { + list = Cons(hi, list); + } + while (hi-- > lo); + } + return list; +} + +function foldr(f, b, xs) +{ + var arr = toArray(xs); + var acc = b; + for (var i = arr.length; i--; ) + { + acc = A2(f, arr[i], acc); + } + return acc; +} + +function map2(f, xs, ys) +{ + var arr = []; + while (xs.ctor !== '[]' && ys.ctor !== '[]') + { + arr.push(A2(f, xs._0, ys._0)); + xs = xs._1; + ys = ys._1; + } + return fromArray(arr); +} + +function map3(f, xs, ys, zs) +{ + var arr = []; + while (xs.ctor !== '[]' && ys.ctor !== '[]' && zs.ctor !== '[]') + { + arr.push(A3(f, xs._0, ys._0, zs._0)); + xs = xs._1; + ys = ys._1; + zs = zs._1; + } + return fromArray(arr); +} + +function map4(f, ws, xs, ys, zs) +{ + var arr = []; + while ( ws.ctor !== '[]' + && xs.ctor !== '[]' + && ys.ctor !== '[]' + && zs.ctor !== '[]') + { + arr.push(A4(f, ws._0, xs._0, ys._0, zs._0)); + ws = ws._1; + xs = xs._1; + ys = ys._1; + zs = zs._1; + } + return fromArray(arr); +} + +function map5(f, vs, ws, xs, ys, zs) +{ + var arr = []; + while ( vs.ctor !== '[]' + && ws.ctor !== '[]' + && xs.ctor !== '[]' + && ys.ctor !== '[]' + && zs.ctor !== '[]') + { + arr.push(A5(f, vs._0, ws._0, xs._0, ys._0, zs._0)); + vs = vs._1; + ws = ws._1; + xs = xs._1; + ys = ys._1; + zs = zs._1; + } + return fromArray(arr); +} + +function sortBy(f, xs) +{ + return fromArray(toArray(xs).sort(function(a, b) { + return _elm_lang$core$Native_Utils.cmp(f(a), f(b)); + })); +} + +function sortWith(f, xs) +{ + return fromArray(toArray(xs).sort(function(a, b) { + var ord = f(a)(b).ctor; + return ord === 'EQ' ? 0 : ord === 'LT' ? -1 : 1; + })); +} + +return { + Nil: Nil, + Cons: Cons, + cons: F2(Cons), + toArray: toArray, + fromArray: fromArray, + range: range, + + foldr: F3(foldr), + + map2: F3(map2), + map3: F4(map3), + map4: F5(map4), + map5: F6(map5), + sortBy: F2(sortBy), + sortWith: F2(sortWith) +}; + +}(); +var _elm_lang$core$List$sortWith = _elm_lang$core$Native_List.sortWith; +var _elm_lang$core$List$sortBy = _elm_lang$core$Native_List.sortBy; +var _elm_lang$core$List$sort = function (xs) { + return A2(_elm_lang$core$List$sortBy, _elm_lang$core$Basics$identity, xs); +}; +var _elm_lang$core$List$drop = F2( + function (n, list) { + drop: + while (true) { + if (_elm_lang$core$Native_Utils.cmp(n, 0) < 1) { + return list; + } else { + var _p0 = list; + if (_p0.ctor === '[]') { + return list; + } else { + var _v1 = n - 1, + _v2 = _p0._1; + n = _v1; + list = _v2; + continue drop; + } + } + } + }); +var _elm_lang$core$List$map5 = _elm_lang$core$Native_List.map5; +var _elm_lang$core$List$map4 = _elm_lang$core$Native_List.map4; +var _elm_lang$core$List$map3 = _elm_lang$core$Native_List.map3; +var _elm_lang$core$List$map2 = _elm_lang$core$Native_List.map2; +var _elm_lang$core$List$any = F2( + function (isOkay, list) { + any: + while (true) { + var _p1 = list; + if (_p1.ctor === '[]') { + return false; + } else { + if (isOkay(_p1._0)) { + return true; + } else { + var _v4 = isOkay, + _v5 = _p1._1; + isOkay = _v4; + list = _v5; + continue any; + } + } + } + }); +var _elm_lang$core$List$all = F2( + function (isOkay, list) { + return _elm_lang$core$Basics$not( + A2( + _elm_lang$core$List$any, + function (_p2) { + return _elm_lang$core$Basics$not( + isOkay(_p2)); + }, + list)); + }); +var _elm_lang$core$List$foldr = _elm_lang$core$Native_List.foldr; +var _elm_lang$core$List$foldl = F3( + function (func, acc, list) { + foldl: + while (true) { + var _p3 = list; + if (_p3.ctor === '[]') { + return acc; + } else { + var _v7 = func, + _v8 = A2(func, _p3._0, acc), + _v9 = _p3._1; + func = _v7; + acc = _v8; + list = _v9; + continue foldl; + } + } + }); +var _elm_lang$core$List$length = function (xs) { + return A3( + _elm_lang$core$List$foldl, + F2( + function (_p4, i) { + return i + 1; + }), + 0, + xs); +}; +var _elm_lang$core$List$sum = function (numbers) { + return A3( + _elm_lang$core$List$foldl, + F2( + function (x, y) { + return x + y; + }), + 0, + numbers); +}; +var _elm_lang$core$List$product = function (numbers) { + return A3( + _elm_lang$core$List$foldl, + F2( + function (x, y) { + return x * y; + }), + 1, + numbers); +}; +var _elm_lang$core$List$maximum = function (list) { + var _p5 = list; + if (_p5.ctor === '::') { + return _elm_lang$core$Maybe$Just( + A3(_elm_lang$core$List$foldl, _elm_lang$core$Basics$max, _p5._0, _p5._1)); + } else { + return _elm_lang$core$Maybe$Nothing; + } +}; +var _elm_lang$core$List$minimum = function (list) { + var _p6 = list; + if (_p6.ctor === '::') { + return _elm_lang$core$Maybe$Just( + A3(_elm_lang$core$List$foldl, _elm_lang$core$Basics$min, _p6._0, _p6._1)); + } else { + return _elm_lang$core$Maybe$Nothing; + } +}; +var _elm_lang$core$List$indexedMap = F2( + function (f, xs) { + return A3( + _elm_lang$core$List$map2, + f, + _elm_lang$core$Native_List.range( + 0, + _elm_lang$core$List$length(xs) - 1), + xs); + }); +var _elm_lang$core$List$member = F2( + function (x, xs) { + return A2( + _elm_lang$core$List$any, + function (a) { + return _elm_lang$core$Native_Utils.eq(a, x); + }, + xs); + }); +var _elm_lang$core$List$isEmpty = function (xs) { + var _p7 = xs; + if (_p7.ctor === '[]') { + return true; + } else { + return false; + } +}; +var _elm_lang$core$List$tail = function (list) { + var _p8 = list; + if (_p8.ctor === '::') { + return _elm_lang$core$Maybe$Just(_p8._1); + } else { + return _elm_lang$core$Maybe$Nothing; + } +}; +var _elm_lang$core$List$head = function (list) { + var _p9 = list; + if (_p9.ctor === '::') { + return _elm_lang$core$Maybe$Just(_p9._0); + } else { + return _elm_lang$core$Maybe$Nothing; + } +}; +var _elm_lang$core$List_ops = _elm_lang$core$List_ops || {}; +_elm_lang$core$List_ops['::'] = _elm_lang$core$Native_List.cons; +var _elm_lang$core$List$map = F2( + function (f, xs) { + return A3( + _elm_lang$core$List$foldr, + F2( + function (x, acc) { + return A2( + _elm_lang$core$List_ops['::'], + f(x), + acc); + }), + _elm_lang$core$Native_List.fromArray( + []), + xs); + }); +var _elm_lang$core$List$filter = F2( + function (pred, xs) { + var conditionalCons = F2( + function (x, xs$) { + return pred(x) ? A2(_elm_lang$core$List_ops['::'], x, xs$) : xs$; + }); + return A3( + _elm_lang$core$List$foldr, + conditionalCons, + _elm_lang$core$Native_List.fromArray( + []), + xs); + }); +var _elm_lang$core$List$maybeCons = F3( + function (f, mx, xs) { + var _p10 = f(mx); + if (_p10.ctor === 'Just') { + return A2(_elm_lang$core$List_ops['::'], _p10._0, xs); + } else { + return xs; + } + }); +var _elm_lang$core$List$filterMap = F2( + function (f, xs) { + return A3( + _elm_lang$core$List$foldr, + _elm_lang$core$List$maybeCons(f), + _elm_lang$core$Native_List.fromArray( + []), + xs); + }); +var _elm_lang$core$List$reverse = function (list) { + return A3( + _elm_lang$core$List$foldl, + F2( + function (x, y) { + return A2(_elm_lang$core$List_ops['::'], x, y); + }), + _elm_lang$core$Native_List.fromArray( + []), + list); +}; +var _elm_lang$core$List$scanl = F3( + function (f, b, xs) { + var scan1 = F2( + function (x, accAcc) { + var _p11 = accAcc; + if (_p11.ctor === '::') { + return A2( + _elm_lang$core$List_ops['::'], + A2(f, x, _p11._0), + accAcc); + } else { + return _elm_lang$core$Native_List.fromArray( + []); + } + }); + return _elm_lang$core$List$reverse( + A3( + _elm_lang$core$List$foldl, + scan1, + _elm_lang$core$Native_List.fromArray( + [b]), + xs)); + }); +var _elm_lang$core$List$append = F2( + function (xs, ys) { + var _p12 = ys; + if (_p12.ctor === '[]') { + return xs; + } else { + return A3( + _elm_lang$core$List$foldr, + F2( + function (x, y) { + return A2(_elm_lang$core$List_ops['::'], x, y); + }), + ys, + xs); + } + }); +var _elm_lang$core$List$concat = function (lists) { + return A3( + _elm_lang$core$List$foldr, + _elm_lang$core$List$append, + _elm_lang$core$Native_List.fromArray( + []), + lists); +}; +var _elm_lang$core$List$concatMap = F2( + function (f, list) { + return _elm_lang$core$List$concat( + A2(_elm_lang$core$List$map, f, list)); + }); +var _elm_lang$core$List$partition = F2( + function (pred, list) { + var step = F2( + function (x, _p13) { + var _p14 = _p13; + var _p16 = _p14._0; + var _p15 = _p14._1; + return pred(x) ? { + ctor: '_Tuple2', + _0: A2(_elm_lang$core$List_ops['::'], x, _p16), + _1: _p15 + } : { + ctor: '_Tuple2', + _0: _p16, + _1: A2(_elm_lang$core$List_ops['::'], x, _p15) + }; + }); + return A3( + _elm_lang$core$List$foldr, + step, + { + ctor: '_Tuple2', + _0: _elm_lang$core$Native_List.fromArray( + []), + _1: _elm_lang$core$Native_List.fromArray( + []) + }, + list); + }); +var _elm_lang$core$List$unzip = function (pairs) { + var step = F2( + function (_p18, _p17) { + var _p19 = _p18; + var _p20 = _p17; + return { + ctor: '_Tuple2', + _0: A2(_elm_lang$core$List_ops['::'], _p19._0, _p20._0), + _1: A2(_elm_lang$core$List_ops['::'], _p19._1, _p20._1) + }; + }); + return A3( + _elm_lang$core$List$foldr, + step, + { + ctor: '_Tuple2', + _0: _elm_lang$core$Native_List.fromArray( + []), + _1: _elm_lang$core$Native_List.fromArray( + []) + }, + pairs); +}; +var _elm_lang$core$List$intersperse = F2( + function (sep, xs) { + var _p21 = xs; + if (_p21.ctor === '[]') { + return _elm_lang$core$Native_List.fromArray( + []); + } else { + var step = F2( + function (x, rest) { + return A2( + _elm_lang$core$List_ops['::'], + sep, + A2(_elm_lang$core$List_ops['::'], x, rest)); + }); + var spersed = A3( + _elm_lang$core$List$foldr, + step, + _elm_lang$core$Native_List.fromArray( + []), + _p21._1); + return A2(_elm_lang$core$List_ops['::'], _p21._0, spersed); + } + }); +var _elm_lang$core$List$takeReverse = F3( + function (n, list, taken) { + takeReverse: + while (true) { + if (_elm_lang$core$Native_Utils.cmp(n, 0) < 1) { + return taken; + } else { + var _p22 = list; + if (_p22.ctor === '[]') { + return taken; + } else { + var _v23 = n - 1, + _v24 = _p22._1, + _v25 = A2(_elm_lang$core$List_ops['::'], _p22._0, taken); + n = _v23; + list = _v24; + taken = _v25; + continue takeReverse; + } + } + } + }); +var _elm_lang$core$List$takeTailRec = F2( + function (n, list) { + return _elm_lang$core$List$reverse( + A3( + _elm_lang$core$List$takeReverse, + n, + list, + _elm_lang$core$Native_List.fromArray( + []))); + }); +var _elm_lang$core$List$takeFast = F3( + function (ctr, n, list) { + if (_elm_lang$core$Native_Utils.cmp(n, 0) < 1) { + return _elm_lang$core$Native_List.fromArray( + []); + } else { + var _p23 = {ctor: '_Tuple2', _0: n, _1: list}; + _v26_5: + do { + _v26_1: + do { + if (_p23.ctor === '_Tuple2') { + if (_p23._1.ctor === '[]') { + return list; + } else { + if (_p23._1._1.ctor === '::') { + switch (_p23._0) { + case 1: + break _v26_1; + case 2: + return _elm_lang$core$Native_List.fromArray( + [_p23._1._0, _p23._1._1._0]); + case 3: + if (_p23._1._1._1.ctor === '::') { + return _elm_lang$core$Native_List.fromArray( + [_p23._1._0, _p23._1._1._0, _p23._1._1._1._0]); + } else { + break _v26_5; + } + default: + if ((_p23._1._1._1.ctor === '::') && (_p23._1._1._1._1.ctor === '::')) { + var _p28 = _p23._1._1._1._0; + var _p27 = _p23._1._1._0; + var _p26 = _p23._1._0; + var _p25 = _p23._1._1._1._1._0; + var _p24 = _p23._1._1._1._1._1; + return (_elm_lang$core$Native_Utils.cmp(ctr, 1000) > 0) ? A2( + _elm_lang$core$List_ops['::'], + _p26, + A2( + _elm_lang$core$List_ops['::'], + _p27, + A2( + _elm_lang$core$List_ops['::'], + _p28, + A2( + _elm_lang$core$List_ops['::'], + _p25, + A2(_elm_lang$core$List$takeTailRec, n - 4, _p24))))) : A2( + _elm_lang$core$List_ops['::'], + _p26, + A2( + _elm_lang$core$List_ops['::'], + _p27, + A2( + _elm_lang$core$List_ops['::'], + _p28, + A2( + _elm_lang$core$List_ops['::'], + _p25, + A3(_elm_lang$core$List$takeFast, ctr + 1, n - 4, _p24))))); + } else { + break _v26_5; + } + } + } else { + if (_p23._0 === 1) { + break _v26_1; + } else { + break _v26_5; + } + } + } + } else { + break _v26_5; + } + } while(false); + return _elm_lang$core$Native_List.fromArray( + [_p23._1._0]); + } while(false); + return list; + } + }); +var _elm_lang$core$List$take = F2( + function (n, list) { + return A3(_elm_lang$core$List$takeFast, 0, n, list); + }); +var _elm_lang$core$List$repeatHelp = F3( + function (result, n, value) { + repeatHelp: + while (true) { + if (_elm_lang$core$Native_Utils.cmp(n, 0) < 1) { + return result; + } else { + var _v27 = A2(_elm_lang$core$List_ops['::'], value, result), + _v28 = n - 1, + _v29 = value; + result = _v27; + n = _v28; + value = _v29; + continue repeatHelp; + } + } + }); +var _elm_lang$core$List$repeat = F2( + function (n, value) { + return A3( + _elm_lang$core$List$repeatHelp, + _elm_lang$core$Native_List.fromArray( + []), + n, + value); + }); + +var _elm_lang$core$Array$append = _elm_lang$core$Native_Array.append; +var _elm_lang$core$Array$length = _elm_lang$core$Native_Array.length; +var _elm_lang$core$Array$isEmpty = function (array) { + return _elm_lang$core$Native_Utils.eq( + _elm_lang$core$Array$length(array), + 0); +}; +var _elm_lang$core$Array$slice = _elm_lang$core$Native_Array.slice; +var _elm_lang$core$Array$set = _elm_lang$core$Native_Array.set; +var _elm_lang$core$Array$get = F2( + function (i, array) { + return ((_elm_lang$core$Native_Utils.cmp(0, i) < 1) && (_elm_lang$core$Native_Utils.cmp( + i, + _elm_lang$core$Native_Array.length(array)) < 0)) ? _elm_lang$core$Maybe$Just( + A2(_elm_lang$core$Native_Array.get, i, array)) : _elm_lang$core$Maybe$Nothing; + }); +var _elm_lang$core$Array$push = _elm_lang$core$Native_Array.push; +var _elm_lang$core$Array$empty = _elm_lang$core$Native_Array.empty; +var _elm_lang$core$Array$filter = F2( + function (isOkay, arr) { + var update = F2( + function (x, xs) { + return isOkay(x) ? A2(_elm_lang$core$Native_Array.push, x, xs) : xs; + }); + return A3(_elm_lang$core$Native_Array.foldl, update, _elm_lang$core$Native_Array.empty, arr); + }); +var _elm_lang$core$Array$foldr = _elm_lang$core$Native_Array.foldr; +var _elm_lang$core$Array$foldl = _elm_lang$core$Native_Array.foldl; +var _elm_lang$core$Array$indexedMap = _elm_lang$core$Native_Array.indexedMap; +var _elm_lang$core$Array$map = _elm_lang$core$Native_Array.map; +var _elm_lang$core$Array$toIndexedList = function (array) { + return A3( + _elm_lang$core$List$map2, + F2( + function (v0, v1) { + return {ctor: '_Tuple2', _0: v0, _1: v1}; + }), + _elm_lang$core$Native_List.range( + 0, + _elm_lang$core$Native_Array.length(array) - 1), + _elm_lang$core$Native_Array.toList(array)); +}; +var _elm_lang$core$Array$toList = _elm_lang$core$Native_Array.toList; +var _elm_lang$core$Array$fromList = _elm_lang$core$Native_Array.fromList; +var _elm_lang$core$Array$initialize = _elm_lang$core$Native_Array.initialize; +var _elm_lang$core$Array$repeat = F2( + function (n, e) { + return A2( + _elm_lang$core$Array$initialize, + n, + _elm_lang$core$Basics$always(e)); + }); +var _elm_lang$core$Array$Array = {ctor: 'Array'}; + +//import Native.Utils // + +var _elm_lang$core$Native_Char = function() { + +return { + fromCode: function(c) { return _elm_lang$core$Native_Utils.chr(String.fromCharCode(c)); }, + toCode: function(c) { return c.charCodeAt(0); }, + toUpper: function(c) { return _elm_lang$core$Native_Utils.chr(c.toUpperCase()); }, + toLower: function(c) { return _elm_lang$core$Native_Utils.chr(c.toLowerCase()); }, + toLocaleUpper: function(c) { return _elm_lang$core$Native_Utils.chr(c.toLocaleUpperCase()); }, + toLocaleLower: function(c) { return _elm_lang$core$Native_Utils.chr(c.toLocaleLowerCase()); } +}; + +}(); +var _elm_lang$core$Char$fromCode = _elm_lang$core$Native_Char.fromCode; +var _elm_lang$core$Char$toCode = _elm_lang$core$Native_Char.toCode; +var _elm_lang$core$Char$toLocaleLower = _elm_lang$core$Native_Char.toLocaleLower; +var _elm_lang$core$Char$toLocaleUpper = _elm_lang$core$Native_Char.toLocaleUpper; +var _elm_lang$core$Char$toLower = _elm_lang$core$Native_Char.toLower; +var _elm_lang$core$Char$toUpper = _elm_lang$core$Native_Char.toUpper; +var _elm_lang$core$Char$isBetween = F3( + function (low, high, $char) { + var code = _elm_lang$core$Char$toCode($char); + return (_elm_lang$core$Native_Utils.cmp( + code, + _elm_lang$core$Char$toCode(low)) > -1) && (_elm_lang$core$Native_Utils.cmp( + code, + _elm_lang$core$Char$toCode(high)) < 1); + }); +var _elm_lang$core$Char$isUpper = A2( + _elm_lang$core$Char$isBetween, + _elm_lang$core$Native_Utils.chr('A'), + _elm_lang$core$Native_Utils.chr('Z')); +var _elm_lang$core$Char$isLower = A2( + _elm_lang$core$Char$isBetween, + _elm_lang$core$Native_Utils.chr('a'), + _elm_lang$core$Native_Utils.chr('z')); +var _elm_lang$core$Char$isDigit = A2( + _elm_lang$core$Char$isBetween, + _elm_lang$core$Native_Utils.chr('0'), + _elm_lang$core$Native_Utils.chr('9')); +var _elm_lang$core$Char$isOctDigit = A2( + _elm_lang$core$Char$isBetween, + _elm_lang$core$Native_Utils.chr('0'), + _elm_lang$core$Native_Utils.chr('7')); +var _elm_lang$core$Char$isHexDigit = function ($char) { + return _elm_lang$core$Char$isDigit($char) || (A3( + _elm_lang$core$Char$isBetween, + _elm_lang$core$Native_Utils.chr('a'), + _elm_lang$core$Native_Utils.chr('f'), + $char) || A3( + _elm_lang$core$Char$isBetween, + _elm_lang$core$Native_Utils.chr('A'), + _elm_lang$core$Native_Utils.chr('F'), + $char)); +}; + +//import Native.Utils // + +var _elm_lang$core$Native_Scheduler = function() { + +var MAX_STEPS = 10000; + + +// TASKS + +function succeed(value) +{ + return { + ctor: '_Task_succeed', + value: value + }; +} + +function fail(error) +{ + return { + ctor: '_Task_fail', + value: error + }; +} + +function nativeBinding(callback) +{ + return { + ctor: '_Task_nativeBinding', + callback: callback, + cancel: null + }; +} + +function andThen(task, callback) +{ + return { + ctor: '_Task_andThen', + task: task, + callback: callback + }; +} + +function onError(task, callback) +{ + return { + ctor: '_Task_onError', + task: task, + callback: callback + }; +} + +function receive(callback) +{ + return { + ctor: '_Task_receive', + callback: callback + }; +} + + +// PROCESSES + +function rawSpawn(task) +{ + var process = { + ctor: '_Process', + id: _elm_lang$core$Native_Utils.guid(), + root: task, + stack: null, + mailbox: [] + }; + + enqueue(process); + + return process; +} + +function spawn(task) +{ + return nativeBinding(function(callback) { + var process = rawSpawn(task); + callback(succeed(process)); + }); +} + +function rawSend(process, msg) +{ + process.mailbox.push(msg); + enqueue(process); +} + +function send(process, msg) +{ + return nativeBinding(function(callback) { + rawSend(process, msg); + callback(succeed(_elm_lang$core$Native_Utils.Tuple0)); + }); +} + +function kill(process) +{ + return nativeBinding(function(callback) { + var root = process.root; + if (root.ctor === '_Task_nativeBinding' && root.cancel) + { + root.cancel(); + } + + process.root = null; + + callback(succeed(_elm_lang$core$Native_Utils.Tuple0)); + }); +} + +function sleep(time) +{ + return nativeBinding(function(callback) { + var id = setTimeout(function() { + callback(succeed(_elm_lang$core$Native_Utils.Tuple0)); + }, time); + + return function() { clearTimeout(id); }; + }); +} + + +// STEP PROCESSES + +function step(numSteps, process) +{ + while (numSteps < MAX_STEPS) + { + var ctor = process.root.ctor; + + if (ctor === '_Task_succeed') + { + while (process.stack && process.stack.ctor === '_Task_onError') + { + process.stack = process.stack.rest; + } + if (process.stack === null) + { + break; + } + process.root = process.stack.callback(process.root.value); + process.stack = process.stack.rest; + ++numSteps; + continue; + } + + if (ctor === '_Task_fail') + { + while (process.stack && process.stack.ctor === '_Task_andThen') + { + process.stack = process.stack.rest; + } + if (process.stack === null) + { + break; + } + process.root = process.stack.callback(process.root.value); + process.stack = process.stack.rest; + ++numSteps; + continue; + } + + if (ctor === '_Task_andThen') + { + process.stack = { + ctor: '_Task_andThen', + callback: process.root.callback, + rest: process.stack + }; + process.root = process.root.task; + ++numSteps; + continue; + } + + if (ctor === '_Task_onError') + { + process.stack = { + ctor: '_Task_onError', + callback: process.root.callback, + rest: process.stack + }; + process.root = process.root.task; + ++numSteps; + continue; + } + + if (ctor === '_Task_nativeBinding') + { + process.root.cancel = process.root.callback(function(newRoot) { + process.root = newRoot; + enqueue(process); + }); + + break; + } + + if (ctor === '_Task_receive') + { + var mailbox = process.mailbox; + if (mailbox.length === 0) + { + break; + } + + process.root = process.root.callback(mailbox.shift()); + ++numSteps; + continue; + } + + throw new Error(ctor); + } + + if (numSteps < MAX_STEPS) + { + return numSteps + 1; + } + enqueue(process); + + return numSteps; +} + + +// WORK QUEUE + +var working = false; +var workQueue = []; + +function enqueue(process) +{ + workQueue.push(process); + + if (!working) + { + setTimeout(work, 0); + working = true; + } +} + +function work() +{ + var numSteps = 0; + var process; + while (numSteps < MAX_STEPS && (process = workQueue.shift())) + { + if (process.root) + { + numSteps = step(numSteps, process); + } + } + if (!process) + { + working = false; + return; + } + setTimeout(work, 0); +} + + +return { + succeed: succeed, + fail: fail, + nativeBinding: nativeBinding, + andThen: F2(andThen), + onError: F2(onError), + receive: receive, + + spawn: spawn, + kill: kill, + sleep: sleep, + send: F2(send), + + rawSpawn: rawSpawn, + rawSend: rawSend +}; + +}(); +//import // + +var _elm_lang$core$Native_Platform = function() { + + +// PROGRAMS + +function addPublicModule(object, name, main) +{ + var init = main ? makeEmbed(name, main) : mainIsUndefined(name); + + object['worker'] = function worker(flags) + { + return init(undefined, flags, false); + } + + object['embed'] = function embed(domNode, flags) + { + return init(domNode, flags, true); + } + + object['fullscreen'] = function fullscreen(flags) + { + return init(document.body, flags, true); + }; +} + + +// PROGRAM FAIL + +function mainIsUndefined(name) +{ + return function(domNode) + { + var message = 'Cannot initialize module `' + name + + '` because it has no `main` value!\nWhat should I show on screen?'; + domNode.innerHTML = errorHtml(message); + throw new Error(message); + }; +} + +function errorHtml(message) +{ + return '
' + + '

Oops! Something went wrong when starting your Elm program.

' + + '
' + message + '
' + + '
'; +} + + +// PROGRAM SUCCESS + +function makeEmbed(moduleName, main) +{ + return function embed(rootDomNode, flags, withRenderer) + { + try + { + var program = mainToProgram(moduleName, main); + if (!withRenderer) + { + program.renderer = dummyRenderer; + } + return makeEmbedHelp(moduleName, program, rootDomNode, flags); + } + catch (e) + { + rootDomNode.innerHTML = errorHtml(e.message); + throw e; + } + }; +} + +function dummyRenderer() +{ + return { update: function() {} }; +} + + +// MAIN TO PROGRAM + +function mainToProgram(moduleName, wrappedMain) +{ + var main = wrappedMain.main; + + if (typeof main.init === 'undefined') + { + var emptyBag = batch(_elm_lang$core$Native_List.Nil); + var noChange = _elm_lang$core$Native_Utils.Tuple2( + _elm_lang$core$Native_Utils.Tuple0, + emptyBag + ); + + return _elm_lang$virtual_dom$VirtualDom$programWithFlags({ + init: function() { return noChange; }, + view: function() { return main; }, + update: F2(function() { return noChange; }), + subscriptions: function () { return emptyBag; } + }); + } + + var flags = wrappedMain.flags; + var init = flags + ? initWithFlags(moduleName, main.init, flags) + : initWithoutFlags(moduleName, main.init); + + return _elm_lang$virtual_dom$VirtualDom$programWithFlags({ + init: init, + view: main.view, + update: main.update, + subscriptions: main.subscriptions, + }); +} + +function initWithoutFlags(moduleName, realInit) +{ + return function init(flags) + { + if (typeof flags !== 'undefined') + { + throw new Error( + 'You are giving module `' + moduleName + '` an argument in JavaScript.\n' + + 'This module does not take arguments though! You probably need to change the\n' + + 'initialization code to something like `Elm.' + moduleName + '.fullscreen()`' + ); + } + return realInit(); + }; +} + +function initWithFlags(moduleName, realInit, flagDecoder) +{ + return function init(flags) + { + var result = A2(_elm_lang$core$Native_Json.run, flagDecoder, flags); + if (result.ctor === 'Err') + { + throw new Error( + 'You are trying to initialize module `' + moduleName + '` with an unexpected argument.\n' + + 'When trying to convert it to a usable Elm value, I run into this problem:\n\n' + + result._0 + ); + } + return realInit(result._0); + }; +} + + +// SETUP RUNTIME SYSTEM + +function makeEmbedHelp(moduleName, program, rootDomNode, flags) +{ + var init = program.init; + var update = program.update; + var subscriptions = program.subscriptions; + var view = program.view; + var makeRenderer = program.renderer; + + // ambient state + var managers = {}; + var renderer; + + // init and update state in main process + var initApp = _elm_lang$core$Native_Scheduler.nativeBinding(function(callback) { + var results = init(flags); + var model = results._0; + renderer = makeRenderer(rootDomNode, enqueue, view(model)); + var cmds = results._1; + var subs = subscriptions(model); + dispatchEffects(managers, cmds, subs); + callback(_elm_lang$core$Native_Scheduler.succeed(model)); + }); + + function onMessage(msg, model) + { + return _elm_lang$core$Native_Scheduler.nativeBinding(function(callback) { + var results = A2(update, msg, model); + model = results._0; + renderer.update(view(model)); + var cmds = results._1; + var subs = subscriptions(model); + dispatchEffects(managers, cmds, subs); + callback(_elm_lang$core$Native_Scheduler.succeed(model)); + }); + } + + var mainProcess = spawnLoop(initApp, onMessage); + + function enqueue(msg) + { + _elm_lang$core$Native_Scheduler.rawSend(mainProcess, msg); + } + + var ports = setupEffects(managers, enqueue); + + return ports ? { ports: ports } : {}; +} + + +// EFFECT MANAGERS + +var effectManagers = {}; + +function setupEffects(managers, callback) +{ + var ports; + + // setup all necessary effect managers + for (var key in effectManagers) + { + var manager = effectManagers[key]; + + if (manager.isForeign) + { + ports = ports || {}; + ports[key] = manager.tag === 'cmd' + ? setupOutgoingPort(key) + : setupIncomingPort(key, callback); + } + + managers[key] = makeManager(manager, callback); + } + + return ports; +} + +function makeManager(info, callback) +{ + var router = { + main: callback, + self: undefined + }; + + var tag = info.tag; + var onEffects = info.onEffects; + var onSelfMsg = info.onSelfMsg; + + function onMessage(msg, state) + { + if (msg.ctor === 'self') + { + return A3(onSelfMsg, router, msg._0, state); + } + + var fx = msg._0; + switch (tag) + { + case 'cmd': + return A3(onEffects, router, fx.cmds, state); + + case 'sub': + return A3(onEffects, router, fx.subs, state); + + case 'fx': + return A4(onEffects, router, fx.cmds, fx.subs, state); + } + } + + var process = spawnLoop(info.init, onMessage); + router.self = process; + return process; +} + +function sendToApp(router, msg) +{ + return _elm_lang$core$Native_Scheduler.nativeBinding(function(callback) + { + router.main(msg); + callback(_elm_lang$core$Native_Scheduler.succeed(_elm_lang$core$Native_Utils.Tuple0)); + }); +} + +function sendToSelf(router, msg) +{ + return A2(_elm_lang$core$Native_Scheduler.send, router.self, { + ctor: 'self', + _0: msg + }); +} + + +// HELPER for STATEFUL LOOPS + +function spawnLoop(init, onMessage) +{ + var andThen = _elm_lang$core$Native_Scheduler.andThen; + + function loop(state) + { + var handleMsg = _elm_lang$core$Native_Scheduler.receive(function(msg) { + return onMessage(msg, state); + }); + return A2(andThen, handleMsg, loop); + } + + var task = A2(andThen, init, loop); + + return _elm_lang$core$Native_Scheduler.rawSpawn(task); +} + + +// BAGS + +function leaf(home) +{ + return function(value) + { + return { + type: 'leaf', + home: home, + value: value + }; + }; +} + +function batch(list) +{ + return { + type: 'node', + branches: list + }; +} + +function map(tagger, bag) +{ + return { + type: 'map', + tagger: tagger, + tree: bag + } +} + + +// PIPE BAGS INTO EFFECT MANAGERS + +function dispatchEffects(managers, cmdBag, subBag) +{ + var effectsDict = {}; + gatherEffects(true, cmdBag, effectsDict, null); + gatherEffects(false, subBag, effectsDict, null); + + for (var home in managers) + { + var fx = home in effectsDict + ? effectsDict[home] + : { + cmds: _elm_lang$core$Native_List.Nil, + subs: _elm_lang$core$Native_List.Nil + }; + + _elm_lang$core$Native_Scheduler.rawSend(managers[home], { ctor: 'fx', _0: fx }); + } +} + +function gatherEffects(isCmd, bag, effectsDict, taggers) +{ + switch (bag.type) + { + case 'leaf': + var home = bag.home; + var effect = toEffect(isCmd, home, taggers, bag.value); + effectsDict[home] = insert(isCmd, effect, effectsDict[home]); + return; + + case 'node': + var list = bag.branches; + while (list.ctor !== '[]') + { + gatherEffects(isCmd, list._0, effectsDict, taggers); + list = list._1; + } + return; + + case 'map': + gatherEffects(isCmd, bag.tree, effectsDict, { + tagger: bag.tagger, + rest: taggers + }); + return; + } +} + +function toEffect(isCmd, home, taggers, value) +{ + function applyTaggers(x) + { + var temp = taggers; + while (temp) + { + x = temp.tagger(x); + temp = temp.rest; + } + return x; + } + + var map = isCmd + ? effectManagers[home].cmdMap + : effectManagers[home].subMap; + + return A2(map, applyTaggers, value) +} + +function insert(isCmd, newEffect, effects) +{ + effects = effects || { + cmds: _elm_lang$core$Native_List.Nil, + subs: _elm_lang$core$Native_List.Nil + }; + if (isCmd) + { + effects.cmds = _elm_lang$core$Native_List.Cons(newEffect, effects.cmds); + return effects; + } + effects.subs = _elm_lang$core$Native_List.Cons(newEffect, effects.subs); + return effects; +} + + +// PORTS + +function checkPortName(name) +{ + if (name in effectManagers) + { + throw new Error('There can only be one port named `' + name + '`, but your program has multiple.'); + } +} + + +// OUTGOING PORTS + +function outgoingPort(name, converter) +{ + checkPortName(name); + effectManagers[name] = { + tag: 'cmd', + cmdMap: outgoingPortMap, + converter: converter, + isForeign: true + }; + return leaf(name); +} + +var outgoingPortMap = F2(function cmdMap(tagger, value) { + return value; +}); + +function setupOutgoingPort(name) +{ + var subs = []; + var converter = effectManagers[name].converter; + + // CREATE MANAGER + + var init = _elm_lang$core$Native_Scheduler.succeed(null); + + function onEffects(router, cmdList, state) + { + while (cmdList.ctor !== '[]') + { + var value = converter(cmdList._0); + for (var i = 0; i < subs.length; i++) + { + subs[i](value); + } + cmdList = cmdList._1; + } + return init; + } + + effectManagers[name].init = init; + effectManagers[name].onEffects = F3(onEffects); + + // PUBLIC API + + function subscribe(callback) + { + subs.push(callback); + } + + function unsubscribe(callback) + { + var index = subs.indexOf(callback); + if (index >= 0) + { + subs.splice(index, 1); + } + } + + return { + subscribe: subscribe, + unsubscribe: unsubscribe + }; +} + + +// INCOMING PORTS + +function incomingPort(name, converter) +{ + checkPortName(name); + effectManagers[name] = { + tag: 'sub', + subMap: incomingPortMap, + converter: converter, + isForeign: true + }; + return leaf(name); +} + +var incomingPortMap = F2(function subMap(tagger, finalTagger) +{ + return function(value) + { + return tagger(finalTagger(value)); + }; +}); + +function setupIncomingPort(name, callback) +{ + var sentBeforeInit = []; + var subs = _elm_lang$core$Native_List.Nil; + var converter = effectManagers[name].converter; + var currentOnEffects = preInitOnEffects; + var currentSend = preInitSend; + + // CREATE MANAGER + + var init = _elm_lang$core$Native_Scheduler.succeed(null); + + function preInitOnEffects(router, subList, state) + { + var postInitResult = postInitOnEffects(router, subList, state); + + for(var i = 0; i < sentBeforeInit.length; i++) + { + postInitSend(sentBeforeInit[i]); + } + + sentBeforeInit = null; // to release objects held in queue + currentSend = postInitSend; + currentOnEffects = postInitOnEffects; + return postInitResult; + } + + function postInitOnEffects(router, subList, state) + { + subs = subList; + return init; + } + + function onEffects(router, subList, state) + { + return currentOnEffects(router, subList, state); + } + + effectManagers[name].init = init; + effectManagers[name].onEffects = F3(onEffects); + + // PUBLIC API + + function preInitSend(value) + { + sentBeforeInit.push(value); + } + + function postInitSend(incomingValue) + { + var result = A2(_elm_lang$core$Json_Decode$decodeValue, converter, incomingValue); + if (result.ctor === 'Err') + { + throw new Error('Trying to send an unexpected type of value through port `' + name + '`:\n' + result._0); + } + + var value = result._0; + var temp = subs; + while (temp.ctor !== '[]') + { + callback(temp._0(value)); + temp = temp._1; + } + } + + function send(incomingValue) + { + currentSend(incomingValue); + } + + return { send: send }; +} + +return { + // routers + sendToApp: F2(sendToApp), + sendToSelf: F2(sendToSelf), + + // global setup + mainToProgram: mainToProgram, + effectManagers: effectManagers, + outgoingPort: outgoingPort, + incomingPort: incomingPort, + addPublicModule: addPublicModule, + + // effect bags + leaf: leaf, + batch: batch, + map: F2(map) +}; + +}(); + +var _elm_lang$core$Platform$hack = _elm_lang$core$Native_Scheduler.succeed; +var _elm_lang$core$Platform$sendToSelf = _elm_lang$core$Native_Platform.sendToSelf; +var _elm_lang$core$Platform$sendToApp = _elm_lang$core$Native_Platform.sendToApp; +var _elm_lang$core$Platform$Program = {ctor: 'Program'}; +var _elm_lang$core$Platform$Task = {ctor: 'Task'}; +var _elm_lang$core$Platform$ProcessId = {ctor: 'ProcessId'}; +var _elm_lang$core$Platform$Router = {ctor: 'Router'}; + +var _elm_lang$core$Platform_Cmd$batch = _elm_lang$core$Native_Platform.batch; +var _elm_lang$core$Platform_Cmd$none = _elm_lang$core$Platform_Cmd$batch( + _elm_lang$core$Native_List.fromArray( + [])); +var _elm_lang$core$Platform_Cmd_ops = _elm_lang$core$Platform_Cmd_ops || {}; +_elm_lang$core$Platform_Cmd_ops['!'] = F2( + function (model, commands) { + return { + ctor: '_Tuple2', + _0: model, + _1: _elm_lang$core$Platform_Cmd$batch(commands) + }; + }); +var _elm_lang$core$Platform_Cmd$map = _elm_lang$core$Native_Platform.map; +var _elm_lang$core$Platform_Cmd$Cmd = {ctor: 'Cmd'}; + +var _elm_lang$core$Result$toMaybe = function (result) { + var _p0 = result; + if (_p0.ctor === 'Ok') { + return _elm_lang$core$Maybe$Just(_p0._0); + } else { + return _elm_lang$core$Maybe$Nothing; + } +}; +var _elm_lang$core$Result$withDefault = F2( + function (def, result) { + var _p1 = result; + if (_p1.ctor === 'Ok') { + return _p1._0; + } else { + return def; + } + }); +var _elm_lang$core$Result$Err = function (a) { + return {ctor: 'Err', _0: a}; +}; +var _elm_lang$core$Result$andThen = F2( + function (result, callback) { + var _p2 = result; + if (_p2.ctor === 'Ok') { + return callback(_p2._0); + } else { + return _elm_lang$core$Result$Err(_p2._0); + } + }); +var _elm_lang$core$Result$Ok = function (a) { + return {ctor: 'Ok', _0: a}; +}; +var _elm_lang$core$Result$map = F2( + function (func, ra) { + var _p3 = ra; + if (_p3.ctor === 'Ok') { + return _elm_lang$core$Result$Ok( + func(_p3._0)); + } else { + return _elm_lang$core$Result$Err(_p3._0); + } + }); +var _elm_lang$core$Result$map2 = F3( + function (func, ra, rb) { + var _p4 = {ctor: '_Tuple2', _0: ra, _1: rb}; + if (_p4._0.ctor === 'Ok') { + if (_p4._1.ctor === 'Ok') { + return _elm_lang$core$Result$Ok( + A2(func, _p4._0._0, _p4._1._0)); + } else { + return _elm_lang$core$Result$Err(_p4._1._0); + } + } else { + return _elm_lang$core$Result$Err(_p4._0._0); + } + }); +var _elm_lang$core$Result$map3 = F4( + function (func, ra, rb, rc) { + var _p5 = {ctor: '_Tuple3', _0: ra, _1: rb, _2: rc}; + if (_p5._0.ctor === 'Ok') { + if (_p5._1.ctor === 'Ok') { + if (_p5._2.ctor === 'Ok') { + return _elm_lang$core$Result$Ok( + A3(func, _p5._0._0, _p5._1._0, _p5._2._0)); + } else { + return _elm_lang$core$Result$Err(_p5._2._0); + } + } else { + return _elm_lang$core$Result$Err(_p5._1._0); + } + } else { + return _elm_lang$core$Result$Err(_p5._0._0); + } + }); +var _elm_lang$core$Result$map4 = F5( + function (func, ra, rb, rc, rd) { + var _p6 = {ctor: '_Tuple4', _0: ra, _1: rb, _2: rc, _3: rd}; + if (_p6._0.ctor === 'Ok') { + if (_p6._1.ctor === 'Ok') { + if (_p6._2.ctor === 'Ok') { + if (_p6._3.ctor === 'Ok') { + return _elm_lang$core$Result$Ok( + A4(func, _p6._0._0, _p6._1._0, _p6._2._0, _p6._3._0)); + } else { + return _elm_lang$core$Result$Err(_p6._3._0); + } + } else { + return _elm_lang$core$Result$Err(_p6._2._0); + } + } else { + return _elm_lang$core$Result$Err(_p6._1._0); + } + } else { + return _elm_lang$core$Result$Err(_p6._0._0); + } + }); +var _elm_lang$core$Result$map5 = F6( + function (func, ra, rb, rc, rd, re) { + var _p7 = {ctor: '_Tuple5', _0: ra, _1: rb, _2: rc, _3: rd, _4: re}; + if (_p7._0.ctor === 'Ok') { + if (_p7._1.ctor === 'Ok') { + if (_p7._2.ctor === 'Ok') { + if (_p7._3.ctor === 'Ok') { + if (_p7._4.ctor === 'Ok') { + return _elm_lang$core$Result$Ok( + A5(func, _p7._0._0, _p7._1._0, _p7._2._0, _p7._3._0, _p7._4._0)); + } else { + return _elm_lang$core$Result$Err(_p7._4._0); + } + } else { + return _elm_lang$core$Result$Err(_p7._3._0); + } + } else { + return _elm_lang$core$Result$Err(_p7._2._0); + } + } else { + return _elm_lang$core$Result$Err(_p7._1._0); + } + } else { + return _elm_lang$core$Result$Err(_p7._0._0); + } + }); +var _elm_lang$core$Result$formatError = F2( + function (f, result) { + var _p8 = result; + if (_p8.ctor === 'Ok') { + return _elm_lang$core$Result$Ok(_p8._0); + } else { + return _elm_lang$core$Result$Err( + f(_p8._0)); + } + }); +var _elm_lang$core$Result$fromMaybe = F2( + function (err, maybe) { + var _p9 = maybe; + if (_p9.ctor === 'Just') { + return _elm_lang$core$Result$Ok(_p9._0); + } else { + return _elm_lang$core$Result$Err(err); + } + }); + +//import Native.Utils // + +var _elm_lang$core$Native_Debug = function() { + +function log(tag, value) +{ + var msg = tag + ': ' + _elm_lang$core$Native_Utils.toString(value); + var process = process || {}; + if (process.stdout) + { + process.stdout.write(msg); + } + else + { + console.log(msg); + } + return value; +} + +function crash(message) +{ + throw new Error(message); +} + +return { + crash: crash, + log: F2(log) +}; + +}(); +//import Maybe, Native.List, Native.Utils, Result // + +var _elm_lang$core$Native_String = function() { + +function isEmpty(str) +{ + return str.length === 0; +} +function cons(chr, str) +{ + return chr + str; +} +function uncons(str) +{ + var hd = str[0]; + if (hd) + { + return _elm_lang$core$Maybe$Just(_elm_lang$core$Native_Utils.Tuple2(_elm_lang$core$Native_Utils.chr(hd), str.slice(1))); + } + return _elm_lang$core$Maybe$Nothing; +} +function append(a, b) +{ + return a + b; +} +function concat(strs) +{ + return _elm_lang$core$Native_List.toArray(strs).join(''); +} +function length(str) +{ + return str.length; +} +function map(f, str) +{ + var out = str.split(''); + for (var i = out.length; i--; ) + { + out[i] = f(_elm_lang$core$Native_Utils.chr(out[i])); + } + return out.join(''); +} +function filter(pred, str) +{ + return str.split('').map(_elm_lang$core$Native_Utils.chr).filter(pred).join(''); +} +function reverse(str) +{ + return str.split('').reverse().join(''); +} +function foldl(f, b, str) +{ + var len = str.length; + for (var i = 0; i < len; ++i) + { + b = A2(f, _elm_lang$core$Native_Utils.chr(str[i]), b); + } + return b; +} +function foldr(f, b, str) +{ + for (var i = str.length; i--; ) + { + b = A2(f, _elm_lang$core$Native_Utils.chr(str[i]), b); + } + return b; +} +function split(sep, str) +{ + return _elm_lang$core$Native_List.fromArray(str.split(sep)); +} +function join(sep, strs) +{ + return _elm_lang$core$Native_List.toArray(strs).join(sep); +} +function repeat(n, str) +{ + var result = ''; + while (n > 0) + { + if (n & 1) + { + result += str; + } + n >>= 1, str += str; + } + return result; +} +function slice(start, end, str) +{ + return str.slice(start, end); +} +function left(n, str) +{ + return n < 1 ? '' : str.slice(0, n); +} +function right(n, str) +{ + return n < 1 ? '' : str.slice(-n); +} +function dropLeft(n, str) +{ + return n < 1 ? str : str.slice(n); +} +function dropRight(n, str) +{ + return n < 1 ? str : str.slice(0, -n); +} +function pad(n, chr, str) +{ + var half = (n - str.length) / 2; + return repeat(Math.ceil(half), chr) + str + repeat(half | 0, chr); +} +function padRight(n, chr, str) +{ + return str + repeat(n - str.length, chr); +} +function padLeft(n, chr, str) +{ + return repeat(n - str.length, chr) + str; +} + +function trim(str) +{ + return str.trim(); +} +function trimLeft(str) +{ + return str.replace(/^\s+/, ''); +} +function trimRight(str) +{ + return str.replace(/\s+$/, ''); +} + +function words(str) +{ + return _elm_lang$core$Native_List.fromArray(str.trim().split(/\s+/g)); +} +function lines(str) +{ + return _elm_lang$core$Native_List.fromArray(str.split(/\r\n|\r|\n/g)); +} + +function toUpper(str) +{ + return str.toUpperCase(); +} +function toLower(str) +{ + return str.toLowerCase(); +} + +function any(pred, str) +{ + for (var i = str.length; i--; ) + { + if (pred(_elm_lang$core$Native_Utils.chr(str[i]))) + { + return true; + } + } + return false; +} +function all(pred, str) +{ + for (var i = str.length; i--; ) + { + if (!pred(_elm_lang$core$Native_Utils.chr(str[i]))) + { + return false; + } + } + return true; +} + +function contains(sub, str) +{ + return str.indexOf(sub) > -1; +} +function startsWith(sub, str) +{ + return str.indexOf(sub) === 0; +} +function endsWith(sub, str) +{ + return str.length >= sub.length && + str.lastIndexOf(sub) === str.length - sub.length; +} +function indexes(sub, str) +{ + var subLen = sub.length; + + if (subLen < 1) + { + return _elm_lang$core$Native_List.Nil; + } + + var i = 0; + var is = []; + + while ((i = str.indexOf(sub, i)) > -1) + { + is.push(i); + i = i + subLen; + } + + return _elm_lang$core$Native_List.fromArray(is); +} + +function toInt(s) +{ + var len = s.length; + if (len === 0) + { + return _elm_lang$core$Result$Err("could not convert string '" + s + "' to an Int" ); + } + var start = 0; + if (s[0] === '-') + { + if (len === 1) + { + return _elm_lang$core$Result$Err("could not convert string '" + s + "' to an Int" ); + } + start = 1; + } + for (var i = start; i < len; ++i) + { + var c = s[i]; + if (c < '0' || '9' < c) + { + return _elm_lang$core$Result$Err("could not convert string '" + s + "' to an Int" ); + } + } + return _elm_lang$core$Result$Ok(parseInt(s, 10)); +} + +function toFloat(s) +{ + var len = s.length; + if (len === 0) + { + return _elm_lang$core$Result$Err("could not convert string '" + s + "' to a Float" ); + } + var start = 0; + if (s[0] === '-') + { + if (len === 1) + { + return _elm_lang$core$Result$Err("could not convert string '" + s + "' to a Float" ); + } + start = 1; + } + var dotCount = 0; + for (var i = start; i < len; ++i) + { + var c = s[i]; + if ('0' <= c && c <= '9') + { + continue; + } + if (c === '.') + { + dotCount += 1; + if (dotCount <= 1) + { + continue; + } + } + return _elm_lang$core$Result$Err("could not convert string '" + s + "' to a Float" ); + } + return _elm_lang$core$Result$Ok(parseFloat(s)); +} + +function toList(str) +{ + return _elm_lang$core$Native_List.fromArray(str.split('').map(_elm_lang$core$Native_Utils.chr)); +} +function fromList(chars) +{ + return _elm_lang$core$Native_List.toArray(chars).join(''); +} + +return { + isEmpty: isEmpty, + cons: F2(cons), + uncons: uncons, + append: F2(append), + concat: concat, + length: length, + map: F2(map), + filter: F2(filter), + reverse: reverse, + foldl: F3(foldl), + foldr: F3(foldr), + + split: F2(split), + join: F2(join), + repeat: F2(repeat), + + slice: F3(slice), + left: F2(left), + right: F2(right), + dropLeft: F2(dropLeft), + dropRight: F2(dropRight), + + pad: F3(pad), + padLeft: F3(padLeft), + padRight: F3(padRight), + + trim: trim, + trimLeft: trimLeft, + trimRight: trimRight, + + words: words, + lines: lines, + + toUpper: toUpper, + toLower: toLower, + + any: F2(any), + all: F2(all), + + contains: F2(contains), + startsWith: F2(startsWith), + endsWith: F2(endsWith), + indexes: F2(indexes), + + toInt: toInt, + toFloat: toFloat, + toList: toList, + fromList: fromList +}; + +}(); + +var _elm_lang$core$String$fromList = _elm_lang$core$Native_String.fromList; +var _elm_lang$core$String$toList = _elm_lang$core$Native_String.toList; +var _elm_lang$core$String$toFloat = _elm_lang$core$Native_String.toFloat; +var _elm_lang$core$String$toInt = _elm_lang$core$Native_String.toInt; +var _elm_lang$core$String$indices = _elm_lang$core$Native_String.indexes; +var _elm_lang$core$String$indexes = _elm_lang$core$Native_String.indexes; +var _elm_lang$core$String$endsWith = _elm_lang$core$Native_String.endsWith; +var _elm_lang$core$String$startsWith = _elm_lang$core$Native_String.startsWith; +var _elm_lang$core$String$contains = _elm_lang$core$Native_String.contains; +var _elm_lang$core$String$all = _elm_lang$core$Native_String.all; +var _elm_lang$core$String$any = _elm_lang$core$Native_String.any; +var _elm_lang$core$String$toLower = _elm_lang$core$Native_String.toLower; +var _elm_lang$core$String$toUpper = _elm_lang$core$Native_String.toUpper; +var _elm_lang$core$String$lines = _elm_lang$core$Native_String.lines; +var _elm_lang$core$String$words = _elm_lang$core$Native_String.words; +var _elm_lang$core$String$trimRight = _elm_lang$core$Native_String.trimRight; +var _elm_lang$core$String$trimLeft = _elm_lang$core$Native_String.trimLeft; +var _elm_lang$core$String$trim = _elm_lang$core$Native_String.trim; +var _elm_lang$core$String$padRight = _elm_lang$core$Native_String.padRight; +var _elm_lang$core$String$padLeft = _elm_lang$core$Native_String.padLeft; +var _elm_lang$core$String$pad = _elm_lang$core$Native_String.pad; +var _elm_lang$core$String$dropRight = _elm_lang$core$Native_String.dropRight; +var _elm_lang$core$String$dropLeft = _elm_lang$core$Native_String.dropLeft; +var _elm_lang$core$String$right = _elm_lang$core$Native_String.right; +var _elm_lang$core$String$left = _elm_lang$core$Native_String.left; +var _elm_lang$core$String$slice = _elm_lang$core$Native_String.slice; +var _elm_lang$core$String$repeat = _elm_lang$core$Native_String.repeat; +var _elm_lang$core$String$join = _elm_lang$core$Native_String.join; +var _elm_lang$core$String$split = _elm_lang$core$Native_String.split; +var _elm_lang$core$String$foldr = _elm_lang$core$Native_String.foldr; +var _elm_lang$core$String$foldl = _elm_lang$core$Native_String.foldl; +var _elm_lang$core$String$reverse = _elm_lang$core$Native_String.reverse; +var _elm_lang$core$String$filter = _elm_lang$core$Native_String.filter; +var _elm_lang$core$String$map = _elm_lang$core$Native_String.map; +var _elm_lang$core$String$length = _elm_lang$core$Native_String.length; +var _elm_lang$core$String$concat = _elm_lang$core$Native_String.concat; +var _elm_lang$core$String$append = _elm_lang$core$Native_String.append; +var _elm_lang$core$String$uncons = _elm_lang$core$Native_String.uncons; +var _elm_lang$core$String$cons = _elm_lang$core$Native_String.cons; +var _elm_lang$core$String$fromChar = function ($char) { + return A2(_elm_lang$core$String$cons, $char, ''); +}; +var _elm_lang$core$String$isEmpty = _elm_lang$core$Native_String.isEmpty; + +var _elm_lang$core$Dict$foldr = F3( + function (f, acc, t) { + foldr: + while (true) { + var _p0 = t; + if (_p0.ctor === 'RBEmpty_elm_builtin') { + return acc; + } else { + var _v1 = f, + _v2 = A3( + f, + _p0._1, + _p0._2, + A3(_elm_lang$core$Dict$foldr, f, acc, _p0._4)), + _v3 = _p0._3; + f = _v1; + acc = _v2; + t = _v3; + continue foldr; + } + } + }); +var _elm_lang$core$Dict$keys = function (dict) { + return A3( + _elm_lang$core$Dict$foldr, + F3( + function (key, value, keyList) { + return A2(_elm_lang$core$List_ops['::'], key, keyList); + }), + _elm_lang$core$Native_List.fromArray( + []), + dict); +}; +var _elm_lang$core$Dict$values = function (dict) { + return A3( + _elm_lang$core$Dict$foldr, + F3( + function (key, value, valueList) { + return A2(_elm_lang$core$List_ops['::'], value, valueList); + }), + _elm_lang$core$Native_List.fromArray( + []), + dict); +}; +var _elm_lang$core$Dict$toList = function (dict) { + return A3( + _elm_lang$core$Dict$foldr, + F3( + function (key, value, list) { + return A2( + _elm_lang$core$List_ops['::'], + {ctor: '_Tuple2', _0: key, _1: value}, + list); + }), + _elm_lang$core$Native_List.fromArray( + []), + dict); +}; +var _elm_lang$core$Dict$foldl = F3( + function (f, acc, dict) { + foldl: + while (true) { + var _p1 = dict; + if (_p1.ctor === 'RBEmpty_elm_builtin') { + return acc; + } else { + var _v5 = f, + _v6 = A3( + f, + _p1._1, + _p1._2, + A3(_elm_lang$core$Dict$foldl, f, acc, _p1._3)), + _v7 = _p1._4; + f = _v5; + acc = _v6; + dict = _v7; + continue foldl; + } + } + }); +var _elm_lang$core$Dict$merge = F6( + function (leftStep, bothStep, rightStep, leftDict, rightDict, initialResult) { + var stepState = F3( + function (rKey, rValue, _p2) { + stepState: + while (true) { + var _p3 = _p2; + var _p9 = _p3._1; + var _p8 = _p3._0; + var _p4 = _p8; + if (_p4.ctor === '[]') { + return { + ctor: '_Tuple2', + _0: _p8, + _1: A3(rightStep, rKey, rValue, _p9) + }; + } else { + var _p7 = _p4._1; + var _p6 = _p4._0._1; + var _p5 = _p4._0._0; + if (_elm_lang$core$Native_Utils.cmp(_p5, rKey) < 0) { + var _v10 = rKey, + _v11 = rValue, + _v12 = { + ctor: '_Tuple2', + _0: _p7, + _1: A3(leftStep, _p5, _p6, _p9) + }; + rKey = _v10; + rValue = _v11; + _p2 = _v12; + continue stepState; + } else { + if (_elm_lang$core$Native_Utils.cmp(_p5, rKey) > 0) { + return { + ctor: '_Tuple2', + _0: _p8, + _1: A3(rightStep, rKey, rValue, _p9) + }; + } else { + return { + ctor: '_Tuple2', + _0: _p7, + _1: A4(bothStep, _p5, _p6, rValue, _p9) + }; + } + } + } + } + }); + var _p10 = A3( + _elm_lang$core$Dict$foldl, + stepState, + { + ctor: '_Tuple2', + _0: _elm_lang$core$Dict$toList(leftDict), + _1: initialResult + }, + rightDict); + var leftovers = _p10._0; + var intermediateResult = _p10._1; + return A3( + _elm_lang$core$List$foldl, + F2( + function (_p11, result) { + var _p12 = _p11; + return A3(leftStep, _p12._0, _p12._1, result); + }), + intermediateResult, + leftovers); + }); +var _elm_lang$core$Dict$reportRemBug = F4( + function (msg, c, lgot, rgot) { + return _elm_lang$core$Native_Debug.crash( + _elm_lang$core$String$concat( + _elm_lang$core$Native_List.fromArray( + [ + 'Internal red-black tree invariant violated, expected ', + msg, + ' and got ', + _elm_lang$core$Basics$toString(c), + '/', + lgot, + '/', + rgot, + '\nPlease report this bug to ' + ]))); + }); +var _elm_lang$core$Dict$isBBlack = function (dict) { + var _p13 = dict; + _v14_2: + do { + if (_p13.ctor === 'RBNode_elm_builtin') { + if (_p13._0.ctor === 'BBlack') { + return true; + } else { + break _v14_2; + } + } else { + if (_p13._0.ctor === 'LBBlack') { + return true; + } else { + break _v14_2; + } + } + } while(false); + return false; +}; +var _elm_lang$core$Dict$sizeHelp = F2( + function (n, dict) { + sizeHelp: + while (true) { + var _p14 = dict; + if (_p14.ctor === 'RBEmpty_elm_builtin') { + return n; + } else { + var _v16 = A2(_elm_lang$core$Dict$sizeHelp, n + 1, _p14._4), + _v17 = _p14._3; + n = _v16; + dict = _v17; + continue sizeHelp; + } + } + }); +var _elm_lang$core$Dict$size = function (dict) { + return A2(_elm_lang$core$Dict$sizeHelp, 0, dict); +}; +var _elm_lang$core$Dict$get = F2( + function (targetKey, dict) { + get: + while (true) { + var _p15 = dict; + if (_p15.ctor === 'RBEmpty_elm_builtin') { + return _elm_lang$core$Maybe$Nothing; + } else { + var _p16 = A2(_elm_lang$core$Basics$compare, targetKey, _p15._1); + switch (_p16.ctor) { + case 'LT': + var _v20 = targetKey, + _v21 = _p15._3; + targetKey = _v20; + dict = _v21; + continue get; + case 'EQ': + return _elm_lang$core$Maybe$Just(_p15._2); + default: + var _v22 = targetKey, + _v23 = _p15._4; + targetKey = _v22; + dict = _v23; + continue get; + } + } + } + }); +var _elm_lang$core$Dict$member = F2( + function (key, dict) { + var _p17 = A2(_elm_lang$core$Dict$get, key, dict); + if (_p17.ctor === 'Just') { + return true; + } else { + return false; + } + }); +var _elm_lang$core$Dict$maxWithDefault = F3( + function (k, v, r) { + maxWithDefault: + while (true) { + var _p18 = r; + if (_p18.ctor === 'RBEmpty_elm_builtin') { + return {ctor: '_Tuple2', _0: k, _1: v}; + } else { + var _v26 = _p18._1, + _v27 = _p18._2, + _v28 = _p18._4; + k = _v26; + v = _v27; + r = _v28; + continue maxWithDefault; + } + } + }); +var _elm_lang$core$Dict$NBlack = {ctor: 'NBlack'}; +var _elm_lang$core$Dict$BBlack = {ctor: 'BBlack'}; +var _elm_lang$core$Dict$Black = {ctor: 'Black'}; +var _elm_lang$core$Dict$blackish = function (t) { + var _p19 = t; + if (_p19.ctor === 'RBNode_elm_builtin') { + var _p20 = _p19._0; + return _elm_lang$core$Native_Utils.eq(_p20, _elm_lang$core$Dict$Black) || _elm_lang$core$Native_Utils.eq(_p20, _elm_lang$core$Dict$BBlack); + } else { + return true; + } +}; +var _elm_lang$core$Dict$Red = {ctor: 'Red'}; +var _elm_lang$core$Dict$moreBlack = function (color) { + var _p21 = color; + switch (_p21.ctor) { + case 'Black': + return _elm_lang$core$Dict$BBlack; + case 'Red': + return _elm_lang$core$Dict$Black; + case 'NBlack': + return _elm_lang$core$Dict$Red; + default: + return _elm_lang$core$Native_Debug.crash('Can\'t make a double black node more black!'); + } +}; +var _elm_lang$core$Dict$lessBlack = function (color) { + var _p22 = color; + switch (_p22.ctor) { + case 'BBlack': + return _elm_lang$core$Dict$Black; + case 'Black': + return _elm_lang$core$Dict$Red; + case 'Red': + return _elm_lang$core$Dict$NBlack; + default: + return _elm_lang$core$Native_Debug.crash('Can\'t make a negative black node less black!'); + } +}; +var _elm_lang$core$Dict$LBBlack = {ctor: 'LBBlack'}; +var _elm_lang$core$Dict$LBlack = {ctor: 'LBlack'}; +var _elm_lang$core$Dict$RBEmpty_elm_builtin = function (a) { + return {ctor: 'RBEmpty_elm_builtin', _0: a}; +}; +var _elm_lang$core$Dict$empty = _elm_lang$core$Dict$RBEmpty_elm_builtin(_elm_lang$core$Dict$LBlack); +var _elm_lang$core$Dict$isEmpty = function (dict) { + return _elm_lang$core$Native_Utils.eq(dict, _elm_lang$core$Dict$empty); +}; +var _elm_lang$core$Dict$RBNode_elm_builtin = F5( + function (a, b, c, d, e) { + return {ctor: 'RBNode_elm_builtin', _0: a, _1: b, _2: c, _3: d, _4: e}; + }); +var _elm_lang$core$Dict$ensureBlackRoot = function (dict) { + var _p23 = dict; + if ((_p23.ctor === 'RBNode_elm_builtin') && (_p23._0.ctor === 'Red')) { + return A5(_elm_lang$core$Dict$RBNode_elm_builtin, _elm_lang$core$Dict$Black, _p23._1, _p23._2, _p23._3, _p23._4); + } else { + return dict; + } +}; +var _elm_lang$core$Dict$lessBlackTree = function (dict) { + var _p24 = dict; + if (_p24.ctor === 'RBNode_elm_builtin') { + return A5( + _elm_lang$core$Dict$RBNode_elm_builtin, + _elm_lang$core$Dict$lessBlack(_p24._0), + _p24._1, + _p24._2, + _p24._3, + _p24._4); + } else { + return _elm_lang$core$Dict$RBEmpty_elm_builtin(_elm_lang$core$Dict$LBlack); + } +}; +var _elm_lang$core$Dict$balancedTree = function (col) { + return function (xk) { + return function (xv) { + return function (yk) { + return function (yv) { + return function (zk) { + return function (zv) { + return function (a) { + return function (b) { + return function (c) { + return function (d) { + return A5( + _elm_lang$core$Dict$RBNode_elm_builtin, + _elm_lang$core$Dict$lessBlack(col), + yk, + yv, + A5(_elm_lang$core$Dict$RBNode_elm_builtin, _elm_lang$core$Dict$Black, xk, xv, a, b), + A5(_elm_lang$core$Dict$RBNode_elm_builtin, _elm_lang$core$Dict$Black, zk, zv, c, d)); + }; + }; + }; + }; + }; + }; + }; + }; + }; + }; +}; +var _elm_lang$core$Dict$blacken = function (t) { + var _p25 = t; + if (_p25.ctor === 'RBEmpty_elm_builtin') { + return _elm_lang$core$Dict$RBEmpty_elm_builtin(_elm_lang$core$Dict$LBlack); + } else { + return A5(_elm_lang$core$Dict$RBNode_elm_builtin, _elm_lang$core$Dict$Black, _p25._1, _p25._2, _p25._3, _p25._4); + } +}; +var _elm_lang$core$Dict$redden = function (t) { + var _p26 = t; + if (_p26.ctor === 'RBEmpty_elm_builtin') { + return _elm_lang$core$Native_Debug.crash('can\'t make a Leaf red'); + } else { + return A5(_elm_lang$core$Dict$RBNode_elm_builtin, _elm_lang$core$Dict$Red, _p26._1, _p26._2, _p26._3, _p26._4); + } +}; +var _elm_lang$core$Dict$balanceHelp = function (tree) { + var _p27 = tree; + _v36_6: + do { + _v36_5: + do { + _v36_4: + do { + _v36_3: + do { + _v36_2: + do { + _v36_1: + do { + _v36_0: + do { + if (_p27.ctor === 'RBNode_elm_builtin') { + if (_p27._3.ctor === 'RBNode_elm_builtin') { + if (_p27._4.ctor === 'RBNode_elm_builtin') { + switch (_p27._3._0.ctor) { + case 'Red': + switch (_p27._4._0.ctor) { + case 'Red': + if ((_p27._3._3.ctor === 'RBNode_elm_builtin') && (_p27._3._3._0.ctor === 'Red')) { + break _v36_0; + } else { + if ((_p27._3._4.ctor === 'RBNode_elm_builtin') && (_p27._3._4._0.ctor === 'Red')) { + break _v36_1; + } else { + if ((_p27._4._3.ctor === 'RBNode_elm_builtin') && (_p27._4._3._0.ctor === 'Red')) { + break _v36_2; + } else { + if ((_p27._4._4.ctor === 'RBNode_elm_builtin') && (_p27._4._4._0.ctor === 'Red')) { + break _v36_3; + } else { + break _v36_6; + } + } + } + } + case 'NBlack': + if ((_p27._3._3.ctor === 'RBNode_elm_builtin') && (_p27._3._3._0.ctor === 'Red')) { + break _v36_0; + } else { + if ((_p27._3._4.ctor === 'RBNode_elm_builtin') && (_p27._3._4._0.ctor === 'Red')) { + break _v36_1; + } else { + if (((((_p27._0.ctor === 'BBlack') && (_p27._4._3.ctor === 'RBNode_elm_builtin')) && (_p27._4._3._0.ctor === 'Black')) && (_p27._4._4.ctor === 'RBNode_elm_builtin')) && (_p27._4._4._0.ctor === 'Black')) { + break _v36_4; + } else { + break _v36_6; + } + } + } + default: + if ((_p27._3._3.ctor === 'RBNode_elm_builtin') && (_p27._3._3._0.ctor === 'Red')) { + break _v36_0; + } else { + if ((_p27._3._4.ctor === 'RBNode_elm_builtin') && (_p27._3._4._0.ctor === 'Red')) { + break _v36_1; + } else { + break _v36_6; + } + } + } + case 'NBlack': + switch (_p27._4._0.ctor) { + case 'Red': + if ((_p27._4._3.ctor === 'RBNode_elm_builtin') && (_p27._4._3._0.ctor === 'Red')) { + break _v36_2; + } else { + if ((_p27._4._4.ctor === 'RBNode_elm_builtin') && (_p27._4._4._0.ctor === 'Red')) { + break _v36_3; + } else { + if (((((_p27._0.ctor === 'BBlack') && (_p27._3._3.ctor === 'RBNode_elm_builtin')) && (_p27._3._3._0.ctor === 'Black')) && (_p27._3._4.ctor === 'RBNode_elm_builtin')) && (_p27._3._4._0.ctor === 'Black')) { + break _v36_5; + } else { + break _v36_6; + } + } + } + case 'NBlack': + if (_p27._0.ctor === 'BBlack') { + if ((((_p27._4._3.ctor === 'RBNode_elm_builtin') && (_p27._4._3._0.ctor === 'Black')) && (_p27._4._4.ctor === 'RBNode_elm_builtin')) && (_p27._4._4._0.ctor === 'Black')) { + break _v36_4; + } else { + if ((((_p27._3._3.ctor === 'RBNode_elm_builtin') && (_p27._3._3._0.ctor === 'Black')) && (_p27._3._4.ctor === 'RBNode_elm_builtin')) && (_p27._3._4._0.ctor === 'Black')) { + break _v36_5; + } else { + break _v36_6; + } + } + } else { + break _v36_6; + } + default: + if (((((_p27._0.ctor === 'BBlack') && (_p27._3._3.ctor === 'RBNode_elm_builtin')) && (_p27._3._3._0.ctor === 'Black')) && (_p27._3._4.ctor === 'RBNode_elm_builtin')) && (_p27._3._4._0.ctor === 'Black')) { + break _v36_5; + } else { + break _v36_6; + } + } + default: + switch (_p27._4._0.ctor) { + case 'Red': + if ((_p27._4._3.ctor === 'RBNode_elm_builtin') && (_p27._4._3._0.ctor === 'Red')) { + break _v36_2; + } else { + if ((_p27._4._4.ctor === 'RBNode_elm_builtin') && (_p27._4._4._0.ctor === 'Red')) { + break _v36_3; + } else { + break _v36_6; + } + } + case 'NBlack': + if (((((_p27._0.ctor === 'BBlack') && (_p27._4._3.ctor === 'RBNode_elm_builtin')) && (_p27._4._3._0.ctor === 'Black')) && (_p27._4._4.ctor === 'RBNode_elm_builtin')) && (_p27._4._4._0.ctor === 'Black')) { + break _v36_4; + } else { + break _v36_6; + } + default: + break _v36_6; + } + } + } else { + switch (_p27._3._0.ctor) { + case 'Red': + if ((_p27._3._3.ctor === 'RBNode_elm_builtin') && (_p27._3._3._0.ctor === 'Red')) { + break _v36_0; + } else { + if ((_p27._3._4.ctor === 'RBNode_elm_builtin') && (_p27._3._4._0.ctor === 'Red')) { + break _v36_1; + } else { + break _v36_6; + } + } + case 'NBlack': + if (((((_p27._0.ctor === 'BBlack') && (_p27._3._3.ctor === 'RBNode_elm_builtin')) && (_p27._3._3._0.ctor === 'Black')) && (_p27._3._4.ctor === 'RBNode_elm_builtin')) && (_p27._3._4._0.ctor === 'Black')) { + break _v36_5; + } else { + break _v36_6; + } + default: + break _v36_6; + } + } + } else { + if (_p27._4.ctor === 'RBNode_elm_builtin') { + switch (_p27._4._0.ctor) { + case 'Red': + if ((_p27._4._3.ctor === 'RBNode_elm_builtin') && (_p27._4._3._0.ctor === 'Red')) { + break _v36_2; + } else { + if ((_p27._4._4.ctor === 'RBNode_elm_builtin') && (_p27._4._4._0.ctor === 'Red')) { + break _v36_3; + } else { + break _v36_6; + } + } + case 'NBlack': + if (((((_p27._0.ctor === 'BBlack') && (_p27._4._3.ctor === 'RBNode_elm_builtin')) && (_p27._4._3._0.ctor === 'Black')) && (_p27._4._4.ctor === 'RBNode_elm_builtin')) && (_p27._4._4._0.ctor === 'Black')) { + break _v36_4; + } else { + break _v36_6; + } + default: + break _v36_6; + } + } else { + break _v36_6; + } + } + } else { + break _v36_6; + } + } while(false); + return _elm_lang$core$Dict$balancedTree(_p27._0)(_p27._3._3._1)(_p27._3._3._2)(_p27._3._1)(_p27._3._2)(_p27._1)(_p27._2)(_p27._3._3._3)(_p27._3._3._4)(_p27._3._4)(_p27._4); + } while(false); + return _elm_lang$core$Dict$balancedTree(_p27._0)(_p27._3._1)(_p27._3._2)(_p27._3._4._1)(_p27._3._4._2)(_p27._1)(_p27._2)(_p27._3._3)(_p27._3._4._3)(_p27._3._4._4)(_p27._4); + } while(false); + return _elm_lang$core$Dict$balancedTree(_p27._0)(_p27._1)(_p27._2)(_p27._4._3._1)(_p27._4._3._2)(_p27._4._1)(_p27._4._2)(_p27._3)(_p27._4._3._3)(_p27._4._3._4)(_p27._4._4); + } while(false); + return _elm_lang$core$Dict$balancedTree(_p27._0)(_p27._1)(_p27._2)(_p27._4._1)(_p27._4._2)(_p27._4._4._1)(_p27._4._4._2)(_p27._3)(_p27._4._3)(_p27._4._4._3)(_p27._4._4._4); + } while(false); + return A5( + _elm_lang$core$Dict$RBNode_elm_builtin, + _elm_lang$core$Dict$Black, + _p27._4._3._1, + _p27._4._3._2, + A5(_elm_lang$core$Dict$RBNode_elm_builtin, _elm_lang$core$Dict$Black, _p27._1, _p27._2, _p27._3, _p27._4._3._3), + A5( + _elm_lang$core$Dict$balance, + _elm_lang$core$Dict$Black, + _p27._4._1, + _p27._4._2, + _p27._4._3._4, + _elm_lang$core$Dict$redden(_p27._4._4))); + } while(false); + return A5( + _elm_lang$core$Dict$RBNode_elm_builtin, + _elm_lang$core$Dict$Black, + _p27._3._4._1, + _p27._3._4._2, + A5( + _elm_lang$core$Dict$balance, + _elm_lang$core$Dict$Black, + _p27._3._1, + _p27._3._2, + _elm_lang$core$Dict$redden(_p27._3._3), + _p27._3._4._3), + A5(_elm_lang$core$Dict$RBNode_elm_builtin, _elm_lang$core$Dict$Black, _p27._1, _p27._2, _p27._3._4._4, _p27._4)); + } while(false); + return tree; +}; +var _elm_lang$core$Dict$balance = F5( + function (c, k, v, l, r) { + var tree = A5(_elm_lang$core$Dict$RBNode_elm_builtin, c, k, v, l, r); + return _elm_lang$core$Dict$blackish(tree) ? _elm_lang$core$Dict$balanceHelp(tree) : tree; + }); +var _elm_lang$core$Dict$bubble = F5( + function (c, k, v, l, r) { + return (_elm_lang$core$Dict$isBBlack(l) || _elm_lang$core$Dict$isBBlack(r)) ? A5( + _elm_lang$core$Dict$balance, + _elm_lang$core$Dict$moreBlack(c), + k, + v, + _elm_lang$core$Dict$lessBlackTree(l), + _elm_lang$core$Dict$lessBlackTree(r)) : A5(_elm_lang$core$Dict$RBNode_elm_builtin, c, k, v, l, r); + }); +var _elm_lang$core$Dict$removeMax = F5( + function (c, k, v, l, r) { + var _p28 = r; + if (_p28.ctor === 'RBEmpty_elm_builtin') { + return A3(_elm_lang$core$Dict$rem, c, l, r); + } else { + return A5( + _elm_lang$core$Dict$bubble, + c, + k, + v, + l, + A5(_elm_lang$core$Dict$removeMax, _p28._0, _p28._1, _p28._2, _p28._3, _p28._4)); + } + }); +var _elm_lang$core$Dict$rem = F3( + function (c, l, r) { + var _p29 = {ctor: '_Tuple2', _0: l, _1: r}; + if (_p29._0.ctor === 'RBEmpty_elm_builtin') { + if (_p29._1.ctor === 'RBEmpty_elm_builtin') { + var _p30 = c; + switch (_p30.ctor) { + case 'Red': + return _elm_lang$core$Dict$RBEmpty_elm_builtin(_elm_lang$core$Dict$LBlack); + case 'Black': + return _elm_lang$core$Dict$RBEmpty_elm_builtin(_elm_lang$core$Dict$LBBlack); + default: + return _elm_lang$core$Native_Debug.crash('cannot have bblack or nblack nodes at this point'); + } + } else { + var _p33 = _p29._1._0; + var _p32 = _p29._0._0; + var _p31 = {ctor: '_Tuple3', _0: c, _1: _p32, _2: _p33}; + if ((((_p31.ctor === '_Tuple3') && (_p31._0.ctor === 'Black')) && (_p31._1.ctor === 'LBlack')) && (_p31._2.ctor === 'Red')) { + return A5(_elm_lang$core$Dict$RBNode_elm_builtin, _elm_lang$core$Dict$Black, _p29._1._1, _p29._1._2, _p29._1._3, _p29._1._4); + } else { + return A4( + _elm_lang$core$Dict$reportRemBug, + 'Black/LBlack/Red', + c, + _elm_lang$core$Basics$toString(_p32), + _elm_lang$core$Basics$toString(_p33)); + } + } + } else { + if (_p29._1.ctor === 'RBEmpty_elm_builtin') { + var _p36 = _p29._1._0; + var _p35 = _p29._0._0; + var _p34 = {ctor: '_Tuple3', _0: c, _1: _p35, _2: _p36}; + if ((((_p34.ctor === '_Tuple3') && (_p34._0.ctor === 'Black')) && (_p34._1.ctor === 'Red')) && (_p34._2.ctor === 'LBlack')) { + return A5(_elm_lang$core$Dict$RBNode_elm_builtin, _elm_lang$core$Dict$Black, _p29._0._1, _p29._0._2, _p29._0._3, _p29._0._4); + } else { + return A4( + _elm_lang$core$Dict$reportRemBug, + 'Black/Red/LBlack', + c, + _elm_lang$core$Basics$toString(_p35), + _elm_lang$core$Basics$toString(_p36)); + } + } else { + var _p40 = _p29._0._2; + var _p39 = _p29._0._4; + var _p38 = _p29._0._1; + var l$ = A5(_elm_lang$core$Dict$removeMax, _p29._0._0, _p38, _p40, _p29._0._3, _p39); + var _p37 = A3(_elm_lang$core$Dict$maxWithDefault, _p38, _p40, _p39); + var k = _p37._0; + var v = _p37._1; + return A5(_elm_lang$core$Dict$bubble, c, k, v, l$, r); + } + } + }); +var _elm_lang$core$Dict$map = F2( + function (f, dict) { + var _p41 = dict; + if (_p41.ctor === 'RBEmpty_elm_builtin') { + return _elm_lang$core$Dict$RBEmpty_elm_builtin(_elm_lang$core$Dict$LBlack); + } else { + var _p42 = _p41._1; + return A5( + _elm_lang$core$Dict$RBNode_elm_builtin, + _p41._0, + _p42, + A2(f, _p42, _p41._2), + A2(_elm_lang$core$Dict$map, f, _p41._3), + A2(_elm_lang$core$Dict$map, f, _p41._4)); + } + }); +var _elm_lang$core$Dict$Same = {ctor: 'Same'}; +var _elm_lang$core$Dict$Remove = {ctor: 'Remove'}; +var _elm_lang$core$Dict$Insert = {ctor: 'Insert'}; +var _elm_lang$core$Dict$update = F3( + function (k, alter, dict) { + var up = function (dict) { + var _p43 = dict; + if (_p43.ctor === 'RBEmpty_elm_builtin') { + var _p44 = alter(_elm_lang$core$Maybe$Nothing); + if (_p44.ctor === 'Nothing') { + return {ctor: '_Tuple2', _0: _elm_lang$core$Dict$Same, _1: _elm_lang$core$Dict$empty}; + } else { + return { + ctor: '_Tuple2', + _0: _elm_lang$core$Dict$Insert, + _1: A5(_elm_lang$core$Dict$RBNode_elm_builtin, _elm_lang$core$Dict$Red, k, _p44._0, _elm_lang$core$Dict$empty, _elm_lang$core$Dict$empty) + }; + } + } else { + var _p55 = _p43._2; + var _p54 = _p43._4; + var _p53 = _p43._3; + var _p52 = _p43._1; + var _p51 = _p43._0; + var _p45 = A2(_elm_lang$core$Basics$compare, k, _p52); + switch (_p45.ctor) { + case 'EQ': + var _p46 = alter( + _elm_lang$core$Maybe$Just(_p55)); + if (_p46.ctor === 'Nothing') { + return { + ctor: '_Tuple2', + _0: _elm_lang$core$Dict$Remove, + _1: A3(_elm_lang$core$Dict$rem, _p51, _p53, _p54) + }; + } else { + return { + ctor: '_Tuple2', + _0: _elm_lang$core$Dict$Same, + _1: A5(_elm_lang$core$Dict$RBNode_elm_builtin, _p51, _p52, _p46._0, _p53, _p54) + }; + } + case 'LT': + var _p47 = up(_p53); + var flag = _p47._0; + var newLeft = _p47._1; + var _p48 = flag; + switch (_p48.ctor) { + case 'Same': + return { + ctor: '_Tuple2', + _0: _elm_lang$core$Dict$Same, + _1: A5(_elm_lang$core$Dict$RBNode_elm_builtin, _p51, _p52, _p55, newLeft, _p54) + }; + case 'Insert': + return { + ctor: '_Tuple2', + _0: _elm_lang$core$Dict$Insert, + _1: A5(_elm_lang$core$Dict$balance, _p51, _p52, _p55, newLeft, _p54) + }; + default: + return { + ctor: '_Tuple2', + _0: _elm_lang$core$Dict$Remove, + _1: A5(_elm_lang$core$Dict$bubble, _p51, _p52, _p55, newLeft, _p54) + }; + } + default: + var _p49 = up(_p54); + var flag = _p49._0; + var newRight = _p49._1; + var _p50 = flag; + switch (_p50.ctor) { + case 'Same': + return { + ctor: '_Tuple2', + _0: _elm_lang$core$Dict$Same, + _1: A5(_elm_lang$core$Dict$RBNode_elm_builtin, _p51, _p52, _p55, _p53, newRight) + }; + case 'Insert': + return { + ctor: '_Tuple2', + _0: _elm_lang$core$Dict$Insert, + _1: A5(_elm_lang$core$Dict$balance, _p51, _p52, _p55, _p53, newRight) + }; + default: + return { + ctor: '_Tuple2', + _0: _elm_lang$core$Dict$Remove, + _1: A5(_elm_lang$core$Dict$bubble, _p51, _p52, _p55, _p53, newRight) + }; + } + } + } + }; + var _p56 = up(dict); + var flag = _p56._0; + var updatedDict = _p56._1; + var _p57 = flag; + switch (_p57.ctor) { + case 'Same': + return updatedDict; + case 'Insert': + return _elm_lang$core$Dict$ensureBlackRoot(updatedDict); + default: + return _elm_lang$core$Dict$blacken(updatedDict); + } + }); +var _elm_lang$core$Dict$insert = F3( + function (key, value, dict) { + return A3( + _elm_lang$core$Dict$update, + key, + _elm_lang$core$Basics$always( + _elm_lang$core$Maybe$Just(value)), + dict); + }); +var _elm_lang$core$Dict$singleton = F2( + function (key, value) { + return A3(_elm_lang$core$Dict$insert, key, value, _elm_lang$core$Dict$empty); + }); +var _elm_lang$core$Dict$union = F2( + function (t1, t2) { + return A3(_elm_lang$core$Dict$foldl, _elm_lang$core$Dict$insert, t2, t1); + }); +var _elm_lang$core$Dict$filter = F2( + function (predicate, dictionary) { + var add = F3( + function (key, value, dict) { + return A2(predicate, key, value) ? A3(_elm_lang$core$Dict$insert, key, value, dict) : dict; + }); + return A3(_elm_lang$core$Dict$foldl, add, _elm_lang$core$Dict$empty, dictionary); + }); +var _elm_lang$core$Dict$intersect = F2( + function (t1, t2) { + return A2( + _elm_lang$core$Dict$filter, + F2( + function (k, _p58) { + return A2(_elm_lang$core$Dict$member, k, t2); + }), + t1); + }); +var _elm_lang$core$Dict$partition = F2( + function (predicate, dict) { + var add = F3( + function (key, value, _p59) { + var _p60 = _p59; + var _p62 = _p60._1; + var _p61 = _p60._0; + return A2(predicate, key, value) ? { + ctor: '_Tuple2', + _0: A3(_elm_lang$core$Dict$insert, key, value, _p61), + _1: _p62 + } : { + ctor: '_Tuple2', + _0: _p61, + _1: A3(_elm_lang$core$Dict$insert, key, value, _p62) + }; + }); + return A3( + _elm_lang$core$Dict$foldl, + add, + {ctor: '_Tuple2', _0: _elm_lang$core$Dict$empty, _1: _elm_lang$core$Dict$empty}, + dict); + }); +var _elm_lang$core$Dict$fromList = function (assocs) { + return A3( + _elm_lang$core$List$foldl, + F2( + function (_p63, dict) { + var _p64 = _p63; + return A3(_elm_lang$core$Dict$insert, _p64._0, _p64._1, dict); + }), + _elm_lang$core$Dict$empty, + assocs); +}; +var _elm_lang$core$Dict$remove = F2( + function (key, dict) { + return A3( + _elm_lang$core$Dict$update, + key, + _elm_lang$core$Basics$always(_elm_lang$core$Maybe$Nothing), + dict); + }); +var _elm_lang$core$Dict$diff = F2( + function (t1, t2) { + return A3( + _elm_lang$core$Dict$foldl, + F3( + function (k, v, t) { + return A2(_elm_lang$core$Dict$remove, k, t); + }), + t1, + t2); + }); + +var _elm_lang$core$Platform_Sub$batch = _elm_lang$core$Native_Platform.batch; +var _elm_lang$core$Platform_Sub$none = _elm_lang$core$Platform_Sub$batch( + _elm_lang$core$Native_List.fromArray( + [])); +var _elm_lang$core$Platform_Sub$map = _elm_lang$core$Native_Platform.map; +var _elm_lang$core$Platform_Sub$Sub = {ctor: 'Sub'}; + +var _elm_lang$core$Debug$crash = _elm_lang$core$Native_Debug.crash; +var _elm_lang$core$Debug$log = _elm_lang$core$Native_Debug.log; + +//import Maybe, Native.Array, Native.List, Native.Utils, Result // + +var _elm_lang$core$Native_Json = function() { + + +// CORE DECODERS + +function succeed(msg) +{ + return { + ctor: '', + tag: 'succeed', + msg: msg + }; +} + +function fail(msg) +{ + return { + ctor: '', + tag: 'fail', + msg: msg + }; +} + +function decodePrimitive(tag) +{ + return { + ctor: '', + tag: tag + }; +} + +function decodeContainer(tag, decoder) +{ + return { + ctor: '', + tag: tag, + decoder: decoder + }; +} + +function decodeNull(value) +{ + return { + ctor: '', + tag: 'null', + value: value + }; +} + +function decodeField(field, decoder) +{ + return { + ctor: '', + tag: 'field', + field: field, + decoder: decoder + }; +} + +function decodeKeyValuePairs(decoder) +{ + return { + ctor: '', + tag: 'key-value', + decoder: decoder + }; +} + +function decodeObject(f, decoders) +{ + return { + ctor: '', + tag: 'map-many', + func: f, + decoders: decoders + }; +} + +function decodeTuple(f, decoders) +{ + return { + ctor: '', + tag: 'tuple', + func: f, + decoders: decoders + }; +} + +function andThen(decoder, callback) +{ + return { + ctor: '', + tag: 'andThen', + decoder: decoder, + callback: callback + }; +} + +function customAndThen(decoder, callback) +{ + return { + ctor: '', + tag: 'customAndThen', + decoder: decoder, + callback: callback + }; +} + +function oneOf(decoders) +{ + return { + ctor: '', + tag: 'oneOf', + decoders: decoders + }; +} + + +// DECODING OBJECTS + +function decodeObject1(f, d1) +{ + return decodeObject(f, [d1]); +} + +function decodeObject2(f, d1, d2) +{ + return decodeObject(f, [d1, d2]); +} + +function decodeObject3(f, d1, d2, d3) +{ + return decodeObject(f, [d1, d2, d3]); +} + +function decodeObject4(f, d1, d2, d3, d4) +{ + return decodeObject(f, [d1, d2, d3, d4]); +} + +function decodeObject5(f, d1, d2, d3, d4, d5) +{ + return decodeObject(f, [d1, d2, d3, d4, d5]); +} + +function decodeObject6(f, d1, d2, d3, d4, d5, d6) +{ + return decodeObject(f, [d1, d2, d3, d4, d5, d6]); +} + +function decodeObject7(f, d1, d2, d3, d4, d5, d6, d7) +{ + return decodeObject(f, [d1, d2, d3, d4, d5, d6, d7]); +} + +function decodeObject8(f, d1, d2, d3, d4, d5, d6, d7, d8) +{ + return decodeObject(f, [d1, d2, d3, d4, d5, d6, d7, d8]); +} + + +// DECODING TUPLES + +function decodeTuple1(f, d1) +{ + return decodeTuple(f, [d1]); +} + +function decodeTuple2(f, d1, d2) +{ + return decodeTuple(f, [d1, d2]); +} + +function decodeTuple3(f, d1, d2, d3) +{ + return decodeTuple(f, [d1, d2, d3]); +} + +function decodeTuple4(f, d1, d2, d3, d4) +{ + return decodeTuple(f, [d1, d2, d3, d4]); +} + +function decodeTuple5(f, d1, d2, d3, d4, d5) +{ + return decodeTuple(f, [d1, d2, d3, d4, d5]); +} + +function decodeTuple6(f, d1, d2, d3, d4, d5, d6) +{ + return decodeTuple(f, [d1, d2, d3, d4, d5, d6]); +} + +function decodeTuple7(f, d1, d2, d3, d4, d5, d6, d7) +{ + return decodeTuple(f, [d1, d2, d3, d4, d5, d6, d7]); +} + +function decodeTuple8(f, d1, d2, d3, d4, d5, d6, d7, d8) +{ + return decodeTuple(f, [d1, d2, d3, d4, d5, d6, d7, d8]); +} + + +// DECODE HELPERS + +function ok(value) +{ + return { tag: 'ok', value: value }; +} + +function badPrimitive(type, value) +{ + return { tag: 'primitive', type: type, value: value }; +} + +function badIndex(index, nestedProblems) +{ + return { tag: 'index', index: index, rest: nestedProblems }; +} + +function badField(field, nestedProblems) +{ + return { tag: 'field', field: field, rest: nestedProblems }; +} + +function badOneOf(problems) +{ + return { tag: 'oneOf', problems: problems }; +} + +function badCustom(msg) +{ + return { tag: 'custom', msg: msg }; +} + +function bad(msg) +{ + return { tag: 'fail', msg: msg }; +} + +function badToString(problem) +{ + var context = '_'; + while (problem) + { + switch (problem.tag) + { + case 'primitive': + return 'Expecting ' + problem.type + + (context === '_' ? '' : ' at ' + context) + + ' but instead got: ' + jsToString(problem.value); + + case 'index': + context += '[' + problem.index + ']'; + problem = problem.rest; + break; + + case 'field': + context += '.' + problem.field; + problem = problem.rest; + break; + + case 'oneOf': + var problems = problem.problems; + for (var i = 0; i < problems.length; i++) + { + problems[i] = badToString(problems[i]); + } + return 'I ran into the following problems' + + (context === '_' ? '' : ' at ' + context) + + ':\n\n' + problems.join('\n'); + + case 'custom': + return 'A `customDecoder` failed' + + (context === '_' ? '' : ' at ' + context) + + ' with the message: ' + problem.msg; + + case 'fail': + return 'I ran into a `fail` decoder' + + (context === '_' ? '' : ' at ' + context) + + ': ' + problem.msg; + } + } +} + +function jsToString(value) +{ + return value === undefined + ? 'undefined' + : JSON.stringify(value); +} + + +// DECODE + +function runOnString(decoder, string) +{ + var json; + try + { + json = JSON.parse(string); + } + catch (e) + { + return _elm_lang$core$Result$Err('Given an invalid JSON: ' + e.message); + } + return run(decoder, json); +} + +function run(decoder, value) +{ + var result = runHelp(decoder, value); + return (result.tag === 'ok') + ? _elm_lang$core$Result$Ok(result.value) + : _elm_lang$core$Result$Err(badToString(result)); +} + +function runHelp(decoder, value) +{ + switch (decoder.tag) + { + case 'bool': + return (typeof value === 'boolean') + ? ok(value) + : badPrimitive('a Bool', value); + + case 'int': + if (typeof value !== 'number') { + return badPrimitive('an Int', value); + } + + if (-2147483647 < value && value < 2147483647 && (value | 0) === value) { + return ok(value); + } + + if (isFinite(value) && !(value % 1)) { + return ok(value); + } + + return badPrimitive('an Int', value); + + case 'float': + return (typeof value === 'number') + ? ok(value) + : badPrimitive('a Float', value); + + case 'string': + return (typeof value === 'string') + ? ok(value) + : (value instanceof String) + ? ok(value + '') + : badPrimitive('a String', value); + + case 'null': + return (value === null) + ? ok(decoder.value) + : badPrimitive('null', value); + + case 'value': + return ok(value); + + case 'list': + if (!(value instanceof Array)) + { + return badPrimitive('a List', value); + } + + var list = _elm_lang$core$Native_List.Nil; + for (var i = value.length; i--; ) + { + var result = runHelp(decoder.decoder, value[i]); + if (result.tag !== 'ok') + { + return badIndex(i, result) + } + list = _elm_lang$core$Native_List.Cons(result.value, list); + } + return ok(list); + + case 'array': + if (!(value instanceof Array)) + { + return badPrimitive('an Array', value); + } + + var len = value.length; + var array = new Array(len); + for (var i = len; i--; ) + { + var result = runHelp(decoder.decoder, value[i]); + if (result.tag !== 'ok') + { + return badIndex(i, result); + } + array[i] = result.value; + } + return ok(_elm_lang$core$Native_Array.fromJSArray(array)); + + case 'maybe': + var result = runHelp(decoder.decoder, value); + return (result.tag === 'ok') + ? ok(_elm_lang$core$Maybe$Just(result.value)) + : ok(_elm_lang$core$Maybe$Nothing); + + case 'field': + var field = decoder.field; + if (typeof value !== 'object' || value === null || !(field in value)) + { + return badPrimitive('an object with a field named `' + field + '`', value); + } + + var result = runHelp(decoder.decoder, value[field]); + return (result.tag === 'ok') + ? result + : badField(field, result); + + case 'key-value': + if (typeof value !== 'object' || value === null || value instanceof Array) + { + return badPrimitive('an object', value); + } + + var keyValuePairs = _elm_lang$core$Native_List.Nil; + for (var key in value) + { + var result = runHelp(decoder.decoder, value[key]); + if (result.tag !== 'ok') + { + return badField(key, result); + } + var pair = _elm_lang$core$Native_Utils.Tuple2(key, result.value); + keyValuePairs = _elm_lang$core$Native_List.Cons(pair, keyValuePairs); + } + return ok(keyValuePairs); + + case 'map-many': + var answer = decoder.func; + var decoders = decoder.decoders; + for (var i = 0; i < decoders.length; i++) + { + var result = runHelp(decoders[i], value); + if (result.tag !== 'ok') + { + return result; + } + answer = answer(result.value); + } + return ok(answer); + + case 'tuple': + var decoders = decoder.decoders; + var len = decoders.length; + + if ( !(value instanceof Array) || value.length !== len ) + { + return badPrimitive('a Tuple with ' + len + ' entries', value); + } + + var answer = decoder.func; + for (var i = 0; i < len; i++) + { + var result = runHelp(decoders[i], value[i]); + if (result.tag !== 'ok') + { + return badIndex(i, result); + } + answer = answer(result.value); + } + return ok(answer); + + case 'customAndThen': + var result = runHelp(decoder.decoder, value); + if (result.tag !== 'ok') + { + return result; + } + var realResult = decoder.callback(result.value); + if (realResult.ctor === 'Err') + { + return badCustom(realResult._0); + } + return ok(realResult._0); + + case 'andThen': + var result = runHelp(decoder.decoder, value); + return (result.tag !== 'ok') + ? result + : runHelp(decoder.callback(result.value), value); + + case 'oneOf': + var errors = []; + var temp = decoder.decoders; + while (temp.ctor !== '[]') + { + var result = runHelp(temp._0, value); + + if (result.tag === 'ok') + { + return result; + } + + errors.push(result); + + temp = temp._1; + } + return badOneOf(errors); + + case 'fail': + return bad(decoder.msg); + + case 'succeed': + return ok(decoder.msg); + } +} + + +// EQUALITY + +function equality(a, b) +{ + if (a === b) + { + return true; + } + + if (a.tag !== b.tag) + { + return false; + } + + switch (a.tag) + { + case 'succeed': + case 'fail': + return a.msg === b.msg; + + case 'bool': + case 'int': + case 'float': + case 'string': + case 'value': + return true; + + case 'null': + return a.value === b.value; + + case 'list': + case 'array': + case 'maybe': + case 'key-value': + return equality(a.decoder, b.decoder); + + case 'field': + return a.field === b.field && equality(a.decoder, b.decoder); + + case 'map-many': + case 'tuple': + if (a.func !== b.func) + { + return false; + } + return listEquality(a.decoders, b.decoders); + + case 'andThen': + case 'customAndThen': + return a.callback === b.callback && equality(a.decoder, b.decoder); + + case 'oneOf': + return listEquality(a.decoders, b.decoders); + } +} + +function listEquality(aDecoders, bDecoders) +{ + var len = aDecoders.length; + if (len !== bDecoders.length) + { + return false; + } + for (var i = 0; i < len; i++) + { + if (!equality(aDecoders[i], bDecoders[i])) + { + return false; + } + } + return true; +} + + +// ENCODE + +function encode(indentLevel, value) +{ + return JSON.stringify(value, null, indentLevel); +} + +function identity(value) +{ + return value; +} + +function encodeObject(keyValuePairs) +{ + var obj = {}; + while (keyValuePairs.ctor !== '[]') + { + var pair = keyValuePairs._0; + obj[pair._0] = pair._1; + keyValuePairs = keyValuePairs._1; + } + return obj; +} + +return { + encode: F2(encode), + runOnString: F2(runOnString), + run: F2(run), + + decodeNull: decodeNull, + decodePrimitive: decodePrimitive, + decodeContainer: F2(decodeContainer), + + decodeField: F2(decodeField), + + decodeObject1: F2(decodeObject1), + decodeObject2: F3(decodeObject2), + decodeObject3: F4(decodeObject3), + decodeObject4: F5(decodeObject4), + decodeObject5: F6(decodeObject5), + decodeObject6: F7(decodeObject6), + decodeObject7: F8(decodeObject7), + decodeObject8: F9(decodeObject8), + decodeKeyValuePairs: decodeKeyValuePairs, + + decodeTuple1: F2(decodeTuple1), + decodeTuple2: F3(decodeTuple2), + decodeTuple3: F4(decodeTuple3), + decodeTuple4: F5(decodeTuple4), + decodeTuple5: F6(decodeTuple5), + decodeTuple6: F7(decodeTuple6), + decodeTuple7: F8(decodeTuple7), + decodeTuple8: F9(decodeTuple8), + + andThen: F2(andThen), + customAndThen: F2(customAndThen), + fail: fail, + succeed: succeed, + oneOf: oneOf, + + identity: identity, + encodeNull: null, + encodeArray: _elm_lang$core$Native_Array.toJSArray, + encodeList: _elm_lang$core$Native_List.toArray, + encodeObject: encodeObject, + + equality: equality +}; + +}(); + +var _elm_lang$core$Json_Encode$list = _elm_lang$core$Native_Json.encodeList; +var _elm_lang$core$Json_Encode$array = _elm_lang$core$Native_Json.encodeArray; +var _elm_lang$core$Json_Encode$object = _elm_lang$core$Native_Json.encodeObject; +var _elm_lang$core$Json_Encode$null = _elm_lang$core$Native_Json.encodeNull; +var _elm_lang$core$Json_Encode$bool = _elm_lang$core$Native_Json.identity; +var _elm_lang$core$Json_Encode$float = _elm_lang$core$Native_Json.identity; +var _elm_lang$core$Json_Encode$int = _elm_lang$core$Native_Json.identity; +var _elm_lang$core$Json_Encode$string = _elm_lang$core$Native_Json.identity; +var _elm_lang$core$Json_Encode$encode = _elm_lang$core$Native_Json.encode; +var _elm_lang$core$Json_Encode$Value = {ctor: 'Value'}; + +var _elm_lang$core$Json_Decode$tuple8 = _elm_lang$core$Native_Json.decodeTuple8; +var _elm_lang$core$Json_Decode$tuple7 = _elm_lang$core$Native_Json.decodeTuple7; +var _elm_lang$core$Json_Decode$tuple6 = _elm_lang$core$Native_Json.decodeTuple6; +var _elm_lang$core$Json_Decode$tuple5 = _elm_lang$core$Native_Json.decodeTuple5; +var _elm_lang$core$Json_Decode$tuple4 = _elm_lang$core$Native_Json.decodeTuple4; +var _elm_lang$core$Json_Decode$tuple3 = _elm_lang$core$Native_Json.decodeTuple3; +var _elm_lang$core$Json_Decode$tuple2 = _elm_lang$core$Native_Json.decodeTuple2; +var _elm_lang$core$Json_Decode$tuple1 = _elm_lang$core$Native_Json.decodeTuple1; +var _elm_lang$core$Json_Decode$succeed = _elm_lang$core$Native_Json.succeed; +var _elm_lang$core$Json_Decode$fail = _elm_lang$core$Native_Json.fail; +var _elm_lang$core$Json_Decode$andThen = _elm_lang$core$Native_Json.andThen; +var _elm_lang$core$Json_Decode$customDecoder = _elm_lang$core$Native_Json.customAndThen; +var _elm_lang$core$Json_Decode$decodeValue = _elm_lang$core$Native_Json.run; +var _elm_lang$core$Json_Decode$value = _elm_lang$core$Native_Json.decodePrimitive('value'); +var _elm_lang$core$Json_Decode$maybe = function (decoder) { + return A2(_elm_lang$core$Native_Json.decodeContainer, 'maybe', decoder); +}; +var _elm_lang$core$Json_Decode$null = _elm_lang$core$Native_Json.decodeNull; +var _elm_lang$core$Json_Decode$array = function (decoder) { + return A2(_elm_lang$core$Native_Json.decodeContainer, 'array', decoder); +}; +var _elm_lang$core$Json_Decode$list = function (decoder) { + return A2(_elm_lang$core$Native_Json.decodeContainer, 'list', decoder); +}; +var _elm_lang$core$Json_Decode$bool = _elm_lang$core$Native_Json.decodePrimitive('bool'); +var _elm_lang$core$Json_Decode$int = _elm_lang$core$Native_Json.decodePrimitive('int'); +var _elm_lang$core$Json_Decode$float = _elm_lang$core$Native_Json.decodePrimitive('float'); +var _elm_lang$core$Json_Decode$string = _elm_lang$core$Native_Json.decodePrimitive('string'); +var _elm_lang$core$Json_Decode$oneOf = _elm_lang$core$Native_Json.oneOf; +var _elm_lang$core$Json_Decode$keyValuePairs = _elm_lang$core$Native_Json.decodeKeyValuePairs; +var _elm_lang$core$Json_Decode$object8 = _elm_lang$core$Native_Json.decodeObject8; +var _elm_lang$core$Json_Decode$object7 = _elm_lang$core$Native_Json.decodeObject7; +var _elm_lang$core$Json_Decode$object6 = _elm_lang$core$Native_Json.decodeObject6; +var _elm_lang$core$Json_Decode$object5 = _elm_lang$core$Native_Json.decodeObject5; +var _elm_lang$core$Json_Decode$object4 = _elm_lang$core$Native_Json.decodeObject4; +var _elm_lang$core$Json_Decode$object3 = _elm_lang$core$Native_Json.decodeObject3; +var _elm_lang$core$Json_Decode$object2 = _elm_lang$core$Native_Json.decodeObject2; +var _elm_lang$core$Json_Decode$object1 = _elm_lang$core$Native_Json.decodeObject1; +var _elm_lang$core$Json_Decode_ops = _elm_lang$core$Json_Decode_ops || {}; +_elm_lang$core$Json_Decode_ops[':='] = _elm_lang$core$Native_Json.decodeField; +var _elm_lang$core$Json_Decode$at = F2( + function (fields, decoder) { + return A3( + _elm_lang$core$List$foldr, + F2( + function (x, y) { + return A2(_elm_lang$core$Json_Decode_ops[':='], x, y); + }), + decoder, + fields); + }); +var _elm_lang$core$Json_Decode$decodeString = _elm_lang$core$Native_Json.runOnString; +var _elm_lang$core$Json_Decode$map = _elm_lang$core$Native_Json.decodeObject1; +var _elm_lang$core$Json_Decode$dict = function (decoder) { + return A2( + _elm_lang$core$Json_Decode$map, + _elm_lang$core$Dict$fromList, + _elm_lang$core$Json_Decode$keyValuePairs(decoder)); +}; +var _elm_lang$core$Json_Decode$Decoder = {ctor: 'Decoder'}; + +//import Native.Json // + +var _elm_lang$virtual_dom$Native_VirtualDom = function() { + +var STYLE_KEY = 'STYLE'; +var EVENT_KEY = 'EVENT'; +var ATTR_KEY = 'ATTR'; +var ATTR_NS_KEY = 'ATTR_NS'; + + + +//////////// VIRTUAL DOM NODES //////////// + + +function text(string) +{ + return { + type: 'text', + text: string + }; +} + + +function node(tag) +{ + return F2(function(factList, kidList) { + return nodeHelp(tag, factList, kidList); + }); +} + + +function nodeHelp(tag, factList, kidList) +{ + var organized = organizeFacts(factList); + var namespace = organized.namespace; + var facts = organized.facts; + + var children = []; + var descendantsCount = 0; + while (kidList.ctor !== '[]') + { + var kid = kidList._0; + descendantsCount += (kid.descendantsCount || 0); + children.push(kid); + kidList = kidList._1; + } + descendantsCount += children.length; + + return { + type: 'node', + tag: tag, + facts: facts, + children: children, + namespace: namespace, + descendantsCount: descendantsCount + }; +} + + +function keyedNode(tag, factList, kidList) +{ + var organized = organizeFacts(factList); + var namespace = organized.namespace; + var facts = organized.facts; + + var children = []; + var descendantsCount = 0; + while (kidList.ctor !== '[]') + { + var kid = kidList._0; + descendantsCount += (kid._1.descendantsCount || 0); + children.push(kid); + kidList = kidList._1; + } + descendantsCount += children.length; + + return { + type: 'keyed-node', + tag: tag, + facts: facts, + children: children, + namespace: namespace, + descendantsCount: descendantsCount + }; +} + + +function custom(factList, model, impl) +{ + var facts = organizeFacts(factList).facts; + + return { + type: 'custom', + facts: facts, + model: model, + impl: impl + }; +} + + +function map(tagger, node) +{ + return { + type: 'tagger', + tagger: tagger, + node: node, + descendantsCount: 1 + (node.descendantsCount || 0) + }; +} + + +function thunk(func, args, thunk) +{ + return { + type: 'thunk', + func: func, + args: args, + thunk: thunk, + node: undefined + }; +} + +function lazy(fn, a) +{ + return thunk(fn, [a], function() { + return fn(a); + }); +} + +function lazy2(fn, a, b) +{ + return thunk(fn, [a,b], function() { + return A2(fn, a, b); + }); +} + +function lazy3(fn, a, b, c) +{ + return thunk(fn, [a,b,c], function() { + return A3(fn, a, b, c); + }); +} + + + +// FACTS + + +function organizeFacts(factList) +{ + var namespace, facts = {}; + + while (factList.ctor !== '[]') + { + var entry = factList._0; + var key = entry.key; + + if (key === ATTR_KEY || key === ATTR_NS_KEY || key === EVENT_KEY) + { + var subFacts = facts[key] || {}; + subFacts[entry.realKey] = entry.value; + facts[key] = subFacts; + } + else if (key === STYLE_KEY) + { + var styles = facts[key] || {}; + var styleList = entry.value; + while (styleList.ctor !== '[]') + { + var style = styleList._0; + styles[style._0] = style._1; + styleList = styleList._1; + } + facts[key] = styles; + } + else if (key === 'namespace') + { + namespace = entry.value; + } + else + { + facts[key] = entry.value; + } + factList = factList._1; + } + + return { + facts: facts, + namespace: namespace + }; +} + + + +//////////// PROPERTIES AND ATTRIBUTES //////////// + + +function style(value) +{ + return { + key: STYLE_KEY, + value: value + }; +} + + +function property(key, value) +{ + return { + key: key, + value: value + }; +} + + +function attribute(key, value) +{ + return { + key: ATTR_KEY, + realKey: key, + value: value + }; +} + + +function attributeNS(namespace, key, value) +{ + return { + key: ATTR_NS_KEY, + realKey: key, + value: { + value: value, + namespace: namespace + } + }; +} + + +function on(name, options, decoder) +{ + return { + key: EVENT_KEY, + realKey: name, + value: { + options: options, + decoder: decoder + } + }; +} + + +function equalEvents(a, b) +{ + if (!a.options === b.options) + { + if (a.stopPropagation !== b.stopPropagation || a.preventDefault !== b.preventDefault) + { + return false; + } + } + return _elm_lang$core$Native_Json.equality(a.decoder, b.decoder); +} + + + +//////////// RENDERER //////////// + + +function renderer(parent, tagger, initialVirtualNode) +{ + var eventNode = { tagger: tagger, parent: undefined }; + + var domNode = render(initialVirtualNode, eventNode); + parent.appendChild(domNode); + + var state = 'NO_REQUEST'; + var currentVirtualNode = initialVirtualNode; + var nextVirtualNode = initialVirtualNode; + + function registerVirtualNode(nextVirtualNode) + { + var patches = diff(currentVirtualNode, nextVirtualNode); + domNode = applyPatches(domNode, currentVirtualNode, patches, eventNode); + currentVirtualNode = nextVirtualNode; + } + + + return { update: registerVirtualNode }; +} + + +var rAF = + typeof requestAnimationFrame !== 'undefined' + ? requestAnimationFrame + : function(cb) { setTimeout(cb, 1000 / 60); }; + + + +//////////// RENDER //////////// + + +function render(vNode, eventNode) +{ + switch (vNode.type) + { + case 'thunk': + if (!vNode.node) + { + vNode.node = vNode.thunk(); + } + return render(vNode.node, eventNode); + + case 'tagger': + var subNode = vNode.node; + var tagger = vNode.tagger; + + while (subNode.type === 'tagger') + { + typeof tagger !== 'object' + ? tagger = [tagger, subNode.tagger] + : tagger.push(subNode.tagger); + + subNode = subNode.node; + } + + var subEventRoot = { + tagger: tagger, + parent: eventNode + }; + + var domNode = render(subNode, subEventRoot); + domNode.elm_event_node_ref = subEventRoot; + return domNode; + + case 'text': + return document.createTextNode(vNode.text); + + case 'node': + var domNode = vNode.namespace + ? document.createElementNS(vNode.namespace, vNode.tag) + : document.createElement(vNode.tag); + + applyFacts(domNode, eventNode, vNode.facts); + + var children = vNode.children; + + for (var i = 0; i < children.length; i++) + { + domNode.appendChild(render(children[i], eventNode)); + } + + return domNode; + + case 'keyed-node': + var domNode = vNode.namespace + ? document.createElementNS(vNode.namespace, vNode.tag) + : document.createElement(vNode.tag); + + applyFacts(domNode, eventNode, vNode.facts); + + var children = vNode.children; + + for (var i = 0; i < children.length; i++) + { + domNode.appendChild(render(children[i]._1, eventNode)); + } + + return domNode; + + case 'custom': + var domNode = vNode.impl.render(vNode.model); + applyFacts(domNode, eventNode, vNode.facts); + return domNode; + } +} + + + +//////////// APPLY FACTS //////////// + + +function applyFacts(domNode, eventNode, facts) +{ + for (var key in facts) + { + var value = facts[key]; + + switch (key) + { + case STYLE_KEY: + applyStyles(domNode, value); + break; + + case EVENT_KEY: + applyEvents(domNode, eventNode, value); + break; + + case ATTR_KEY: + applyAttrs(domNode, value); + break; + + case ATTR_NS_KEY: + applyAttrsNS(domNode, value); + break; + + case 'value': + if (domNode[key] !== value) + { + domNode[key] = value; + } + break; + + default: + domNode[key] = value; + break; + } + } +} + +function applyStyles(domNode, styles) +{ + var domNodeStyle = domNode.style; + + for (var key in styles) + { + domNodeStyle[key] = styles[key]; + } +} + +function applyEvents(domNode, eventNode, events) +{ + var allHandlers = domNode.elm_handlers || {}; + + for (var key in events) + { + var handler = allHandlers[key]; + var value = events[key]; + + if (typeof value === 'undefined') + { + domNode.removeEventListener(key, handler); + allHandlers[key] = undefined; + } + else if (typeof handler === 'undefined') + { + var handler = makeEventHandler(eventNode, value); + domNode.addEventListener(key, handler); + allHandlers[key] = handler; + } + else + { + handler.info = value; + } + } + + domNode.elm_handlers = allHandlers; +} + +function makeEventHandler(eventNode, info) +{ + function eventHandler(event) + { + var info = eventHandler.info; + + var value = A2(_elm_lang$core$Native_Json.run, info.decoder, event); + + if (value.ctor === 'Ok') + { + var options = info.options; + if (options.stopPropagation) + { + event.stopPropagation(); + } + if (options.preventDefault) + { + event.preventDefault(); + } + + var message = value._0; + + var currentEventNode = eventNode; + while (currentEventNode) + { + var tagger = currentEventNode.tagger; + if (typeof tagger === 'function') + { + message = tagger(message); + } + else + { + for (var i = tagger.length; i--; ) + { + message = tagger[i](message); + } + } + currentEventNode = currentEventNode.parent; + } + } + }; + + eventHandler.info = info; + + return eventHandler; +} + +function applyAttrs(domNode, attrs) +{ + for (var key in attrs) + { + var value = attrs[key]; + if (typeof value === 'undefined') + { + domNode.removeAttribute(key); + } + else + { + domNode.setAttribute(key, value); + } + } +} + +function applyAttrsNS(domNode, nsAttrs) +{ + for (var key in nsAttrs) + { + var pair = nsAttrs[key]; + var namespace = pair.namespace; + var value = pair.value; + + if (typeof value === 'undefined') + { + domNode.removeAttributeNS(namespace, key); + } + else + { + domNode.setAttributeNS(namespace, key, value); + } + } +} + + + +//////////// DIFF //////////// + + +function diff(a, b) +{ + var patches = []; + diffHelp(a, b, patches, 0); + return patches; +} + + +function makePatch(type, index, data) +{ + return { + index: index, + type: type, + data: data, + domNode: undefined, + eventNode: undefined + }; +} + + +function diffHelp(a, b, patches, index) +{ + if (a === b) + { + return; + } + + var aType = a.type; + var bType = b.type; + + // Bail if you run into different types of nodes. Implies that the + // structure has changed significantly and it's not worth a diff. + if (aType !== bType) + { + patches.push(makePatch('p-redraw', index, b)); + return; + } + + // Now we know that both nodes are the same type. + switch (bType) + { + case 'thunk': + var aArgs = a.args; + var bArgs = b.args; + var i = aArgs.length; + var same = a.func === b.func && i === bArgs.length; + while (same && i--) + { + same = aArgs[i] === bArgs[i]; + } + if (same) + { + b.node = a.node; + return; + } + b.node = b.thunk(); + var subPatches = []; + diffHelp(a.node, b.node, subPatches, 0); + if (subPatches.length > 0) + { + patches.push(makePatch('p-thunk', index, subPatches)); + } + return; + + case 'tagger': + // gather nested taggers + var aTaggers = a.tagger; + var bTaggers = b.tagger; + var nesting = false; + + var aSubNode = a.node; + while (aSubNode.type === 'tagger') + { + nesting = true; + + typeof aTaggers !== 'object' + ? aTaggers = [aTaggers, aSubNode.tagger] + : aTaggers.push(aSubNode.tagger); + + aSubNode = aSubNode.node; + } + + var bSubNode = b.node; + while (bSubNode.type === 'tagger') + { + nesting = true; + + typeof bTaggers !== 'object' + ? bTaggers = [bTaggers, bSubNode.tagger] + : bTaggers.push(bSubNode.tagger); + + bSubNode = bSubNode.node; + } + + // Just bail if different numbers of taggers. This implies the + // structure of the virtual DOM has changed. + if (nesting && aTaggers.length !== bTaggers.length) + { + patches.push(makePatch('p-redraw', index, b)); + return; + } + + // check if taggers are "the same" + if (nesting ? !pairwiseRefEqual(aTaggers, bTaggers) : aTaggers !== bTaggers) + { + patches.push(makePatch('p-tagger', index, bTaggers)); + } + + // diff everything below the taggers + diffHelp(aSubNode, bSubNode, patches, index + 1); + return; + + case 'text': + if (a.text !== b.text) + { + patches.push(makePatch('p-text', index, b.text)); + return; + } + + return; + + case 'node': + // Bail if obvious indicators have changed. Implies more serious + // structural changes such that it's not worth it to diff. + if (a.tag !== b.tag || a.namespace !== b.namespace) + { + patches.push(makePatch('p-redraw', index, b)); + return; + } + + var factsDiff = diffFacts(a.facts, b.facts); + + if (typeof factsDiff !== 'undefined') + { + patches.push(makePatch('p-facts', index, factsDiff)); + } + + diffChildren(a, b, patches, index); + return; + + case 'keyed-node': + // Bail if obvious indicators have changed. Implies more serious + // structural changes such that it's not worth it to diff. + if (a.tag !== b.tag || a.namespace !== b.namespace) + { + patches.push(makePatch('p-redraw', index, b)); + return; + } + + var factsDiff = diffFacts(a.facts, b.facts); + + if (typeof factsDiff !== 'undefined') + { + patches.push(makePatch('p-facts', index, factsDiff)); + } + + diffKeyedChildren(a, b, patches, index); + return; + + case 'custom': + if (a.impl !== b.impl) + { + patches.push(makePatch('p-redraw', index, b)); + return; + } + + var factsDiff = diffFacts(a.facts, b.facts); + if (typeof factsDiff !== 'undefined') + { + patches.push(makePatch('p-facts', index, factsDiff)); + } + + var patch = b.impl.diff(a,b); + if (patch) + { + patches.push(makePatch('p-custom', index, patch)); + return; + } + + return; + } +} + + +// assumes the incoming arrays are the same length +function pairwiseRefEqual(as, bs) +{ + for (var i = 0; i < as.length; i++) + { + if (as[i] !== bs[i]) + { + return false; + } + } + + return true; +} + + +// TODO Instead of creating a new diff object, it's possible to just test if +// there *is* a diff. During the actual patch, do the diff again and make the +// modifications directly. This way, there's no new allocations. Worth it? +function diffFacts(a, b, category) +{ + var diff; + + // look for changes and removals + for (var aKey in a) + { + if (aKey === STYLE_KEY || aKey === EVENT_KEY || aKey === ATTR_KEY || aKey === ATTR_NS_KEY) + { + var subDiff = diffFacts(a[aKey], b[aKey] || {}, aKey); + if (subDiff) + { + diff = diff || {}; + diff[aKey] = subDiff; + } + continue; + } + + // remove if not in the new facts + if (!(aKey in b)) + { + diff = diff || {}; + diff[aKey] = + (typeof category === 'undefined') + ? (typeof a[aKey] === 'string' ? '' : null) + : + (category === STYLE_KEY) + ? '' + : + (category === EVENT_KEY || category === ATTR_KEY) + ? undefined + : + { namespace: a[aKey].namespace, value: undefined }; + + continue; + } + + var aValue = a[aKey]; + var bValue = b[aKey]; + + // reference equal, so don't worry about it + if (aValue === bValue && aKey !== 'value' + || category === EVENT_KEY && equalEvents(aValue, bValue)) + { + continue; + } + + diff = diff || {}; + diff[aKey] = bValue; + } + + // add new stuff + for (var bKey in b) + { + if (!(bKey in a)) + { + diff = diff || {}; + diff[bKey] = b[bKey]; + } + } + + return diff; +} + + +function diffChildren(aParent, bParent, patches, rootIndex) +{ + var aChildren = aParent.children; + var bChildren = bParent.children; + + var aLen = aChildren.length; + var bLen = bChildren.length; + + // FIGURE OUT IF THERE ARE INSERTS OR REMOVALS + + if (aLen > bLen) + { + patches.push(makePatch('p-remove-last', rootIndex, aLen - bLen)); + } + else if (aLen < bLen) + { + patches.push(makePatch('p-append', rootIndex, bChildren.slice(aLen))); + } + + // PAIRWISE DIFF EVERYTHING ELSE + + var index = rootIndex; + var minLen = aLen < bLen ? aLen : bLen; + for (var i = 0; i < minLen; i++) + { + index++; + var aChild = aChildren[i]; + diffHelp(aChild, bChildren[i], patches, index); + index += aChild.descendantsCount || 0; + } +} + + + +//////////// KEYED DIFF //////////// + + +function diffKeyedChildren(aParent, bParent, patches, rootIndex) +{ + var localPatches = []; + + var changes = {}; // Dict String Entry + var inserts = []; // Array { index : Int, entry : Entry } + // type Entry = { tag : String, vnode : VNode, index : Int, data : _ } + + var aChildren = aParent.children; + var bChildren = bParent.children; + var aLen = aChildren.length; + var bLen = bChildren.length; + var aIndex = 0; + var bIndex = 0; + + var index = rootIndex; + + while (aIndex < aLen && bIndex < bLen) + { + var a = aChildren[aIndex]; + var b = bChildren[bIndex]; + + var aKey = a._0; + var bKey = b._0; + var aNode = a._1; + var bNode = b._1; + + // check if keys match + + if (aKey === bKey) + { + index++; + diffHelp(aNode, bNode, localPatches, index); + index += aNode.descendantsCount || 0; + + aIndex++; + bIndex++; + continue; + } + + // look ahead 1 to detect insertions and removals. + + var aLookAhead = aIndex + 1 < aLen; + var bLookAhead = bIndex + 1 < bLen; + + if (aLookAhead) + { + var aNext = aChildren[aIndex + 1]; + var aNextKey = aNext._0; + var aNextNode = aNext._1; + var oldMatch = bKey === aNextKey; + } + + if (bLookAhead) + { + var bNext = bChildren[bIndex + 1]; + var bNextKey = bNext._0; + var bNextNode = bNext._1; + var newMatch = aKey === bNextKey; + } + + + // swap a and b + if (aLookAhead && bLookAhead && newMatch && oldMatch) + { + index++; + diffHelp(aNode, bNextNode, localPatches, index); + insertNode(changes, localPatches, aKey, bNode, bIndex, inserts); + index += aNode.descendantsCount || 0; + + index++; + removeNode(changes, localPatches, aKey, aNextNode, index); + index += aNextNode.descendantsCount || 0; + + aIndex += 2; + bIndex += 2; + continue; + } + + // insert b + if (bLookAhead && newMatch) + { + index++; + insertNode(changes, localPatches, bKey, bNode, bIndex, inserts); + diffHelp(aNode, bNextNode, localPatches, index); + index += aNode.descendantsCount || 0; + + aIndex += 1; + bIndex += 2; + continue; + } + + // remove a + if (aLookAhead && oldMatch) + { + index++; + removeNode(changes, localPatches, aKey, aNode, index); + index += aNode.descendantsCount || 0; + + index++; + diffHelp(aNextNode, bNode, localPatches, index); + index += aNextNode.descendantsCount || 0; + + aIndex += 2; + bIndex += 1; + continue; + } + + // remove a, insert b + if (aLookAhead && bLookAhead && aNextKey === bNextKey) + { + index++; + removeNode(changes, localPatches, aKey, aNode, index); + insertNode(changes, localPatches, bKey, bNode, bIndex, inserts); + index += aNode.descendantsCount || 0; + + index++; + diffHelp(aNextNode, bNextNode, localPatches, index); + index += aNextNode.descendantsCount || 0; + + aIndex += 2; + bIndex += 2; + continue; + } + + break; + } + + // eat up any remaining nodes with removeNode and insertNode + + while (aIndex < aLen) + { + index++; + var a = aChildren[aIndex]; + var aNode = a._1; + removeNode(changes, localPatches, a._0, aNode, index); + index += aNode.descendantsCount || 0; + aIndex++; + } + + var endInserts; + while (bIndex < bLen) + { + endInserts = endInserts || []; + var b = bChildren[bIndex]; + insertNode(changes, localPatches, b._0, b._1, undefined, endInserts); + bIndex++; + } + + if (localPatches.length > 0 || inserts.length > 0 || typeof endInserts !== 'undefined') + { + patches.push(makePatch('p-reorder', rootIndex, { + patches: localPatches, + inserts: inserts, + endInserts: endInserts + })); + } +} + + + +//////////// CHANGES FROM KEYED DIFF //////////// + + +var POSTFIX = '_elmW6BL'; + + +function insertNode(changes, localPatches, key, vnode, bIndex, inserts) +{ + var entry = changes[key]; + + // never seen this key before + if (typeof entry === 'undefined') + { + entry = { + tag: 'insert', + vnode: vnode, + index: bIndex, + data: undefined + }; + + inserts.push({ index: bIndex, entry: entry }); + changes[key] = entry; + + return; + } + + // this key was removed earlier, a match! + if (entry.tag === 'remove') + { + inserts.push({ index: bIndex, entry: entry }); + + entry.tag = 'move'; + var subPatches = []; + diffHelp(entry.vnode, vnode, subPatches, entry.index); + entry.index = bIndex; + entry.data.data = { + patches: subPatches, + entry: entry + }; + + return; + } + + // this key has already been inserted or moved, a duplicate! + insertNode(changes, localPatches, key + POSTFIX, vnode, bIndex, inserts); +} + + +function removeNode(changes, localPatches, key, vnode, index) +{ + var entry = changes[key]; + + // never seen this key before + if (typeof entry === 'undefined') + { + var patch = makePatch('p-remove', index, undefined); + localPatches.push(patch); + + changes[key] = { + tag: 'remove', + vnode: vnode, + index: index, + data: patch + }; + + return; + } + + // this key was inserted earlier, a match! + if (entry.tag === 'insert') + { + entry.tag = 'move'; + var subPatches = []; + diffHelp(vnode, entry.vnode, subPatches, index); + + var patch = makePatch('p-remove', index, { + patches: subPatches, + entry: entry + }); + localPatches.push(patch); + + return; + } + + // this key has already been removed or moved, a duplicate! + removeNode(changes, localPatches, key + POSTFIX, vnode, index); +} + + + +//////////// ADD DOM NODES //////////// +// +// Each DOM node has an "index" assigned in order of traversal. It is important +// to minimize our crawl over the actual DOM, so these indexes (along with the +// descendantsCount of virtual nodes) let us skip touching entire subtrees of +// the DOM if we know there are no patches there. + + +function addDomNodes(domNode, vNode, patches, eventNode) +{ + addDomNodesHelp(domNode, vNode, patches, 0, 0, vNode.descendantsCount, eventNode); +} + + +// assumes `patches` is non-empty and indexes increase monotonically. +function addDomNodesHelp(domNode, vNode, patches, i, low, high, eventNode) +{ + var patch = patches[i]; + var index = patch.index; + + while (index === low) + { + var patchType = patch.type; + + if (patchType === 'p-thunk') + { + addDomNodes(domNode, vNode.node, patch.data, eventNode); + } + else if (patchType === 'p-reorder') + { + patch.domNode = domNode; + patch.eventNode = eventNode; + + var subPatches = patch.data.patches; + if (subPatches.length > 0) + { + addDomNodesHelp(domNode, vNode, subPatches, 0, low, high, eventNode); + } + } + else if (patchType === 'p-remove') + { + patch.domNode = domNode; + patch.eventNode = eventNode; + + var data = patch.data; + if (typeof data !== 'undefined') + { + data.entry.data = domNode; + var subPatches = data.patches; + if (subPatches.length > 0) + { + addDomNodesHelp(domNode, vNode, subPatches, 0, low, high, eventNode); + } + } + } + else + { + patch.domNode = domNode; + patch.eventNode = eventNode; + } + + i++; + + if (!(patch = patches[i]) || (index = patch.index) > high) + { + return i; + } + } + + switch (vNode.type) + { + case 'tagger': + var subNode = vNode.node; + + while (subNode.type === "tagger") + { + subNode = subNode.node; + } + + return addDomNodesHelp(domNode, subNode, patches, i, low + 1, high, domNode.elm_event_node_ref); + + case 'node': + var vChildren = vNode.children; + var childNodes = domNode.childNodes; + for (var j = 0; j < vChildren.length; j++) + { + low++; + var vChild = vChildren[j]; + var nextLow = low + (vChild.descendantsCount || 0); + if (low <= index && index <= nextLow) + { + i = addDomNodesHelp(childNodes[j], vChild, patches, i, low, nextLow, eventNode); + if (!(patch = patches[i]) || (index = patch.index) > high) + { + return i; + } + } + low = nextLow; + } + return i; + + case 'keyed-node': + var vChildren = vNode.children; + var childNodes = domNode.childNodes; + for (var j = 0; j < vChildren.length; j++) + { + low++; + var vChild = vChildren[j]._1; + var nextLow = low + (vChild.descendantsCount || 0); + if (low <= index && index <= nextLow) + { + i = addDomNodesHelp(childNodes[j], vChild, patches, i, low, nextLow, eventNode); + if (!(patch = patches[i]) || (index = patch.index) > high) + { + return i; + } + } + low = nextLow; + } + return i; + + case 'text': + case 'thunk': + throw new Error('should never traverse `text` or `thunk` nodes like this'); + } +} + + + +//////////// APPLY PATCHES //////////// + + +function applyPatches(rootDomNode, oldVirtualNode, patches, eventNode) +{ + if (patches.length === 0) + { + return rootDomNode; + } + + addDomNodes(rootDomNode, oldVirtualNode, patches, eventNode); + return applyPatchesHelp(rootDomNode, patches); +} + +function applyPatchesHelp(rootDomNode, patches) +{ + for (var i = 0; i < patches.length; i++) + { + var patch = patches[i]; + var localDomNode = patch.domNode + var newNode = applyPatch(localDomNode, patch); + if (localDomNode === rootDomNode) + { + rootDomNode = newNode; + } + } + return rootDomNode; +} + +function applyPatch(domNode, patch) +{ + switch (patch.type) + { + case 'p-redraw': + return applyPatchRedraw(domNode, patch.data, patch.eventNode); + + case 'p-facts': + applyFacts(domNode, patch.eventNode, patch.data); + return domNode; + + case 'p-text': + domNode.replaceData(0, domNode.length, patch.data); + return domNode; + + case 'p-thunk': + return applyPatchesHelp(domNode, patch.data); + + case 'p-tagger': + domNode.elm_event_node_ref.tagger = patch.data; + return domNode; + + case 'p-remove-last': + var i = patch.data; + while (i--) + { + domNode.removeChild(domNode.lastChild); + } + return domNode; + + case 'p-append': + var newNodes = patch.data; + for (var i = 0; i < newNodes.length; i++) + { + domNode.appendChild(render(newNodes[i], patch.eventNode)); + } + return domNode; + + case 'p-remove': + var data = patch.data; + if (typeof data === 'undefined') + { + domNode.parentNode.removeChild(domNode); + return domNode; + } + var entry = data.entry; + if (typeof entry.index !== 'undefined') + { + domNode.parentNode.removeChild(domNode); + } + entry.data = applyPatchesHelp(domNode, data.patches); + return domNode; + + case 'p-reorder': + return applyPatchReorder(domNode, patch); + + case 'p-custom': + var impl = patch.data; + return impl.applyPatch(domNode, impl.data); + + default: + throw new Error('Ran into an unknown patch!'); + } +} + + +function applyPatchRedraw(domNode, vNode, eventNode) +{ + var parentNode = domNode.parentNode; + var newNode = render(vNode, eventNode); + + if (typeof newNode.elm_event_node_ref === 'undefined') + { + newNode.elm_event_node_ref = domNode.elm_event_node_ref; + } + + if (parentNode && newNode !== domNode) + { + parentNode.replaceChild(newNode, domNode); + } + return newNode; +} + + +function applyPatchReorder(domNode, patch) +{ + var data = patch.data; + + // remove end inserts + var frag = applyPatchReorderEndInsertsHelp(data.endInserts, patch); + + // removals + domNode = applyPatchesHelp(domNode, data.patches); + + // inserts + var inserts = data.inserts; + for (var i = 0; i < inserts.length; i++) + { + var insert = inserts[i]; + var entry = insert.entry; + var node = entry.tag === 'move' + ? entry.data + : render(entry.vnode, patch.eventNode); + domNode.insertBefore(node, domNode.childNodes[insert.index]); + } + + // add end inserts + if (typeof frag !== 'undefined') + { + domNode.appendChild(frag); + } + + return domNode; +} + + +function applyPatchReorderEndInsertsHelp(endInserts, patch) +{ + if (typeof endInserts === 'undefined') + { + return; + } + + var frag = document.createDocumentFragment(); + for (var i = 0; i < endInserts.length; i++) + { + var insert = endInserts[i]; + var entry = insert.entry; + frag.appendChild(entry.tag === 'move' + ? entry.data + : render(entry.vnode, patch.eventNode) + ); + } + return frag; +} + + + +//////////// PROGRAMS //////////// + + +function programWithFlags(details) +{ + return { + init: details.init, + update: details.update, + subscriptions: details.subscriptions, + view: details.view, + renderer: renderer + }; +} + + +return { + node: node, + text: text, + + custom: custom, + + map: F2(map), + + on: F3(on), + style: style, + property: F2(property), + attribute: F2(attribute), + attributeNS: F3(attributeNS), + + lazy: F2(lazy), + lazy2: F3(lazy2), + lazy3: F4(lazy3), + keyedNode: F3(keyedNode), + + programWithFlags: programWithFlags +}; + +}(); +var _elm_lang$virtual_dom$VirtualDom$programWithFlags = _elm_lang$virtual_dom$Native_VirtualDom.programWithFlags; +var _elm_lang$virtual_dom$VirtualDom$keyedNode = _elm_lang$virtual_dom$Native_VirtualDom.keyedNode; +var _elm_lang$virtual_dom$VirtualDom$lazy3 = _elm_lang$virtual_dom$Native_VirtualDom.lazy3; +var _elm_lang$virtual_dom$VirtualDom$lazy2 = _elm_lang$virtual_dom$Native_VirtualDom.lazy2; +var _elm_lang$virtual_dom$VirtualDom$lazy = _elm_lang$virtual_dom$Native_VirtualDom.lazy; +var _elm_lang$virtual_dom$VirtualDom$defaultOptions = {stopPropagation: false, preventDefault: false}; +var _elm_lang$virtual_dom$VirtualDom$onWithOptions = _elm_lang$virtual_dom$Native_VirtualDom.on; +var _elm_lang$virtual_dom$VirtualDom$on = F2( + function (eventName, decoder) { + return A3(_elm_lang$virtual_dom$VirtualDom$onWithOptions, eventName, _elm_lang$virtual_dom$VirtualDom$defaultOptions, decoder); + }); +var _elm_lang$virtual_dom$VirtualDom$style = _elm_lang$virtual_dom$Native_VirtualDom.style; +var _elm_lang$virtual_dom$VirtualDom$attributeNS = _elm_lang$virtual_dom$Native_VirtualDom.attributeNS; +var _elm_lang$virtual_dom$VirtualDom$attribute = _elm_lang$virtual_dom$Native_VirtualDom.attribute; +var _elm_lang$virtual_dom$VirtualDom$property = _elm_lang$virtual_dom$Native_VirtualDom.property; +var _elm_lang$virtual_dom$VirtualDom$map = _elm_lang$virtual_dom$Native_VirtualDom.map; +var _elm_lang$virtual_dom$VirtualDom$text = _elm_lang$virtual_dom$Native_VirtualDom.text; +var _elm_lang$virtual_dom$VirtualDom$node = _elm_lang$virtual_dom$Native_VirtualDom.node; +var _elm_lang$virtual_dom$VirtualDom$Options = F2( + function (a, b) { + return {stopPropagation: a, preventDefault: b}; + }); +var _elm_lang$virtual_dom$VirtualDom$Node = {ctor: 'Node'}; +var _elm_lang$virtual_dom$VirtualDom$Property = {ctor: 'Property'}; + +var _elm_lang$html$Html$text = _elm_lang$virtual_dom$VirtualDom$text; +var _elm_lang$html$Html$node = _elm_lang$virtual_dom$VirtualDom$node; +var _elm_lang$html$Html$body = _elm_lang$html$Html$node('body'); +var _elm_lang$html$Html$section = _elm_lang$html$Html$node('section'); +var _elm_lang$html$Html$nav = _elm_lang$html$Html$node('nav'); +var _elm_lang$html$Html$article = _elm_lang$html$Html$node('article'); +var _elm_lang$html$Html$aside = _elm_lang$html$Html$node('aside'); +var _elm_lang$html$Html$h1 = _elm_lang$html$Html$node('h1'); +var _elm_lang$html$Html$h2 = _elm_lang$html$Html$node('h2'); +var _elm_lang$html$Html$h3 = _elm_lang$html$Html$node('h3'); +var _elm_lang$html$Html$h4 = _elm_lang$html$Html$node('h4'); +var _elm_lang$html$Html$h5 = _elm_lang$html$Html$node('h5'); +var _elm_lang$html$Html$h6 = _elm_lang$html$Html$node('h6'); +var _elm_lang$html$Html$header = _elm_lang$html$Html$node('header'); +var _elm_lang$html$Html$footer = _elm_lang$html$Html$node('footer'); +var _elm_lang$html$Html$address = _elm_lang$html$Html$node('address'); +var _elm_lang$html$Html$main$ = _elm_lang$html$Html$node('main'); +var _elm_lang$html$Html$p = _elm_lang$html$Html$node('p'); +var _elm_lang$html$Html$hr = _elm_lang$html$Html$node('hr'); +var _elm_lang$html$Html$pre = _elm_lang$html$Html$node('pre'); +var _elm_lang$html$Html$blockquote = _elm_lang$html$Html$node('blockquote'); +var _elm_lang$html$Html$ol = _elm_lang$html$Html$node('ol'); +var _elm_lang$html$Html$ul = _elm_lang$html$Html$node('ul'); +var _elm_lang$html$Html$li = _elm_lang$html$Html$node('li'); +var _elm_lang$html$Html$dl = _elm_lang$html$Html$node('dl'); +var _elm_lang$html$Html$dt = _elm_lang$html$Html$node('dt'); +var _elm_lang$html$Html$dd = _elm_lang$html$Html$node('dd'); +var _elm_lang$html$Html$figure = _elm_lang$html$Html$node('figure'); +var _elm_lang$html$Html$figcaption = _elm_lang$html$Html$node('figcaption'); +var _elm_lang$html$Html$div = _elm_lang$html$Html$node('div'); +var _elm_lang$html$Html$a = _elm_lang$html$Html$node('a'); +var _elm_lang$html$Html$em = _elm_lang$html$Html$node('em'); +var _elm_lang$html$Html$strong = _elm_lang$html$Html$node('strong'); +var _elm_lang$html$Html$small = _elm_lang$html$Html$node('small'); +var _elm_lang$html$Html$s = _elm_lang$html$Html$node('s'); +var _elm_lang$html$Html$cite = _elm_lang$html$Html$node('cite'); +var _elm_lang$html$Html$q = _elm_lang$html$Html$node('q'); +var _elm_lang$html$Html$dfn = _elm_lang$html$Html$node('dfn'); +var _elm_lang$html$Html$abbr = _elm_lang$html$Html$node('abbr'); +var _elm_lang$html$Html$time = _elm_lang$html$Html$node('time'); +var _elm_lang$html$Html$code = _elm_lang$html$Html$node('code'); +var _elm_lang$html$Html$var = _elm_lang$html$Html$node('var'); +var _elm_lang$html$Html$samp = _elm_lang$html$Html$node('samp'); +var _elm_lang$html$Html$kbd = _elm_lang$html$Html$node('kbd'); +var _elm_lang$html$Html$sub = _elm_lang$html$Html$node('sub'); +var _elm_lang$html$Html$sup = _elm_lang$html$Html$node('sup'); +var _elm_lang$html$Html$i = _elm_lang$html$Html$node('i'); +var _elm_lang$html$Html$b = _elm_lang$html$Html$node('b'); +var _elm_lang$html$Html$u = _elm_lang$html$Html$node('u'); +var _elm_lang$html$Html$mark = _elm_lang$html$Html$node('mark'); +var _elm_lang$html$Html$ruby = _elm_lang$html$Html$node('ruby'); +var _elm_lang$html$Html$rt = _elm_lang$html$Html$node('rt'); +var _elm_lang$html$Html$rp = _elm_lang$html$Html$node('rp'); +var _elm_lang$html$Html$bdi = _elm_lang$html$Html$node('bdi'); +var _elm_lang$html$Html$bdo = _elm_lang$html$Html$node('bdo'); +var _elm_lang$html$Html$span = _elm_lang$html$Html$node('span'); +var _elm_lang$html$Html$br = _elm_lang$html$Html$node('br'); +var _elm_lang$html$Html$wbr = _elm_lang$html$Html$node('wbr'); +var _elm_lang$html$Html$ins = _elm_lang$html$Html$node('ins'); +var _elm_lang$html$Html$del = _elm_lang$html$Html$node('del'); +var _elm_lang$html$Html$img = _elm_lang$html$Html$node('img'); +var _elm_lang$html$Html$iframe = _elm_lang$html$Html$node('iframe'); +var _elm_lang$html$Html$embed = _elm_lang$html$Html$node('embed'); +var _elm_lang$html$Html$object = _elm_lang$html$Html$node('object'); +var _elm_lang$html$Html$param = _elm_lang$html$Html$node('param'); +var _elm_lang$html$Html$video = _elm_lang$html$Html$node('video'); +var _elm_lang$html$Html$audio = _elm_lang$html$Html$node('audio'); +var _elm_lang$html$Html$source = _elm_lang$html$Html$node('source'); +var _elm_lang$html$Html$track = _elm_lang$html$Html$node('track'); +var _elm_lang$html$Html$canvas = _elm_lang$html$Html$node('canvas'); +var _elm_lang$html$Html$svg = _elm_lang$html$Html$node('svg'); +var _elm_lang$html$Html$math = _elm_lang$html$Html$node('math'); +var _elm_lang$html$Html$table = _elm_lang$html$Html$node('table'); +var _elm_lang$html$Html$caption = _elm_lang$html$Html$node('caption'); +var _elm_lang$html$Html$colgroup = _elm_lang$html$Html$node('colgroup'); +var _elm_lang$html$Html$col = _elm_lang$html$Html$node('col'); +var _elm_lang$html$Html$tbody = _elm_lang$html$Html$node('tbody'); +var _elm_lang$html$Html$thead = _elm_lang$html$Html$node('thead'); +var _elm_lang$html$Html$tfoot = _elm_lang$html$Html$node('tfoot'); +var _elm_lang$html$Html$tr = _elm_lang$html$Html$node('tr'); +var _elm_lang$html$Html$td = _elm_lang$html$Html$node('td'); +var _elm_lang$html$Html$th = _elm_lang$html$Html$node('th'); +var _elm_lang$html$Html$form = _elm_lang$html$Html$node('form'); +var _elm_lang$html$Html$fieldset = _elm_lang$html$Html$node('fieldset'); +var _elm_lang$html$Html$legend = _elm_lang$html$Html$node('legend'); +var _elm_lang$html$Html$label = _elm_lang$html$Html$node('label'); +var _elm_lang$html$Html$input = _elm_lang$html$Html$node('input'); +var _elm_lang$html$Html$button = _elm_lang$html$Html$node('button'); +var _elm_lang$html$Html$select = _elm_lang$html$Html$node('select'); +var _elm_lang$html$Html$datalist = _elm_lang$html$Html$node('datalist'); +var _elm_lang$html$Html$optgroup = _elm_lang$html$Html$node('optgroup'); +var _elm_lang$html$Html$option = _elm_lang$html$Html$node('option'); +var _elm_lang$html$Html$textarea = _elm_lang$html$Html$node('textarea'); +var _elm_lang$html$Html$keygen = _elm_lang$html$Html$node('keygen'); +var _elm_lang$html$Html$output = _elm_lang$html$Html$node('output'); +var _elm_lang$html$Html$progress = _elm_lang$html$Html$node('progress'); +var _elm_lang$html$Html$meter = _elm_lang$html$Html$node('meter'); +var _elm_lang$html$Html$details = _elm_lang$html$Html$node('details'); +var _elm_lang$html$Html$summary = _elm_lang$html$Html$node('summary'); +var _elm_lang$html$Html$menuitem = _elm_lang$html$Html$node('menuitem'); +var _elm_lang$html$Html$menu = _elm_lang$html$Html$node('menu'); + +var _elm_lang$html$Html_App$programWithFlags = _elm_lang$virtual_dom$VirtualDom$programWithFlags; +var _elm_lang$html$Html_App$program = function (app) { + return _elm_lang$html$Html_App$programWithFlags( + _elm_lang$core$Native_Utils.update( + app, + { + init: function (_p0) { + return app.init; + } + })); +}; +var _elm_lang$html$Html_App$beginnerProgram = function (_p1) { + var _p2 = _p1; + return _elm_lang$html$Html_App$programWithFlags( + { + init: function (_p3) { + return A2( + _elm_lang$core$Platform_Cmd_ops['!'], + _p2.model, + _elm_lang$core$Native_List.fromArray( + [])); + }, + update: F2( + function (msg, model) { + return A2( + _elm_lang$core$Platform_Cmd_ops['!'], + A2(_p2.update, msg, model), + _elm_lang$core$Native_List.fromArray( + [])); + }), + view: _p2.view, + subscriptions: function (_p4) { + return _elm_lang$core$Platform_Sub$none; + } + }); +}; +var _elm_lang$html$Html_App$map = _elm_lang$virtual_dom$VirtualDom$map; + +var _elm_lang$html$Html_Attributes$attribute = _elm_lang$virtual_dom$VirtualDom$attribute; +var _elm_lang$html$Html_Attributes$contextmenu = function (value) { + return A2(_elm_lang$html$Html_Attributes$attribute, 'contextmenu', value); +}; +var _elm_lang$html$Html_Attributes$draggable = function (value) { + return A2(_elm_lang$html$Html_Attributes$attribute, 'draggable', value); +}; +var _elm_lang$html$Html_Attributes$list = function (value) { + return A2(_elm_lang$html$Html_Attributes$attribute, 'list', value); +}; +var _elm_lang$html$Html_Attributes$maxlength = function (n) { + return A2( + _elm_lang$html$Html_Attributes$attribute, + 'maxlength', + _elm_lang$core$Basics$toString(n)); +}; +var _elm_lang$html$Html_Attributes$datetime = function (value) { + return A2(_elm_lang$html$Html_Attributes$attribute, 'datetime', value); +}; +var _elm_lang$html$Html_Attributes$pubdate = function (value) { + return A2(_elm_lang$html$Html_Attributes$attribute, 'pubdate', value); +}; +var _elm_lang$html$Html_Attributes$colspan = function (n) { + return A2( + _elm_lang$html$Html_Attributes$attribute, + 'colspan', + _elm_lang$core$Basics$toString(n)); +}; +var _elm_lang$html$Html_Attributes$rowspan = function (n) { + return A2( + _elm_lang$html$Html_Attributes$attribute, + 'rowspan', + _elm_lang$core$Basics$toString(n)); +}; +var _elm_lang$html$Html_Attributes$property = _elm_lang$virtual_dom$VirtualDom$property; +var _elm_lang$html$Html_Attributes$stringProperty = F2( + function (name, string) { + return A2( + _elm_lang$html$Html_Attributes$property, + name, + _elm_lang$core$Json_Encode$string(string)); + }); +var _elm_lang$html$Html_Attributes$class = function (name) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'className', name); +}; +var _elm_lang$html$Html_Attributes$id = function (name) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'id', name); +}; +var _elm_lang$html$Html_Attributes$title = function (name) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'title', name); +}; +var _elm_lang$html$Html_Attributes$accesskey = function ($char) { + return A2( + _elm_lang$html$Html_Attributes$stringProperty, + 'accessKey', + _elm_lang$core$String$fromChar($char)); +}; +var _elm_lang$html$Html_Attributes$dir = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'dir', value); +}; +var _elm_lang$html$Html_Attributes$dropzone = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'dropzone', value); +}; +var _elm_lang$html$Html_Attributes$itemprop = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'itemprop', value); +}; +var _elm_lang$html$Html_Attributes$lang = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'lang', value); +}; +var _elm_lang$html$Html_Attributes$tabindex = function (n) { + return A2( + _elm_lang$html$Html_Attributes$stringProperty, + 'tabIndex', + _elm_lang$core$Basics$toString(n)); +}; +var _elm_lang$html$Html_Attributes$charset = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'charset', value); +}; +var _elm_lang$html$Html_Attributes$content = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'content', value); +}; +var _elm_lang$html$Html_Attributes$httpEquiv = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'httpEquiv', value); +}; +var _elm_lang$html$Html_Attributes$language = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'language', value); +}; +var _elm_lang$html$Html_Attributes$src = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'src', value); +}; +var _elm_lang$html$Html_Attributes$height = function (value) { + return A2( + _elm_lang$html$Html_Attributes$stringProperty, + 'height', + _elm_lang$core$Basics$toString(value)); +}; +var _elm_lang$html$Html_Attributes$width = function (value) { + return A2( + _elm_lang$html$Html_Attributes$stringProperty, + 'width', + _elm_lang$core$Basics$toString(value)); +}; +var _elm_lang$html$Html_Attributes$alt = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'alt', value); +}; +var _elm_lang$html$Html_Attributes$preload = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'preload', value); +}; +var _elm_lang$html$Html_Attributes$poster = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'poster', value); +}; +var _elm_lang$html$Html_Attributes$kind = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'kind', value); +}; +var _elm_lang$html$Html_Attributes$srclang = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'srclang', value); +}; +var _elm_lang$html$Html_Attributes$sandbox = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'sandbox', value); +}; +var _elm_lang$html$Html_Attributes$srcdoc = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'srcdoc', value); +}; +var _elm_lang$html$Html_Attributes$type$ = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'type', value); +}; +var _elm_lang$html$Html_Attributes$value = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'value', value); +}; +var _elm_lang$html$Html_Attributes$defaultValue = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'defaultValue', value); +}; +var _elm_lang$html$Html_Attributes$placeholder = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'placeholder', value); +}; +var _elm_lang$html$Html_Attributes$accept = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'accept', value); +}; +var _elm_lang$html$Html_Attributes$acceptCharset = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'acceptCharset', value); +}; +var _elm_lang$html$Html_Attributes$action = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'action', value); +}; +var _elm_lang$html$Html_Attributes$autocomplete = function (bool) { + return A2( + _elm_lang$html$Html_Attributes$stringProperty, + 'autocomplete', + bool ? 'on' : 'off'); +}; +var _elm_lang$html$Html_Attributes$autosave = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'autosave', value); +}; +var _elm_lang$html$Html_Attributes$enctype = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'enctype', value); +}; +var _elm_lang$html$Html_Attributes$formaction = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'formAction', value); +}; +var _elm_lang$html$Html_Attributes$minlength = function (n) { + return A2( + _elm_lang$html$Html_Attributes$stringProperty, + 'minLength', + _elm_lang$core$Basics$toString(n)); +}; +var _elm_lang$html$Html_Attributes$method = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'method', value); +}; +var _elm_lang$html$Html_Attributes$name = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'name', value); +}; +var _elm_lang$html$Html_Attributes$pattern = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'pattern', value); +}; +var _elm_lang$html$Html_Attributes$size = function (n) { + return A2( + _elm_lang$html$Html_Attributes$stringProperty, + 'size', + _elm_lang$core$Basics$toString(n)); +}; +var _elm_lang$html$Html_Attributes$for = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'htmlFor', value); +}; +var _elm_lang$html$Html_Attributes$form = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'form', value); +}; +var _elm_lang$html$Html_Attributes$max = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'max', value); +}; +var _elm_lang$html$Html_Attributes$min = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'min', value); +}; +var _elm_lang$html$Html_Attributes$step = function (n) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'step', n); +}; +var _elm_lang$html$Html_Attributes$cols = function (n) { + return A2( + _elm_lang$html$Html_Attributes$stringProperty, + 'cols', + _elm_lang$core$Basics$toString(n)); +}; +var _elm_lang$html$Html_Attributes$rows = function (n) { + return A2( + _elm_lang$html$Html_Attributes$stringProperty, + 'rows', + _elm_lang$core$Basics$toString(n)); +}; +var _elm_lang$html$Html_Attributes$wrap = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'wrap', value); +}; +var _elm_lang$html$Html_Attributes$usemap = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'useMap', value); +}; +var _elm_lang$html$Html_Attributes$shape = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'shape', value); +}; +var _elm_lang$html$Html_Attributes$coords = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'coords', value); +}; +var _elm_lang$html$Html_Attributes$challenge = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'challenge', value); +}; +var _elm_lang$html$Html_Attributes$keytype = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'keytype', value); +}; +var _elm_lang$html$Html_Attributes$align = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'align', value); +}; +var _elm_lang$html$Html_Attributes$cite = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'cite', value); +}; +var _elm_lang$html$Html_Attributes$href = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'href', value); +}; +var _elm_lang$html$Html_Attributes$target = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'target', value); +}; +var _elm_lang$html$Html_Attributes$downloadAs = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'download', value); +}; +var _elm_lang$html$Html_Attributes$hreflang = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'hreflang', value); +}; +var _elm_lang$html$Html_Attributes$media = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'media', value); +}; +var _elm_lang$html$Html_Attributes$ping = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'ping', value); +}; +var _elm_lang$html$Html_Attributes$rel = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'rel', value); +}; +var _elm_lang$html$Html_Attributes$start = function (n) { + return A2( + _elm_lang$html$Html_Attributes$stringProperty, + 'start', + _elm_lang$core$Basics$toString(n)); +}; +var _elm_lang$html$Html_Attributes$headers = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'headers', value); +}; +var _elm_lang$html$Html_Attributes$scope = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'scope', value); +}; +var _elm_lang$html$Html_Attributes$manifest = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'manifest', value); +}; +var _elm_lang$html$Html_Attributes$boolProperty = F2( + function (name, bool) { + return A2( + _elm_lang$html$Html_Attributes$property, + name, + _elm_lang$core$Json_Encode$bool(bool)); + }); +var _elm_lang$html$Html_Attributes$hidden = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'hidden', bool); +}; +var _elm_lang$html$Html_Attributes$contenteditable = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'contentEditable', bool); +}; +var _elm_lang$html$Html_Attributes$spellcheck = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'spellcheck', bool); +}; +var _elm_lang$html$Html_Attributes$async = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'async', bool); +}; +var _elm_lang$html$Html_Attributes$defer = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'defer', bool); +}; +var _elm_lang$html$Html_Attributes$scoped = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'scoped', bool); +}; +var _elm_lang$html$Html_Attributes$autoplay = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'autoplay', bool); +}; +var _elm_lang$html$Html_Attributes$controls = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'controls', bool); +}; +var _elm_lang$html$Html_Attributes$loop = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'loop', bool); +}; +var _elm_lang$html$Html_Attributes$default = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'default', bool); +}; +var _elm_lang$html$Html_Attributes$seamless = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'seamless', bool); +}; +var _elm_lang$html$Html_Attributes$checked = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'checked', bool); +}; +var _elm_lang$html$Html_Attributes$selected = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'selected', bool); +}; +var _elm_lang$html$Html_Attributes$autofocus = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'autofocus', bool); +}; +var _elm_lang$html$Html_Attributes$disabled = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'disabled', bool); +}; +var _elm_lang$html$Html_Attributes$multiple = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'multiple', bool); +}; +var _elm_lang$html$Html_Attributes$novalidate = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'noValidate', bool); +}; +var _elm_lang$html$Html_Attributes$readonly = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'readOnly', bool); +}; +var _elm_lang$html$Html_Attributes$required = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'required', bool); +}; +var _elm_lang$html$Html_Attributes$ismap = function (value) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'isMap', value); +}; +var _elm_lang$html$Html_Attributes$download = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'download', bool); +}; +var _elm_lang$html$Html_Attributes$reversed = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'reversed', bool); +}; +var _elm_lang$html$Html_Attributes$classList = function (list) { + return _elm_lang$html$Html_Attributes$class( + A2( + _elm_lang$core$String$join, + ' ', + A2( + _elm_lang$core$List$map, + _elm_lang$core$Basics$fst, + A2(_elm_lang$core$List$filter, _elm_lang$core$Basics$snd, list)))); +}; +var _elm_lang$html$Html_Attributes$style = _elm_lang$virtual_dom$VirtualDom$style; + +var _elm_lang$html$Html_Events$keyCode = A2(_elm_lang$core$Json_Decode_ops[':='], 'keyCode', _elm_lang$core$Json_Decode$int); +var _elm_lang$html$Html_Events$targetChecked = A2( + _elm_lang$core$Json_Decode$at, + _elm_lang$core$Native_List.fromArray( + ['target', 'checked']), + _elm_lang$core$Json_Decode$bool); +var _elm_lang$html$Html_Events$targetValue = A2( + _elm_lang$core$Json_Decode$at, + _elm_lang$core$Native_List.fromArray( + ['target', 'value']), + _elm_lang$core$Json_Decode$string); +var _elm_lang$html$Html_Events$defaultOptions = _elm_lang$virtual_dom$VirtualDom$defaultOptions; +var _elm_lang$html$Html_Events$onWithOptions = _elm_lang$virtual_dom$VirtualDom$onWithOptions; +var _elm_lang$html$Html_Events$on = _elm_lang$virtual_dom$VirtualDom$on; +var _elm_lang$html$Html_Events$onFocus = function (msg) { + return A2( + _elm_lang$html$Html_Events$on, + 'focus', + _elm_lang$core$Json_Decode$succeed(msg)); +}; +var _elm_lang$html$Html_Events$onBlur = function (msg) { + return A2( + _elm_lang$html$Html_Events$on, + 'blur', + _elm_lang$core$Json_Decode$succeed(msg)); +}; +var _elm_lang$html$Html_Events$onSubmitOptions = _elm_lang$core$Native_Utils.update( + _elm_lang$html$Html_Events$defaultOptions, + {preventDefault: true}); +var _elm_lang$html$Html_Events$onSubmit = function (msg) { + return A3( + _elm_lang$html$Html_Events$onWithOptions, + 'submit', + _elm_lang$html$Html_Events$onSubmitOptions, + _elm_lang$core$Json_Decode$succeed(msg)); +}; +var _elm_lang$html$Html_Events$onCheck = function (tagger) { + return A2( + _elm_lang$html$Html_Events$on, + 'change', + A2(_elm_lang$core$Json_Decode$map, tagger, _elm_lang$html$Html_Events$targetChecked)); +}; +var _elm_lang$html$Html_Events$onInput = function (tagger) { + return A2( + _elm_lang$html$Html_Events$on, + 'input', + A2(_elm_lang$core$Json_Decode$map, tagger, _elm_lang$html$Html_Events$targetValue)); +}; +var _elm_lang$html$Html_Events$onMouseOut = function (msg) { + return A2( + _elm_lang$html$Html_Events$on, + 'mouseout', + _elm_lang$core$Json_Decode$succeed(msg)); +}; +var _elm_lang$html$Html_Events$onMouseOver = function (msg) { + return A2( + _elm_lang$html$Html_Events$on, + 'mouseover', + _elm_lang$core$Json_Decode$succeed(msg)); +}; +var _elm_lang$html$Html_Events$onMouseLeave = function (msg) { + return A2( + _elm_lang$html$Html_Events$on, + 'mouseleave', + _elm_lang$core$Json_Decode$succeed(msg)); +}; +var _elm_lang$html$Html_Events$onMouseEnter = function (msg) { + return A2( + _elm_lang$html$Html_Events$on, + 'mouseenter', + _elm_lang$core$Json_Decode$succeed(msg)); +}; +var _elm_lang$html$Html_Events$onMouseUp = function (msg) { + return A2( + _elm_lang$html$Html_Events$on, + 'mouseup', + _elm_lang$core$Json_Decode$succeed(msg)); +}; +var _elm_lang$html$Html_Events$onMouseDown = function (msg) { + return A2( + _elm_lang$html$Html_Events$on, + 'mousedown', + _elm_lang$core$Json_Decode$succeed(msg)); +}; +var _elm_lang$html$Html_Events$onDoubleClick = function (msg) { + return A2( + _elm_lang$html$Html_Events$on, + 'dblclick', + _elm_lang$core$Json_Decode$succeed(msg)); +}; +var _elm_lang$html$Html_Events$onClick = function (msg) { + return A2( + _elm_lang$html$Html_Events$on, + 'click', + _elm_lang$core$Json_Decode$succeed(msg)); +}; +var _elm_lang$html$Html_Events$Options = F2( + function (a, b) { + return {stopPropagation: a, preventDefault: b}; + }); + +var _evancz$elm_todomvc$Todo$infoFooter = A2( + _elm_lang$html$Html$footer, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$class('info') + ]), + _elm_lang$core$Native_List.fromArray( + [ + A2( + _elm_lang$html$Html$p, + _elm_lang$core$Native_List.fromArray( + []), + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html$text('Double-click to edit a todo') + ])), + A2( + _elm_lang$html$Html$p, + _elm_lang$core$Native_List.fromArray( + []), + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html$text('Written by '), + A2( + _elm_lang$html$Html$a, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$href('https://github.com/evancz') + ]), + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html$text('Evan Czaplicki') + ])) + ])), + A2( + _elm_lang$html$Html$p, + _elm_lang$core$Native_List.fromArray( + []), + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html$text('Part of '), + A2( + _elm_lang$html$Html$a, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$href('http://todomvc.com') + ]), + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html$text('TodoMVC') + ])) + ])) + ])); +var _evancz$elm_todomvc$Todo$viewControlsCount = function (entriesLeft) { + var item_ = _elm_lang$core$Native_Utils.eq(entriesLeft, 1) ? ' item' : ' items'; + return A2( + _elm_lang$html$Html$span, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$class('todo-count') + ]), + _elm_lang$core$Native_List.fromArray( + [ + A2( + _elm_lang$html$Html$strong, + _elm_lang$core$Native_List.fromArray( + []), + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html$text( + _elm_lang$core$Basics$toString(entriesLeft)) + ])), + _elm_lang$html$Html$text( + A2(_elm_lang$core$Basics_ops['++'], item_, ' left')) + ])); +}; +var _evancz$elm_todomvc$Todo$newEntry = F2( + function (desc, id) { + return {description: desc, completed: false, editing: false, id: id}; + }); +var _evancz$elm_todomvc$Todo$emptyModel = { + entries: _elm_lang$core$Native_List.fromArray( + []), + visibility: 'All', + field: '', + uid: 0 +}; +var _evancz$elm_todomvc$Todo$init = A2( + _elm_lang$core$Platform_Cmd_ops['!'], + _evancz$elm_todomvc$Todo$emptyModel, + _elm_lang$core$Native_List.fromArray( + [])); +var _evancz$elm_todomvc$Todo$focus = _elm_lang$core$Native_Platform.outgoingPort( + 'focus', + function (v) { + return v; + }); +var _evancz$elm_todomvc$Todo$update = F2( + function (msg, model) { + var _p0 = msg; + switch (_p0.ctor) { + case 'NoOp': + return A2( + _elm_lang$core$Platform_Cmd_ops['!'], + model, + _elm_lang$core$Native_List.fromArray( + [])); + case 'Add': + return A2( + _elm_lang$core$Platform_Cmd_ops['!'], + _elm_lang$core$Native_Utils.update( + model, + { + uid: model.uid + 1, + field: '', + entries: _elm_lang$core$String$isEmpty(model.field) ? model.entries : A2( + _elm_lang$core$Basics_ops['++'], + model.entries, + _elm_lang$core$Native_List.fromArray( + [ + A2(_evancz$elm_todomvc$Todo$newEntry, model.field, model.uid) + ])) + }), + _elm_lang$core$Native_List.fromArray( + [])); + case 'UpdateField': + return A2( + _elm_lang$core$Platform_Cmd_ops['!'], + _elm_lang$core$Native_Utils.update( + model, + {field: _p0._0}), + _elm_lang$core$Native_List.fromArray( + [])); + case 'EditingEntry': + var _p1 = _p0._0; + var updateEntry = function (t) { + return _elm_lang$core$Native_Utils.eq(t.id, _p1) ? _elm_lang$core$Native_Utils.update( + t, + {editing: _p0._1}) : t; + }; + return A2( + _elm_lang$core$Platform_Cmd_ops['!'], + _elm_lang$core$Native_Utils.update( + model, + { + entries: A2(_elm_lang$core$List$map, updateEntry, model.entries) + }), + _elm_lang$core$Native_List.fromArray( + [ + _evancz$elm_todomvc$Todo$focus( + A2( + _elm_lang$core$Basics_ops['++'], + '#todo-', + _elm_lang$core$Basics$toString(_p1))) + ])); + case 'UpdateEntry': + var updateEntry = function (t) { + return _elm_lang$core$Native_Utils.eq(t.id, _p0._0) ? _elm_lang$core$Native_Utils.update( + t, + {description: _p0._1}) : t; + }; + return A2( + _elm_lang$core$Platform_Cmd_ops['!'], + _elm_lang$core$Native_Utils.update( + model, + { + entries: A2(_elm_lang$core$List$map, updateEntry, model.entries) + }), + _elm_lang$core$Native_List.fromArray( + [])); + case 'Delete': + return A2( + _elm_lang$core$Platform_Cmd_ops['!'], + _elm_lang$core$Native_Utils.update( + model, + { + entries: A2( + _elm_lang$core$List$filter, + function (t) { + return !_elm_lang$core$Native_Utils.eq(t.id, _p0._0); + }, + model.entries) + }), + _elm_lang$core$Native_List.fromArray( + [])); + case 'DeleteComplete': + return A2( + _elm_lang$core$Platform_Cmd_ops['!'], + _elm_lang$core$Native_Utils.update( + model, + { + entries: A2( + _elm_lang$core$List$filter, + function (_p2) { + return _elm_lang$core$Basics$not( + function (_) { + return _.completed; + }(_p2)); + }, + model.entries) + }), + _elm_lang$core$Native_List.fromArray( + [])); + case 'Check': + var updateEntry = function (t) { + return _elm_lang$core$Native_Utils.eq(t.id, _p0._0) ? _elm_lang$core$Native_Utils.update( + t, + {completed: _p0._1}) : t; + }; + return A2( + _elm_lang$core$Platform_Cmd_ops['!'], + _elm_lang$core$Native_Utils.update( + model, + { + entries: A2(_elm_lang$core$List$map, updateEntry, model.entries) + }), + _elm_lang$core$Native_List.fromArray( + [])); + case 'CheckAll': + var updateEntry = function (t) { + return _elm_lang$core$Native_Utils.update( + t, + {completed: _p0._0}); + }; + return A2( + _elm_lang$core$Platform_Cmd_ops['!'], + _elm_lang$core$Native_Utils.update( + model, + { + entries: A2(_elm_lang$core$List$map, updateEntry, model.entries) + }), + _elm_lang$core$Native_List.fromArray( + [])); + default: + return A2( + _elm_lang$core$Platform_Cmd_ops['!'], + _elm_lang$core$Native_Utils.update( + model, + {visibility: _p0._0}), + _elm_lang$core$Native_List.fromArray( + [])); + } + }); +var _evancz$elm_todomvc$Todo$Model = F4( + function (a, b, c, d) { + return {entries: a, field: b, uid: c, visibility: d}; + }); +var _evancz$elm_todomvc$Todo$Entry = F4( + function (a, b, c, d) { + return {description: a, completed: b, editing: c, id: d}; + }); +var _evancz$elm_todomvc$Todo$ChangeVisibility = function (a) { + return {ctor: 'ChangeVisibility', _0: a}; +}; +var _evancz$elm_todomvc$Todo$visibilitySwap = F3( + function (uri, visibility, actualVisibility) { + return A2( + _elm_lang$html$Html$li, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Events$onClick( + _evancz$elm_todomvc$Todo$ChangeVisibility(visibility)) + ]), + _elm_lang$core$Native_List.fromArray( + [ + A2( + _elm_lang$html$Html$a, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$href(uri), + _elm_lang$html$Html_Attributes$classList( + _elm_lang$core$Native_List.fromArray( + [ + { + ctor: '_Tuple2', + _0: 'selected', + _1: _elm_lang$core$Native_Utils.eq(visibility, actualVisibility) + } + ])) + ]), + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html$text(visibility) + ])) + ])); + }); +var _evancz$elm_todomvc$Todo$viewControlsFilters = function (visibility) { + return A2( + _elm_lang$html$Html$ul, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$class('filters') + ]), + _elm_lang$core$Native_List.fromArray( + [ + A3(_evancz$elm_todomvc$Todo$visibilitySwap, '#/', 'All', visibility), + _elm_lang$html$Html$text(' '), + A3(_evancz$elm_todomvc$Todo$visibilitySwap, '#/active', 'Active', visibility), + _elm_lang$html$Html$text(' '), + A3(_evancz$elm_todomvc$Todo$visibilitySwap, '#/completed', 'Completed', visibility) + ])); +}; +var _evancz$elm_todomvc$Todo$CheckAll = function (a) { + return {ctor: 'CheckAll', _0: a}; +}; +var _evancz$elm_todomvc$Todo$Check = F2( + function (a, b) { + return {ctor: 'Check', _0: a, _1: b}; + }); +var _evancz$elm_todomvc$Todo$DeleteComplete = {ctor: 'DeleteComplete'}; +var _evancz$elm_todomvc$Todo$viewControlsClear = function (entriesCompleted) { + return A2( + _elm_lang$html$Html$button, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$class('clear-completed'), + _elm_lang$html$Html_Attributes$hidden( + _elm_lang$core$Native_Utils.eq(entriesCompleted, 0)), + _elm_lang$html$Html_Events$onClick(_evancz$elm_todomvc$Todo$DeleteComplete) + ]), + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html$text( + A2( + _elm_lang$core$Basics_ops['++'], + 'Clear completed (', + A2( + _elm_lang$core$Basics_ops['++'], + _elm_lang$core$Basics$toString(entriesCompleted), + ')'))) + ])); +}; +var _evancz$elm_todomvc$Todo$viewControls = F2( + function (visibility, entries) { + var entriesCompleted = _elm_lang$core$List$length( + A2( + _elm_lang$core$List$filter, + function (_) { + return _.completed; + }, + entries)); + var entriesLeft = _elm_lang$core$List$length(entries) - entriesCompleted; + return A2( + _elm_lang$html$Html$footer, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$class('footer'), + _elm_lang$html$Html_Attributes$hidden( + _elm_lang$core$List$isEmpty(entries)) + ]), + _elm_lang$core$Native_List.fromArray( + [ + _evancz$elm_todomvc$Todo$viewControlsCount(entriesLeft), + _evancz$elm_todomvc$Todo$viewControlsFilters(visibility), + _evancz$elm_todomvc$Todo$viewControlsClear(entriesCompleted) + ])); + }); +var _evancz$elm_todomvc$Todo$Delete = function (a) { + return {ctor: 'Delete', _0: a}; +}; +var _evancz$elm_todomvc$Todo$Add = {ctor: 'Add'}; +var _evancz$elm_todomvc$Todo$UpdateEntry = F2( + function (a, b) { + return {ctor: 'UpdateEntry', _0: a, _1: b}; + }); +var _evancz$elm_todomvc$Todo$EditingEntry = F2( + function (a, b) { + return {ctor: 'EditingEntry', _0: a, _1: b}; + }); +var _evancz$elm_todomvc$Todo$UpdateField = function (a) { + return {ctor: 'UpdateField', _0: a}; +}; +var _evancz$elm_todomvc$Todo$NoOp = {ctor: 'NoOp'}; +var _evancz$elm_todomvc$Todo$onEnter = function (msg) { + var tagger = function (code) { + return _elm_lang$core$Native_Utils.eq(code, 13) ? msg : _evancz$elm_todomvc$Todo$NoOp; + }; + return A2( + _elm_lang$html$Html_Events$on, + 'keydown', + A2(_elm_lang$core$Json_Decode$map, tagger, _elm_lang$html$Html_Events$keyCode)); +}; +var _evancz$elm_todomvc$Todo$viewInput = function (task) { + return A2( + _elm_lang$html$Html$header, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$class('header') + ]), + _elm_lang$core$Native_List.fromArray( + [ + A2( + _elm_lang$html$Html$h1, + _elm_lang$core$Native_List.fromArray( + []), + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html$text('todos') + ])), + A2( + _elm_lang$html$Html$input, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$class('new-todo'), + _elm_lang$html$Html_Attributes$placeholder('What needs to be done?'), + _elm_lang$html$Html_Attributes$autofocus(true), + _elm_lang$html$Html_Attributes$value(task), + _elm_lang$html$Html_Attributes$name('newTodo'), + _elm_lang$html$Html_Events$onInput(_evancz$elm_todomvc$Todo$UpdateField), + _evancz$elm_todomvc$Todo$onEnter(_evancz$elm_todomvc$Todo$Add) + ]), + _elm_lang$core$Native_List.fromArray( + [])) + ])); +}; +var _evancz$elm_todomvc$Todo$viewEntry = function (todo) { + return A2( + _elm_lang$html$Html$li, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$classList( + _elm_lang$core$Native_List.fromArray( + [ + {ctor: '_Tuple2', _0: 'completed', _1: todo.completed}, + {ctor: '_Tuple2', _0: 'editing', _1: todo.editing} + ])) + ]), + _elm_lang$core$Native_List.fromArray( + [ + A2( + _elm_lang$html$Html$div, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$class('view') + ]), + _elm_lang$core$Native_List.fromArray( + [ + A2( + _elm_lang$html$Html$input, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$class('toggle'), + _elm_lang$html$Html_Attributes$type$('checkbox'), + _elm_lang$html$Html_Attributes$checked(todo.completed), + _elm_lang$html$Html_Events$onClick( + A2( + _evancz$elm_todomvc$Todo$Check, + todo.id, + _elm_lang$core$Basics$not(todo.completed))) + ]), + _elm_lang$core$Native_List.fromArray( + [])), + A2( + _elm_lang$html$Html$label, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Events$onDoubleClick( + A2(_evancz$elm_todomvc$Todo$EditingEntry, todo.id, true)) + ]), + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html$text(todo.description) + ])), + A2( + _elm_lang$html$Html$button, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$class('destroy'), + _elm_lang$html$Html_Events$onClick( + _evancz$elm_todomvc$Todo$Delete(todo.id)) + ]), + _elm_lang$core$Native_List.fromArray( + [])) + ])), + A2( + _elm_lang$html$Html$input, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$class('edit'), + _elm_lang$html$Html_Attributes$value(todo.description), + _elm_lang$html$Html_Attributes$name('title'), + _elm_lang$html$Html_Attributes$id( + A2( + _elm_lang$core$Basics_ops['++'], + 'todo-', + _elm_lang$core$Basics$toString(todo.id))), + _elm_lang$html$Html_Events$onInput( + _evancz$elm_todomvc$Todo$UpdateEntry(todo.id)), + _elm_lang$html$Html_Events$onBlur( + A2(_evancz$elm_todomvc$Todo$EditingEntry, todo.id, false)), + _evancz$elm_todomvc$Todo$onEnter( + A2(_evancz$elm_todomvc$Todo$EditingEntry, todo.id, false)) + ]), + _elm_lang$core$Native_List.fromArray( + [])) + ])); +}; +var _evancz$elm_todomvc$Todo$viewEntries = F2( + function (visibility, entries) { + var cssVisibility = _elm_lang$core$List$isEmpty(entries) ? 'hidden' : 'visible'; + var allCompleted = A2( + _elm_lang$core$List$all, + function (_) { + return _.completed; + }, + entries); + var isVisible = function (todo) { + var _p3 = visibility; + switch (_p3) { + case 'Completed': + return todo.completed; + case 'Active': + return _elm_lang$core$Basics$not(todo.completed); + default: + return true; + } + }; + return A2( + _elm_lang$html$Html$section, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$class('main'), + _elm_lang$html$Html_Attributes$style( + _elm_lang$core$Native_List.fromArray( + [ + {ctor: '_Tuple2', _0: 'visibility', _1: cssVisibility} + ])) + ]), + _elm_lang$core$Native_List.fromArray( + [ + A2( + _elm_lang$html$Html$input, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$class('toggle-all'), + _elm_lang$html$Html_Attributes$type$('checkbox'), + _elm_lang$html$Html_Attributes$name('toggle'), + _elm_lang$html$Html_Attributes$checked(allCompleted), + _elm_lang$html$Html_Events$onClick( + _evancz$elm_todomvc$Todo$CheckAll( + _elm_lang$core$Basics$not(allCompleted))) + ]), + _elm_lang$core$Native_List.fromArray( + [])), + A2( + _elm_lang$html$Html$label, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$for('toggle-all') + ]), + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html$text('Mark all as complete') + ])), + A2( + _elm_lang$html$Html$ul, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$class('todo-list') + ]), + A2( + _elm_lang$core$List$map, + _evancz$elm_todomvc$Todo$viewEntry, + A2(_elm_lang$core$List$filter, isVisible, entries))) + ])); + }); +var _evancz$elm_todomvc$Todo$view = function (model) { + return A2( + _elm_lang$html$Html$div, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$class('todomvc-wrapper'), + _elm_lang$html$Html_Attributes$style( + _elm_lang$core$Native_List.fromArray( + [ + {ctor: '_Tuple2', _0: 'visibility', _1: 'hidden'} + ])) + ]), + _elm_lang$core$Native_List.fromArray( + [ + A2( + _elm_lang$html$Html$section, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$class('todoapp') + ]), + _elm_lang$core$Native_List.fromArray( + [ + _evancz$elm_todomvc$Todo$viewInput(model.field), + A2(_evancz$elm_todomvc$Todo$viewEntries, model.visibility, model.entries), + A2(_evancz$elm_todomvc$Todo$viewControls, model.visibility, model.entries) + ])), + _evancz$elm_todomvc$Todo$infoFooter + ])); +}; +var _evancz$elm_todomvc$Todo$main = { + main: _elm_lang$html$Html_App$program( + { + init: _evancz$elm_todomvc$Todo$init, + view: _evancz$elm_todomvc$Todo$view, + update: _evancz$elm_todomvc$Todo$update, + subscriptions: function (_p4) { + return _elm_lang$core$Platform_Sub$none; + } + }) +}; + +var Elm = {}; +Elm['Todo'] = Elm['Todo'] || {}; +_elm_lang$core$Native_Platform.addPublicModule(Elm['Todo'], 'Todo', typeof _evancz$elm_todomvc$Todo$main === 'undefined' ? null : _evancz$elm_todomvc$Todo$main); + +if (typeof define === "function" && define['amd']) +{ + define([], function() { return Elm; }); + return; +} + +if (typeof module === "object") +{ + module['exports'] = Elm; + return; +} + +var globalElm = this['Elm']; +if (typeof globalElm === "undefined") +{ + this['Elm'] = Elm; + return; +} + +for (var publicModule in Elm) +{ + if (publicModule in globalElm) + { + throw new Error('There are two Elm modules called `' + publicModule + '` on this page! Rename one of them.'); + } + globalElm[publicModule] = Elm[publicModule]; +} + +}).call(this); + diff --git a/bench/implementations/elm-0.17/index.html b/bench/implementations/elm-0.17/index.html new file mode 100644 index 0000000..dcb938e --- /dev/null +++ b/bench/implementations/elm-0.17/index.html @@ -0,0 +1,29 @@ + + + + + + Elm • TodoMVC + + + + + + + + + + diff --git a/bench/implementations/elm-0.17/style.css b/bench/implementations/elm-0.17/style.css new file mode 100644 index 0000000..fc2e67b --- /dev/null +++ b/bench/implementations/elm-0.17/style.css @@ -0,0 +1,382 @@ +html, +body { + margin: 0; + padding: 0; +} + +.todomvc-wrapper { + visibility: visible !important; +} + +button { + margin: 0; + padding: 0; + border: 0; + background: none; + font-size: 100%; + vertical-align: baseline; + font-family: inherit; + font-weight: inherit; + color: inherit; + -webkit-appearance: none; + appearance: none; + -webkit-font-smoothing: antialiased; + -moz-font-smoothing: antialiased; + font-smoothing: antialiased; +} + +body { + font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif; + line-height: 1.4em; + background: #f5f5f5; + color: #4d4d4d; + min-width: 230px; + max-width: 550px; + margin: 0 auto; + -webkit-font-smoothing: antialiased; + -moz-font-smoothing: antialiased; + font-smoothing: antialiased; + font-weight: 300; +} + +button, +input[type="checkbox"] { + outline: none; +} + +.hidden { + display: none; +} + +.todoapp { + background: #fff; + margin: 130px 0 40px 0; + position: relative; + box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), + 0 25px 50px 0 rgba(0, 0, 0, 0.1); +} + +.todoapp input::-webkit-input-placeholder { + font-style: italic; + font-weight: 300; + color: #e6e6e6; +} + +.todoapp input::-moz-placeholder { + font-style: italic; + font-weight: 300; + color: #e6e6e6; +} + +.todoapp input::input-placeholder { + font-style: italic; + font-weight: 300; + color: #e6e6e6; +} + +.todoapp h1 { + position: absolute; + top: -155px; + width: 100%; + font-size: 100px; + font-weight: 100; + text-align: center; + color: rgba(175, 47, 47, 0.15); + -webkit-text-rendering: optimizeLegibility; + -moz-text-rendering: optimizeLegibility; + text-rendering: optimizeLegibility; +} + +.new-todo, +.edit { + position: relative; + margin: 0; + width: 100%; + font-size: 24px; + font-family: inherit; + font-weight: 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); + box-sizing: border-box; + -webkit-font-smoothing: antialiased; + -moz-font-smoothing: antialiased; + font-smoothing: antialiased; +} + +.new-todo { + padding: 16px 16px 16px 60px; + border: none; + background: rgba(0, 0, 0, 0.003); + box-shadow: inset 0 -2px 1px rgba(0,0,0,0.03); +} + +.main { + position: relative; + z-index: 2; + border-top: 1px solid #e6e6e6; +} + +label[for='toggle-all'] { + display: none; +} + +.toggle-all { + position: absolute; + top: -55px; + left: -12px; + width: 60px; + height: 34px; + text-align: center; + border: none; /* Mobile Safari */ +} + +.toggle-all:before { + content: '❯'; + font-size: 22px; + color: #e6e6e6; + padding: 10px 27px 10px 27px; +} + +.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 solid #ededed; +} + +.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; + appearance: none; +} + +.todo-list li .toggle:after { + content: url('data:image/svg+xml;utf8,'); +} + +.todo-list li .toggle:checked:after { + content: url('data:image/svg+xml;utf8,'); +} + +.todo-list li label { + white-space: pre-line; + word-break: break-all; + padding: 15px 60px 15px 15px; + margin-left: 45px; + display: block; + line-height: 1.2; + transition: color 0.4s; +} + +.todo-list li.completed label { + color: #d9d9d9; + 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: 30px; + color: #cc9a9a; + margin-bottom: 11px; + transition: color 0.2s ease-out; +} + +.todo-list li .destroy:hover { + color: #af5b5e; +} + +.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: 10px 15px; + height: 20px; + text-align: center; + border-top: 1px solid #e6e6e6; +} + +.footer:before { + content: ''; + position: absolute; + right: 0; + bottom: 0; + left: 0; + height: 50px; + overflow: hidden; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), + 0 8px 0 -3px #f6f6f6, + 0 9px 1px -3px rgba(0, 0, 0, 0.2), + 0 16px 0 -6px #f6f6f6, + 0 17px 2px -6px rgba(0, 0, 0, 0.2); +} + +.todo-count { + float: left; + text-align: left; +} + +.todo-count strong { + font-weight: 300; +} + +.filters { + margin: 0; + padding: 0; + list-style: none; + position: absolute; + right: 0; + left: 0; +} + +.filters li { + display: inline; +} + +.filters li a { + color: inherit; + margin: 3px; + padding: 3px 7px; + text-decoration: none; + border: 1px solid transparent; + border-radius: 3px; +} + +.filters li a.selected, +.filters li a:hover { + border-color: rgba(175, 47, 47, 0.1); +} + +.filters li a.selected { + border-color: rgba(175, 47, 47, 0.2); +} + +.clear-completed, +html .clear-completed:active { + float: right; + position: relative; + line-height: 20px; + text-decoration: none; + cursor: pointer; + position: relative; +} + +.clear-completed:hover { + text-decoration: underline; +} + +.info { + margin: 65px auto 0; + color: #bfbfbf; + font-size: 10px; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + text-align: center; +} + +.info p { + line-height: 1; +} + +.info a { + color: inherit; + text-decoration: none; + font-weight: 400; +} + +.info a:hover { + text-decoration: underline; +} + +/* + Hack to remove background from Mobile Safari. + Can't use it globally since it destroys checkboxes in Firefox +*/ +@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 { + -webkit-transform: rotate(90deg); + transform: rotate(90deg); + -webkit-appearance: none; + appearance: none; + } +} + +@media (max-width: 430px) { + .footer { + height: 50px; + } + + .filters { + bottom: 10px; + } +} \ No newline at end of file diff --git a/bench/implementations/ember-2.6.3/.gitignore b/bench/implementations/ember-2.6.3/.gitignore new file mode 100644 index 0000000..7514eca --- /dev/null +++ b/bench/implementations/ember-2.6.3/.gitignore @@ -0,0 +1,16 @@ +# See http://help.github.com/ignore-files/ for more about ignoring files. + +# compiled output +/tmp + +# dependencies +/node_modules +/bower_components + +# misc +/.sass-cache +/connect.lock +/coverage/* +/libpeerconnection.log +npm-debug.log +testem.log diff --git a/bench/implementations/ember-2.6.3/README.md b/bench/implementations/ember-2.6.3/README.md new file mode 100755 index 0000000..7ba6519 --- /dev/null +++ b/bench/implementations/ember-2.6.3/README.md @@ -0,0 +1,15 @@ +# Ember.js TodoMVC for Benchmarking + +This is an update of the +_[Ember.js TodoMVC example](https://github.com/tastejs/todomvc/tree/gh-pages/examples/emberjs)_ +with the following changes: + +* Upgrade to Ember 2.6.2 +* Configure router to support relative URLs +* Remove localStorage functionality - not relevant to measuring render performance + +# Building + +1. `npm install` +2. `npm run make` +3. `open dist/index.html` diff --git a/bench/implementations/ember-2.6.3/app/app.js b/bench/implementations/ember-2.6.3/app/app.js new file mode 100755 index 0000000..904926f --- /dev/null +++ b/bench/implementations/ember-2.6.3/app/app.js @@ -0,0 +1,18 @@ +import Ember from 'ember'; +import Resolver from './resolver'; +import loadInitializers from 'ember-load-initializers'; +import config from './config/environment'; + +let App; + +Ember.MODEL_FACTORY_INJECTIONS = true; + +App = Ember.Application.extend({ + modulePrefix: config.modulePrefix, + podModulePrefix: config.podModulePrefix, + Resolver +}); + +loadInitializers(App, config.modulePrefix); + +export default App; diff --git a/bench/implementations/ember-2.6.3/app/components/todo-item.js b/bench/implementations/ember-2.6.3/app/components/todo-item.js new file mode 100755 index 0000000..4fe8161 --- /dev/null +++ b/bench/implementations/ember-2.6.3/app/components/todo-item.js @@ -0,0 +1,48 @@ +import Ember from 'ember'; + +export default Ember.Component.extend({ + repo: Ember.inject.service(), + tagName: 'li', + editing: false, + classNameBindings: ['todo.completed', 'editing'], + + actions: { + startEditing() { + this.get('onStartEdit')(); + this.set('editing', true); + Ember.run.scheduleOnce('afterRender', this, 'focusInput'); + }, + + doneEditing(todoTitle) { + if (!this.get('editing')) { return; } + if (Ember.isBlank(todoTitle)) { + this.send('removeTodo'); + } else { + this.set('todo.title', todoTitle.trim()); + this.set('editing', false); + this.get('onEndEdit')(); + } + }, + + handleKeydown(e) { + if (e.keyCode === 13) { + e.target.blur(); + } else if (e.keyCode === 27) { + this.set('editing', false); + } + }, + + toggleCompleted(e) { + let todo = this.get('todo'); + Ember.set(todo, 'completed', e.target.checked); + }, + + removeTodo() { + this.get('repo').delete(this.get('todo')); + } + }, + + focusInput() { + this.element.querySelector('input.edit').focus(); + } +}); diff --git a/bench/implementations/ember-2.6.3/app/components/todo-list.js b/bench/implementations/ember-2.6.3/app/components/todo-list.js new file mode 100755 index 0000000..3b73dbc --- /dev/null +++ b/bench/implementations/ember-2.6.3/app/components/todo-list.js @@ -0,0 +1,26 @@ +import Ember from 'ember'; + +export default Ember.Component.extend({ + repo: Ember.inject.service(), + tagName: 'section', + elementId: 'main', + canToggle: true, + allCompleted: Ember.computed('todos.@each.completed', function () { + return this.get('todos').isEvery('completed'); + }), + + actions: { + enableToggle() { + this.set('canToggle', true); + }, + + disableToggle() { + this.set('canToggle', false); + }, + + toggleAll() { + let allCompleted = this.get('allCompleted'); + this.get('todos').forEach(todo => Ember.set(todo, 'completed', !allCompleted)); + } + } +}); diff --git a/bench/implementations/ember-2.6.3/app/controllers/active.js b/bench/implementations/ember-2.6.3/app/controllers/active.js new file mode 100755 index 0000000..4b603f7 --- /dev/null +++ b/bench/implementations/ember-2.6.3/app/controllers/active.js @@ -0,0 +1,5 @@ +import Ember from 'ember'; + +export default Ember.Controller.extend({ + todos: Ember.computed.filterBy('model', 'completed', false) +}); diff --git a/bench/implementations/ember-2.6.3/app/controllers/application.js b/bench/implementations/ember-2.6.3/app/controllers/application.js new file mode 100755 index 0000000..deb4f97 --- /dev/null +++ b/bench/implementations/ember-2.6.3/app/controllers/application.js @@ -0,0 +1,19 @@ +import Ember from 'ember'; + +export default Ember.Controller.extend({ + repo: Ember.inject.service(), + remaining: Ember.computed.filterBy('model', 'completed', false), + completed: Ember.computed.filterBy('model', 'completed'), + actions: { + createTodo(e) { + if (e.keyCode === 13 && !Ember.isBlank(e.target.value)) { + this.get('repo').add({ title: e.target.value.trim(), completed: false }); + e.target.value = ''; + } + }, + + clearCompleted() { + this.get('model').removeObjects(this.get('completed')); + } + } +}); diff --git a/bench/implementations/ember-2.6.3/app/controllers/completed.js b/bench/implementations/ember-2.6.3/app/controllers/completed.js new file mode 100755 index 0000000..278324a --- /dev/null +++ b/bench/implementations/ember-2.6.3/app/controllers/completed.js @@ -0,0 +1,5 @@ +import Ember from 'ember'; + +export default Ember.Controller.extend({ + todos: Ember.computed.filterBy('model', 'completed', true) +}); diff --git a/bench/implementations/ember-2.6.3/app/helpers/gt.js b/bench/implementations/ember-2.6.3/app/helpers/gt.js new file mode 100755 index 0000000..44df678 --- /dev/null +++ b/bench/implementations/ember-2.6.3/app/helpers/gt.js @@ -0,0 +1,7 @@ +import Ember from 'ember'; + +export function gt([n1, n2]/*, hash*/) { + return n1 > n2; +} + +export default Ember.Helper.helper(gt); diff --git a/bench/implementations/ember-2.6.3/app/helpers/pluralize.js b/bench/implementations/ember-2.6.3/app/helpers/pluralize.js new file mode 100755 index 0000000..feac8ff --- /dev/null +++ b/bench/implementations/ember-2.6.3/app/helpers/pluralize.js @@ -0,0 +1,8 @@ +import Ember from 'ember'; +import { pluralize } from 'ember-inflector'; + +export function pluralizeHelper([singular, count]/*, hash*/) { + return count === 1 ? singular : pluralize(singular); +} + +export default Ember.Helper.helper(pluralizeHelper); diff --git a/bench/implementations/ember-2.6.3/app/index.html b/bench/implementations/ember-2.6.3/app/index.html new file mode 100755 index 0000000..b1730fb --- /dev/null +++ b/bench/implementations/ember-2.6.3/app/index.html @@ -0,0 +1,24 @@ + + + + + + Todomvc + + + {{content-for "head"}} + + + + + {{content-for "head-footer"}} + + + {{content-for "body"}} + + + + + {{content-for "body-footer"}} + + diff --git a/bench/implementations/ember-2.6.3/app/resolver.js b/bench/implementations/ember-2.6.3/app/resolver.js new file mode 100755 index 0000000..2fb563d --- /dev/null +++ b/bench/implementations/ember-2.6.3/app/resolver.js @@ -0,0 +1,3 @@ +import Resolver from 'ember-resolver'; + +export default Resolver; diff --git a/bench/implementations/ember-2.6.3/app/router.js b/bench/implementations/ember-2.6.3/app/router.js new file mode 100755 index 0000000..80c146d --- /dev/null +++ b/bench/implementations/ember-2.6.3/app/router.js @@ -0,0 +1,13 @@ +import Ember from 'ember'; +import config from './config/environment'; + +const Router = Ember.Router.extend({ + location: config.locationType +}); + +Router.map(function () { + this.route('active'); + this.route('completed'); +}); + +export default Router; diff --git a/bench/implementations/ember-2.6.3/app/routes/application.js b/bench/implementations/ember-2.6.3/app/routes/application.js new file mode 100755 index 0000000..b7a85e5 --- /dev/null +++ b/bench/implementations/ember-2.6.3/app/routes/application.js @@ -0,0 +1,8 @@ +import Ember from 'ember'; + +export default Ember.Route.extend({ + repo: Ember.inject.service(), + model() { + return this.get('repo').findAll(); + } +}); diff --git a/bench/implementations/ember-2.6.3/app/services/repo.js b/bench/implementations/ember-2.6.3/app/services/repo.js new file mode 100755 index 0000000..546b737 --- /dev/null +++ b/bench/implementations/ember-2.6.3/app/services/repo.js @@ -0,0 +1,19 @@ +import Ember from 'ember'; + +export default Ember.Service.extend({ + lastId: 0, + data: null, + findAll() { + return this.get('data') || this.set('data', []); + }, + + add(attrs) { + let todo = Object.assign({ id: this.incrementProperty('lastId') }, attrs); + this.get('data').pushObject(todo); + return todo; + }, + + delete(todo) { + this.get('data').removeObject(todo); + } +}); diff --git a/bench/implementations/ember-2.6.3/app/styles/app.css b/bench/implementations/ember-2.6.3/app/styles/app.css new file mode 100755 index 0000000..e69de29 diff --git a/bench/implementations/ember-2.6.3/app/templates/active.hbs b/bench/implementations/ember-2.6.3/app/templates/active.hbs new file mode 100755 index 0000000..de244f4 --- /dev/null +++ b/bench/implementations/ember-2.6.3/app/templates/active.hbs @@ -0,0 +1 @@ +{{todo-list todos=todos}} \ No newline at end of file diff --git a/bench/implementations/ember-2.6.3/app/templates/application.hbs b/bench/implementations/ember-2.6.3/app/templates/application.hbs new file mode 100755 index 0000000..bdf6d9e --- /dev/null +++ b/bench/implementations/ember-2.6.3/app/templates/application.hbs @@ -0,0 +1,29 @@ +
+ + {{outlet}} + {{#if (gt model.length 0)}} +
+ {{remaining.length}} {{pluralize 'item' remaining.length}} left +
    +
  • {{#link-to "index" activeClass="selected"}}All{{/link-to}}
  • +
  • {{#link-to "active" activeClass="selected"}}Active{{/link-to}}
  • +
  • {{#link-to "completed" activeClass="selected"}}Completed{{/link-to}}
  • +
+ {{#if completed.length}} + + {{/if}} +
+ {{/if}} +
+ diff --git a/bench/implementations/ember-2.6.3/app/templates/completed.hbs b/bench/implementations/ember-2.6.3/app/templates/completed.hbs new file mode 100755 index 0000000..de244f4 --- /dev/null +++ b/bench/implementations/ember-2.6.3/app/templates/completed.hbs @@ -0,0 +1 @@ +{{todo-list todos=todos}} \ No newline at end of file diff --git a/bench/implementations/ember-2.6.3/app/templates/components/todo-item.hbs b/bench/implementations/ember-2.6.3/app/templates/components/todo-item.hbs new file mode 100755 index 0000000..c06975e --- /dev/null +++ b/bench/implementations/ember-2.6.3/app/templates/components/todo-item.hbs @@ -0,0 +1,6 @@ +
+ + + +
+ \ No newline at end of file diff --git a/bench/implementations/ember-2.6.3/app/templates/components/todo-list.hbs b/bench/implementations/ember-2.6.3/app/templates/components/todo-list.hbs new file mode 100755 index 0000000..309d07a --- /dev/null +++ b/bench/implementations/ember-2.6.3/app/templates/components/todo-list.hbs @@ -0,0 +1,10 @@ +{{#if todos.length}} + {{#if canToggle}} + + {{/if}} +
    + {{#each todos as |todo|}} + {{todo-item todo=todo onStartEdit=(action 'disableToggle') onEndEdit=(action 'enableToggle')}} + {{/each}} +
+{{/if}} diff --git a/bench/implementations/ember-2.6.3/app/templates/index.hbs b/bench/implementations/ember-2.6.3/app/templates/index.hbs new file mode 100755 index 0000000..7d5565c --- /dev/null +++ b/bench/implementations/ember-2.6.3/app/templates/index.hbs @@ -0,0 +1,3 @@ +{{#if model.length}} + {{todo-list todos=model}} +{{/if}} diff --git a/bench/implementations/ember-2.6.3/bower.json b/bench/implementations/ember-2.6.3/bower.json new file mode 100755 index 0000000..b5d3d92 --- /dev/null +++ b/bench/implementations/ember-2.6.3/bower.json @@ -0,0 +1,9 @@ +{ + "name": "todomvc", + "dependencies": { + "ember": "~2.6.2", + "ember-cli-shims": "0.1.1", + "ember-cli-test-loader": "0.2.2", + "ember-qunit-notifications": "0.1.0" + } +} diff --git a/bench/implementations/ember-2.6.3/config/environment.js b/bench/implementations/ember-2.6.3/config/environment.js new file mode 100755 index 0000000..e961eb8 --- /dev/null +++ b/bench/implementations/ember-2.6.3/config/environment.js @@ -0,0 +1,47 @@ +/* jshint node: true */ + +module.exports = function (environment) { + var ENV = { + modulePrefix: 'todomvc', + environment: environment, + baseURL: null, + locationType: 'none', + EmberENV: { + FEATURES: { + // Here you can enable experimental features on an ember canary build + // e.g. 'with-controller': true + } + }, + + APP: { + // Here you can pass flags/options to your application instance + // when it is created + } + }; + + // if (environment === 'development') { + // ENV.APP.LOG_RESOLVER = true; + // ENV.APP.LOG_ACTIVE_GENERATION = true; + // ENV.APP.LOG_TRANSITIONS = true; + // ENV.APP.LOG_TRANSITIONS_INTERNAL = true; + // ENV.APP.LOG_VIEW_LOOKUPS = true; + // } + + if (environment === 'test') { + // Testem prefers this... + ENV.baseURL = '/'; + ENV.locationType = 'none'; + + // keep test console output quieter + ENV.APP.LOG_ACTIVE_GENERATION = false; + ENV.APP.LOG_VIEW_LOOKUPS = false; + + ENV.APP.rootElement = '#ember-testing'; + } + + // if (environment === 'production') { + + // } + + return ENV; +}; diff --git a/bench/implementations/ember-2.6.3/dist/assets/todomvc-b88bd0267dade133c112b65a28b90916.js b/bench/implementations/ember-2.6.3/dist/assets/todomvc-b88bd0267dade133c112b65a28b90916.js new file mode 100644 index 0000000..9d1d5c3 --- /dev/null +++ b/bench/implementations/ember-2.6.3/dist/assets/todomvc-b88bd0267dade133c112b65a28b90916.js @@ -0,0 +1 @@ +"use strict";define("todomvc/app",["exports","ember","todomvc/resolver","ember-load-initializers","todomvc/config/environment"],function(e,t,n,r,a){var o=void 0;t.default.MODEL_FACTORY_INJECTIONS=!0,o=t.default.Application.extend({modulePrefix:a.default.modulePrefix,podModulePrefix:a.default.podModulePrefix,Resolver:n.default}),(0,r.default)(o,a.default.modulePrefix),e.default=o}),define("todomvc/components/app-version",["exports","ember-cli-app-version/components/app-version","todomvc/config/environment"],function(e,t,n){var r=n.default.APP.name,a=n.default.APP.version;e.default=t.default.extend({version:a,name:r})}),define("todomvc/components/todo-item",["exports","ember"],function(e,t){e.default=t.default.Component.extend({repo:t.default.inject.service(),tagName:"li",editing:!1,classNameBindings:["todo.completed","editing"],actions:{startEditing:function(){this.get("onStartEdit")(),this.set("editing",!0),t.default.run.scheduleOnce("afterRender",this,"focusInput")},doneEditing:function(e){this.get("editing")&&(t.default.isBlank(e)?this.send("removeTodo"):(this.set("todo.title",e.trim()),this.set("editing",!1),this.get("onEndEdit")()))},handleKeydown:function(e){13===e.keyCode?e.target.blur():27===e.keyCode&&this.set("editing",!1)},toggleCompleted:function(e){var n=this.get("todo");t.default.set(n,"completed",e.target.checked)},removeTodo:function(){this.get("repo").delete(this.get("todo"))}},focusInput:function(){this.element.querySelector("input.edit").focus()}})}),define("todomvc/components/todo-list",["exports","ember"],function(e,t){e.default=t.default.Component.extend({repo:t.default.inject.service(),tagName:"section",elementId:"main",canToggle:!0,allCompleted:t.default.computed("todos.@each.completed",function(){return this.get("todos").isEvery("completed")}),actions:{enableToggle:function(){this.set("canToggle",!0)},disableToggle:function(){this.set("canToggle",!1)},toggleAll:function(){var e=this.get("allCompleted");this.get("todos").forEach(function(n){return t.default.set(n,"completed",!e)})}}})}),define("todomvc/controllers/active",["exports","ember"],function(e,t){e.default=t.default.Controller.extend({todos:t.default.computed.filterBy("model","completed",!1)})}),define("todomvc/controllers/application",["exports","ember"],function(e,t){e.default=t.default.Controller.extend({repo:t.default.inject.service(),remaining:t.default.computed.filterBy("model","completed",!1),completed:t.default.computed.filterBy("model","completed"),actions:{createTodo:function(e){13!==e.keyCode||t.default.isBlank(e.target.value)||(this.get("repo").add({title:e.target.value.trim(),completed:!1}),e.target.value="")},clearCompleted:function(){this.get("model").removeObjects(this.get("completed"))}}})}),define("todomvc/controllers/completed",["exports","ember"],function(e,t){e.default=t.default.Controller.extend({todos:t.default.computed.filterBy("model","completed",!0)})}),define("todomvc/helpers/gt",["exports","ember"],function(e,t){function n(e){var t=r(e,2),n=t[0],a=t[1];return n>a}var r=function(){function e(e,t){var n=[],r=!0,a=!1,o=void 0;try{for(var l,d=e[Symbol.iterator]();!(r=(l=d.next()).done)&&(n.push(l.value),!t||n.length!==t);r=!0);}catch(e){a=!0,o=e}finally{try{!r&&d.return&&d.return()}finally{if(a)throw o}}return n}return function(t,n){if(Array.isArray(t))return t;if(Symbol.iterator in Object(t))return e(t,n);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}();e.gt=n,e.default=t.default.Helper.helper(n)}),define("todomvc/helpers/pluralize",["exports","ember","ember-inflector"],function(e,t,n){function r(e){var t=a(e,2),r=t[0],o=t[1];return 1===o?r:(0,n.pluralize)(r)}var a=function(){function e(e,t){var n=[],r=!0,a=!1,o=void 0;try{for(var l,d=e[Symbol.iterator]();!(r=(l=d.next()).done)&&(n.push(l.value),!t||n.length!==t);r=!0);}catch(e){a=!0,o=e}finally{try{!r&&d.return&&d.return()}finally{if(a)throw o}}return n}return function(t,n){if(Array.isArray(t))return t;if(Symbol.iterator in Object(t))return e(t,n);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}();e.pluralizeHelper=r,e.default=t.default.Helper.helper(r)}),define("todomvc/helpers/singularize",["exports","ember-inflector/lib/helpers/singularize"],function(e,t){e.default=t.default}),define("todomvc/initializers/app-version",["exports","ember-cli-app-version/initializer-factory","todomvc/config/environment"],function(e,t,n){e.default={name:"App Version",initialize:(0,t.default)(n.default.APP.name,n.default.APP.version)}}),define("todomvc/initializers/container-debug-adapter",["exports","ember-resolver/container-debug-adapter"],function(e,t){e.default={name:"container-debug-adapter",initialize:function(){var e=arguments[1]||arguments[0];e.register("container-debug-adapter:main",t.default),e.inject("container-debug-adapter:main","namespace","application:main")}}}),define("todomvc/initializers/export-application-global",["exports","ember","todomvc/config/environment"],function(e,t,n){function r(){var e=arguments[1]||arguments[0];if(n.default.exportApplicationGlobal!==!1){var r,a=n.default.exportApplicationGlobal;r="string"==typeof a?a:t.default.String.classify(n.default.modulePrefix),window[r]||(window[r]=e,e.reopen({willDestroy:function(){this._super.apply(this,arguments),delete window[r]}}))}}e.initialize=r,e.default={name:"export-application-global",initialize:r}}),define("todomvc/resolver",["exports","ember-resolver"],function(e,t){e.default=t.default}),define("todomvc/router",["exports","ember","todomvc/config/environment"],function(e,t,n){var r=t.default.Router.extend({location:n.default.locationType});r.map(function(){this.route("active"),this.route("completed")}),e.default=r}),define("todomvc/routes/application",["exports","ember"],function(e,t){e.default=t.default.Route.extend({repo:t.default.inject.service(),model:function(){return this.get("repo").findAll()}})}),define("todomvc/services/ajax",["exports","ember-ajax/services/ajax"],function(e,t){Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})}),define("todomvc/services/repo",["exports","ember"],function(e,t){e.default=t.default.Service.extend({lastId:0,data:null,findAll:function(){return this.get("data")||this.set("data",[])},add:function(e){var t=Object.assign({id:this.incrementProperty("lastId")},e);return this.get("data").pushObject(t),t},delete:function(e){this.get("data").removeObject(e)}})}),define("todomvc/templates/active",["exports"],function(e){e.default=Ember.HTMLBars.template(function(){return{meta:{fragmentReason:{name:"missing-wrapper",problems:["wrong-type"]},revision:"Ember@2.6.2",loc:{source:null,start:{line:1,column:0},end:{line:1,column:25}},moduleName:"todomvc/templates/active.hbs"},isEmpty:!1,arity:0,cachedFragment:null,hasRendered:!1,buildFragment:function(e){var t=e.createDocumentFragment(),n=e.createComment("");return e.appendChild(t,n),t},buildRenderNodes:function(e,t,n){var r=new Array(1);return r[0]=e.createMorphAt(t,0,0,n),e.insertBoundary(t,0),e.insertBoundary(t,null),r},statements:[["inline","todo-list",[],["todos",["subexpr","@mut",[["get","todos",["loc",[null,[1,18],[1,23]]]]],[],[]]],["loc",[null,[1,0],[1,25]]]]],locals:[],templates:[]}}())}),define("todomvc/templates/application",["exports"],function(e){e.default=Ember.HTMLBars.template(function(){var e=function(){var e=function(){return{meta:{fragmentReason:!1,revision:"Ember@2.6.2",loc:{source:null,start:{line:11,column:14},end:{line:11,column:60}},moduleName:"todomvc/templates/application.hbs"},isEmpty:!1,arity:0,cachedFragment:null,hasRendered:!1,buildFragment:function(e){var t=e.createDocumentFragment(),n=e.createTextNode("All");return e.appendChild(t,n),t},buildRenderNodes:function(){return[]},statements:[],locals:[],templates:[]}}(),t=function(){return{meta:{fragmentReason:!1,revision:"Ember@2.6.2",loc:{source:null,start:{line:12,column:14},end:{line:12,column:64}},moduleName:"todomvc/templates/application.hbs"},isEmpty:!1,arity:0,cachedFragment:null,hasRendered:!1,buildFragment:function(e){var t=e.createDocumentFragment(),n=e.createTextNode("Active");return e.appendChild(t,n),t},buildRenderNodes:function(){return[]},statements:[],locals:[],templates:[]}}(),n=function(){return{meta:{fragmentReason:!1,revision:"Ember@2.6.2",loc:{source:null,start:{line:13,column:14},end:{line:13,column:70}},moduleName:"todomvc/templates/application.hbs"},isEmpty:!1,arity:0,cachedFragment:null,hasRendered:!1,buildFragment:function(e){var t=e.createDocumentFragment(),n=e.createTextNode("Completed");return e.appendChild(t,n),t},buildRenderNodes:function(){return[]},statements:[],locals:[],templates:[]}}(),r=function(){return{meta:{fragmentReason:!1,revision:"Ember@2.6.2",loc:{source:null,start:{line:15,column:8},end:{line:17,column:8}},moduleName:"todomvc/templates/application.hbs"},isEmpty:!1,arity:0,cachedFragment:null,hasRendered:!1,buildFragment:function(e){var t=e.createDocumentFragment(),n=e.createTextNode(" ");e.appendChild(t,n);var n=e.createElement("button");e.setAttribute(n,"id","clear-completed");var r=e.createTextNode("Clear completed");e.appendChild(n,r),e.appendChild(t,n);var n=e.createTextNode("\n");return e.appendChild(t,n),t},buildRenderNodes:function(e,t,n){var r=e.childAt(t,[1]),a=new Array(1);return a[0]=e.createAttrMorph(r,"onclick"),a},statements:[["attribute","onclick",["subexpr","action",["clearCompleted"],[],["loc",[null,[16,47],[16,74]]]]]],locals:[],templates:[]}}();return{meta:{fragmentReason:!1,revision:"Ember@2.6.2",loc:{source:null,start:{line:7,column:4},end:{line:19,column:4}},moduleName:"todomvc/templates/application.hbs"},isEmpty:!1,arity:0,cachedFragment:null,hasRendered:!1,buildFragment:function(e){var t=e.createDocumentFragment(),n=e.createTextNode(" ");e.appendChild(t,n);var n=e.createElement("footer");e.setAttribute(n,"id","footer");var r=e.createTextNode("\n ");e.appendChild(n,r);var r=e.createElement("span");e.setAttribute(r,"id","todo-count");var a=e.createElement("strong"),o=e.createComment("");e.appendChild(a,o),e.appendChild(r,a);var a=e.createTextNode(" ");e.appendChild(r,a);var a=e.createComment("");e.appendChild(r,a);var a=e.createTextNode(" left");e.appendChild(r,a),e.appendChild(n,r);var r=e.createTextNode("\n ");e.appendChild(n,r);var r=e.createElement("ul");e.setAttribute(r,"id","filters");var a=e.createTextNode("\n ");e.appendChild(r,a);var a=e.createElement("li"),o=e.createComment("");e.appendChild(a,o),e.appendChild(r,a);var a=e.createTextNode("\n ");e.appendChild(r,a);var a=e.createElement("li"),o=e.createComment("");e.appendChild(a,o),e.appendChild(r,a);var a=e.createTextNode("\n ");e.appendChild(r,a);var a=e.createElement("li"),o=e.createComment("");e.appendChild(a,o),e.appendChild(r,a);var a=e.createTextNode("\n ");e.appendChild(r,a),e.appendChild(n,r);var r=e.createTextNode("\n");e.appendChild(n,r);var r=e.createComment("");e.appendChild(n,r);var r=e.createTextNode(" ");e.appendChild(n,r),e.appendChild(t,n);var n=e.createTextNode("\n");return e.appendChild(t,n),t},buildRenderNodes:function(e,t,n){var r=e.childAt(t,[1]),a=e.childAt(r,[1]),o=e.childAt(r,[3]),l=new Array(6);return l[0]=e.createMorphAt(e.childAt(a,[0]),0,0),l[1]=e.createMorphAt(a,2,2),l[2]=e.createMorphAt(e.childAt(o,[1]),0,0),l[3]=e.createMorphAt(e.childAt(o,[3]),0,0),l[4]=e.createMorphAt(e.childAt(o,[5]),0,0),l[5]=e.createMorphAt(r,5,5),l},statements:[["content","remaining.length",["loc",[null,[9,38],[9,58]]]],["inline","pluralize",["item",["get","remaining.length",["loc",[null,[9,87],[9,103]]]]],[],["loc",[null,[9,68],[9,105]]]],["block","link-to",["index"],["activeClass","selected"],0,null,["loc",[null,[11,14],[11,72]]]],["block","link-to",["active"],["activeClass","selected"],1,null,["loc",[null,[12,14],[12,76]]]],["block","link-to",["completed"],["activeClass","selected"],2,null,["loc",[null,[13,14],[13,82]]]],["block","if",[["get","completed.length",["loc",[null,[15,14],[15,30]]]]],[],3,null,["loc",[null,[15,8],[17,15]]]]],locals:[],templates:[e,t,n,r]}}();return{meta:{fragmentReason:{name:"missing-wrapper",problems:["multiple-nodes"]},revision:"Ember@2.6.2",loc:{source:null,start:{line:1,column:0},end:{line:30,column:0}},moduleName:"todomvc/templates/application.hbs"},isEmpty:!1,arity:0,cachedFragment:null,hasRendered:!1,buildFragment:function(e){var t=e.createDocumentFragment(),n=e.createElement("section");e.setAttribute(n,"id","todoapp");var r=e.createTextNode("\n ");e.appendChild(n,r);var r=e.createElement("header");e.setAttribute(r,"id","header");var a=e.createTextNode("\n ");e.appendChild(r,a);var a=e.createElement("h1"),o=e.createTextNode("todos");e.appendChild(a,o),e.appendChild(r,a);var a=e.createTextNode("\n ");e.appendChild(r,a);var a=e.createElement("input");e.setAttribute(a,"type","text"),e.setAttribute(a,"id","new-todo"),e.setAttribute(a,"class","new-todo"),e.setAttribute(a,"placeholder","What needs to be done?"),e.setAttribute(a,"autofocus",""),e.appendChild(r,a);var a=e.createTextNode("\n ");e.appendChild(r,a),e.appendChild(n,r);var r=e.createTextNode("\n ");e.appendChild(n,r);var r=e.createComment("");e.appendChild(n,r);var r=e.createTextNode("\n");e.appendChild(n,r);var r=e.createComment("");e.appendChild(n,r),e.appendChild(t,n);var n=e.createTextNode("\n");e.appendChild(t,n);var n=e.createElement("footer");e.setAttribute(n,"id","info");var r=e.createTextNode("\n ");e.appendChild(n,r);var r=e.createElement("p"),a=e.createTextNode("Double-click to edit a todo");e.appendChild(r,a),e.appendChild(n,r);var r=e.createTextNode("\n ");e.appendChild(n,r);var r=e.createElement("p"),a=e.createTextNode("\n Created by\n ");e.appendChild(r,a);var a=e.createElement("a");e.setAttribute(a,"href","http://github.com/cibernox");var o=e.createTextNode("Miguel Camba");e.appendChild(a,o),e.appendChild(r,a);var a=e.createTextNode(",\n ");e.appendChild(r,a);var a=e.createElement("a");e.setAttribute(a,"href","http://github.com/addyosmani");var o=e.createTextNode("Addy Osmani");e.appendChild(a,o),e.appendChild(r,a);var a=e.createTextNode("\n ");e.appendChild(r,a),e.appendChild(n,r);var r=e.createTextNode("\n ");e.appendChild(n,r);var r=e.createElement("p"),a=e.createTextNode("Part of ");e.appendChild(r,a);var a=e.createElement("a");e.setAttribute(a,"href","http://todomvc.com");var o=e.createTextNode("TodoMVC");e.appendChild(a,o),e.appendChild(r,a),e.appendChild(n,r);var r=e.createTextNode("\n");e.appendChild(n,r),e.appendChild(t,n);var n=e.createTextNode("\n");return e.appendChild(t,n),t},buildRenderNodes:function(e,t,n){var r=e.childAt(t,[0]),a=e.childAt(r,[1,3]),o=new Array(3);return o[0]=e.createAttrMorph(a,"onkeydown"),o[1]=e.createMorphAt(r,3,3),o[2]=e.createMorphAt(r,5,5),o},statements:[["attribute","onkeydown",["subexpr","action",["createTodo"],[],["loc",[null,[4,64],[4,87]]]]],["content","outlet",["loc",[null,[6,4],[6,14]]]],["block","if",[["subexpr","gt",[["get","model.length",["loc",[null,[7,14],[7,26]]]],0],[],["loc",[null,[7,10],[7,29]]]]],[],0,null,["loc",[null,[7,4],[19,11]]]]],locals:[],templates:[e]}}())}),define("todomvc/templates/completed",["exports"],function(e){e.default=Ember.HTMLBars.template(function(){return{meta:{fragmentReason:{name:"missing-wrapper",problems:["wrong-type"]},revision:"Ember@2.6.2",loc:{source:null,start:{line:1,column:0},end:{line:1,column:25}},moduleName:"todomvc/templates/completed.hbs"},isEmpty:!1,arity:0,cachedFragment:null,hasRendered:!1,buildFragment:function(e){var t=e.createDocumentFragment(),n=e.createComment("");return e.appendChild(t,n),t},buildRenderNodes:function(e,t,n){var r=new Array(1);return r[0]=e.createMorphAt(t,0,0,n),e.insertBoundary(t,0),e.insertBoundary(t,null),r},statements:[["inline","todo-list",[],["todos",["subexpr","@mut",[["get","todos",["loc",[null,[1,18],[1,23]]]]],[],[]]],["loc",[null,[1,0],[1,25]]]]],locals:[],templates:[]}}())}),define("todomvc/templates/components/todo-item",["exports"],function(e){e.default=Ember.HTMLBars.template(function(){return{meta:{fragmentReason:{name:"missing-wrapper",problems:["multiple-nodes"]},revision:"Ember@2.6.2",loc:{source:null,start:{line:1,column:0},end:{line:6,column:153}},moduleName:"todomvc/templates/components/todo-item.hbs"},isEmpty:!1,arity:0,cachedFragment:null,hasRendered:!1,buildFragment:function(e){var t=e.createDocumentFragment(),n=e.createElement("div");e.setAttribute(n,"class","view");var r=e.createTextNode("\n ");e.appendChild(n,r);var r=e.createElement("input");e.setAttribute(r,"type","checkbox"),e.setAttribute(r,"class","toggle"),e.appendChild(n,r);var r=e.createTextNode("\n ");e.appendChild(n,r);var r=e.createElement("label"),a=e.createComment("");e.appendChild(r,a),e.appendChild(n,r);var r=e.createTextNode("\n ");e.appendChild(n,r);var r=e.createElement("button");e.setAttribute(r,"class","destroy"),e.appendChild(n,r);var r=e.createTextNode("\n");e.appendChild(n,r),e.appendChild(t,n);var n=e.createTextNode("\n");e.appendChild(t,n);var n=e.createElement("input");return e.setAttribute(n,"type","text"),e.setAttribute(n,"class","edit"),e.setAttribute(n,"autofocus",""),e.appendChild(t,n),t},buildRenderNodes:function(e,t,n){var r=e.childAt(t,[0]),a=e.childAt(r,[1]);this.cachedFragment&&e.repairClonedNode(a,[],!0);var o=e.childAt(r,[3]),l=e.childAt(r,[5]),d=e.childAt(t,[2]),i=new Array(8);return i[0]=e.createAttrMorph(a,"checked"),i[1]=e.createAttrMorph(a,"onchange"),i[2]=e.createAttrMorph(o,"ondblclick"),i[3]=e.createMorphAt(o,0,0),i[4]=e.createAttrMorph(l,"onclick"),i[5]=e.createAttrMorph(d,"value"),i[6]=e.createAttrMorph(d,"onblur"),i[7]=e.createAttrMorph(d,"onkeydown"),i},statements:[["attribute","checked",["get","todo.completed",["loc",[null,[2,50],[2,64]]]]],["attribute","onchange",["subexpr","action",["toggleCompleted"],[],["loc",[null,[2,76],[2,104]]]]],["attribute","ondblclick",["subexpr","action",["startEditing"],[],["loc",[null,[3,20],[3,45]]]]],["content","todo.title",["loc",[null,[3,46],[3,60]]]],["attribute","onclick",["subexpr","action",["removeTodo"],[],["loc",[null,[4,18],[4,41]]]]],["attribute","value",["get","todo.title",["loc",[null,[6,40],[6,50]]]]],["attribute","onblur",["subexpr","action",["doneEditing"],["value","target.value"],["loc",[null,[6,60],[6,105]]]]],["attribute","onkeydown",["subexpr","action",["handleKeydown"],[],["loc",[null,[6,116],[6,142]]]]]],locals:[],templates:[]}}())}),define("todomvc/templates/components/todo-list",["exports"],function(e){e.default=Ember.HTMLBars.template(function(){var e=function(){var e=function(){return{meta:{fragmentReason:!1,revision:"Ember@2.6.2",loc:{source:null,start:{line:2,column:2},end:{line:4,column:2}},moduleName:"todomvc/templates/components/todo-list.hbs"},isEmpty:!1,arity:0,cachedFragment:null,hasRendered:!1,buildFragment:function(e){var t=e.createDocumentFragment(),n=e.createTextNode(" ");e.appendChild(t,n);var n=e.createElement("input");e.setAttribute(n,"type","checkbox"),e.setAttribute(n,"id","toggle-all"),e.appendChild(t,n);var n=e.createTextNode("\n");return e.appendChild(t,n),t},buildRenderNodes:function(e,t,n){var r=e.childAt(t,[1]);this.cachedFragment&&e.repairClonedNode(r,[],!0);var a=new Array(2);return a[0]=e.createAttrMorph(r,"checked"),a[1]=e.createAttrMorph(r,"onchange"),a},statements:[["attribute","checked",["get","allCompleted",["loc",[null,[3,53],[3,65]]]]],["attribute","onchange",["subexpr","action",["toggleAll"],[],["loc",[null,[3,77],[3,99]]]]]],locals:[],templates:[]}}(),t=function(){return{meta:{fragmentReason:!1,revision:"Ember@2.6.2",loc:{source:null,start:{line:6,column:4},end:{line:8,column:4}},moduleName:"todomvc/templates/components/todo-list.hbs"},isEmpty:!1,arity:1,cachedFragment:null,hasRendered:!1,buildFragment:function(e){var t=e.createDocumentFragment(),n=e.createTextNode(" ");e.appendChild(t,n);var n=e.createComment("");e.appendChild(t,n);var n=e.createTextNode("\n");return e.appendChild(t,n),t},buildRenderNodes:function(e,t,n){var r=new Array(1);return r[0]=e.createMorphAt(t,1,1,n),r},statements:[["inline","todo-item",[],["todo",["subexpr","@mut",[["get","todo",["loc",[null,[7,23],[7,27]]]]],[],[]],"onStartEdit",["subexpr","action",["disableToggle"],[],["loc",[null,[7,40],[7,64]]]],"onEndEdit",["subexpr","action",["enableToggle"],[],["loc",[null,[7,75],[7,98]]]]],["loc",[null,[7,6],[7,100]]]]],locals:["todo"],templates:[]}}();return{meta:{fragmentReason:{name:"missing-wrapper",problems:["wrong-type","multiple-nodes"]},revision:"Ember@2.6.2",loc:{source:null,start:{line:1,column:0},end:{line:10,column:0}},moduleName:"todomvc/templates/components/todo-list.hbs"},isEmpty:!1,arity:0,cachedFragment:null,hasRendered:!1,buildFragment:function(e){var t=e.createDocumentFragment(),n=e.createComment("");e.appendChild(t,n);var n=e.createTextNode(" ");e.appendChild(t,n);var n=e.createElement("ul");e.setAttribute(n,"id","todo-list"),e.setAttribute(n,"class","todo-list");var r=e.createTextNode("\n");e.appendChild(n,r);var r=e.createComment("");e.appendChild(n,r);var r=e.createTextNode(" ");e.appendChild(n,r),e.appendChild(t,n);var n=e.createTextNode("\n");return e.appendChild(t,n),t},buildRenderNodes:function(e,t,n){var r=new Array(2);return r[0]=e.createMorphAt(t,0,0,n),r[1]=e.createMorphAt(e.childAt(t,[2]),1,1),e.insertBoundary(t,0),r},statements:[["block","if",[["get","canToggle",["loc",[null,[2,8],[2,17]]]]],[],0,null,["loc",[null,[2,2],[4,9]]]],["block","each",[["get","todos",["loc",[null,[6,12],[6,17]]]]],[],1,null,["loc",[null,[6,4],[8,13]]]]],locals:[],templates:[e,t]}}();return{meta:{fragmentReason:{name:"missing-wrapper",problems:["wrong-type"]},revision:"Ember@2.6.2",loc:{source:null,start:{line:1,column:0},end:{line:11,column:0}},moduleName:"todomvc/templates/components/todo-list.hbs"},isEmpty:!1,arity:0,cachedFragment:null,hasRendered:!1,buildFragment:function(e){var t=e.createDocumentFragment(),n=e.createComment("");return e.appendChild(t,n),t},buildRenderNodes:function(e,t,n){var r=new Array(1);return r[0]=e.createMorphAt(t,0,0,n),e.insertBoundary(t,0),e.insertBoundary(t,null),r},statements:[["block","if",[["get","todos.length",["loc",[null,[1,6],[1,18]]]]],[],0,null,["loc",[null,[1,0],[10,7]]]]],locals:[],templates:[e]}}())}),define("todomvc/templates/index",["exports"],function(e){e.default=Ember.HTMLBars.template(function(){var e=function(){return{meta:{fragmentReason:{name:"missing-wrapper",problems:["wrong-type"]},revision:"Ember@2.6.2",loc:{source:null,start:{line:1,column:0},end:{line:3,column:0}},moduleName:"todomvc/templates/index.hbs"},isEmpty:!1,arity:0,cachedFragment:null,hasRendered:!1,buildFragment:function(e){var t=e.createDocumentFragment(),n=e.createTextNode(" ");e.appendChild(t,n);var n=e.createComment("");e.appendChild(t,n);var n=e.createTextNode("\n");return e.appendChild(t,n),t},buildRenderNodes:function(e,t,n){var r=new Array(1);return r[0]=e.createMorphAt(t,1,1,n),r},statements:[["inline","todo-list",[],["todos",["subexpr","@mut",[["get","model",["loc",[null,[2,20],[2,25]]]]],[],[]]],["loc",[null,[2,2],[2,27]]]]],locals:[],templates:[]}}();return{meta:{fragmentReason:{name:"missing-wrapper",problems:["wrong-type"]},revision:"Ember@2.6.2",loc:{source:null,start:{line:1,column:0},end:{line:4,column:0}},moduleName:"todomvc/templates/index.hbs"},isEmpty:!1,arity:0,cachedFragment:null,hasRendered:!1,buildFragment:function(e){var t=e.createDocumentFragment(),n=e.createComment("");return e.appendChild(t,n),t},buildRenderNodes:function(e,t,n){var r=new Array(1);return r[0]=e.createMorphAt(t,0,0,n),e.insertBoundary(t,0),e.insertBoundary(t,null),r},statements:[["block","if",[["get","model.length",["loc",[null,[1,6],[1,18]]]]],[],0,null,["loc",[null,[1,0],[3,7]]]]],locals:[],templates:[e]}}())}),define("todomvc/config/environment",["ember"],function(e){var t="todomvc";try{var n=t+"/config/environment",r=e.default.$('meta[name="'+n+'"]').attr("content"),a=JSON.parse(unescape(r));return{default:a}}catch(e){throw new Error('Could not read config from meta tag with name "'+n+'".')}}),runningTests||require("todomvc/app").default.create({name:"todomvc",version:"0.0.0+9b29a440"}); \ No newline at end of file diff --git a/bench/implementations/ember-2.6.3/dist/assets/todomvc-d41d8cd98f00b204e9800998ecf8427e.css b/bench/implementations/ember-2.6.3/dist/assets/todomvc-d41d8cd98f00b204e9800998ecf8427e.css new file mode 100644 index 0000000..e69de29 diff --git a/bench/implementations/ember-2.6.3/dist/assets/vendor-01de4edc8253c2828fa6f36d3b1ca849.js b/bench/implementations/ember-2.6.3/dist/assets/vendor-01de4edc8253c2828fa6f36d3b1ca849.js new file mode 100644 index 0000000..7b504e3 --- /dev/null +++ b/bench/implementations/ember-2.6.3/dist/assets/vendor-01de4edc8253c2828fa6f36d3b1ca849.js @@ -0,0 +1,18 @@ +function createDeprecatedModule(e){define(e,["exports","ember-resolver/resolver","ember"],function(t,r,n){n.default.deprecate("Usage of `"+e+"` module is deprecated, please update to `ember-resolver`.",!1,{id:"ember-resolver.legacy-shims",until:"3.0.0"}),t.default=r.default})}window.EmberENV={FEATURES:{}};var runningTests=!1,loader,define,requireModule,require,requirejs;!function(e){"use strict";function t(){l={define:0,require:0,reify:0,findDeps:0,modules:0,exports:0,resolve:0,resolveRelative:0,findModule:0,pendingQueueLength:0},requirejs._stats=l}function r(e){throw new Error("an unsupported module was defined, expected `define(name, deps, module)` instead got: `"+e+"` arguments to define`")}function n(e,t,r,n){l.modules++,this.id=h++,this.name=e,this.deps=!t.length&&r.length?m:t,this.module={exports:{}},this.callback=r,this.finalized=!1,this.hasExportsAsDep=!1,this.isAlias=n,this.reified=new Array(t.length),this._foundDeps=!1,this.isPending=!1}function i(e){this.name=e}function o(e,t){throw new Error("Could not find module `"+e+"` imported from `"+t+"`")}function a(e,t,r){l.findModule++;for(var n=d[e]||d[e+"/index"];n&&n.isAlias;)n=d[n.name];return n||o(e,t),!r||n.finalized||n.isPending||(n.findDeps(r),r.push(n),l.pendingQueueLength++),n}function s(e,t){if(l.resolve++,"."!==e.charAt(0))return e;l.resolveRelative++;for(var r=e.split("/"),n=t.split("/"),i=n.slice(0,-1),o=0,a=r.length;o=0;n--)t[n].exports();return r.module.exports},t(),loader={noConflict:function(t){var r,n;for(r in t)t.hasOwnProperty(r)&&c.hasOwnProperty(r)&&(n=t[r],e[n]=e[r],e[r]=c[r])}};var f;f=Array.isArray?Array.isArray:function(e){return"[object Array]"===Object.prototype.toString.call(e)};var d={},p={},h=0,m=["require","exports","module"];n.prototype.makeDefaultExport=function(){var e=this.module.exports;null===e||"object"!=typeof e&&"function"!=typeof e||void 0!==e.default||(e.default=e)},n.prototype.exports=function(){if(this.finalized)return this.module.exports;l.exports++,this.finalized=!0,this.isPending=!1,loader.wrapModules&&(this.callback=loader.wrapModules(this.name,this.callback)),this.reify();var e=this.callback.apply(this,this.reified);return this.hasExportsAsDep&&void 0===e||(this.module.exports=e),this.makeDefaultExport(),this.module.exports},n.prototype.unsee=function(){this.finalized=!1,this._foundDeps=!1,this.isPending=!1,this.module={exports:{}}},n.prototype.reify=function(){l.reify++;for(var e=this.reified,t=0;t0&&t-1 in e)}function n(e,t,r){if(oe.isFunction(t))return oe.grep(e,function(e,n){return!!t.call(e,n,e)!==r});if(t.nodeType)return oe.grep(e,function(e){return e===t!==r});if("string"==typeof t){if(me.test(t))return oe.filter(t,e,r);t=oe.filter(t,e)}return oe.grep(e,function(e){return Z.call(t,e)>-1!==r})}function i(e,t){for(;(e=e[t])&&1!==e.nodeType;);return e}function o(e){var t={};return oe.each(e.match(we)||[],function(e,r){t[r]=!0}),t}function a(){G.removeEventListener("DOMContentLoaded",a),e.removeEventListener("load",a),oe.ready()}function s(){this.expando=oe.expando+s.uid++}function u(e,t,r){var n;if(void 0===r&&1===e.nodeType)if(n="data-"+t.replace(Ne,"-$&").toLowerCase(),r=e.getAttribute(n),"string"==typeof r){try{r="true"===r||"false"!==r&&("null"===r?null:+r+""===r?+r:Te.test(r)?oe.parseJSON(r):r)}catch(e){}Oe.set(e,t,r)}else r=void 0;return r}function l(e,t,r,n){var i,o=1,a=20,s=n?function(){return n.cur()}:function(){return oe.css(e,t,"")},u=s(),l=r&&r[3]||(oe.cssNumber[t]?"":"px"),c=(oe.cssNumber[t]||"px"!==l&&+u)&&Ae.exec(oe.css(e,t));if(c&&c[3]!==l){l=l||c[3],r=r||[],c=+u||1;do o=o||".5",c/=o,oe.style(e,t,c+l);while(o!==(o=s()/u)&&1!==o&&--a)}return r&&(c=+c||+u||0,i=r[1]?c+(r[1]+1)*r[2]:+r[2],n&&(n.unit=l,n.start=c,n.end=i)),i}function c(e,t){var r="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[];return void 0===t||t&&oe.nodeName(e,t)?oe.merge([e],r):r}function f(e,t){for(var r=0,n=e.length;r-1)i&&i.push(o);else if(l=oe.contains(o.ownerDocument,o),a=c(p.appendChild(o),"script"),l&&f(a),r)for(d=0;o=a[d++];)De.test(o.type||"")&&r.push(o);return p}function p(){return!0}function h(){return!1}function m(){try{return G.activeElement}catch(e){}}function v(e,t,r,n,i,o){var a,s;if("object"==typeof t){"string"!=typeof r&&(n=n||r,r=void 0);for(s in t)v(e,s,r,n,t[s],o);return e}if(null==n&&null==i?(i=r,n=r=void 0):null==i&&("string"==typeof r?(i=n,n=void 0):(i=n,n=r,r=void 0)),i===!1)i=h;else if(!i)return e;return 1===o&&(a=i,i=function(e){return oe().off(e),a.apply(this,arguments)},i.guid=a.guid||(a.guid=oe.guid++)),e.each(function(){oe.event.add(this,t,i,n,r)})}function b(e,t){return oe.nodeName(e,"table")&&oe.nodeName(11!==t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function g(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function y(e){var t=Ue.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function _(e,t){var r,n,i,o,a,s,u,l;if(1===t.nodeType){if(Ce.hasData(e)&&(o=Ce.access(e),a=Ce.set(t,o),l=o.events)){delete a.handle,a.events={};for(i in l)for(r=0,n=l[i].length;r1&&"string"==typeof m&&!ne.checkClone&&Be.test(m))return e.each(function(i){var o=e.eq(i);v&&(t[0]=m.call(this,i,o.html())),x(o,t,r,n)});if(p&&(i=d(t,e[0].ownerDocument,!1,e,n),o=i.firstChild,1===i.childNodes.length&&(i=o),o||n)){for(a=oe.map(c(i,"script"),g),s=a.length;f")).appendTo(t.documentElement),t=$e[0].contentDocument,t.write(),t.close(),r=E(e,t),$e.detach()),Ke[e]=r),r}function O(e,t,r){var n,i,o,a,s=e.style;return r=r||Ye(e),a=r?r.getPropertyValue(t)||r[t]:void 0,""!==a&&void 0!==a||oe.contains(e.ownerDocument,e)||(a=oe.style(e,t)),r&&!ne.pixelMarginRight()&&Ge.test(a)&&Qe.test(t)&&(n=s.width,i=s.minWidth,o=s.maxWidth,s.minWidth=s.maxWidth=s.width=a,a=r.width,s.width=n,s.minWidth=i,s.maxWidth=o),void 0!==a?a+"":a}function T(e,t){return{get:function(){return e()?void delete this.get:(this.get=t).apply(this,arguments)}}}function N(e){if(e in nt)return e;for(var t=e[0].toUpperCase()+e.slice(1),r=rt.length;r--;)if(e=rt[r]+t,e in nt)return e}function S(e,t,r){var n=Ae.exec(t);return n?Math.max(0,n[2]-(r||0))+(n[3]||"px"):t}function A(e,t,r,n,i){for(var o=r===(n?"border":"content")?4:"width"===t?1:0,a=0;o<4;o+=2)"margin"===r&&(a+=oe.css(e,r+je[o],!0,i)),n?("content"===r&&(a-=oe.css(e,"padding"+je[o],!0,i)),"margin"!==r&&(a-=oe.css(e,"border"+je[o]+"Width",!0,i))):(a+=oe.css(e,"padding"+je[o],!0,i),"padding"!==r&&(a+=oe.css(e,"border"+je[o]+"Width",!0,i)));return a}function j(e,t,r){var n=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Ye(e),a="border-box"===oe.css(e,"boxSizing",!1,o);if(i<=0||null==i){if(i=O(e,t,o),(i<0||null==i)&&(i=e.style[t]),Ge.test(i))return i;n=a&&(ne.boxSizingReliable()||i===e.style[t]),i=parseFloat(i)||0}return i+A(e,t,r||(a?"border":"content"),n,o)+"px"}function P(e,t){for(var r,n,i,o=[],a=0,s=e.length;a=0&&r=0},isPlainObject:function(e){var t;if("object"!==oe.type(e)||e.nodeType||oe.isWindow(e))return!1;if(e.constructor&&!re.call(e,"constructor")&&!re.call(e.constructor.prototype||{},"isPrototypeOf"))return!1;for(t in e);return void 0===t||re.call(e,t)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?ee[te.call(e)]||"object":typeof e},globalEval:function(e){var t,r=eval;e=oe.trim(e),e&&(1===e.indexOf("use strict")?(t=G.createElement("script"),t.text=e,G.head.appendChild(t).parentNode.removeChild(t)):r(e))},camelCase:function(e){return e.replace(se,"ms-").replace(ue,le)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t){var n,i=0;if(r(e))for(n=e.length;ix.cacheLength&&delete e[t.shift()],e[r+" "]=n}var t=[];return e}function n(e){return e[H]=!0,e}function i(e){var t=P.createElement("div");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function o(e,t){for(var r=e.split("|"),n=r.length;n--;)x.attrHandle[r[n]]=t}function a(e,t){var r=t&&e,n=r&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||K)-(~e.sourceIndex||K);if(n)return n;if(r)for(;r=r.nextSibling;)if(r===t)return-1;return e?1:-1}function s(e){return function(t){var r=t.nodeName.toLowerCase();return"input"===r&&t.type===e}}function u(e){return function(t){var r=t.nodeName.toLowerCase();return("input"===r||"button"===r)&&t.type===e}}function l(e){return n(function(t){return t=+t,n(function(r,n){for(var i,o=e([],r.length,t),a=o.length;a--;)r[i=o[a]]&&(r[i]=!(n[i]=r[i]))})})}function c(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}function f(){}function d(e){for(var t=0,r=e.length,n="";t1?function(t,r,n){for(var i=e.length;i--;)if(!e[i](t,r,n))return!1;return!0}:e[0]}function m(e,r,n){for(var i=0,o=r.length;i-1&&(n[l]=!(a[l]=f))}}else y=v(y===a?y.splice(h,y.length):y),o?o(null,a,y,u):J.apply(a,y)})}function g(e){for(var t,r,n,i=e.length,o=x.relative[e[0].type],a=o||x.relative[" "],s=o?1:0,u=p(function(e){return e===t},a,!0),l=p(function(e){return ee(t,e)>-1},a,!0),c=[function(e,r,n){var i=!o&&(n||r!==N)||((t=r).nodeType?u(e,r,n):l(e,r,n));return t=null,i}];s1&&h(c),s>1&&d(e.slice(0,s-1).concat({value:" "===e[s-2].type?"*":""})).replace(se,"$1"),r,s0,o=e.length>0,a=function(n,a,s,u,l){var c,f,d,p=0,h="0",m=n&&[],b=[],g=N,y=n||o&&x.find.TAG("*",l),_=V+=null==g?1:Math.random()||.1,w=y.length;for(l&&(N=a===P||a||l);h!==w&&null!=(c=y[h]);h++){if(o&&c){for(f=0,a||c.ownerDocument===P||(j(c),s=!L);d=e[f++];)if(d(c,a||P,s)){u.push(c);break}l&&(V=_)}i&&((c=!d&&c)&&p--,n&&m.push(c))}if(p+=h,i&&h!==p){for(f=0;d=r[f++];)d(m,b,a,s);if(n){if(p>0)for(;h--;)m[h]||b[h]||(b[h]=Y.call(u));b=v(b)}J.apply(u,b),l&&!n&&b.length>0&&p+r.length>1&&t.uniqueSort(u)}return l&&(V=_,N=g),m};return i?n(a):a}var _,w,x,k,E,C,O,T,N,S,A,j,P,R,L,D,M,I,F,H="sizzle"+1*new Date,q=e.document,V=0,z=0,B=r(),U=r(),W=r(),$=function(e,t){return e===t&&(A=!0),0},K=1<<31,Q={}.hasOwnProperty,G=[],Y=G.pop,X=G.push,J=G.push,Z=G.slice,ee=function(e,t){for(var r=0,n=e.length;r+~]|"+re+")"+re+"*"),ce=new RegExp("="+re+"*([^\\]'\"]*?)"+re+"*\\]","g"),fe=new RegExp(oe),de=new RegExp("^"+ne+"$"),pe={ID:new RegExp("^#("+ne+")"),CLASS:new RegExp("^\\.("+ne+")"),TAG:new RegExp("^("+ne+"|[*])"),ATTR:new RegExp("^"+ie),PSEUDO:new RegExp("^"+oe),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+re+"*(even|odd|(([+-]|)(\\d*)n|)"+re+"*(?:([+-]|)"+re+"*(\\d+)|))"+re+"*\\)|)","i"),bool:new RegExp("^(?:"+te+")$","i"),needsContext:new RegExp("^"+re+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+re+"*((?:-\\d)?\\d*)"+re+"*\\)|)(?=[^-]|$)","i")},he=/^(?:input|select|textarea|button)$/i,me=/^h\d$/i,ve=/^[^{]+\{\s*\[native \w/,be=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ge=/[+~]/,ye=/'|\\/g,_e=new RegExp("\\\\([\\da-f]{1,6}"+re+"?|("+re+")|.)","ig"),we=function(e,t,r){var n="0x"+t-65536;return n!==n||r?t:n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320)},xe=function(){j()};try{J.apply(G=Z.call(q.childNodes),q.childNodes),G[q.childNodes.length].nodeType}catch(e){J={apply:G.length?function(e,t){X.apply(e,Z.call(t))}:function(e,t){for(var r=e.length,n=0;e[r++]=t[n++];);e.length=r-1}}}w=t.support={},E=t.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return!!t&&"HTML"!==t.nodeName},j=t.setDocument=function(e){var t,r,n=e?e.ownerDocument||e:q;return n!==P&&9===n.nodeType&&n.documentElement?(P=n,R=P.documentElement,L=!E(P),(r=P.defaultView)&&r.top!==r&&(r.addEventListener?r.addEventListener("unload",xe,!1):r.attachEvent&&r.attachEvent("onunload",xe)),w.attributes=i(function(e){return e.className="i",!e.getAttribute("className")}),w.getElementsByTagName=i(function(e){return e.appendChild(P.createComment("")),!e.getElementsByTagName("*").length}),w.getElementsByClassName=ve.test(P.getElementsByClassName),w.getById=i(function(e){return R.appendChild(e).id=H,!P.getElementsByName||!P.getElementsByName(H).length}),w.getById?(x.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&L){var r=t.getElementById(e);return r?[r]:[]}},x.filter.ID=function(e){var t=e.replace(_e,we);return function(e){return e.getAttribute("id")===t}}):(delete x.find.ID,x.filter.ID=function(e){var t=e.replace(_e,we);return function(e){var r="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return r&&r.value===t}}),x.find.TAG=w.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):w.qsa?t.querySelectorAll(e):void 0}:function(e,t){var r,n=[],i=0,o=t.getElementsByTagName(e);if("*"===e){for(;r=o[i++];)1===r.nodeType&&n.push(r);return n}return o},x.find.CLASS=w.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&L)return t.getElementsByClassName(e)},M=[],D=[],(w.qsa=ve.test(P.querySelectorAll))&&(i(function(e){R.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&D.push("[*^$]="+re+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||D.push("\\["+re+"*(?:value|"+te+")"),e.querySelectorAll("[id~="+H+"-]").length||D.push("~="),e.querySelectorAll(":checked").length||D.push(":checked"),e.querySelectorAll("a#"+H+"+*").length||D.push(".#.+[+~]")}),i(function(e){var t=P.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&D.push("name"+re+"*[*^$|!~]?="),e.querySelectorAll(":enabled").length||D.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),D.push(",.*:")})),(w.matchesSelector=ve.test(I=R.matches||R.webkitMatchesSelector||R.mozMatchesSelector||R.oMatchesSelector||R.msMatchesSelector))&&i(function(e){w.disconnectedMatch=I.call(e,"div"),I.call(e,"[s!='']:x"),M.push("!=",oe)}),D=D.length&&new RegExp(D.join("|")),M=M.length&&new RegExp(M.join("|")),t=ve.test(R.compareDocumentPosition),F=t||ve.test(R.contains)?function(e,t){var r=9===e.nodeType?e.documentElement:e,n=t&&t.parentNode;return e===n||!(!n||1!==n.nodeType||!(r.contains?r.contains(n):e.compareDocumentPosition&&16&e.compareDocumentPosition(n)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},$=t?function(e,t){if(e===t)return A=!0,0;var r=!e.compareDocumentPosition-!t.compareDocumentPosition;return r?r:(r=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1,1&r||!w.sortDetached&&t.compareDocumentPosition(e)===r?e===P||e.ownerDocument===q&&F(q,e)?-1:t===P||t.ownerDocument===q&&F(q,t)?1:S?ee(S,e)-ee(S,t):0:4&r?-1:1)}:function(e,t){if(e===t)return A=!0,0;var r,n=0,i=e.parentNode,o=t.parentNode,s=[e],u=[t];if(!i||!o)return e===P?-1:t===P?1:i?-1:o?1:S?ee(S,e)-ee(S,t):0;if(i===o)return a(e,t);for(r=e;r=r.parentNode;)s.unshift(r);for(r=t;r=r.parentNode;)u.unshift(r);for(;s[n]===u[n];)n++;return n?a(s[n],u[n]):s[n]===q?-1:u[n]===q?1:0},P):P},t.matches=function(e,r){return t(e,null,null,r)},t.matchesSelector=function(e,r){if((e.ownerDocument||e)!==P&&j(e),r=r.replace(ce,"='$1']"),w.matchesSelector&&L&&!W[r+" "]&&(!M||!M.test(r))&&(!D||!D.test(r)))try{var n=I.call(e,r);if(n||w.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){}return t(r,P,null,[e]).length>0},t.contains=function(e,t){return(e.ownerDocument||e)!==P&&j(e),F(e,t)},t.attr=function(e,t){(e.ownerDocument||e)!==P&&j(e);var r=x.attrHandle[t.toLowerCase()],n=r&&Q.call(x.attrHandle,t.toLowerCase())?r(e,t,!L):void 0;return void 0!==n?n:w.attributes||!L?e.getAttribute(t):(n=e.getAttributeNode(t))&&n.specified?n.value:null},t.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},t.uniqueSort=function(e){var t,r=[],n=0,i=0;if(A=!w.detectDuplicates,S=!w.sortStable&&e.slice(0),e.sort($),A){for(;t=e[i++];)t===e[i]&&(n=r.push(i));for(;n--;)e.splice(r[n],1)}return S=null,e},k=t.getText=function(e){var t,r="",n=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)r+=k(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[n++];)r+=k(t);return r},x=t.selectors={cacheLength:50,createPseudo:n,match:pe,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(_e,we), +e[3]=(e[3]||e[4]||e[5]||"").replace(_e,we),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||t.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&t.error(e[0]),e},PSEUDO:function(e){var t,r=!e[6]&&e[2];return pe.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":r&&fe.test(r)&&(t=C(r,!0))&&(t=r.indexOf(")",r.length-t)-r.length)&&(e[0]=e[0].slice(0,t),e[2]=r.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(_e,we).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=B[e+" "];return t||(t=new RegExp("(^|"+re+")"+e+"("+re+"|$)"))&&B(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(e,r,n){return function(i){var o=t.attr(i,e);return null==o?"!="===r:!r||(o+="","="===r?o===n:"!="===r?o!==n:"^="===r?n&&0===o.indexOf(n):"*="===r?n&&o.indexOf(n)>-1:"$="===r?n&&o.slice(-n.length)===n:"~="===r?(" "+o.replace(ae," ")+" ").indexOf(n)>-1:"|="===r&&(o===n||o.slice(0,n.length+1)===n+"-"))}},CHILD:function(e,t,r,n,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===n&&0===i?function(e){return!!e.parentNode}:function(t,r,u){var l,c,f,d,p,h,m=o!==a?"nextSibling":"previousSibling",v=t.parentNode,b=s&&t.nodeName.toLowerCase(),g=!u&&!s,y=!1;if(v){if(o){for(;m;){for(d=t;d=d[m];)if(s?d.nodeName.toLowerCase()===b:1===d.nodeType)return!1;h=m="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?v.firstChild:v.lastChild],a&&g){for(d=v,f=d[H]||(d[H]={}),c=f[d.uniqueID]||(f[d.uniqueID]={}),l=c[e]||[],p=l[0]===V&&l[1],y=p&&l[2],d=p&&v.childNodes[p];d=++p&&d&&d[m]||(y=p=0)||h.pop();)if(1===d.nodeType&&++y&&d===t){c[e]=[V,p,y];break}}else if(g&&(d=t,f=d[H]||(d[H]={}),c=f[d.uniqueID]||(f[d.uniqueID]={}),l=c[e]||[],p=l[0]===V&&l[1],y=p),y===!1)for(;(d=++p&&d&&d[m]||(y=p=0)||h.pop())&&((s?d.nodeName.toLowerCase()!==b:1!==d.nodeType)||!++y||(g&&(f=d[H]||(d[H]={}),c=f[d.uniqueID]||(f[d.uniqueID]={}),c[e]=[V,y]),d!==t)););return y-=i,y===n||y%n===0&&y/n>=0}}},PSEUDO:function(e,r){var i,o=x.pseudos[e]||x.setFilters[e.toLowerCase()]||t.error("unsupported pseudo: "+e);return o[H]?o(r):o.length>1?(i=[e,e,"",r],x.setFilters.hasOwnProperty(e.toLowerCase())?n(function(e,t){for(var n,i=o(e,r),a=i.length;a--;)n=ee(e,i[a]),e[n]=!(t[n]=i[a])}):function(e){return o(e,0,i)}):o}},pseudos:{not:n(function(e){var t=[],r=[],i=O(e.replace(se,"$1"));return i[H]?n(function(e,t,r,n){for(var o,a=i(e,null,n,[]),s=e.length;s--;)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,n,o){return t[0]=e,i(t,null,o,r),t[0]=null,!r.pop()}}),has:n(function(e){return function(r){return t(e,r).length>0}}),contains:n(function(e){return e=e.replace(_e,we),function(t){return(t.textContent||t.innerText||k(t)).indexOf(e)>-1}}),lang:n(function(e){return de.test(e||"")||t.error("unsupported lang: "+e),e=e.replace(_e,we).toLowerCase(),function(t){var r;do if(r=L?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return r=r.toLowerCase(),r===e||0===r.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var r=e.location&&e.location.hash;return r&&r.slice(1)===t.id},root:function(e){return e===R},focus:function(e){return e===P.activeElement&&(!P.hasFocus||P.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!x.pseudos.empty(e)},header:function(e){return me.test(e.nodeName)},input:function(e){return he.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:l(function(){return[0]}),last:l(function(e,t){return[t-1]}),eq:l(function(e,t,r){return[r<0?r+t:r]}),even:l(function(e,t){for(var r=0;r=0;)e.push(n);return e}),gt:l(function(e,t,r){for(var n=r<0?r+t:r;++n2&&"ID"===(a=o[0]).type&&w.getById&&9===t.nodeType&&L&&x.relative[o[1].type]){if(t=(x.find.ID(a.matches[0].replace(_e,we),t)||[])[0],!t)return r;l&&(t=t.parentNode),e=e.slice(o.shift().value.length)}for(i=pe.needsContext.test(e)?0:o.length;i--&&(a=o[i],!x.relative[s=a.type]);)if((u=x.find[s])&&(n=u(a.matches[0].replace(_e,we),ge.test(o[0].type)&&c(t.parentNode)||t))){if(o.splice(i,1),e=n.length&&d(o),!e)return J.apply(r,n),r;break}}return(l||O(e,f))(n,t,!L,r,!t||ge.test(e)&&c(t.parentNode)||t),r},w.sortStable=H.split("").sort($).join("")===H,w.detectDuplicates=!!A,j(),w.sortDetached=i(function(e){return 1&e.compareDocumentPosition(P.createElement("div"))}),i(function(e){return e.innerHTML="","#"===e.firstChild.getAttribute("href")})||o("type|href|height|width",function(e,t,r){if(!r)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),w.attributes&&i(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||o("value",function(e,t,r){if(!r&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),i(function(e){return null==e.getAttribute("disabled")})||o(te,function(e,t,r){var n;if(!r)return e[t]===!0?t.toLowerCase():(n=e.getAttributeNode(t))&&n.specified?n.value:null}),t}(e);oe.find=ce,oe.expr=ce.selectors,oe.expr[":"]=oe.expr.pseudos,oe.uniqueSort=oe.unique=ce.uniqueSort,oe.text=ce.getText,oe.isXMLDoc=ce.isXML,oe.contains=ce.contains;var fe=function(e,t,r){for(var n=[],i=void 0!==r;(e=e[t])&&9!==e.nodeType;)if(1===e.nodeType){if(i&&oe(e).is(r))break;n.push(e)}return n},de=function(e,t){for(var r=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&r.push(e);return r},pe=oe.expr.match.needsContext,he=/^<([\w-]+)\s*\/?>(?:<\/\1>|)$/,me=/^.[^:#\[\.,]*$/;oe.filter=function(e,t,r){var n=t[0];return r&&(e=":not("+e+")"),1===t.length&&1===n.nodeType?oe.find.matchesSelector(n,e)?[n]:[]:oe.find.matches(e,oe.grep(t,function(e){return 1===e.nodeType}))},oe.fn.extend({find:function(e){var t,r=this.length,n=[],i=this;if("string"!=typeof e)return this.pushStack(oe(e).filter(function(){for(t=0;t1?oe.unique(n):n),n.selector=this.selector?this.selector+" "+e:e,n},filter:function(e){return this.pushStack(n(this,e||[],!1))},not:function(e){return this.pushStack(n(this,e||[],!0))},is:function(e){return!!n(this,"string"==typeof e&&pe.test(e)?oe(e):e||[],!1).length}});var ve,be=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,ge=oe.fn.init=function(e,t,r){var n,i;if(!e)return this;if(r=r||ve,"string"==typeof e){if(n="<"===e[0]&&">"===e[e.length-1]&&e.length>=3?[null,e,null]:be.exec(e),!n||!n[1]&&t)return!t||t.jquery?(t||r).find(e):this.constructor(t).find(e);if(n[1]){if(t=t instanceof oe?t[0]:t,oe.merge(this,oe.parseHTML(n[1],t&&t.nodeType?t.ownerDocument||t:G,!0)),he.test(n[1])&&oe.isPlainObject(t))for(n in t)oe.isFunction(this[n])?this[n](t[n]):this.attr(n,t[n]);return this}return i=G.getElementById(n[2]),i&&i.parentNode&&(this.length=1,this[0]=i),this.context=G,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):oe.isFunction(e)?void 0!==r.ready?r.ready(e):e(oe):(void 0!==e.selector&&(this.selector=e.selector,this.context=e.context),oe.makeArray(e,this))};ge.prototype=oe.fn,ve=oe(G);var ye=/^(?:parents|prev(?:Until|All))/,_e={children:!0,contents:!0,next:!0,prev:!0};oe.fn.extend({has:function(e){var t=oe(e,this),r=t.length;return this.filter(function(){for(var e=0;e-1:1===r.nodeType&&oe.find.matchesSelector(r,e))){o.push(r);break}return this.pushStack(o.length>1?oe.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?Z.call(oe(e),this[0]):Z.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(oe.uniqueSort(oe.merge(this.get(),oe(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),oe.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return fe(e,"parentNode")},parentsUntil:function(e,t,r){return fe(e,"parentNode",r)},next:function(e){return i(e,"nextSibling")},prev:function(e){return i(e,"previousSibling")},nextAll:function(e){return fe(e,"nextSibling")},prevAll:function(e){return fe(e,"previousSibling")},nextUntil:function(e,t,r){return fe(e,"nextSibling",r)},prevUntil:function(e,t,r){return fe(e,"previousSibling",r)},siblings:function(e){return de((e.parentNode||{}).firstChild,e)},children:function(e){return de(e.firstChild)},contents:function(e){return e.contentDocument||oe.merge([],e.childNodes)}},function(e,t){oe.fn[e]=function(r,n){var i=oe.map(this,t,r);return"Until"!==e.slice(-5)&&(n=r),n&&"string"==typeof n&&(i=oe.filter(n,i)),this.length>1&&(_e[e]||oe.uniqueSort(i),ye.test(e)&&i.reverse()),this.pushStack(i)}});var we=/\S+/g;oe.Callbacks=function(e){e="string"==typeof e?o(e):oe.extend({},e);var t,r,n,i,a=[],s=[],u=-1,l=function(){for(i=e.once,n=t=!0;s.length;u=-1)for(r=s.shift();++u-1;)a.splice(r,1),r<=u&&u--}),this},has:function(e){return e?oe.inArray(e,a)>-1:a.length>0},empty:function(){return a&&(a=[]),this},disable:function(){return i=s=[],a=r="",this},disabled:function(){return!a},lock:function(){return i=s=[],r||(a=r=""),this},locked:function(){return!!i},fireWith:function(e,r){return i||(r=r||[],r=[e,r.slice?r.slice():r],s.push(r),t||l()),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!n}};return c},oe.extend({Deferred:function(e){var t=[["resolve","done",oe.Callbacks("once memory"),"resolved"],["reject","fail",oe.Callbacks("once memory"),"rejected"],["notify","progress",oe.Callbacks("memory")]],r="pending",n={state:function(){return r},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return oe.Deferred(function(r){oe.each(t,function(t,o){var a=oe.isFunction(e[t])&&e[t];i[o[1]](function(){var e=a&&a.apply(this,arguments);e&&oe.isFunction(e.promise)?e.promise().progress(r.notify).done(r.resolve).fail(r.reject):r[o[0]+"With"](this===n?r.promise():this,a?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?oe.extend(e,n):n}},i={};return n.pipe=n.then,oe.each(t,function(e,o){var a=o[2],s=o[3];n[o[1]]=a.add,s&&a.add(function(){r=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?n:this,arguments),this},i[o[0]+"With"]=a.fireWith}),n.promise(i),e&&e.call(i,i),i},when:function(e){var t,r,n,i=0,o=Y.call(arguments),a=o.length,s=1!==a||e&&oe.isFunction(e.promise)?a:0,u=1===s?e:oe.Deferred(),l=function(e,r,n){return function(i){r[e]=this,n[e]=arguments.length>1?Y.call(arguments):i,n===t?u.notifyWith(r,n):--s||u.resolveWith(r,n)}};if(a>1)for(t=new Array(a),r=new Array(a),n=new Array(a);i0||(xe.resolveWith(G,[oe]),oe.fn.triggerHandler&&(oe(G).triggerHandler("ready"),oe(G).off("ready"))))}}),oe.ready.promise=function(t){return xe||(xe=oe.Deferred(),"complete"===G.readyState||"loading"!==G.readyState&&!G.documentElement.doScroll?e.setTimeout(oe.ready):(G.addEventListener("DOMContentLoaded",a),e.addEventListener("load",a))),xe.promise(t)},oe.ready.promise();var ke=function(e,t,r,n,i,o,a){var s=0,u=e.length,l=null==r;if("object"===oe.type(r)){i=!0;for(s in r)ke(e,t,s,r[s],!0,o,a)}else if(void 0!==n&&(i=!0,oe.isFunction(n)||(a=!0),l&&(a?(t.call(e,n),t=null):(l=t,t=function(e,t,r){return l.call(oe(e),r)})),t))for(;s-1&&void 0!==r&&Oe.set(this,e,t)})},null,t,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){Oe.remove(this,e)})}}),oe.extend({queue:function(e,t,r){var n;if(e)return t=(t||"fx")+"queue",n=Ce.get(e,t),r&&(!n||oe.isArray(r)?n=Ce.access(e,t,oe.makeArray(r)):n.push(r)),n||[]},dequeue:function(e,t){t=t||"fx";var r=oe.queue(e,t),n=r.length,i=r.shift(),o=oe._queueHooks(e,t),a=function(){oe.dequeue(e,t)};"inprogress"===i&&(i=r.shift(),n--),i&&("fx"===t&&r.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!n&&o&&o.empty.fire()},_queueHooks:function(e,t){var r=t+"queueHooks";return Ce.get(e,r)||Ce.access(e,r,{empty:oe.Callbacks("once memory").add(function(){Ce.remove(e,[t+"queue",r])})})}}),oe.fn.extend({queue:function(e,t){var r=2;return"string"!=typeof e&&(t=e,e="fx",r--),arguments.length",""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};Me.optgroup=Me.option,Me.tbody=Me.tfoot=Me.colgroup=Me.caption=Me.thead,Me.th=Me.td;var Ie=/<|&#?\w+;/;!function(){var e=G.createDocumentFragment(),t=e.appendChild(G.createElement("div")),r=G.createElement("input");r.setAttribute("type","radio"),r.setAttribute("checked","checked"),r.setAttribute("name","t"),t.appendChild(r),ne.checkClone=t.cloneNode(!0).cloneNode(!0).lastChild.checked,t.innerHTML="",ne.noCloneChecked=!!t.cloneNode(!0).lastChild.defaultValue}();var Fe=/^key/,He=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,qe=/^([^.]*)(?:\.(.+)|)/;oe.event={global:{},add:function(e,t,r,n,i){var o,a,s,u,l,c,f,d,p,h,m,v=Ce.get(e);if(v)for(r.handler&&(o=r,r=o.handler,i=o.selector),r.guid||(r.guid=oe.guid++),(u=v.events)||(u=v.events={}),(a=v.handle)||(a=v.handle=function(t){return"undefined"!=typeof oe&&oe.event.triggered!==t.type?oe.event.dispatch.apply(e,arguments):void 0}),t=(t||"").match(we)||[""],l=t.length;l--;)s=qe.exec(t[l])||[],p=m=s[1],h=(s[2]||"").split(".").sort(),p&&(f=oe.event.special[p]||{},p=(i?f.delegateType:f.bindType)||p,f=oe.event.special[p]||{},c=oe.extend({type:p,origType:m,data:n,handler:r,guid:r.guid,selector:i,needsContext:i&&oe.expr.match.needsContext.test(i),namespace:h.join(".")},o),(d=u[p])||(d=u[p]=[],d.delegateCount=0,f.setup&&f.setup.call(e,n,h,a)!==!1||e.addEventListener&&e.addEventListener(p,a)),f.add&&(f.add.call(e,c),c.handler.guid||(c.handler.guid=r.guid)),i?d.splice(d.delegateCount++,0,c):d.push(c),oe.event.global[p]=!0)},remove:function(e,t,r,n,i){var o,a,s,u,l,c,f,d,p,h,m,v=Ce.hasData(e)&&Ce.get(e);if(v&&(u=v.events)){for(t=(t||"").match(we)||[""],l=t.length;l--;)if(s=qe.exec(t[l])||[],p=m=s[1],h=(s[2]||"").split(".").sort(),p){for(f=oe.event.special[p]||{},p=(n?f.delegateType:f.bindType)||p,d=u[p]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=d.length;o--;)c=d[o],!i&&m!==c.origType||r&&r.guid!==c.guid||s&&!s.test(c.namespace)||n&&n!==c.selector&&("**"!==n||!c.selector)||(d.splice(o,1),c.selector&&d.delegateCount--,f.remove&&f.remove.call(e,c));a&&!d.length&&(f.teardown&&f.teardown.call(e,h,v.handle)!==!1||oe.removeEvent(e,p,v.handle),delete u[p])}else for(p in u)oe.event.remove(e,p+t[l],r,n,!0);oe.isEmptyObject(u)&&Ce.remove(e,"handle events")}},dispatch:function(e){e=oe.event.fix(e);var t,r,n,i,o,a=[],s=Y.call(arguments),u=(Ce.get(this,"events")||{})[e.type]||[],l=oe.event.special[e.type]||{};if(s[0]=e,e.delegateTarget=this,!l.preDispatch||l.preDispatch.call(this,e)!==!1){for(a=oe.event.handlers.call(this,e,u),t=0;(i=a[t++])&&!e.isPropagationStopped();)for(e.currentTarget=i.elem,r=0;(o=i.handlers[r++])&&!e.isImmediatePropagationStopped();)e.rnamespace&&!e.rnamespace.test(o.namespace)||(e.handleObj=o,e.data=o.data,n=((oe.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,s),void 0!==n&&(e.result=n)===!1&&(e.preventDefault(),e.stopPropagation()));return l.postDispatch&&l.postDispatch.call(this,e),e.result}},handlers:function(e,t){var r,n,i,o,a=[],s=t.delegateCount,u=e.target;if(s&&u.nodeType&&("click"!==e.type||isNaN(e.button)||e.button<1))for(;u!==this;u=u.parentNode||this)if(1===u.nodeType&&(u.disabled!==!0||"click"!==e.type)){for(n=[],r=0;r-1:oe.find(i,this,null,[u]).length),n[i]&&n.push(o);n.length&&a.push({elem:u,handlers:n})}return s]*)\/>/gi,ze=/\s*$/g;oe.extend({htmlPrefilter:function(e){return e.replace(Ve,"<$1>")},clone:function(e,t,r){var n,i,o,a,s=e.cloneNode(!0),u=oe.contains(e.ownerDocument,e);if(!(ne.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||oe.isXMLDoc(e)))for(a=c(s),o=c(e),n=0,i=o.length;n0&&f(a,!u&&c(e,"script")),s},cleanData:function(e){for(var t,r,n,i=oe.event.special,o=0;void 0!==(r=e[o]);o++)if(Ee(r)){if(t=r[Ce.expando]){if(t.events)for(n in t.events)i[n]?oe.event.remove(r,n):oe.removeEvent(r,n,t.handle);r[Ce.expando]=void 0}r[Oe.expando]&&(r[Oe.expando]=void 0)}}}),oe.fn.extend({domManip:x,detach:function(e){return k(this,e,!0)},remove:function(e){return k(this,e)},text:function(e){return ke(this,function(e){return void 0===e?oe.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return x(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=b(this,e);t.appendChild(e)}})},prepend:function(){return x(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=b(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return x(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return x(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(oe.cleanData(c(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return oe.clone(this,e,t)})},html:function(e){return ke(this,function(e){var t=this[0]||{},r=0,n=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!ze.test(e)&&!Me[(Le.exec(e)||["",""])[1].toLowerCase()]){e=oe.htmlPrefilter(e);try{for(;r1)},show:function(){return P(this,!0)},hide:function(){return P(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){Pe(this)?oe(this).show():oe(this).hide()})}}),oe.Tween=R,R.prototype={constructor:R,init:function(e,t,r,n,i,o){this.elem=e,this.prop=r,this.easing=i||oe.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=n,this.unit=o||(oe.cssNumber[r]?"":"px")},cur:function(){var e=R.propHooks[this.prop];return e&&e.get?e.get(this):R.propHooks._default.get(this)},run:function(e){var t,r=R.propHooks[this.prop];return this.options.duration?this.pos=t=oe.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),r&&r.set?r.set(this):R.propHooks._default.set(this),this}},R.prototype.init.prototype=R.prototype,R.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=oe.css(e.elem,e.prop,""),t&&"auto"!==t?t:0)},set:function(e){oe.fx.step[e.prop]?oe.fx.step[e.prop](e):1!==e.elem.nodeType||null==e.elem.style[oe.cssProps[e.prop]]&&!oe.cssHooks[e.prop]?e.elem[e.prop]=e.now:oe.style(e.elem,e.prop,e.now+e.unit)}}},R.propHooks.scrollTop=R.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},oe.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},oe.fx=R.prototype.init,oe.fx.step={};var it,ot,at=/^(?:toggle|show|hide)$/,st=/queueHooks$/;oe.Animation=oe.extend(H,{tweeners:{"*":[function(e,t){var r=this.createTween(e,t);return l(r.elem,e,Ae.exec(t),r),r}]},tweener:function(e,t){oe.isFunction(e)?(t=e,e=["*"]):e=e.match(we);for(var r,n=0,i=e.length;n1)},removeAttr:function(e){return this.each(function(){oe.removeAttr(this,e)})}}),oe.extend({attr:function(e,t,r){var n,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return"undefined"==typeof e.getAttribute?oe.prop(e,t,r):(1===o&&oe.isXMLDoc(e)||(t=t.toLowerCase(),i=oe.attrHooks[t]||(oe.expr.match.bool.test(t)?ut:void 0)),void 0!==r?null===r?void oe.removeAttr(e,t):i&&"set"in i&&void 0!==(n=i.set(e,r,t))?n:(e.setAttribute(t,r+""),r):i&&"get"in i&&null!==(n=i.get(e,t))?n:(n=oe.find.attr(e,t),null==n?void 0:n))},attrHooks:{type:{set:function(e,t){if(!ne.radioValue&&"radio"===t&&oe.nodeName(e,"input")){var r=e.value;return e.setAttribute("type",t),r&&(e.value=r),t}}}},removeAttr:function(e,t){var r,n,i=0,o=t&&t.match(we);if(o&&1===e.nodeType)for(;r=o[i++];)n=oe.propFix[r]||r,oe.expr.match.bool.test(r)&&(e[n]=!1),e.removeAttribute(r)}}),ut={set:function(e,t,r){return t===!1?oe.removeAttr(e,r):e.setAttribute(r,r),r}},oe.each(oe.expr.match.bool.source.match(/\w+/g),function(e,t){var r=lt[t]||oe.find.attr;lt[t]=function(e,t,n){var i,o;return n||(o=lt[t],lt[t]=i,i=null!=r(e,t,n)?t.toLowerCase():null,lt[t]=o),i}});var ct=/^(?:input|select|textarea|button)$/i,ft=/^(?:a|area)$/i;oe.fn.extend({prop:function(e,t){return ke(this,oe.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[oe.propFix[e]||e]})}}),oe.extend({prop:function(e,t,r){var n,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&oe.isXMLDoc(e)||(t=oe.propFix[t]||t,i=oe.propHooks[t]),void 0!==r?i&&"set"in i&&void 0!==(n=i.set(e,r,t))?n:e[t]=r:i&&"get"in i&&null!==(n=i.get(e,t))?n:e[t]},propHooks:{tabIndex:{get:function(e){var t=oe.find.attr(e,"tabindex");return t?parseInt(t,10):ct.test(e.nodeName)||ft.test(e.nodeName)&&e.href?0:-1}}},propFix:{for:"htmlFor",class:"className"}}),ne.optSelected||(oe.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),oe.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){oe.propFix[this.toLowerCase()]=this});var dt=/[\t\r\n\f]/g;oe.fn.extend({addClass:function(e){var t,r,n,i,o,a,s,u=0;if(oe.isFunction(e))return this.each(function(t){oe(this).addClass(e.call(this,t,q(this)))});if("string"==typeof e&&e)for(t=e.match(we)||[];r=this[u++];)if(i=q(r),n=1===r.nodeType&&(" "+i+" ").replace(dt," ")){for(a=0;o=t[a++];)n.indexOf(" "+o+" ")<0&&(n+=o+" ");s=oe.trim(n),i!==s&&r.setAttribute("class",s)}return this},removeClass:function(e){var t,r,n,i,o,a,s,u=0;if(oe.isFunction(e))return this.each(function(t){oe(this).removeClass(e.call(this,t,q(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof e&&e)for(t=e.match(we)||[];r=this[u++];)if(i=q(r),n=1===r.nodeType&&(" "+i+" ").replace(dt," ")){for(a=0;o=t[a++];)for(;n.indexOf(" "+o+" ")>-1;)n=n.replace(" "+o+" "," ");s=oe.trim(n),i!==s&&r.setAttribute("class",s)}return this},toggleClass:function(e,t){var r=typeof e;return"boolean"==typeof t&&"string"===r?t?this.addClass(e):this.removeClass(e):oe.isFunction(e)?this.each(function(r){oe(this).toggleClass(e.call(this,r,q(this),t),t)}):this.each(function(){var t,n,i,o;if("string"===r)for(n=0,i=oe(this),o=e.match(we)||[];t=o[n++];)i.hasClass(t)?i.removeClass(t):i.addClass(t);else void 0!==e&&"boolean"!==r||(t=q(this),t&&Ce.set(this,"__className__",t),this.setAttribute&&this.setAttribute("class",t||e===!1?"":Ce.get(this,"__className__")||""))})},hasClass:function(e){var t,r,n=0;for(t=" "+e+" ";r=this[n++];)if(1===r.nodeType&&(" "+q(r)+" ").replace(dt," ").indexOf(t)>-1)return!0;return!1}});var pt=/\r/g,ht=/[\x20\t\r\n\f]+/g;oe.fn.extend({val:function(e){var t,r,n,i=this[0];{if(arguments.length)return n=oe.isFunction(e),this.each(function(r){var i;1===this.nodeType&&(i=n?e.call(this,r,oe(this).val()):e,null==i?i="":"number"==typeof i?i+="":oe.isArray(i)&&(i=oe.map(i,function(e){return null==e?"":e+""})),t=oe.valHooks[this.type]||oe.valHooks[this.nodeName.toLowerCase()],t&&"set"in t&&void 0!==t.set(this,i,"value")||(this.value=i))});if(i)return t=oe.valHooks[i.type]||oe.valHooks[i.nodeName.toLowerCase()],t&&"get"in t&&void 0!==(r=t.get(i,"value"))?r:(r=i.value,"string"==typeof r?r.replace(pt,""):null==r?"":r)}}}),oe.extend({valHooks:{option:{get:function(e){var t=oe.find.attr(e,"value");return null!=t?t:oe.trim(oe.text(e)).replace(ht," ")}},select:{get:function(e){for(var t,r,n=e.options,i=e.selectedIndex,o="select-one"===e.type||i<0,a=o?null:[],s=o?i+1:n.length,u=i<0?s:o?i:0;u-1)&&(r=!0);return r||(e.selectedIndex=-1),o}}}}),oe.each(["radio","checkbox"],function(){oe.valHooks[this]={set:function(e,t){if(oe.isArray(t))return e.checked=oe.inArray(oe(e).val(),t)>-1}},ne.checkOn||(oe.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var mt=/^(?:focusinfocus|focusoutblur)$/;oe.extend(oe.event,{trigger:function(t,r,n,i){var o,a,s,u,l,c,f,d=[n||G],p=re.call(t,"type")?t.type:t,h=re.call(t,"namespace")?t.namespace.split("."):[];if(a=s=n=n||G,3!==n.nodeType&&8!==n.nodeType&&!mt.test(p+oe.event.triggered)&&(p.indexOf(".")>-1&&(h=p.split("."),p=h.shift(),h.sort()),l=p.indexOf(":")<0&&"on"+p,t=t[oe.expando]?t:new oe.Event(p,"object"==typeof t&&t),t.isTrigger=i?2:3,t.namespace=h.join("."),t.rnamespace=t.namespace?new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=void 0,t.target||(t.target=n),r=null==r?[t]:oe.makeArray(r,[t]),f=oe.event.special[p]||{},i||!f.trigger||f.trigger.apply(n,r)!==!1)){if(!i&&!f.noBubble&&!oe.isWindow(n)){for(u=f.delegateType||p,mt.test(u+p)||(a=a.parentNode);a;a=a.parentNode)d.push(a),s=a;s===(n.ownerDocument||G)&&d.push(s.defaultView||s.parentWindow||e)}for(o=0;(a=d[o++])&&!t.isPropagationStopped();)t.type=o>1?u:f.bindType||p,c=(Ce.get(a,"events")||{})[t.type]&&Ce.get(a,"handle"),c&&c.apply(a,r),c=l&&a[l],c&&c.apply&&Ee(a)&&(t.result=c.apply(a,r),t.result===!1&&t.preventDefault());return t.type=p,i||t.isDefaultPrevented()||f._default&&f._default.apply(d.pop(),r)!==!1||!Ee(n)||l&&oe.isFunction(n[p])&&!oe.isWindow(n)&&(s=n[l],s&&(n[l]=null),oe.event.triggered=p,n[p](),oe.event.triggered=void 0,s&&(n[l]=s)),t.result}},simulate:function(e,t,r){var n=oe.extend(new oe.Event,r,{type:e,isSimulated:!0});oe.event.trigger(n,null,t)}}),oe.fn.extend({trigger:function(e,t){return this.each(function(){oe.event.trigger(e,t,this)})},triggerHandler:function(e,t){var r=this[0];if(r)return oe.event.trigger(e,t,r,!0)}}),oe.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(e,t){oe.fn[t]=function(e,r){return arguments.length>0?this.on(t,null,e,r):this.trigger(t)}}),oe.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),ne.focusin="onfocusin"in e,ne.focusin||oe.each({focus:"focusin",blur:"focusout"},function(e,t){var r=function(e){oe.event.simulate(t,e.target,oe.event.fix(e))};oe.event.special[t]={setup:function(){var n=this.ownerDocument||this,i=Ce.access(n,t);i||n.addEventListener(e,r,!0),Ce.access(n,t,(i||0)+1)},teardown:function(){var n=this.ownerDocument||this,i=Ce.access(n,t)-1;i?Ce.access(n,t,i):(n.removeEventListener(e,r,!0),Ce.remove(n,t))}}});var vt=e.location,bt=oe.now(),gt=/\?/;oe.parseJSON=function(e){return JSON.parse(e+"")},oe.parseXML=function(t){var r;if(!t||"string"!=typeof t)return null;try{r=(new e.DOMParser).parseFromString(t,"text/xml")}catch(e){r=void 0}return r&&!r.getElementsByTagName("parsererror").length||oe.error("Invalid XML: "+t),r};var yt=/#.*$/,_t=/([?&])_=[^&]*/,wt=/^(.*?):[ \t]*([^\r\n]*)$/gm,xt=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,kt=/^(?:GET|HEAD)$/,Et=/^\/\//,Ct={},Ot={},Tt="*/".concat("*"),Nt=G.createElement("a");Nt.href=vt.href,oe.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:vt.href,type:"GET",isLocal:xt.test(vt.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Tt,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":oe.parseJSON,"text xml":oe.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?B(B(e,oe.ajaxSettings),t):B(oe.ajaxSettings,e)},ajaxPrefilter:V(Ct),ajaxTransport:V(Ot),ajax:function(t,r){function n(t,r,n,s){var l,f,g,y,w,k=r;2!==_&&(_=2,u&&e.clearTimeout(u),i=void 0,a=s||"",x.readyState=t>0?4:0,l=t>=200&&t<300||304===t,n&&(y=U(d,x,n)),y=W(d,y,x,l),l?(d.ifModified&&(w=x.getResponseHeader("Last-Modified"),w&&(oe.lastModified[o]=w),w=x.getResponseHeader("etag"),w&&(oe.etag[o]=w)),204===t||"HEAD"===d.type?k="nocontent":304===t?k="notmodified":(k=y.state,f=y.data,g=y.error,l=!g)):(g=k,!t&&k||(k="error",t<0&&(t=0))),x.status=t,x.statusText=(r||k)+"",l?m.resolveWith(p,[f,k,x]):m.rejectWith(p,[x,k,g]),x.statusCode(b),b=void 0,c&&h.trigger(l?"ajaxSuccess":"ajaxError",[x,d,l?f:g]),v.fireWith(p,[x,k]),c&&(h.trigger("ajaxComplete",[x,d]),--oe.active||oe.event.trigger("ajaxStop")))}"object"==typeof t&&(r=t,t=void 0),r=r||{};var i,o,a,s,u,l,c,f,d=oe.ajaxSetup({},r),p=d.context||d,h=d.context&&(p.nodeType||p.jquery)?oe(p):oe.event,m=oe.Deferred(),v=oe.Callbacks("once memory"),b=d.statusCode||{},g={},y={},_=0,w="canceled",x={readyState:0,getResponseHeader:function(e){var t;if(2===_){if(!s)for(s={};t=wt.exec(a);)s[t[1].toLowerCase()]=t[2];t=s[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===_?a:null},setRequestHeader:function(e,t){var r=e.toLowerCase();return _||(e=y[r]=y[r]||e,g[e]=t),this},overrideMimeType:function(e){return _||(d.mimeType=e),this},statusCode:function(e){var t;if(e)if(_<2)for(t in e)b[t]=[b[t],e[t]];else x.always(e[x.status]);return this},abort:function(e){var t=e||w;return i&&i.abort(t),n(0,t),this}};if(m.promise(x).complete=v.add,x.success=x.done,x.error=x.fail,d.url=((t||d.url||vt.href)+"").replace(yt,"").replace(Et,vt.protocol+"//"),d.type=r.method||r.type||d.method||d.type,d.dataTypes=oe.trim(d.dataType||"*").toLowerCase().match(we)||[""],null==d.crossDomain){l=G.createElement("a");try{l.href=d.url,l.href=l.href,d.crossDomain=Nt.protocol+"//"+Nt.host!=l.protocol+"//"+l.host}catch(e){d.crossDomain=!0}}if(d.data&&d.processData&&"string"!=typeof d.data&&(d.data=oe.param(d.data,d.traditional)),z(Ct,d,r,x),2===_)return x;c=oe.event&&d.global,c&&0===oe.active++&&oe.event.trigger("ajaxStart"),d.type=d.type.toUpperCase(),d.hasContent=!kt.test(d.type),o=d.url,d.hasContent||(d.data&&(o=d.url+=(gt.test(o)?"&":"?")+d.data,delete d.data),d.cache===!1&&(d.url=_t.test(o)?o.replace(_t,"$1_="+bt++):o+(gt.test(o)?"&":"?")+"_="+bt++)),d.ifModified&&(oe.lastModified[o]&&x.setRequestHeader("If-Modified-Since",oe.lastModified[o]),oe.etag[o]&&x.setRequestHeader("If-None-Match",oe.etag[o])),(d.data&&d.hasContent&&d.contentType!==!1||r.contentType)&&x.setRequestHeader("Content-Type",d.contentType),x.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+("*"!==d.dataTypes[0]?", "+Tt+"; q=0.01":""):d.accepts["*"]);for(f in d.headers)x.setRequestHeader(f,d.headers[f]);if(d.beforeSend&&(d.beforeSend.call(p,x,d)===!1||2===_))return x.abort();w="abort";for(f in{success:1,error:1,complete:1})x[f](d[f]);if(i=z(Ot,d,r,x)){if(x.readyState=1,c&&h.trigger("ajaxSend",[x,d]),2===_)return x;d.async&&d.timeout>0&&(u=e.setTimeout(function(){x.abort("timeout")},d.timeout));try{_=1,i.send(g,n)}catch(e){if(!(_<2))throw e;n(-1,e)}}else n(-1,"No Transport");return x},getJSON:function(e,t,r){return oe.get(e,t,r,"json")},getScript:function(e,t){return oe.get(e,void 0,t,"script")}}),oe.each(["get","post"],function(e,t){oe[t]=function(e,r,n,i){return oe.isFunction(r)&&(i=i||n,n=r,r=void 0),oe.ajax(oe.extend({url:e,type:t,dataType:i,data:r,success:n},oe.isPlainObject(e)&&e))}}),oe._evalUrl=function(e){return oe.ajax({url:e,type:"GET",dataType:"script",async:!1,global:!1,throws:!0})},oe.fn.extend({wrapAll:function(e){var t;return oe.isFunction(e)?this.each(function(t){oe(this).wrapAll(e.call(this,t))}):(this[0]&&(t=oe(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){for(var e=this;e.firstElementChild;)e=e.firstElementChild;return e}).append(this)),this)},wrapInner:function(e){return oe.isFunction(e)?this.each(function(t){oe(this).wrapInner(e.call(this,t))}):this.each(function(){var t=oe(this),r=t.contents();r.length?r.wrapAll(e):t.append(e)})},wrap:function(e){var t=oe.isFunction(e);return this.each(function(r){oe(this).wrapAll(t?e.call(this,r):e)})},unwrap:function(){return this.parent().each(function(){oe.nodeName(this,"body")||oe(this).replaceWith(this.childNodes)}).end()}}),oe.expr.filters.hidden=function(e){return!oe.expr.filters.visible(e)},oe.expr.filters.visible=function(e){return e.offsetWidth>0||e.offsetHeight>0||e.getClientRects().length>0};var St=/%20/g,At=/\[\]$/,jt=/\r?\n/g,Pt=/^(?:submit|button|image|reset|file)$/i,Rt=/^(?:input|select|textarea|keygen)/i;oe.param=function(e,t){var r,n=[],i=function(e,t){t=oe.isFunction(t)?t():null==t?"":t,n[n.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};if(void 0===t&&(t=oe.ajaxSettings&&oe.ajaxSettings.traditional),oe.isArray(e)||e.jquery&&!oe.isPlainObject(e))oe.each(e,function(){i(this.name,this.value)});else for(r in e)$(r,e[r],t,i);return n.join("&").replace(St,"+")},oe.fn.extend({serialize:function(){return oe.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=oe.prop(this,"elements");return e?oe.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!oe(this).is(":disabled")&&Rt.test(this.nodeName)&&!Pt.test(e)&&(this.checked||!Re.test(e))}).map(function(e,t){var r=oe(this).val();return null==r?null:oe.isArray(r)?oe.map(r,function(e){return{name:t.name,value:e.replace(jt,"\r\n")}}):{name:t.name,value:r.replace(jt,"\r\n")}}).get()}}),oe.ajaxSettings.xhr=function(){try{return new e.XMLHttpRequest}catch(e){}};var Lt={0:200,1223:204},Dt=oe.ajaxSettings.xhr();ne.cors=!!Dt&&"withCredentials"in Dt,ne.ajax=Dt=!!Dt,oe.ajaxTransport(function(t){var r,n;if(ne.cors||Dt&&!t.crossDomain)return{send:function(i,o){var a,s=t.xhr();if(s.open(t.type,t.url,t.async,t.username,t.password),t.xhrFields)for(a in t.xhrFields)s[a]=t.xhrFields[a];t.mimeType&&s.overrideMimeType&&s.overrideMimeType(t.mimeType),t.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");for(a in i)s.setRequestHeader(a,i[a]);r=function(e){return function(){r&&(r=n=s.onload=s.onerror=s.onabort=s.onreadystatechange=null,"abort"===e?s.abort():"error"===e?"number"!=typeof s.status?o(0,"error"):o(s.status,s.statusText):o(Lt[s.status]||s.status,s.statusText,"text"!==(s.responseType||"text")||"string"!=typeof s.responseText?{binary:s.response}:{text:s.responseText},s.getAllResponseHeaders()))}},s.onload=r(),n=s.onerror=r("error"),void 0!==s.onabort?s.onabort=n:s.onreadystatechange=function(){4===s.readyState&&e.setTimeout(function(){r&&n()})},r=r("abort");try{s.send(t.hasContent&&t.data||null)}catch(e){if(r)throw e}},abort:function(){r&&r()}}}),oe.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return oe.globalEval(e),e}}}),oe.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),oe.ajaxTransport("script",function(e){if(e.crossDomain){var t,r;return{send:function(n,i){t=oe("",""===t.firstChild.innerHTML}(s),c=s&&function(e){var t=e.createElement("div");return t.innerHTML="Test: Value","Test:"===t.childNodes[0].nodeValue&&" Value"===t.childNodes[2].nodeValue}(s),f=s&&function(e){var t,r,n=e.createElement("table");try{n.innerHTML=""}catch(e){}finally{r=0===n.childNodes.length}r&&(t={colgroup:["table"],table:[],tbody:["table"],tfoot:["table"],thead:["table"],tr:["table","tbody"]});var i=e.createElement("select");return i.innerHTML="",i.childNodes[0]||(t=t||{},t.select=[]),t}(s);a=l?function(e,r,i){return e=n(e,r),r=i.cloneNode(r,!1),t(r,e),r.childNodes}:function(e,t,r){return e=n(e,t),t=r.cloneNode(t,!1),t.innerHTML=e,t.childNodes};var d;d=f||c?function(e,t,n){var i=[],o=[];"string"==typeof e&&(e=e.replace(/(\s*)()(\s*)/g,function(e,t,r){return o.push(r),t}));var s;s=f[t.tagName.toLowerCase()]?r(e,t):a(e,t,n);var u,l,c,d,p=[];for(u=0;u0&&(m=n.document.createTextNode(v),h.parentNode.insertBefore(m,h)),b=o[u],b&&b.length>0&&(m=n.document.createTextNode(b),h.parentNode.insertBefore(m,h.nextSibling));return s}:a;var p;u?e.buildHTMLDOM=p=function(e,t,r){return i[t.tagName]?d(e,document.createElement("div"),r):d(e,t,r)}:e.buildHTMLDOM=p=d,e.buildHTMLDOM=p}),e("dom-helper/classes",["exports"],function(e){"use strict";function t(e){var t=e.getAttribute("class")||"";return""!==t&&" "!==t?t.split(" "):[]}function r(e,t){for(var r=0,n=e.length,i=0,o=t.length,a=new Array(o);r0?i.join(" "):"")}function i(e,n){for(var i=t(e),o=r(n,i),a=!1,s=[],u=0,l=i.length;u0?s.join(" "):"")}var o,a,s="undefined"!=typeof document&&document,u=s&&function(){var e=document.createElement("div");return!!e.classList&&(e.classList.add("boo"),e.classList.add("boo","baz"),"boo baz"===e.className)}();u?(e.addClasses=o=function(e,t){e.classList?1===t.length?e.classList.add(t[0]):2===t.length?e.classList.add(t[0],t[1]):e.classList.add.apply(e.classList,t):n(e,t)},e.removeClasses=a=function(e,t){e.classList?1===t.length?e.classList.remove(t[0]):2===t.length?e.classList.remove(t[0],t[1]):e.classList.remove.apply(e.classList,t):i(e,t)}):(e.addClasses=o=n,e.removeClasses=a=i),e.addClasses=o,e.removeClasses=a}),e("dom-helper/prop",["exports"],function(e){"use strict";function t(e){return null===e||void 0===e}function r(e,t){var r,i;if(t in e)i=t,r="prop";else{var o=t.toLowerCase();o in e?(r="prop",i=o):(r="attr",i=t)}return"prop"!==r||"style"!==i.toLowerCase()&&!n(e.tagName,i)||(r="attr"),{normalized:i,type:r}}function n(e,t){var r=i[e.toUpperCase()];return r&&r[t.toLowerCase()]||!1}e.isAttrRemovalValue=t,e.normalizeProperty=r;var i={BUTTON:{type:!0,form:!0},INPUT:{list:!0,type:!0,form:!0,autocorrect:!0},SELECT:{form:!0},OPTION:{form:!0},TEXTAREA:{form:!0},LABEL:{form:!0},FIELDSET:{form:!0},LEGEND:{form:!0},OBJECT:{form:!0}}}),e("ember-application/index",["exports","ember-metal/core","ember-metal/features","ember-runtime/system/lazy_load","ember-application/system/resolver","ember-application/system/application","ember-application/system/application-instance","ember-application/system/engine","ember-application/system/engine-instance"],function(e,t,r,n,i,o,a,s,u){"use strict";t.default.Application=o.default,t.default.Resolver=i.Resolver,t.default.DefaultResolver=i.default,n.runLoadHooks("Ember.Application",o.default)}),e("ember-application/system/application-instance",["exports","ember-metal/debug","ember-metal/property_get","ember-metal/property_set","ember-metal/symbol","ember-metal/run_loop","ember-metal/computed","ember-runtime/mixins/registry_proxy","ember-metal/assign","ember-metal/environment","ember-runtime/ext/rsvp","ember-views/system/jquery","ember-application/system/engine-instance"],function(e,t,r,n,i,o,a,s,u,l,c,f,d){"use strict";var p=i.default("INTERNAL_BOOT_OPTIONS");e.INTERNAL_BOOT_OPTIONS=p;var h=void 0,m=d.default.extend({application:null,customEvents:null,rootElement:null,init:function(){this._super.apply(this,arguments),this.register("-application-instance:main",this,{instantiate:!1}),this._booted=!1},boot:function(){var e=this,t=arguments.length<=0||void 0===arguments[0]?{}:arguments[0];return this._bootPromise?this._bootPromise:(this._bootPromise=new c.default.Promise(function(r){return r(e._bootSync(t))}),this._bootPromise)},_bootSync:function(e){if(this._booted)return this;e=new h(e);var t=this.__registry__;if(t.register("-environment:main",e.toEnvironment(),{instantiate:!1}),t.injection("view","_environment","-environment:main"),t.injection("route","_environment","-environment:main"),t.register("service:-document",e.document,{ +instantiate:!1}),e.isInteractive?(t.injection("view","renderer","renderer:-dom"),t.injection("component","renderer","renderer:-dom")):(t.injection("view","renderer","renderer:-inert"),t.injection("component","renderer","renderer:-inert")),e.rootElement?this.rootElement=e.rootElement:this.rootElement=this.application.rootElement,e.location){var i=r.get(this,"router");n.set(i,"location",e.location)}return this.application.runInstanceInitializers(this),e.isInteractive&&this.setupEventDispatcher(),this._booted=!0,this},router:a.computed(function(){return this.lookup("router:main")}).readOnly(),didCreateRootView:function(e){e.appendTo(this.rootElement)},startRouting:function(){var e=r.get(this,"router");e.startRouting(),this._didSetupRouter=!0},setupRouter:function(){if(!this._didSetupRouter){this._didSetupRouter=!0;var e=r.get(this,"router");e.setupRouter()}},handleURL:function(e){var t=r.get(this,"router");return this.setupRouter(),t.handleURL(e)},setupEventDispatcher:function(){var e=this.lookup("event_dispatcher:main"),t=r.get(this.application,"customEvents"),n=r.get(this,"customEvents"),i=u.default({},t,n);return e.setup(i,this.rootElement),e},getURL:function(){var e=r.get(this,"router");return r.get(e,"url")},visit:function(e){var t=this;this.setupRouter();var n=r.get(this,"router"),i=function(){return new c.default.Promise(function(e){o.default.next(null,e,t)})},a=function(e){if(e.error)throw e.error;if("TransitionAborted"===e.name&&n.router.activeTransition)return n.router.activeTransition.then(i,a);throw"TransitionAborted"===e.name?new Error(e.message):e},s=r.get(n,"location");return s.setURL(e),n.handleURL(s.getURL()).then(i,a)}});h=function(){var e=arguments.length<=0||void 0===arguments[0]?{}:arguments[0];this.jQuery=f.default,this.isInteractive=l.default.hasDOM,void 0!==e.isBrowser?this.isBrowser=!!e.isBrowser:this.isBrowser=l.default.hasDOM,this.isBrowser||(this.jQuery=null,this.isInteractive=!1,this.location="none"),void 0!==e.shouldRender?this.shouldRender=!!e.shouldRender:this.shouldRender=!0,this.shouldRender||(this.jQuery=null,this.isInteractive=!1),e.document?this.document=e.document:this.document="undefined"!=typeof document?document:null,e.rootElement&&(this.rootElement=e.rootElement),void 0!==e.location&&(this.location=e.location),void 0!==e.jQuery&&(this.jQuery=e.jQuery),void 0!==e.isInteractive&&(this.isInteractive=!!e.isInteractive)},h.prototype.toEnvironment=function(){var e=u.default({},l.default);return e.hasDOM=this.isBrowser,e.options=this,e},Object.defineProperty(m.prototype,"container",{configurable:!0,enumerable:!1,get:function(){var e=this;return{lookup:function(){return e.lookup.apply(e,arguments)}}}}),Object.defineProperty(m.prototype,"registry",{configurable:!0,enumerable:!1,get:function(){return s.buildFakeRegistryWithDeprecations(this,"ApplicationInstance")}}),e.default=m}),e("ember-application/system/application",["exports","ember-metal","ember-metal/debug","ember-metal/property_get","ember-runtime/system/lazy_load","ember-metal/run_loop","ember-runtime/controllers/controller","ember-htmlbars/system/dom-helper","ember-metal-views","ember-htmlbars/templates/top-level-view","ember-routing-views/views/outlet","ember-views/views/view","ember-views/system/event_dispatcher","ember-views/system/jquery","ember-routing/system/route","ember-routing/system/router","ember-routing/location/hash_location","ember-routing/location/history_location","ember-routing/location/auto_location","ember-routing/location/none_location","ember-routing/system/cache","ember-application/system/application-instance","ember-views/views/text_field","ember-views/views/text_area","ember-views/views/checkbox","ember-routing-views/components/link-to","ember-routing/services/routing","ember-extension-support/container_debug_adapter","ember-runtime/mixins/registry_proxy","container/registry","ember-metal/environment","ember-runtime/ext/rsvp","ember-application/system/engine","require"],function(e,t,r,n,i,o,a,s,u,l,c,f,d,p,h,m,v,b,g,y,_,w,x,k,E,C,O,T,N,S,A,j,P,R){"use strict";function L(e,t){return e.raw=t,e}function D(){U=!1,W=!1}function M(e){e.optionsForType("component",{singleton:!1}),e.optionsForType("view",{singleton:!1}),e.injection("renderer","dom","service:-dom-helper"),e.register("controller:basic",a.default,{instantiate:!1}),e.injection("service:-dom-helper","document","service:-document"),e.register("-view-registry:main",{create:function(){return{}}}),e.injection("view","_viewRegistry","-view-registry:main"),e.injection("route","_topLevelViewTemplate","template:-outlet"),e.register("route:basic",h.default),e.register("event_dispatcher:main",d.default),e.injection("router:main","namespace","application:main"),e.injection("view:-outlet","namespace","application:main"),e.register("location:auto",g.default),e.register("location:hash",v.default),e.register("location:history",b.default),e.register("location:none",y.default),e.injection("controller","target","router:main"),e.injection("controller","namespace","application:main"),e.register(S.privatize(V),_.default),e.injection("router","_bucketCache",S.privatize(V)),e.injection("route","_bucketCache",S.privatize(V)),e.injection("controller","_bucketCache",S.privatize(V)),e.injection("route","router","router:main"),e.register("component:-text-field",x.default),e.register("component:-text-area",k.default),e.register("component:-checkbox",E.default),e.register("component:link-to",C.default),e.register("service:-routing",O.default),e.injection("service:-routing","router","router:main"),e.register("resolver-for-debugging:main",e.resolver,{instantiate:!1}),e.injection("container-debug-adapter:main","resolver","resolver-for-debugging:main"),e.injection("data-adapter:main","containerDebugAdapter","container-debug-adapter:main"),e.register("container-debug-adapter:main",T.default)}function I(e){M(e);var t=R.default("ember-glimmer/environment").default;e.register("service:-glimmer-environment",t),e.injection("service:-glimmer-environment","dom","service:-dom-helper"),e.injection("renderer","env","service:-glimmer-environment");var r=R.default("ember-glimmer/ember-routing-view").OutletView;e.register("view:-outlet",r);var n=R.default("ember-glimmer/ember-metal-views"),i=n.InteractiveRenderer,o=n.InertRenderer;e.register("renderer:-dom",i),e.register("renderer:-inert",o);var a=R.default("ember-glimmer/dom").default;e.register("service:-dom-helper",{create:function(e){var t=e.document;return new a(t)}});var s=R.default("ember-glimmer/templates/outlet").default,u=R.default("ember-glimmer/templates/component").default;e.register(S.privatize(z),u),e.register("template:-outlet",s),e.injection("view:-outlet","template","template:-outlet"),e.injection("template","env","service:-glimmer-environment"),e.optionsForType("helper",{instantiate:!1})}function F(e){M(e),e.optionsForType("template",{instantiate:!1}),e.register("view:-outlet",c.OutletView);var t=u.InteractiveRenderer,r=u.InertRenderer;e.register("renderer:-dom",t),e.register("renderer:-inert",r),e.register("service:-dom-helper",{create:function(e){var t=e.document;return new s.default(t)}}),e.register("template:-outlet",l.default),e.register("view:toplevel",f.default.extend())}function H(){B||(B=!0,A.default.hasDOM&&t.default.libraries.registerCoreLibrary("jQuery",p.default().jquery))}function q(){if(t.default.LOG_VERSION){t.default.LOG_VERSION=!1;for(var e=t.default.libraries._registry,r=e.map(function(e){return n.get(e,"name.length")}),i=Math.max.apply(this,r),o=0,a=e.length;o-1&&(i=i.replace(/\.(.)/g,function(e){return e.charAt(1).toUpperCase()})),n.indexOf("_")>-1&&(i=i.replace(/_(.)/g,function(e){return e.charAt(1).toUpperCase()})),n.indexOf("-")>-1&&(i=i.replace(/-(.)/g,function(e){return e.charAt(1).toUpperCase()})),r+":"+i}return e},resolve:function(e){var t,r=this.parseName(e),n=r.resolveMethodName;return this[n]&&(t=this[n](r)),t=t||this.resolveOther(r),r.root&&r.root.LOG_RESOLVER&&this._logLookup(t,r),t&&s.default(t,r),t},parseName:function(e){return this._parseNameCache[e]||(this._parseNameCache[e]=this._parseName(e))},_parseName:function(e){var t=e.split(":"),i=t[0],a=t[1],s=a,u=r.get(this,"namespace"),l=u,c=s.lastIndexOf("/"),f=c!==-1?s.slice(0,c):null;if("template"!==i&&c!==-1){var d=s.split("/");s=d[d.length-1];var p=n.capitalize(d.slice(0,-1).join("."));l=o.default.byName(p)}var h="main"===a?"Main":n.classify(i);if(!s||!i)throw new TypeError("Invalid fullName: `"+e+"`, must be of the form `type:name` ");return{fullName:e,type:i,fullNameWithoutType:a,dirname:f,name:s,root:l,resolveMethodName:"resolve"+h}},lookupDescription:function(e){var t,r=this.parseName(e);return"template"===r.type?"template at "+r.fullNameWithoutType.replace(/\./g,"/"):(t=r.root+"."+n.classify(r.name).replace(/\./g,""),"model"!==r.type&&(t+=n.classify(r.type)),t)},makeToString:function(e,t){return e.toString()},useRouterNaming:function(e){e.name=e.name.replace(/\./g,"_"),"basic"===e.name&&(e.name="")},resolveTemplate:function(e){var t=e.fullNameWithoutType.replace(/\./g,"/");return l.get(t)||l.get(n.decamelize(t))},resolveView:function(e){return this.useRouterNaming(e),this.resolveOther(e)},resolveController:function(e){return this.useRouterNaming(e),this.resolveOther(e)},resolveRoute:function(e){return this.useRouterNaming(e),this.resolveOther(e)},resolveModel:function(e){var t=n.classify(e.name),i=r.get(e.root,t);if(i)return i},resolveHelper:function(e){return this.resolveOther(e)||a.default[e.fullNameWithoutType]},resolveOther:function(e){var t=n.classify(e.name)+n.classify(e.type),i=r.get(e.root,t);if(i)return i},resolveMain:function(e){var t=n.classify(e.type);return r.get(e.root,t)},_logLookup:function(e,t){var r,n;r=e?"[✓]":"[ ]",n=t.fullName.length>60?".":new Array(60-t.fullName.length).join(".")},knownForType:function(e){for(var t=r.get(this,"namespace"),i=n.classify(e),o=new RegExp(i+"$"),a=u.default(null),s=Object.keys(t),l=0,c=s.length;l$/)})}),e("ember-htmlbars/hooks/concat",["exports","ember-metal/streams/utils"],function(e,t){"use strict";function r(e,r){return t.concat(r,"")}e.default=r}),e("ember-htmlbars/hooks/create-fresh-scope",["exports","ember-metal/streams/proxy-stream","ember-metal/empty_object"],function(e,t,r){"use strict";function n(e){this._self=void 0,this._blocks=void 0,this._component=void 0,this._view=void 0,this._attrs=void 0,this._locals=void 0,this._localPresent=void 0,this.overrideController=void 0,this.parent=e}function i(){return new n(s)}function o(e){return new n(e)}e.default=i,e.createChildScope=o;var a=n.prototype;a.getSelf=function(){return this._self||this.parent.getSelf()},a.bindSelf=function(e){this._self=e},a.updateSelf=function(e,r){var n=this._self;n?n.setSource(e):this._self=new t.default(e,r)},a.getBlock=function(e){return this._blocks?this._blocks[e]||this.parent.getBlock(e):this.parent.getBlock(e)},a.hasBlock=function(e){return this._blocks?!(!this._blocks[e]&&!this.parent.hasBlock(e)):this.parent.hasBlock(e)},a.bindBlock=function(e,t){this._blocks||(this._blocks=new r.default),this._blocks[e]=t},a.getComponent=function(){return this._component||this.parent.getComponent()},a.bindComponent=function(e){this._component=e},a.getView=function(){return this._view||this.parent.getView()},a.bindView=function(e){this._view=e},a.getAttrs=function(){return this._attrs||this.parent.getAttrs()},a.bindAttrs=function(e){this._attrs=e},a.hasLocal=function(e){return this._localPresent?this._localPresent[e]||this.parent.hasLocal(e):this.parent.hasLocal(e)},a.hasOwnLocal=function(e){return this._localPresent&&this._localPresent[e]},a.getLocal=function(e){return this._localPresent&&this._localPresent[e]?this._locals[e]:this.parent.getLocal(e)},a.bindLocal=function(e,t){this._localPresent||(this._localPresent=new r.default,this._locals=new r.default),this._localPresent[e]=!0,this._locals[e]=t};var s={_self:void 0,_blocks:void 0,_component:void 0,_view:void 0,_attrs:void 0,_locals:void 0,_localPresent:void 0,overrideController:void 0,getSelf:function(){return null},bindSelf:function(e){return null},updateSelf:function(e,t){return null},getBlock:function(e){return null},bindBlock:function(e,t){return null},hasBlock:function(e){return!1},getComponent:function(){return null},bindComponent:function(){return null},getView:function(){return null},bindView:function(e){return null},getAttrs:function(){return null},bindAttrs:function(e){return null},hasLocal:function(e){return!1},hasOwnLocal:function(e){return!1},getLocal:function(e){return null},bindLocal:function(e,t){return null}}}),e("ember-htmlbars/hooks/destroy-render-node",["exports"],function(e){"use strict";function t(e){e.emberView&&e.emberView.destroy();var t=e.streamUnsubscribers;if(t)for(var r=0,n=t.length;r0&&t(a):"boolean"==typeof u?!!u&&t(a):t(a)},"ShouldDisplay");return n.addDependency(a,i),n.addDependency(a,o),a}function c(e){return!!e}function f(e){return e}function d(e,t){return n.isStream(e)?e.getKey(t):e&&e[t]}e.default=a,e.linkParamsFor=s}),e("ember-htmlbars/hooks/lookup-helper",["exports","ember-htmlbars/system/lookup-helper"],function(e,t){"use strict";function r(e,r,n){return t.default(n,r.getSelf(),e)}e.default=r}),e("ember-htmlbars/hooks/subexpr",["exports","ember-htmlbars/system/lookup-helper","ember-htmlbars/system/invoke-helper","ember-metal/streams/utils","ember-htmlbars/hooks/link-render-node"],function(e,t,r,n,i){"use strict";function o(e,n,o,s,u){var l=e.hooks.keywords[o];if(l)return l(null,e,n,s,u,null,null);i.linkParamsFor(o,s);for(var c=a(s,u,o),f=t.default(o,n.getSelf(),e),d=r.buildHelperStream(f,s,u,null,e,n,c),p=0,h=s.length;p1?r-1:0),i=1;i1?t-1:0),n=1;n("+this._from+" -> "+this._to+")"+e},connect:function(e){var r=void 0,n=void 0;if(c.isGlobalPath(this._from)){var i=c.getFirstKey(this._from),s=t.default.lookup[i];s&&(r=s,n=c.getTailPath(this._from))}return void 0===r&&(r=e,n=this._from),a.trySet(e,this._to,o.get(r,n)),l.addObserver(r,n,this,"fromDidChange"),this._oneWay||l.addObserver(e,this._to,this,"toDidChange"),u.addListener(e,"willDestroy",this,"disconnect"),this._readyToSync=!0,this._fromObj=r,this._fromPath=n,this._toObj=e,this},disconnect:function(){return l.removeObserver(this._fromObj,this._fromPath,this,"fromDidChange"),this._oneWay||l.removeObserver(this._toObj,this._to,this,"toDidChange"),this._readyToSync=!1,this},fromDidChange:function(e){this._scheduleSync("fwd")},toDidChange:function(e){this._scheduleSync("back")},_scheduleSync:function(e){var t=this._direction;void 0===t&&(n.default.schedule("sync",this,"_sync"),this._direction=e),"back"===t&&"fwd"===e&&(this._direction="fwd")},_sync:function(){var e=t.default.LOG_BINDINGS,n=this._toObj;if(!n.isDestroyed&&this._readyToSync){var i=this._direction,s=this._fromObj,u=this._fromPath;if(this._direction=void 0,"fwd"===i){var c=o.get(s,u);e&&r.default.log(" ",this.toString(),"->",c,s),this._oneWay?a.trySet(n,this._to,c):l._suspendObserver(n,this._to,this,"toDidChange",function(){a.trySet(n,this._to,c)})}else if("back"===i){var f=o.get(n,this._to);e&&r.default.log(" ",this.toString(),"<-",f,n),l._suspendObserver(s,u,this,"fromDidChange",function(){a.trySet(s,u,f)})}}}},d(f,{from:function(e){var t=this;return new t(void 0,e)},to:function(e){var t=this;return new t(e,void 0)}}),e.Binding=f}),e("ember-metal/cache",["exports","ember-metal/empty_object"],function(e,t){"use strict";function r(e,r){this.store=new t.default,this.size=0,this.misses=0,this.hits=0,this.limit=e,this.func=r}e.default=r;var n=function(){};r.prototype={set:function(e,t){return this.limit>this.size&&(this.size++,void 0===t?this.store[e]=n:this.store[e]=t),t},get:function(e){var t=this.store[e];return void 0===t?(this.misses++,t=this.set(e,this.func(e))):t===n?(this.hits++,t=void 0):this.hits++,t},purge:function(){this.store=new t.default,this.size=0,this.hits=0,this.misses=0}}}),e("ember-metal/chains",["exports","ember-metal/property_get","ember-metal/meta","ember-metal/watch_key","ember-metal/empty_object"],function(e,t,r,n,i){"use strict";function o(e){return e.match(m)[0]}function a(e){return e&&"object"==typeof e}function s(e){return!(a(e)&&e.isDescriptor&&e._volatile===!1)}function u(){this.chains=new i.default}function l(){return new u}function c(e,t,i){if(a(e)){var o=r.meta(e);o.writableChainWatchers(l).add(t,i),n.watchKey(e,t,o)}}function f(e,t,i){if(a(e)){var o=r.peekMeta(e);o&&o.readableChainWatchers()&&(o=r.meta(e),o.readableChainWatchers().remove(t,i),n.unwatchKey(e,t,o))}}function d(e,t,r){this._parent=e,this._key=t,this._watching=void 0===r,this._chains=void 0,this._object=void 0,this.count=0,this._value=r,this._paths={},this._watching&&(this._object=e.value(),this._object&&c(this._object,this._key,this))}function p(e,n){if(e){var i=r.peekMeta(e);if(!i||i.proto!==e){if(s(e[n]))return t.get(e,n);var o=i.readableCache();return o&&n in o?o[n]:void 0}}}function h(e){var t=r.peekMeta(e);if(t){t=r.meta(e);var n=t.readableChainWatchers();n&&n.revalidateAll(),t.readableChains()&&t.writableChains()}}e.finishChains=h;var m=/^([^\.]+)/;u.prototype={add:function(e,t){var r=this.chains[e];void 0===r?this.chains[e]=[t]:r.push(t)},remove:function(e,t){var r=this.chains[e];if(r)for(var n=0,i=r.length;n0&&t[e]--;var r=o(e),n=e.slice(r.length+1);this.unchain(r,n)},chain:function(e,t){var r,n=this._chains;void 0===n?n=this._chains=new i.default:r=n[e],void 0===r&&(r=n[e]=new d(this,e,void 0)),r.count++,t&&(e=o(t),t=t.slice(e.length+1),r.chain(e,t))},unchain:function(e,t){var r=this._chains,n=r[e];if(t&&t.length>1){var i=o(t),a=t.slice(i.length+1);n.unchain(i,a)}n.count--,n.count<=0&&(r[n._key]=void 0,n.destroy())},notify:function(e,t){if(e&&this._watching){var r=this._parent.value();r!==this._object&&(f(this._object,this._key,this),this._object=r,c(r,this._key,this)),this._value=void 0}var n,i=this._chains;if(i)for(var o in i)n=i[o],void 0!==n&&n.notify(e,t);t&&this._parent&&this._parent.populateAffected(this._key,1,t)},populateAffected:function(e,t,r){this._key&&(e=this._key+"."+e),this._parent?this._parent.populateAffected(e,t+1,r):t>1&&r.push(this.value(),e)}},e.removeChainWatcher=f,e.ChainNode=d}),e("ember-metal/computed",["exports","ember-metal/debug","ember-metal/property_set","ember-metal/utils","ember-metal/meta","ember-metal/expand_properties","ember-metal/error","ember-metal/properties","ember-metal/property_events","ember-metal/dependent_keys"],function(e,t,r,n,i,o,a,s,u,l){"use strict";function c(){}function f(e,t){this.isDescriptor=!0,"function"==typeof e?this._getter=e:(this._getter=e.get,this._setter=e.set),this._dependentKeys=void 0,this._suspended=void 0,this._meta=void 0,this._volatile=!1,this._dependentKeys=t&&t.dependentKeys,this._readOnly=!1}function d(e){var t;arguments.length>1&&(t=[].slice.call(arguments),e=t.pop());var r=new f(e);return t&&r.property.apply(r,t),r}function p(e,t){var r=i.peekMeta(e),n=r&&r.source===e&&r.readableCache(),o=n&&n[t];if(o!==c)return o}e.default=d;f.prototype=new s.Descriptor;var h=f.prototype;h.volatile=function(){return this._volatile=!0,this},h.readOnly=function(){return this._readOnly=!0,this},h.property=function(){var e,t=function(t){e.push(t)};e=[];for(var r=0,n=arguments.length;rt})}function y(e,t){return i.computed(e,function(){return r.get(this,e)>=t})}function _(e,t){return i.computed(e,function(){return r.get(this,e)=0;i-=3)if(t===e[i]&&r===e[i+1]){n=i;break}return n}function a(e,t,r){var i=n.peekMeta(e);if(i){for(var a=i.matchingListeners(t),s=[],u=a.length-3;u>=0;u-=3){var l=a[u],c=a[u+1],f=a[u+2],d=o(r,l,c);d===-1&&(r.push(l,c,f),s.push(l,c,f))}return s}}function s(e,t,r,o,a){o||"function"!=typeof r||(o=r,r=null);var s=0;a&&(s|=i.ONCE),n.meta(e).addToListeners(t,r,o,s),"function"==typeof e.didAddListener&&e.didAddListener(t,r,o)}function u(e,t,r,i){i||"function"!=typeof r||(i=r,r=null),n.meta(e).removeFromListeners(t,r,i,function(){"function"==typeof e.didRemoveListener&&e.didRemoveListener.apply(e,arguments)})}function l(e,t,r,n,i){return c(e,[t],r,n,i)}function c(e,t,r,i,o){return i||"function"!=typeof r||(i=r,r=null),n.meta(e).suspendListeners(t,r,i,o)}function f(e){return n.meta(e).watchedEvents()}function d(e,t,o,a){if(!a){var s=n.peekMeta(e);a=s&&s.matchingListeners(t)}if(a&&0!==a.length){for(var l=a.length-3;l>=0;l-=3){var c=a[l],f=a[l+1],d=a[l+2];f&&(d&i.SUSPENDED||(d&i.ONCE&&u(e,t,c,f),c||(c=e),"string"==typeof f?o?r.applyStr(c,f,o):c[f]():o?f.apply(c,o):f.call(c)))}return!0}}function p(e,t){var r=n.peekMeta(e);return!!r&&r.matchingListeners(t).length>0}function h(e,t){var r=[],i=n.peekMeta(e),o=i&&i.matchingListeners(t);if(!o)return r;for(var a=0,s=o.length;a=0&&(a=n(a,u.split(","),s))}for(var s=0;s-1&&o.splice(a,1),this.size=o.length,!0}return!1},isEmpty:function(){return 0===this.size},has:function(e){if(0===this.size)return!1;var t=r.guidFor(e),n=this.presenceSet;return n[t]===!0},forEach:function(e){if("function"!=typeof e&&i(e),0!==this.size){var t,r=this.list,n=arguments.length;if(2===n)for(t=0;t=0;a-=4)if(o[a]===e&&(!r||o[a+1]===t&&o[a+2]===r)){if(i!==this)return this._finalizeListeners(),this.removeFromListeners(e,t,r);"function"==typeof n&&n(e,t,o[a+2]),o.splice(a,4)}if(i._listenersFinalized)break;i=i.parent}},matchingListeners:function(e){for(var r=this,i=[];r;){var o=r._listeners;if(o)for(var a=0;a=0;o-=3)i[o+1]===t&&i[o+2]===r&&e.indexOf(i[o])!==-1&&i.splice(o,3)}},watchedEvents:function(){for(var e=this,t={};e;){var r=e._listeners;if(r)for(var n=0;n=0||"concatenatedProperties"===t||"mergedProperties"===t?r=k(e,t,r,o):s&&s.indexOf(t)>=0?r=E(e,t,r,o):g(r)&&(r=x(e,t,r,o,i)),i[t]=void 0,o[t]=r}function O(e,t,r,n,i,o){function a(e){delete r[e],delete n[e]}for(var s,u,c,f,d,p,h=0,m=e.length;h1?t-1:0),n=1;n0){for(var n=new Array(r),i=0;i=0;)if(I(i[o],t,r))return!0;return!1}function F(e,t,r){if(!r[u.guidFor(t)])if(r[u.guidFor(t)]=!0,t.properties)for(var n=Object.keys(t.properties),i=0;i0,l&&l.teardown(e,t),r instanceof o?(f=r,e[t]=f,r.setup&&r.setup(e,t)):null==r?(f=a,e[t]=a):(f=r,Object.defineProperty(e,t,r)),c&&i.overrideChains(e,t,s),e.didDefineProperty&&e.didDefineProperty(e,t,f),this}e.Descriptor=o,e.MANDATORY_SETTER_FUNCTION=a,e.DEFAULT_GETTER_FUNCTION=s,e.INHERITING_GETTER_FUNCTION=u,e.defineProperty=l;(function(){var e=Object.create(Object.prototype,{prop:{configurable:!0,value:1}});return Object.defineProperty(e,"prop",{configurable:!0,value:2}),2===e.prop})()}),e("ember-metal/property_events",["exports","ember-metal/utils","ember-metal/meta","ember-metal/events","ember-metal/observer_set","ember-metal/symbol"],function(e,t,r,n,i,o){"use strict";function a(e,t){var n=r.peekMeta(e),i=n&&n.peekWatching(t)>0||"length"===t,o=n&&n.proto,a=e[t],s=null!==a&&"object"==typeof a&&a.isDescriptor?a:void 0;i&&o!==e&&(s&&s.willChange&&s.willChange(e,t),u(e,t,n),f(e,t,n),b(e,t))}function s(e,t){var n=r.peekMeta(e),i=n&&n.peekWatching(t)>0||"length"===t,o=n&&n.proto,a=e[t],s=null!==a&&"object"==typeof a&&a.isDescriptor?a:void 0;o!==e&&(s&&s.didChange&&s.didChange(e,t),e[y]&&e[y](t),(i||"length"===t)&&(n&&n.hasDeps(t)&&l(e,t,n),d(e,t,n,!1),g(e,t)))}function u(e,t,r){if(!e.isDestroying&&r&&r.hasDeps(t)){var n=_,i=!n;i&&(n=_={}),c(a,e,t,n,r),i&&(_=null)}}function l(e,t,r){if(!e.isDestroying&&r&&r.hasDeps(t)){var n=w,i=!n;i&&(n=w={}),c(s,e,t,n,r),i&&(w=null)}}function c(e,r,n,i,o){var a,s,u=t.guidFor(r),l=i[u];l||(l=i[u]={}),l[n]||(l[n]=!0,o.forEachInDeps(n,function(t,n){n&&(a=r[t],s=null!==a&&"object"==typeof a&&a.isDescriptor?a:void 0,s&&s._suspended===r||e(r,t))}))}function f(e,t,r){var n=r.readableChainWatchers();n&&n.notify(t,!1,a)}function d(e,t,r){var n=r.readableChainWatchers();n&&n.notify(t,!0,s)}function p(e,t,r){var n=r.readableChainWatchers();n&&n.revalidate(t)}function h(){E++}function m(){E--,E<=0&&(x.clear(),k.flush())}function v(e,t){h();try{e.call(t)}finally{m.call(t)}}function b(e,t){if(!e.isDestroying){var r,i,o=t+":before";E?(r=x.add(e,t,o),i=n.accumulateListeners(e,o,r),n.sendEvent(e,o,[e,t],i)):n.sendEvent(e,o,[e,t])}}function g(e,t){if(!e.isDestroying){var r,i=t+":change";E?(r=k.add(e,t,i),n.accumulateListeners(e,i,r)):n.sendEvent(e,i,[e,t])}}var y=o.default("PROPERTY_DID_CHANGE");e.PROPERTY_DID_CHANGE=y;var _,w,x=new i.default,k=new i.default,E=0;e.propertyWillChange=a,e.propertyDidChange=s,e.overrideChains=p,e.beginPropertyChanges=h,e.endPropertyChanges=m,e.changeProperties=v}),e("ember-metal/property_get",["exports","ember-metal/debug","ember-metal/path_cache"],function(e,t,r){"use strict";function n(e,t){if(""===t)return e;var n,o=e[t],a=null!==o&&"object"==typeof o&&o.isDescriptor?o:void 0;return void 0===a&&r.isPath(t)?i(e,t):a?a.get(e,t):(n=o,void 0!==n||"object"!=typeof e||t in e||"function"!=typeof e.unknownProperty?n:e.unknownProperty(t))}function i(e,t){for(var r=e,i=t.split("."),a=0;a0?(o.proto!==e&&(p=e[t]),r!==p&&(i.propertyWillChange(e,t),e[t]=r,i.propertyDidChange(e,t))):(e[t]=r,e[i.PROPERTY_DID_CHANGE]&&e[i.PROPERTY_DID_CHANGE](t))}return r}function d(e,t,r,i){var o;if(o=t.slice(t.lastIndexOf(".")+1),t=t===o?o:t.slice(0,t.length-(o.length+1)),"this"!==t&&(e=n._getPath(e,t)),!o||0===o.length)throw new a.default("Property set failed: You passed an empty path");if(!e){if(i)return;throw new a.default('Property set failed: object in path "'+t+'" could not be found or was destroyed.')}return f(e,o,r)}function p(e,t,r){return f(e,t,r,!0)}e.set=f,e.trySet=p}),e("ember-metal/replace",["exports"],function(e){"use strict";function t(e,t,r,i){for(var o,a,s=[].concat(i),u=[],l=6e4,c=t,f=r;s.length;)o=f>l?l:f,o<=0&&(o=0),a=s.splice(0,l),a=[c,o].concat(a),c+=l,f-=o,u=u.concat(n.apply(e,a));return u}function r(e,r,n,i){return e.replace?e.replace(r,n,i):t(e,r,n,i)}e._replace=t,e.default=r;var n=Array.prototype.splice}),e("ember-metal/run_loop",["exports","ember-metal/core","ember-metal/debug","ember-metal/utils","ember-metal/property_events","backburner"],function(e,t,r,n,i,o){"use strict";function a(e){u.currentRunLoop=e}function s(e,t){u.currentRunLoop=t}function u(){return c.run.apply(c,arguments)}function l(){!u.currentRunLoop}e.default=u;var c=new o.default(["sync","actions","destroy"],{GUID_KEY:n.GUID_KEY,sync:{before:i.beginPropertyChanges,after:i.endPropertyChanges},defaultQueue:"actions",onBegin:a,onEnd:s,onErrorTarget:t.default,onErrorMethod:"onerror"});u.join=function(){return c.join.apply(c,arguments)},u.bind=function(){for(var e=arguments.length,t=Array(e),r=0;r-1;return e?function(e){return E.test(C.call(e))}:function(){return!0}}();e.checkHasSuper=O,o.__hasSuper=!1;var T=Object.prototype.toString;e.GUID_KEY=_,e.makeArray=f,e.canInvoke=l}),e("ember-metal/watch_key",["exports","ember-metal/features","ember-metal/meta","ember-metal/properties","ember-metal/utils"],function(e,t,r,n,i){"use strict";function o(e,t,n){if("length"!==t||!Array.isArray(e)){var i=n||r.meta(e);if(i.peekWatching(t))i.writeWatching(t,(i.peekWatching(t)||0)+1);else{i.writeWatching(t,1);var o=e[t],a=null!==o&&"object"==typeof o&&o.isDescriptor?o:void 0;a&&a.willWatch&&a.willWatch(e,t),"function"==typeof e.willWatchProperty&&e.willWatchProperty(t)}}}function a(e,t,n){var i=n||r.meta(e),o=i.peekWatching(t);if(1===o){i.writeWatching(t,0);var a=e[t],s=null!==a&&"object"==typeof a&&a.isDescriptor?a:void 0;s&&s.didUnwatch&&s.didUnwatch(e,t),"function"==typeof e.didUnwatchProperty&&e.didUnwatchProperty(t)}else o>1&&i.writeWatching(t,o-1)}e.watchKey=o,e.unwatchKey=a}),e("ember-metal/watch_path",["exports","ember-metal/meta","ember-metal/chains"],function(e,t,r){"use strict";function n(e,r){return(r||t.meta(e)).writableChains(i)}function i(e){return new r.ChainNode(null,null,e)}function o(e,r,i){if("length"!==r||!Array.isArray(e)){var o=i||t.meta(e),a=o.peekWatching(r)||0;a?o.writeWatching(r,a+1):(o.writeWatching(r,1),n(e,o).add(r))}}function a(e,r,i){var o=i||t.meta(e),a=o.peekWatching(r)||0;1===a?(o.writeWatching(r,0),n(e,o).remove(r)):a>1&&o.writeWatching(r,a-1)}e.watchPath=o,e.unwatchPath=a}),e("ember-metal/watching",["exports","ember-metal/chains","ember-metal/watch_key","ember-metal/watch_path","ember-metal/path_cache","ember-metal/meta"],function(e,t,r,n,i,o){"use strict";function a(e,t,o){"length"===t&&Array.isArray(e)||(i.isPath(t)?n.watchPath(e,t,o):r.watchKey(e,t,o))}function s(e,t){var r=o.peekMeta(e);return(r&&r.peekWatching(t))>0}function u(e,t){var r=o.peekMeta(e);return r&&r.peekWatching(t)||0}function l(e,t,o){"length"===t&&Array.isArray(e)||(i.isPath(t)?n.unwatchPath(e,t,o):r.unwatchKey(e,t,o))}function c(e){var r,n,i,a,s=o.peekMeta(e);if(s&&(o.deleteMeta(e),r=s.readableChains()))for(f.push(r);f.length>0;){if(r=f.pop(),n=r._chains)for(i in n)void 0!==n[i]&&f.push(n[i]);r._watching&&(a=r._object,a&&t.removeChainWatcher(a,r._key,r))}}e.isWatching=s,e.watcherCount=u,e.unwatch=l,e.destroy=c,e.watch=a;var f=[]}),e("ember-metal/weak_map",["exports","ember-metal/debug","ember-metal/utils","ember-metal/meta"],function(e,t,r,n){"use strict";function i(){}function o(){this._id=r.GUID_KEY+a++}e.default=o;var a=0;o.prototype.get=function(e){var t=n.peekMeta(e);if(t){var r=t.readableWeak();if(r){if(r[this._id]===i)return;return r[this._id]}}},o.prototype.set=function(e,t){return void 0===t&&(t=i),n.meta(e).writableWeak()[this._id]=t,this},o.prototype.has=function(e){var t=n.peekMeta(e);if(t){var r=t.readableWeak();if(r)return void 0!==r[this._id]}return!1},o.prototype.delete=function(e){return!!this.has(e)&&(delete n.meta(e).writableWeak()[this._id],!0)}}),e("ember-routing-htmlbars/helpers/query-params",["exports","ember-metal/debug","ember-routing/system/query_params"],function(e,t,r){"use strict";function n(e,t){return r.default.create({values:t})}e.queryParamsHelper=n}),e("ember-routing-htmlbars/index",["exports","ember-metal/core","ember-htmlbars/helpers","ember-htmlbars/keywords","ember-routing-htmlbars/helpers/query-params","ember-routing-htmlbars/keywords/action","ember-routing-htmlbars/keywords/element-action","ember-routing-htmlbars/keywords/render"],function(e,t,r,n,i,o,a,s){"use strict";r.registerHelper("query-params",i.queryParamsHelper),n.registerKeyword("action",o.default),n.registerKeyword("@element_action",a.default),n.registerKeyword("render",s.default),e.default=t.default}),e("ember-routing-htmlbars/keywords/action",["exports","htmlbars-runtime/hooks","ember-routing-htmlbars/keywords/closure-action"],function(e,t,r){"use strict";e.default=function(e,n,i,o,a,s,u,l){return e?(t.keyword("@element_action",e,n,i,o,a,s,u,l),!0):r.default(e,n,i,o,a,s,u,l)}}),e("ember-routing-htmlbars/keywords/closure-action",["exports","ember-metal/streams/stream","ember-metal/streams/utils","ember-metal/symbol","ember-metal/property_get","ember-htmlbars/hooks/subexpr","ember-metal/error","ember-metal/run_loop","ember-metal/instrumentation","ember-metal/is_none"],function(e,t,r,n,i,o,a,s,u,l){"use strict";function c(e,n,i,s,u,c,p,h){var m=new t.Stream(function(){var e=s[0],t=r.readArray(s.slice(1,s.length)),n=void 0,c=void 0,p=void 0;if(l.default(e)){var h=o.labelForSubexpr(s,u,"action");throw new a.default("Action passed is null or undefined in "+h+" from "+r.read(i.getSelf())+".")}if(e[d])n=e,c=e[d];else{n=r.read(i.getSelf()),c=r.read(e);var m=typeof c;if("string"===m){var v=c;if(c=null,u.target&&(n=r.read(u.target)),n.actions&&(c=n.actions[v]),!c)throw new a.default("An action named '"+v+"' was not found in "+n+".")}else if(c&&"function"==typeof c[d])n=c,c=c[d];else if("function"!==m)throw new a.default("An action could not be made for `"+e.label+"` in "+n+". Please confirm that you are using either a quoted action name (i.e. `(action '"+e.label+"')`) or a function available in "+n+".")}return u.value&&(p=r.read(u.value)),f(this,n,c,p,t)},function(){return o.labelForSubexpr(s,u,"action")});return s.forEach(m.addDependency,m),Object.keys(u).forEach(function(e){return m.addDependency(e)}),m}function f(e,t,n,o,a){var l;return l=a.length>0?function(){for(var l=a,c=arguments.length,f=Array(c),d=0;d0&&(l=a.concat(f)),o&&l.length>0&&(l[0]=i.get(l[0],o));var p={target:t,args:l,label:r.labelFor(e)};return u.flaggedInstrument("interaction.ember-action",p,function(){return s.default.join.apply(s.default,[t,n].concat(l))})}:function(){for(var a=arguments.length,l=Array(a),c=0;c0&&(l[0]=i.get(l[0],o));var f={target:t,args:l,label:r.labelFor(e)};return u.flaggedInstrument("interaction.ember-action",f,function(){return s.default.join.apply(s.default,[t,n].concat(l))})},l[p]=!0,l}e.default=c;var d=n.default("INVOKE");e.INVOKE=d;var p=n.default("ACTION");e.ACTION=p}),e("ember-routing-htmlbars/keywords/element-action",["exports","ember-metal/debug","ember-metal/utils","ember-metal/streams/utils","ember-metal/run_loop","ember-views/streams/utils","ember-views/system/utils","ember-views/system/action_manager"],function(e,t,r,n,i,o,a,s){"use strict";function u(e,t){if("undefined"==typeof t){if(f.test(e.type))return a.isSimpleClick(e);t=""}if(t.indexOf("any")>=0)return!0;for(var r=0,n=c.length;r1){var O=b._lookupFactory(k)||s.generateControllerFactory(b,x);E=O.create({model:o.read(v),target:C}),e.addDestruction(E)}else E=b.lookup(k)||s.default(b,x),E.setProperties({target:C});_&&_.set("controller",E),h.controller=E,c.viewName=a.camelize(m),f&&f.raw&&(f=f.raw);var T={layout:null,self:E};_&&(T.component=_);var N=u.default.create(e,t,c,T,h.parentView,null,null,f);h.manager=N,g&&1===l.length&&g._connectActiveComponentNode(m,N),N.render(t,c,p)},rerender:function(e,t,r,n,i,a,s,u){if(n.length>1){var l=o.read(n[1]);e.getState().controller.set("model",l)}}}}),e("ember-routing-views/components/link-to",["exports","ember-metal/features","ember-metal/logger","ember-metal/debug","ember-metal/property_get","ember-metal/computed","ember-metal/computed_macros","ember-views/system/utils","ember-views/components/component","ember-runtime/inject","ember-runtime/system/service","ember-runtime/mixins/controller","ember-htmlbars/node-managers/component-node-manager","ember-htmlbars/templates/link-to","require"],function(e,t,r,n,i,o,a,s,u,l,c,f,d,p,h){"use strict";var m=p.default,v=u.default.extend({layout:m,tagName:"a",currentWhen:a.deprecatingAlias("current-when",{id:"ember-routing-view.deprecated-current-when",until:"3.0.0"}),"current-when":null,title:null,rel:null,tabindex:null,target:null,activeClass:"active",loadingClass:"loading",disabledClass:"disabled",_isDisabled:!1,replace:!1,attributeBindings:["href","title","rel","tabindex","target"],classNameBindings:["active","loading","disabled","transitioningIn","transitioningOut"],eventName:"click",init:function(){this._super.apply(this,arguments);var e=i.get(this,"eventName");this.on(e,this,this._invoke)},_routing:l.default.service("-routing"),disabled:o.computed({get:function(e,t){return!1},set:function(e,t){return void 0!==t&&this.set("_isDisabled",t),!!t&&i.get(this,"disabledClass")}}),_computeActive:function(e){if(i.get(this,"loading"))return!1;var t=i.get(this,"_routing"),r=i.get(this,"models"),n=i.get(this,"resolvedQueryParams"),o=i.get(this,"current-when"),a=!!o;o=o||i.get(this,"qualifiedRouteName"),o=o.split(" ");for(var s=0,u=o.length;s1?this.set("models",this._getModels(t)):this.set("models",[])}});v.toString=function(){return"LinkComponent"},v.reopenClass({positionalParams:"params"}),e.default=v}),e("ember-routing-views/index",["exports","ember-metal/core","ember-routing-views/components/link-to","ember-routing-views/views/outlet"],function(e,t,r,n){"use strict";t.default.LinkComponent=r.default,t.default.OutletView=n.OutletView,e.default=t.default}),e("ember-routing-views/views/outlet",["exports","ember-views/views/view","ember-htmlbars/templates/top-level-view"],function(e,t,r){"use strict";var n=t.default.extend({defaultTemplate:r.default,init:function(){this._super(),this._outlets=[]},setOutletState:function(e){this.outletState={main:e},this.env&&(this.env.outletState=this.outletState),this.lastResult&&(this.dirtyOutlets(),this._outlets=[],this.scheduleRevalidate(null,null))},dirtyOutlets:function(){for(var e=0;e7)}function s(e,t){return(e.indexOf("Android 2.")===-1&&e.indexOf("Android 4.0")===-1||e.indexOf("Mobile Safari")===-1||e.indexOf("Chrome")!==-1||e.indexOf("Windows Phone")!==-1)&&!!(t&&"pushState"in t)}function u(e,t){e.replace(o(e)+t)}e.getPath=t,e.getQuery=r,e.getHash=n,e.getFullPath=i,e.getOrigin=o,e.supportsHashChange=a,e.supportsHistory=s,e.replacePath=u}),e("ember-routing/services/routing",["exports","ember-runtime/system/service","ember-metal/property_get","ember-metal/computed_macros","ember-routing/utils","ember-metal/assign"],function(e,t,r,n,i,o){"use strict";function a(e,t){for(var r=0,n=0,i=t.length;nc&&(n=l),i.isActiveIntent(n,e,t,!o)}})}),e("ember-routing/system/cache",["exports","ember-runtime/system/object"],function(e,t){"use strict";e.default=t.default.extend({init:function(){this.cache={}},has:function(e){return e in this.cache},stash:function(e,t,r){var n=this.cache[e];n||(n=this.cache[e]={}),n[t]=r},lookup:function(e,t,r){var n=this.cache;if(!(e in n))return r;var i=n[e];return t in i?i[t]:r},cache:null})}),e("ember-routing/system/controller_for",["exports"],function(e){"use strict";function t(e,t,r){return e.lookup("controller:"+t,r)}e.default=t}),e("ember-routing/system/dsl",["exports","ember-metal/debug"],function(e,t){"use strict";function r(e,t){this.parent=e,this.enableLoadingSubstates=t&&t.enableLoadingSubstates,this.matches=[],this.explicitIndex=void 0,this.options=t}function n(e){return e.parent&&"application"!==e.parent}function i(e,t,r){return n(e)&&r!==!0?e.parent+"."+t:t}function o(e,t,r,n){r=r||{};var o=i(e,t,r.resetNamespace);"string"!=typeof r.path&&(r.path="/"+t),e.push(r.path,o,n)}e.default=r,r.prototype={route:function(e,t,n){var a="/_unused_dummy_error_path_route_"+e+"/:error";if(2===arguments.length&&"function"==typeof t&&(n=t,t={}),1===arguments.length&&(t={}),this.enableLoadingSubstates&&(o(this,e+"_loading",{resetNamespace:t.resetNamespace}),o(this,e+"_error",{path:a})),n){var s=i(this,e,t.resetNamespace),u=new r(s,this.options);o(u,"loading"),o(u,"error",{path:a}),n.call(u),o(this,e,t,u.generate())}else o(this,e,t)},push:function(e,t,r){var n=t.split(".");""!==e&&"/"!==e&&"index"!==n[n.length-1]||(this.explicitIndex=!0),this.matches.push([e,t,r])},resource:function(e,t,r){2===arguments.length&&"function"==typeof t&&(r=t,t={}),1===arguments.length&&(t={}),t.resetNamespace=!0,this.route(e,t,r)},generate:function(){var e=this.matches;return this.explicitIndex||this.route("index",{path:"/"}),function(t){for(var r=0,n=e.length;r0&&(this.connections=[],d.default.once(this.router,"_setOutlets"))}});g.deprecateUnderscoreActions(R),R.reopenClass({isRouteFactory:!0}),e.default=R});e("ember-routing/system/router",["exports","ember-metal/logger","ember-metal/debug","ember-metal/error","ember-metal/property_get","ember-metal/property_set","ember-metal/properties","ember-metal/empty_object","ember-metal/computed","ember-metal/assign","ember-metal/run_loop","ember-runtime/system/object","ember-runtime/mixins/evented","ember-routing/system/dsl","ember-routing/location/api","ember-routing/utils","ember-metal/utils","ember-routing/system/router_state","container/owner","ember-metal/dictionary","router","router/transition"],function(e,t,r,n,i,o,a,s,u,l,c,f,d,p,h,m,v,b,g,y,_,w){"use strict";function x(){return this}function k(e,t,r){for(var n,i,o=t.state.handlerInfos,a=!1,s=o.length-1;s>=0;--s)if(n=o[s],i=n.handler,a){if(r(i,o[s+1].handler)!==!0)return!1}else e===i&&(a=!0);return!0}function E(e,r){var n,i=[];n=e&&"object"==typeof e&&"object"==typeof e.errorThrown?e.errorThrown:e,r&&i.push(r),n&&(n.message&&i.push(n.message),n.stack&&i.push(n.stack),"string"==typeof n&&i.push(n)),t.default.error.apply(this,i)}function C(e,t,r){var n,i=e.router,o=t.routeName.split(".").pop(),a="application"===e.routeName?"":e.routeName+".";return n=a+o+"_"+r,O(i,n)?n:(n=a+r,O(i,n)?n:void 0)}function O(e,t){var r=g.getOwner(e);return e.hasRoute(t)&&(r.hasRegistration("template:"+t)||r.hasRegistration("route:"+t))}function T(e,t,r){var i=r.shift();if(!e){if(t)return;throw new n.default("Can't trigger action '"+i+"' because your app hasn't finished transitioning into its first route. To trigger an action on destination routes during a transition, you can call `.send()` on the `Transition` object passed to the `model/beforeModel/afterModel` hooks."); +}for(var o,a,s=!1,u=e.length-1;u>=0;u--)if(o=e[u],a=o.handler,a.actions&&a.actions[i]){if(a.actions[i].apply(a,r)!==!0){if("error"===i){var l=v.guidFor(r[0]);a.router._markErrorAsHandled(l)}return}s=!0}if(H[i])return void H[i].apply(null,r);if(!s&&!t)throw new n.default("Nothing handled the action '"+i+"'. If you did handle the action, this error can be caused by returning true from an action handler in a controller, causing the action to bubble.")}function N(e,t,r){for(var n=e.router,i=n.applyIntent(t,r),o=i.handlerInfos,a=i.params,s=0,u=o.length;s0;){var n=r.shift();if(n.render.name===t)return n;var i=n.outlets;for(var o in i)r.push(i[o])}}function L(e,t,r){var n,i={render:r,outlets:new s.default};return n=r.into?R(e,r.into):t,n?o.set(n.outlets,r.outlet,i):r.into?D(e,r.into,i):e=i,{liveRoutes:e,ownState:i}}function D(e,t,r){e.outlets.__ember_orphans__||(e.outlets.__ember_orphans__={render:{name:"__ember_orphans__"},outlets:new s.default}),e.outlets.__ember_orphans__.outlets[t]=r,c.default.schedule("afterRender",function(){})}function M(e,t,r){var n=R(e,r.routeName);return n?n:(t.outlets.main={render:{name:r.routeName,outlet:"main"},outlets:{}},t)}e.triggerEvent=T;var I=[].slice,F=f.default.extend(d.default,{location:"hash",rootURL:"/",_initRouterJs:function(){var e=this.router=new _.default;e.triggerEvent=T,e._triggerWillChangeContext=x,e._triggerWillLeave=x;var r=this.constructor.dslCallbacks||[x],n=this._buildDSL();n.route("application",{path:"/",resetNamespace:!0,overrideNameAssertion:!0},function(){for(var e=0;e0)-(r<0)}function i(e,a){if(e===a)return 0;var s=t.typeOf(e),u=t.typeOf(a);if(r.default){if("instance"===s&&r.default.detect(e)&&e.constructor.compare)return e.constructor.compare(e,a);if("instance"===u&&r.default.detect(a)&&a.constructor.compare)return a.constructor.compare(a,e)*-1}var l=n(o[s],o[u]);if(0!==l)return l;switch(s){case"boolean":case"number":return n(e,a);case"string":return n(e.localeCompare(a),0);case"array":for(var c=e.length,f=a.length,d=Math.min(c,f),p=0;p=0)return o[s];if(Array.isArray(e)){if(a=e.slice(),t)for(s=a.length;--s>=0;)a[s]=i(a[s],t,r,o)}else if(n.default&&n.default.detect(e))a=e.copy(t,r,o);else if(e instanceof Date)a=new Date(e.getTime());else{a={};for(u in e)Object.prototype.hasOwnProperty.call(e,u)&&"__"!==u.substring(0,2)&&(a[u]=t?i(e[u],t,r,o):e[u])}return t&&(r.push(e),o.push(a)),a}function o(e,t){return"object"!=typeof e||null===e?e:n.default&&n.default.detect(e)?e.copy(t):i(e,t,t?[]:null,t?[]:null)}e.default=o}),e("ember-runtime/core",["exports"],function(e){"use strict"}),e("ember-runtime/ext/function",["exports","ember-metal/core","ember-metal/debug","ember-metal/computed","ember-metal/mixin"],function(e,t,r,n,i){"use strict";var o=Array.prototype.slice,a=Function.prototype;(t.default.EXTEND_PROTOTYPES===!0||t.default.EXTEND_PROTOTYPES.Function)&&(a.property=function(){var e=n.computed(this);return e.property.apply(e,arguments)},a.observes=function(){for(var e=arguments.length,t=Array(e),r=0;r1?t-1:0),i=1;i=n.get(this,"length")))return n.get(this,e)},g.objectsAt=function(e){var t=this;return e.map(function(e){return v(t,e)})},g.nextObject=function(e){return v(this,e)},g["[]"]=i.computed({get:function(e){return this},set:function(e,t){return this.replace(0,n.get(this,"length"),t),this}}),g.firstObject=i.computed(function(){return v(this,0)}).readOnly(),g.lastObject=i.computed(function(){return v(this,n.get(this,"length")-1)}).readOnly(),g.contains=function(e){return this.indexOf(e)>=0},g.slice=function(e,r){var i=t.default.A(),a=n.get(this,"length");for(o.default(e)&&(e=0),(o.default(r)||r>a)&&(r=a),e<0&&(e=a+e),r<0&&(r=a+r);e=i)&&(t=i-1),t<0&&(t+=i),r=t;r>=0;r--)if(v(this,r)===e)return r;return-1},g.addArrayObserver=function(e,t){return h(this,e,t)},g.removeArrayObserver=function(e,t){return m(this,e,t)},g.hasArrayObservers=i.computed(function(){return l.hasListeners(this,"@array:change")||l.hasListeners(this,"@array:before")}),g.arrayContentWillChange=function(e,t,r){var i,o;if(void 0===e?(e=0,t=r=-1):(void 0===t&&(t=-1),void 0===r&&(r=-1)),this.__each&&this.__each.arrayWillChange(this,e,t,r),l.sendEvent(this,"@array:before",[this,e,t,r]),e>=0&&t>=0&&n.get(this,"hasEnumerableObservers")){i=[],o=e+t;for(var a=e;a=0&&r>=0&&n.get(this,"hasEnumerableObservers")){o=[],a=e+r;for(var s=e;s1?t-1:0),n=1;n1?t-1:0),i=1;it.get(this,"length"))throw new r.default(s);return this.replace(e,0,[n]),this},removeAt:function(e,n){if("number"==typeof e){if(e<0||e>=t.get(this,"length"))throw new r.default(s);void 0===n&&(n=1),this.replace(e,n,u)}return this},pushObject:function(e){return this.insertAt(t.get(this,"length"),e),e},pushObjects:function(e){if(!a.default.detect(e)&&!Array.isArray(e))throw new TypeError("Must pass Ember.Enumerable to Ember.MutableArray#pushObjects");return this.replace(t.get(this,"length"),0,e),this},popObject:function(){var e=t.get(this,"length");if(0===e)return null;var r=i.objectAt(this,e-1);return this.removeAt(e-1,1),r},shiftObject:function(){if(0===t.get(this,"length"))return null;var e=i.objectAt(this,0);return this.removeAt(0),e},unshiftObject:function(e){return this.insertAt(0,e),e},unshiftObjects:function(e){return this.replace(0,0,e),this},reverseObjects:function(){var e=t.get(this,"length");if(0===e)return this;var r=this.toArray().reverse();return this.replace(0,e,r),this},setObjects:function(e){if(0===e.length)return this.clear();var r=t.get(this,"length");return this.replace(0,r,e),this},removeObject:function(e){for(var r=t.get(this,"length")||0;--r>=0;){var n=i.objectAt(this,r);n===e&&this.removeAt(r)}return this},addObject:function(e){return this.contains(e)||this.pushObject(e),this}})}),e("ember-runtime/mixins/mutable_enumerable",["exports","ember-runtime/mixins/enumerable","ember-metal/mixin","ember-metal/property_events"],function(e,t,r,n){"use strict";e.default=r.Mixin.create(t.default,{addObject:null,addObjects:function(e){var t=this;return n.beginPropertyChanges(this),e.forEach(function(e){return t.addObject(e)}),n.endPropertyChanges(this),this},removeObject:null,removeObjects:function(e){n.beginPropertyChanges(this);for(var t=e.length-1;t>=0;t--)this.removeObject(e[t]);return n.endPropertyChanges(this),this}})}),e("ember-runtime/mixins/observable",["exports","ember-metal/debug","ember-metal/property_get","ember-metal/property_set","ember-metal/get_properties","ember-metal/set_properties","ember-metal/mixin","ember-metal/events","ember-metal/property_events","ember-metal/observer","ember-metal/computed","ember-metal/is_none"],function(e,t,r,n,i,o,a,s,u,l,c,f){"use strict";e.default=a.Mixin.create({get:function(e){return r.get(this,e)},getProperties:function(){for(var e=arguments.length,t=Array(e),r=0;rr.get(this,"content.length"))throw new s.default(h);return this._replace(e,0,[t]),this},insertAt:function(e,t){if(r.get(this,"arrangedContent")===r.get(this,"content"))return this._insertAt(e,t);throw new s.default("Using insertAt on an arranged ArrayProxy is not allowed.")},removeAt:function(e,t){if("number"==typeof e){var n,i=r.get(this,"content"),o=r.get(this,"arrangedContent"),u=[];if(e<0||e>=r.get(this,"length"))throw new s.default(h);for(void 0===t&&(t=1),n=e;n0&&(e=[arguments[0]]),this.__defineNonEnumerable(o.GUID_KEY_PROPERTY);var i=a.meta(this),f=i.proto;if(i.proto=this,e){var d=e;e=null;for(var p=this.concatenatedProperties,h=this.mergedProperties,m=0,v=d.length;m0&&p.indexOf(w)>=0){var T=this[w];x=T?"function"==typeof T.concat?T.concat(x):o.makeArray(T).concat(x):o.makeArray(x)}if(h&&h.length&&h.indexOf(w)>=0){var N=this[w];x=n.default({},N,x)}C?C.set(this,w,x):"function"!=typeof this.setUnknownProperty||w in this?this[w]=x:this.setUnknownProperty(w,x)}}}O(this,i);var S=arguments.length;if(0===S)this.init();else if(1===S)this.init(arguments[0]);else{for(var A=new Array(S),j=0;j";return r},x)),S.PrototypeMixin.ownerConstructor=S,S.__super__=null;var A={ClassMixin:l.REQUIRED,PrototypeMixin:l.REQUIRED,isClass:!0,isMethod:!1,extend:function(){var e,t=w();return t.ClassMixin=l.Mixin.create(this.ClassMixin),t.PrototypeMixin=l.Mixin.create(this.PrototypeMixin),t.ClassMixin.ownerConstructor=t,t.PrototypeMixin.ownerConstructor=t,T.apply(t.PrototypeMixin,arguments),t.superclass=this,t.__super__=this.prototype,e=t.prototype=Object.create(this.prototype),e.constructor=t,o.generateGuid(e),a.meta(e).proto=e,t.ClassMixin.apply(t),t},create:function(){for(var e=this,t=arguments.length,r=Array(t),n=0;n0&&this._initProperties(r),new e},reopen:function(){return this.willReopen(),T.apply(this.PrototypeMixin,arguments),this},reopenClass:function(){return T.apply(this.ClassMixin,arguments),C(this,arguments,!1),this},detect:function(e){if("function"!=typeof e)return!1;for(;e;){if(e===this)return!0;e=e.superclass}return!1},detectInstance:function(e){return e instanceof this},metaForProperty:function(e){var t=this.proto(),r=t[e],n=null!==r&&"object"==typeof r&&r.isDescriptor?r:void 0;return n._meta||{}},_computedProperties:h.computed(function(){N=!0;var e,t=this.proto(),r=[];for(var n in t)e=t[n],e&&e.isDescriptor&&r.push({name:n,meta:e._meta});return r}).readOnly(),eachComputedProperty:function(e,t){for(var r,n={},o=i.get(this,"_computedProperties"),a=0,s=o.length;a=i;){var s=a.objectAt(e,o);s&&(n._addBeforeObserver(s,t,r,"contentKeyWillChange"),n.addObserver(s,t,r,"contentKeyDidChange"))}}function l(e,t,r,i,o){for(;--o>=i;){var s=a.objectAt(e,o);s&&(n._removeBeforeObserver(s,t,r,"contentKeyWillChange"),n.removeObserver(s,t,r,"contentKeyDidChange"))}}s.prototype={__defineNonEnumerable:function(e){this[e.name]=e.descriptor.value},arrayWillChange:function(e,t,r,n){var o=this._keys,a=r>0?t+r:-1;for(var s in o)a>0&&l(e,s,this,t,a),i.propertyWillChange(this,s)},arrayDidChange:function(e,t,r,n){var o=this._keys,a=n>0?t+n:-1;for(var s in o)a>0&&u(e,s,this,t,a),i.propertyDidChange(this,s)},willWatchProperty:function(e){this.beginObservingContentKey(e)},didUnwatchProperty:function(e){this.stopObservingContentKey(e)},beginObservingContentKey:function(e){var t=this._keys;if(t||(t=this._keys=new o.default),t[e])t[e]++;else{t[e]=1;var n=this._content,i=r.get(n,"length");u(n,e,this,0,i)}},stopObservingContentKey:function(e){var t=this._keys;if(t&&t[e]>0&&--t[e]<=0){var n=this._content,i=r.get(n,"length");l(n,e,this,0,i)}},contentKeyWillChange:function(e,t){i.propertyWillChange(this,t)},contentKeyDidChange:function(e,t){i.propertyDidChange(this,t)}},e.default=s}),e("ember-runtime/system/lazy_load",["exports","ember-metal/core","ember-runtime/system/native_array"],function(e,t,r){"use strict";function n(e,t){var n=a[e];o[e]=o[e]||r.A(),o[e].pushObject(t),n&&t(n)}function i(e,t){if(a[e]=t,"object"==typeof window&&"function"==typeof window.dispatchEvent&&"function"==typeof CustomEvent){var r=new CustomEvent(e,{detail:t,name:e});window.dispatchEvent(r)}o[e]&&o[e].forEach(function(e){return e(t)})}e.onLoad=n,e.runLoadHooks=i;var o=t.default.ENV.EMBER_LOAD_HOOKS||{},a={},s=a;e._loaded=s}),e("ember-runtime/system/namespace",["exports","ember-metal/core","ember-metal/property_get","ember-metal/utils","ember-metal/mixin","ember-runtime/system/object"],function(e,t,r,n,i,o){"use strict";function a(e,t,r){var i=e.length;h[e.join(".")]=t;for(var o in t)if(m.call(t,o)){var s=t[o];if(e[i]=o,s&&s.toString===c&&!s[b])s[b]=e.join(".");else if(s&&s.isNamespace){if(r[n.guidFor(s)])continue;r[n.guidFor(s)]=!0,a(e,s,r)}}e.length=i}function s(e,t){try{var r=e[t];return r&&r.isNamespace&&r}catch(e){}}function u(){var e,r=t.default.lookup;if(!p.PROCESSED)for(var n in r)v.test(n)&&(r.hasOwnProperty&&!r.hasOwnProperty(n)||(e=s(r,n),e&&(e[b]=n)))}function l(e){var t=e.superclass;return t?t[b]?t[b]:l(t):void 0}function c(){t.default.BOOTED||this[b]||f();var e;if(this[b])e=this[b];else if(this._toString)e=this._toString;else{var r=l(this);e=r?"(subclass of "+r+")":"(unknown mixin)",this.toString=d(e)}return e}function f(){var e=!p.PROCESSED,r=t.default.anyUnprocessedMixins;if(e&&(u(),p.PROCESSED=!0),e||r){for(var n,i=p.NAMESPACES,o=0,s=i.length;o2){i=new Array(arguments.length-1);for(var o=1,a=arguments.length;o2)&&(t=Array.prototype.slice.call(arguments,1)),e=i.get(e)||e,a(e,t)}function l(e){return e.split(/\s+/)}function c(e){return j.get(e)}function f(e){return b.get(e)}function d(e){return _.get(e)}function p(e){return E.get(e)}function h(e){return T.get(e)}function m(e){return S.get(e)}var v=/[ _]/g,b=new o.default(1e3,function(e){return c(e).replace(v,"-")}),g=/(\-|\_|\.|\s)+(.)?/g,y=/(^|\/)([A-Z])/g,_=new o.default(1e3,function(e){return e.replace(g,function(e,t,r){return r?r.toUpperCase():""}).replace(y,function(e,t,r){return e.toLowerCase()})}),w=/^(\-|_)+(.)?/,x=/(.)(\-|\_|\.|\s)+(.)?/g,k=/(^|\/|\.)([a-z])/g,E=new o.default(1e3,function(e){for(var t=function(e,t,r){return r?"_"+r.toUpperCase():""},r=function(e,t,r,n){return t+(n?n.toUpperCase():"")},n=e.split("/"),i=0,o=n.length;i1}function o(e,t){for(var r=0,n=e.length;r")}),e},e.default=t}),e("ember-template-compiler/plugins/transform-closure-component-attrs-into-mut",["exports"],function(e){"use strict";function t(){this.syntax=null}function r(e){return"SubExpression"===e.type&&"component"===e.path.original}function n(e,t){for(var r=1;r0)return!1;"ComponentNode"!==c.type&&"ElementNode"!==c.type||(o=c,a=u)}}o&&"ComponentNode"===o.type&&t(o)}}t.prototype.transform=function(e){var t=this.syntax.builders;return r(e,function(e){"ComponentNode"===e.type&&(e.tag="@"+e.tag,e.isStatic=!0)},function(e){var r=e.attributes.some(function(e){return e.value.escaped===!1});if(e.modifiers.length||r)return e;var n=t.program(e.children),i=t.component("@<"+e.tag+">",e.attributes,n,e.loc);return i.isStatic=!0,i}),e},e.default=t}),e("ember-template-compiler/system/calculate-location-display",["exports"],function(e){"use strict";function t(e,t){var r=t||{},n=r.start||{},i=n.column,o=n.line,a="";return e&&(a+="'"+e+"' "),void 0!==o&&void 0!==i&&(e&&(a+="@ "),a+="L"+o+":C"+i),a&&(a="("+a+") "),a}e.default=t}),e("ember-template-compiler/system/compile",["exports","ember-metal/features","require","ember-template-compiler/system/compile_options","ember-template-compiler/system/template"],function(e,t,r,n,i){"use strict";var o;e.default=function(e,t){if(!o&&r.has("htmlbars-compiler/compiler")&&(o=r.default("htmlbars-compiler/compiler").compile),!o)throw new Error("Cannot call `compile` without the template compiler loaded. Please load `ember-template-compiler.js` prior to calling `compile`.");var a=o(e,n.default(t));return i.default(a)}}),e("ember-template-compiler/system/compile_options",["exports","ember-metal/assign","ember-template-compiler/plugins"],function(e,t,r){"use strict";var n=void 0,i=void 0;n=function(e){var n=!0,o=void 0;o=e===!0?{}:t.default({},e),o.disableComponentGeneration=n;var a={ast:r.default.ast.slice()};return o.plugins&&o.plugins.ast&&(a.ast=a.ast.concat(o.plugins.ast)),o.plugins=a,o.buildMeta=function(e){return{fragmentReason:i(e),revision:"Ember@2.6.2",loc:e.loc,moduleName:o.moduleName}},o},i=function(e){var t=e.loc,r=e.body;if(!t||1!==t.start.line||0!==t.start.column)return!1;for(var n=void 0,i=0,o={},a=0,s=r.length;a0&&(o["multiple-nodes"]=!0),"ComponentNode"===u.type||"ElementNode"===u.type?n=u:o["wrong-type"]=!0)}if(0===i)return{name:"missing-wrapper",problems:["empty-body"]};var l=Object.keys(o);return l.length?{name:"missing-wrapper",problems:l}:"ComponentNode"!==n.type&&(n.modifiers.length?{name:"modifiers",modifiers:n.modifiers.map(function(e){return e.path.original})}:!!n.attributes.some(function(e){return!e.value.escaped})&&{name:"triple-curlies"})},e.default=n}),e("ember-template-compiler/system/precompile",["exports","ember-metal/features","require","ember-template-compiler/system/compile_options"],function(e,t,r,n){"use strict";var i;e.default=function(e,t){if(!i&&r.has("htmlbars-compiler/compiler")&&(i=r.default("htmlbars-compiler/compiler").compileSpec),!i)throw new Error("Cannot call `compileSpec` without the template compiler loaded. Please load `ember-template-compiler.js` prior to calling `compileSpec`.");return i(e,n.default(t))}}),e("ember-template-compiler/system/template",["exports","ember-metal/features","require"],function(e,t,r){"use strict";var n=void 0,i=r.default("htmlbars-runtime/hooks"),o=i.wrap;n=function(e){return e.render||(e=o(e)),e.isTop=!0,e.isMethod=!1,e},e.default=n}),e("ember-views/compat/attrs-proxy",["exports","ember-metal/mixin","ember-metal/symbol","ember-metal/property_events"],function(e,t,r,n){"use strict";function i(e){return"You tried to look up an attribute directly on the component. This is deprecated. Use attrs."+e+" instead."}function o(e){return e&&e[a]}e.deprecation=i;var a=r.default("MUTABLE_CELL");e.MUTABLE_CELL=a;var s={attrs:null,getAttr:function(e){var t=this.attrs;if(t)return this.getAttrFor(t,e)},getAttrFor:function(e,t){var r=e[t];return o(r)?r.value:r},setAttr:function(e,t){var r=this.attrs,n=r[e];if(!o(n))throw new Error("You can't update attrs."+e+", because it's not mutable");n.update(t)},_propagateAttrsToThis:function(e){this._isDispatchingAttrs=!0,this.setProperties(e),this._isDispatchingAttrs=!1}};s[n.PROPERTY_DID_CHANGE]=function(e){this._isAngleBracket||this._isDispatchingAttrs||this._currentState&&this._currentState.legacyPropertyDidChange(this,e)},e.default=t.Mixin.create(s)}),e("ember-views/component_lookup",["exports","ember-metal/core","ember-metal/debug","ember-runtime/system/object","ember-htmlbars/system/lookup-helper","container/owner"],function(e,t,r,n,i,o){"use strict";e.default=n.default.extend({invalidName:function(e){if(!i.CONTAINS_DASH_CACHE.get(e))return!0},lookupFactory:function(e,r){r=r||o.getOwner(this);var n="component:"+e,i="template:components/"+e,a=r&&r.hasRegistration(i);a&&r.inject(n,"layout",i);var s=r._lookupFactory(n);if(a||s)return s||(r.register(n,t.default.Component),s=r._lookupFactory(n)),s},componentFor:function(e,t,r){if(!this.invalidName(e)){var n="component:"+e;return t._lookupFactory(n,r)}},layoutFor:function(e,t,r){if(!this.invalidName(e)){var n="template:components/"+e;return t.lookup(n,r)}}})}),e("ember-views/components/component",["exports","ember-metal/debug","ember-metal/environment","ember-runtime/mixins/target_action_support","ember-views/views/view","ember-metal/property_get","ember-metal/property_set","ember-metal/is_none","ember-metal/utils","ember-metal/computed","ember-views/compat/attrs-proxy","container/owner"],function(e,t,r,n,i,o,a,s,u,l,c,f){"use strict";function d(e,t){return t&&t[c.MUTABLE_CELL]&&(t=t.value),t}var p=i.default.extend(n.default,{isComponent:!0,controller:null,context:null,instrumentName:"component",instrumentDisplay:l.computed(function(){if(this._debugContainerKey)return"{{"+this._debugContainerKey.split(":")[1]+"}}"}),init:function(){if(this._super.apply(this,arguments),a.set(this,"controller",this),a.set(this,"context",this),!this.layout&&this.layoutName&&f.getOwner(this)){var e=o.get(this,"layoutName");this.layout=this.templateForName(e)}this.defaultLayout&&!this.layout&&(this.layout=this.defaultLayout)},template:null,layoutName:null,layout:null,targetObject:l.computed("controller",function(e){if(this._targetObject)return this._targetObject;if(this._controller)return this._controller;var t=o.get(this,"parentView");return t?o.get(t,"controller"):null}),sendAction:function(e){for(var t=arguments.length,r=Array(t>1?t-1:0),n=1;n1?t-1:0),n=1;n=0;)t=r[i],e(this,t,i);return this},removeAllChildren:function(){return this.mutateChildViews(function(e,t){e.removeChild(t)})},destroyAllChildren:function(){return this.mutateChildViews(function(e,t){t.destroy()})},nearestChildOf:function(e){for(var t=n.get(this,"parentView");t;){if(n.get(t,"parentView")instanceof e)return t;t=n.get(t,"parentView")}},nearestInstanceOf:function(e){for(var t=n.get(this,"parentView");t;){if(t instanceof e)return t;t=n.get(t,"parentView")}},_contextDidChange:r.observer("context",function(){this.rerender()})});e.default=i}),e("ember-views/mixins/template_rendering_support",["exports","ember-metal/mixin"],function(e,t){"use strict";var n,i=t.Mixin.create({renderBlock:function(e,t){return void 0===n&&(n=r("ember-htmlbars/system/render-view")),n.renderHTMLBarsBlock(this,e,t)}});e.default=i}),e("ember-views/mixins/text_support",["exports","ember-metal/property_get","ember-metal/property_set","ember-metal/mixin","ember-runtime/mixins/target_action_support"],function(e,t,r,n,i){"use strict";function o(e,r,n){var i=t.get(r,"attrs."+e)||t.get(r,e),o=t.get(r,"onEvent"),a=t.get(r,"value");(o===e||"keyPress"===o&&"key-press"===e)&&r.sendAction("action",a),r.sendAction(e,a),(i||o===e)&&(t.get(r,"bubbles")||n.stopPropagation())}var a={13:"insertNewline",27:"cancel"},s=n.Mixin.create(i.default,{value:"",attributeBindings:["autocapitalize","autocorrect","autofocus","disabled","form","maxlength","placeholder","readonly","required","selectionDirection","spellcheck","tabindex","title"],placeholder:null,disabled:!1,maxlength:null,init:function(){this._super.apply(this,arguments),this.on("paste",this,this._elementValueDidChange),this.on("cut",this,this._elementValueDidChange),this.on("input",this,this._elementValueDidChange)},action:null,onEvent:"enter",bubbles:!1,interpretKeyEvents:function(e){var t=a,r=t[e.keyCode];if(this._elementValueDidChange(),r)return this[r](e)},_elementValueDidChange:function(){r.set(this,"value",this.readDOMAttr("value"))},change:function(e){this._elementValueDidChange(e)},insertNewline:function(e){o("enter",this,e),o("insert-newline",this,e)},cancel:function(e){o("escape-press",this,e)},focusIn:function(e){o("focus-in",this,e)},focusOut:function(e){this._elementValueDidChange(e),o("focus-out",this,e)},keyPress:function(e){o("key-press",this,e)},keyUp:function(e){this.interpretKeyEvents(e),this.sendAction("key-up",t.get(this,"value"),e)},keyDown:function(e){this.sendAction("key-down",t.get(this,"value"),e)}});e.default=s}),e("ember-views/mixins/view_child_views_support",["exports","ember-metal/debug","ember-metal/mixin","ember-metal/property_get","ember-metal/property_set","ember-metal/set_properties","ember-runtime/system/native_array","container/owner"],function(e,t,r,n,i,o,a,s){"use strict";var u=[];e.default=r.Mixin.create({childViews:u,init:function(){this._super.apply(this,arguments),this.childViews=a.A(this.childViews.slice()),this.ownerView=this.ownerView||this},appendChild:function(e){this.linkChild(e),this.childViews.push(e)},destroyChild:function(e){e.destroy()},removeChild:function(e){if(!this.isDestroying){this.unlinkChild(e);var t=n.get(this,"childViews"),r=t.indexOf(e);return r!==-1&&t.splice(r,1),this}},createChildView:function(e){var t=arguments.length<=1||void 0===arguments[1]?{}:arguments[1];if(!e)throw new TypeError("createChildViews first argument must exist");var r=s.getOwner(this);if(e.isView&&e.parentView===this&&s.getOwner(e)===r)return e;var n;if(t.parentView=this,t.renderer=this.renderer,t._viewRegistry=this._viewRegistry,e.isViewFactory)s.setOwner(t,r),n=e.create(t),n.viewName&&i.set(this,n.viewName,n);else if("string"==typeof e){var a="view:"+e,u=r._lookupFactory(a);n=u.create(t)}else n=e,s.setOwner(t,r),o.default(n,t);return this.linkChild(n),n},linkChild:function(e){e[s.OWNER]||s.setOwner(e,s.getOwner(this)),e.parentView=this,e.ownerView=this.ownerView},unlinkChild:function(e){e.parentView=null}})}),e("ember-views/mixins/view_context_support",["exports","ember-metal/mixin","ember-metal/computed","ember-metal/property_get","ember-metal/property_set","ember-views/mixins/legacy_view_support","ember-metal/events"],function(e,t,r,n,i,o,a){"use strict";var s=t.Mixin.create(o.default,{context:r.computed({get:function(){return n.get(this,"_context")},set:function(e,t){return i.set(this,"_context",t),t}}),_context:r.computed({get:function(){var e,t;return(t=n.get(this,"controller"))?t:(e=this.parentView,e?n.get(e,"_context"):null)},set:function(e,t){return t}}),_controller:null,controller:r.computed({get:function(){return this._controller?this._controller:this.parentView?n.get(this.parentView,"controller"):null},set:function(e,t){return this._controller=t,t}}),_legacyControllerDidChange:t.observer("controller",function(){this.childViews.forEach(function(e){return e.notifyPropertyChange("controller")})}),_notifyControllerChange:a.on("parentViewDidChange",function(){this.notifyPropertyChange("controller")})});e.default=s}),e("ember-views/mixins/view_state_support",["exports","ember-metal/debug","ember-metal/mixin"],function(e,t,r){"use strict";var n=r.Mixin.create({transitionTo:function(e){this._transitionTo(e)},_transitionTo:function(e){var t=this._currentState,r=this._currentState=this._states[e];this._state=e,t&&t.exit&&t.exit(this),r.enter&&r.enter(this)}});e.default=n}),e("ember-views/mixins/view_support",["exports","ember-metal/debug","ember-metal/error","ember-metal/property_get","ember-metal/run_loop","ember-metal/observer","ember-metal/utils","ember-metal/computed","ember-metal/mixin","ember-runtime/system/core_object","ember-metal/symbol","container/owner","ember-views/system/jquery"],function(e,t,r,n,i,o,a,s,u,l,c,f,d){"use strict";function p(){return this}var h,m=c.default("INIT_WAS_CALLED");e.default=u.Mixin.create((h={concatenatedProperties:["attributeBindings"],isView:!0,templateName:null,layoutName:null,template:s.computed({get:function(){var e=n.get(this,"templateName"),t=this.templateForName(e,"template");return t||n.get(this,"defaultTemplate")},set:function(e,t){return void 0!==t?t:n.get(this,e)}}),layout:s.computed({get:function(e){var t=n.get(this,"layoutName"),r=this.templateForName(t,"layout");return r||n.get(this,"defaultLayout")},set:function(e,t){return t}}),templateForName:function(e,t){if(e){var n=f.getOwner(this);if(!n)throw new r.default("Container was not found when looking up a views template. This is most likely due to manually instantiating an Ember.View. See: http://git.io/EKPpnA");return n.lookup("template:"+e)}},nearestOfType:function(e){for(var t=n.get(this,"parentView"),r=e instanceof u.Mixin?function(t){return e.detect(t)}:function(t){return e.detect(t.constructor)};t;){if(r(t))return t;t=n.get(t,"parentView")}},nearestWithProperty:function(e){for(var t=n.get(this,"parentView");t;){if(e in t)return t;t=n.get(t,"parentView")}},rerender:function(){return this._currentState.rerender(this)},element:null,$:function(e){return this._currentState.$(this,e)},forEachChildView:function(e){var t=this.childViews;if(!t)return this;var r,n,i=t.length;for(n=0;n1&&(t=n[1],3===n.length&&(r=n[2]),o=":"+t,r&&(o+=":"+r)),{path:i,classNames:o,className:""===t?void 0:t,falsyClassName:r}}function s(e,t,i,a){if(n.isArray(t)&&(t=0!==r.get(t,"length")),i||a)return i&&t?i:a&&!t?a:null;if(t===!0){var s=e.split(".");return o.dasherize(s[s.length-1])}return t!==!1&&null!=t?t:null}function u(e,t,r){r=r||"";var n=a(t);if(""===n.path)return s(n.path,!0,n.className,n.falsyClassName);var o=e.getStream(r+n.path);return i.chain(o,function(){return s(n.path,i.read(o),n.className,n.falsyClassName)})}e.parsePropertyPath=a,e.classStringForValue=s,e.streamifyClassNameBinding=u}),e("ember-views/streams/should_display",["exports","ember-metal/debug","ember-metal/property_get","ember-runtime/utils","ember-metal/streams/stream","ember-metal/streams/utils"],function(e,t,r,n,i,o){"use strict";function a(e){if(o.isStream(e))return new s(e);var t=typeof e;if("boolean"===t)return e;if(t&&"object"===t&&null!==e){var i=r.get(e,"isTruthy");if("boolean"==typeof i)return i}return n.isArray(e)?0!==r.get(e,"length"):!!e}e.default=a;var s=i.default.extend({init:function(e){var t=e.get("isTruthy");this.init(),this.predicate=e,this.isTruthy=t,this.lengthDep=null,this.addDependency(e),this.addDependency(t)},compute:function(){var e=o.read(this.isTruthy);return"boolean"==typeof e?e:this.lengthDep?0!==this.lengthDep.getValue():!!o.read(this.predicate)},revalidate:function(){n.isArray(o.read(this.predicate))?this.lengthDep||(this.lengthDep=this.addMutableDependency(this.predicate.get("length"))):this.lengthDep&&(this.lengthDep.destroy(),this.lengthDep=null)}})}),e("ember-views/streams/utils",["exports","ember-metal/debug","ember-metal/property_get","ember-metal/streams/utils","ember-runtime/mixins/controller"],function(e,t,r,n,i){"use strict";function o(e,t){var r,i=n.read(e);return r="string"==typeof i?t._lookupFactory("view:"+i):i}function a(e,t){var r=n.read(e),i=t.lookup("component-lookup:main");return i.lookupFactory(r,t)}function s(e){if(n.isStream(e)){var t=e.value();if("controller"!==e.label)for(;i.default.detect(t);)t=r.get(t,"model");return t}return e}e.readViewFactory=o,e.readComponentFactory=a,e.readUnwrappedModel=s}),e("ember-views/system/action_manager",["exports"],function(e){"use strict";function t(){}t.registeredActions={},e.default=t}),e("ember-views/system/build-component-template",["exports","ember-metal/debug","ember-metal/property_get","ember-metal/assign","htmlbars-runtime","ember-htmlbars/hooks/get-value","ember-metal/streams/utils"],function(e,t,r,n,i,o,a){"use strict";function s(e,t,r){var n,o,a=e.component,s=e.tagName,u=e.layout,c=e.isAngleBracket,b=e.isComponentElement,g=e.outerAttrs;if(void 0===a&&(a=null),u&&u.raw){var _=d(r.templates,r.scope,r.self,a);n=p(u.raw,_,r.self,a,t),o=u.raw.meta}else r.templates&&r.templates.default&&(n=f(r.templates.default,r.scope,r.self,a),o=r.templates.default.meta);if(a&&!a._isAngleBracket||b)if(s=s||m(a),""!==s){b&&(t=l(t,g));var w=v(a,c,t),x=i.internal.manualElement(s,w);x.meta=o,n=h(x,n,a)}else y(a);return{createdElement:!!s,block:n}}function u(e,t,r){var n={};for(var o in t){var a=t[o];"string"==typeof a?n[o]=a:n[o]=["value",a]}var s=r.templates.default,u=i.internal.manualElement(e,n,s.isEmpty);if(s.isEmpty)return c(u,{scope:r.scope});var l=c(r.templates.default,r);return c(u,{yieldTo:l,scope:r.scope})}function l(e,t){var r=n.default({},e,t);return e.class&&t.class&&(r.class=["subexpr","-join-classes",[["value",e.class],["value",t.class]],[]]),r}function c(e,t){return i.internal.blockFor(i.render,e,t)}function f(e,t,r,n){return c(e,{scope:t,self:r,options:{view:n}})}function d(e,t,r,n){if(e){var i={};for(var o in e)if(e.hasOwnProperty(o)){var a=e[o];a&&(i[o]=f(e[o],t,r,n))}return i}}function p(e,t,r,n,i){return c(e,{yieldTo:t,self:r||n,options:{view:n,attrs:i}})}function h(e,t,r){return c(e,{yieldTo:t,self:r,options:{view:r}})}function m(e){var t=e.tagName;return null!==t&&"object"==typeof t&&t.isDescriptor&&(t=r.get(e,"tagName")),null!==t&&void 0!==t||(t=e._defaultTagName||"div"),t}function v(e,t,n){var i,a,s={},u=e.attributeBindings,l=e.isComponent?"":"view.";if(n.id&&o.default(n.id)?(s.id=o.default(n.id),e.elementId=s.id):s.id=e.elementId,u)for(i=0,a=u.length;i1;return!t&&!r}function r(e){var t=document.createRange();return t.setStartBefore(e._renderNode.firstNode),t.setEndAfter(e._renderNode.lastNode),t}function n(e){var t=r(e);return t.getClientRects()}function i(e){var t=r(e);return t.getBoundingClientRect()}e.isSimpleClick=t,e.getViewClientRects=n,e.getViewBoundingClientRect=i}),e("ember-views/views/checkbox",["exports","ember-metal/property_get","ember-metal/property_set","ember-views/components/component"],function(e,t,r,n){"use strict";e.default=n.default.extend({instrumentDisplay:'{{input type="checkbox"}}',classNames:["ember-checkbox"],tagName:"input",attributeBindings:["type","checked","indeterminate","disabled","tabindex","name","autofocus","required","form"],type:"checkbox",checked:!1,disabled:!1,indeterminate:!1,didInsertElement:function(){this._super.apply(this,arguments),t.get(this,"element").indeterminate=!!t.get(this,"indeterminate")},change:function(){r.set(this,"checked",this.$().prop("checked"))}})}),e("ember-views/views/core_view",["exports","ember-metal/debug","ember-metal/property_get","ember-runtime/system/object","ember-runtime/mixins/evented","ember-runtime/mixins/action_handler","ember-runtime/utils","ember-metal-views","ember-views/views/states","htmlbars-runtime","require"],function(e,t,r,n,i,o,a,s,u,l,c){"use strict";function f(){return h=h||c.default("ember-htmlbars/system/dom-helper").default}var d,p=n.default.extend(i.default,o.default,{isView:!0,_states:u.cloneStates(u.states),init:function(){if(this._super.apply(this,arguments),this._state="preRender",this._currentState=this._states.preRender,this._isVisible=r.get(this,"isVisible"),!this.renderer){var e=f();d=d||s.InteractiveRenderer.create({dom:new e}),this.renderer=d}this._destroyingSubtreeForView=null,this._dispatching=null},parentView:null,instrumentName:"core_view",instrumentDetails:function(e){e.object=this.toString(),e.containerKey=this._debugContainerKey,e.view=this},trigger:function(){this._super.apply(this,arguments);var e=arguments[0],t=this[e];if(t){for(var r=arguments.length,n=new Array(r-1),i=1;i":">",'"':""","'":"'","`":"`"},l=/[&<>"'`]/g,c=/[&<>"'`]/,f=Object.prototype.toString;e.toString=f;var d=function(e){return"function"==typeof e};d(/x/)&&(e.isFunction=d=function(e){return"function"==typeof e&&"[object Function]"===f.call(e)});var d;e.isFunction=d;var p=Array.isArray||function(e){return!(!e||"object"!=typeof e)&&"[object Array]"===f.call(e)};e.isArray=p}),e("htmlbars-util/morph-utils",["exports"],function(e){"use strict";function t(e,t){if(e&&0!==e.length)for(e=e.slice();e.length;){var r=e.pop();if(t(r),r.childNodes)e.push.apply(e,r.childNodes);else if(r.firstChildMorph)for(var n=r.firstChildMorph;n;)e.push(n),n=n.nextMorph;else if(r.morphList)for(var n=r.morphList.firstChildMorph;n;)e.push(n),n=n.nextMorph}}function r(e,t,n){var i=t.morphList;if(t.morphList)for(var o=i.firstChildMorph;o;){var a=o.nextMorph;r(e,o,n),o=a}else if(t.lastResult)t.lastResult.revalidateWith(e,void 0,void 0,void 0,n);else if(t.childNodes)for(var s=0,u=t.childNodes.length;s2&&"[]"===a.slice(s-2)&&(u=!0,a=a.slice(0,s-2),r[a]||(r[a]=[])),i=o[1]?h(o[1]):""),u?r[a].push(i):r[a]=i}return r},recognize:function(e){var t,r,n,i,o=[this.rootState],a={},s=!1;if(i=e.indexOf("?"),i!==-1){var u=e.substr(i+1,e.length);e=e.substr(0,i),a=this.parseQueryString(u)}for(e=decodeURI(e),"/"!==e.charAt(0)&&(e="/"+e),t=e.length,t>1&&"/"===e.charAt(t-1)&&(e=e.substr(0,t-1),s=!0),r=0,n=e.length;r=0;--l){var c=a[l];n.merge(u,c.params),c.handler.inaccessibleByURL&&(i=null)}if(i){u.queryParams=e._visibleQueryParams||t.queryParams;var f=o.recognizer.generate(s,u);"replace"===i?o.replaceURL(f):o.updateURL(f)}}}function v(e,t){try{n.log(e.router,e.sequence,"Resolved all models on destination route; finalizing transition.");var i=e.router,a=t.handlerInfos;e.sequence;return d(i,t,e),e.isAborted?(i.state.handlerInfos=i.currentHandlerInfos,r.default.reject(o.logAbort(e))):(m(e,t,e.intent.url),e.isActive=!1,i.activeTransition=null,n.trigger(i,i.currentHandlerInfos,!0,["didTransition"]),i.didTransition&&i.didTransition(i.currentHandlerInfos),n.log(i,e.sequence,"TRANSITION COMPLETE."),a[a.length-1].handler)}catch(t){if(!(t instanceof o.TransitionAborted)){var s=e.state.handlerInfos;e.trigger(!0,"error",t,e,s[s.length-1].handler),e.abort()}throw t}}function b(e,t,r){var i=t[0]||"/",o=t[t.length-1],u={};o&&o.hasOwnProperty("queryParams")&&(u=w.call(t).queryParams);var l;if(0===t.length){n.log(e,"Updating query params");var c=e.state.handlerInfos;l=new a.default({name:c[c.length-1].name,contexts:[],queryParams:u})}else"/"===i.charAt(0)?(n.log(e,"Attempting URL transition to "+i),l=new s.default({url:i})):(n.log(e,"Attempting transition to "+i),l=new a.default({name:t[0],contexts:n.slice.call(t,1),queryParams:u}));return e.transitionByIntent(l,r)}function g(e,t){if(e.length!==t.length)return!1;for(var r=0,n=e.length;r=0&&n;--r){var i=t[r];e.add(t,{as:i.handler}),n="/"===i.path||""===i.path||".index"===i.handler.slice(-6)}})},hasRoute:function(e){return this.recognizer.hasRoute(e)},getHandler:function(){},queryParamsTransition:function(e,t,r,i){var a=this;if(f(this,i,e),!t&&this.activeTransition)return this.activeTransition;var s=new o.Transition(this);return s.queryParamsOnly=!0,r.queryParams=y(this,i.handlerInfos,i.queryParams,s),s.promise=s.promise.then(function(e){return m(s,r,!0),a.didTransition&&a.didTransition(a.currentHandlerInfos),e},null,n.promiseLabel("Transition complete")),s},transitionByIntent:function(e,t){try{return c.apply(this,arguments)}catch(t){return new o.Transition(this,e,null,t)}},reset:function(){this.state&&n.forEach(this.state.handlerInfos.slice().reverse(),function(e){var t=e.handler;n.callHook(t,"exit")}),this.state=new i.default,this.currentHandlerInfos=null},activeTransition:null,handleURL:function(e){var t=n.slice.call(arguments);return"/"!==e.charAt(0)&&(t[0]="/"+e),b(this,t).method(null)},updateURL:function(){throw new Error("updateURL is not implemented")},replaceURL:function(e){this.updateURL(e)},transitionTo:function(e){return b(this,arguments)},intermediateTransitionTo:function(e){return b(this,arguments,!0)},refresh:function(e){for(var t=this.activeTransition?this.activeTransition.state:this.state,r=t.handlerInfos,i={},o=0,s=r.length;o=0;--u){var p=t[u],h=p.handler,m=n(h),v=e.handlerInfos[u],b=null;if(b=p.names.length>0?u>=d?this.createParamHandlerInfo(h,m,p.names,f,v):this.getHandlerInfoForDynamicSegment(h,m,p.names,f,v,o,u):this.createParamHandlerInfo(h,m,p.names,f,v),s){b=b.becomeResolved(null,b.context);var g=v&&v.context;p.names.length>0&&b.context===g&&(b.params=v&&v.params),b.context=g}var y=v;(u>=d||b.shouldSupercede(v))&&(d=Math.min(u,d),y=b),a&&!s&&(y=y.becomeResolved(null,y.context)),c.handlerInfos.unshift(y)}if(f.length>0)throw new Error("More context objects were passed than there are dynamic segments for the route: "+o);return a||this.invalidateChildren(c.handlerInfos,d),i.merge(c.queryParams,this.queryParams||{}),c},invalidateChildren:function(e,t){for(var r=t,n=e.length;r0){if(l=o[o.length-1],i.isParam(l))return this.createParamHandlerInfo(e,t,r,o,a);o.pop()}else{if(a&&a.name===e)return a;if(!this.preTransitionState)return a;var c=this.preTransitionState.handlerInfos[u];l=c&&c.context}return n.default("object",{name:e,handler:t,context:l,names:r})},createParamHandlerInfo:function(e,t,r,o,a){for(var s={},u=r.length;u--;){var l=a&&e===a.name&&a.params||{},c=o[o.length-1],f=r[u];if(i.isParam(c))s[f]=""+o.pop();else{if(!l.hasOwnProperty(f))throw new Error("You didn't provide enough string/numeric parameters to satisfy all of the dynamic segments for route "+e);s[f]=l[f]}}return n.default("param",{name:e,handler:t,params:s})}})}),e("router/transition-intent/url-transition-intent",["exports","router/transition-intent","router/transition-state","router/handler-info/factory","router/utils","router/unrecognized-url-error"],function(e,t,r,n,i,o){"use strict";e.default=i.subclass(t.default,{url:null,initialize:function(e){this.url=e.url},applyToState:function(e,t,a){var s,u,l=new r.default,c=t.recognize(this.url);if(!c)throw new o.default(this.url);var f=!1;for(s=0,u=c.length;s=r.length?r.length-1:t.resolveIndex;return n.default.reject({error:e,handlerWithError:l.handlerInfos[i].handler,wasAborted:c,state:l})}function a(e){var n=l.handlerInfos[t.resolveIndex].isResolved;if(l.handlerInfos[t.resolveIndex++]=e,!n){var o=e.handler;r.callHook(o,"redirect",e.context,t)}return i().then(s,null,l.promiseLabel("Resolve handler"))}function s(){if(t.resolveIndex===l.handlerInfos.length)return{error:null,state:l};var e=l.handlerInfos[t.resolveIndex];return e.resolve(i,t).then(a,null,l.promiseLabel("Proceed"))}var u=this.params;r.forEach(this.handlerInfos,function(e){u[e.name]=e.params||{}}),t=t||{},t.resolveIndex=0;var l=this,c=!1;return n.default.resolve(null,this.promiseLabel("Start transition")).then(s,null,this.promiseLabel("Resolve handler")).catch(o,this.promiseLabel("Handle error"))}},e.default=i}),e("router/transition",["exports","rsvp/promise","router/handler-info","router/utils"],function(e,t,r,n){"use strict";function i(e,r,a,s){function u(){if(l.isAborted)return t.default.reject(void 0,n.promiseLabel("Transition aborted - reject"))}var l=this;if(this.state=a||e.state,this.intent=r,this.router=e,this.data=this.intent&&this.intent.data||{},this.resolvedModels={},this.queryParams={},s)return this.promise=t.default.reject(s),void(this.error=s);if(a){this.params=a.params,this.queryParams=a.queryParams,this.handlerInfos=a.handlerInfos;var c=a.handlerInfos.length;c&&(this.targetName=a.handlerInfos[c-1].name);for(var f=0;f0&&e[n-1]&&e[n-1].hasOwnProperty("queryParams")?(r=e[n-1].queryParams,t=v.call(e,0,n-1),[t,r]):[e,null]}function n(e){for(var t in e)if("number"==typeof e[t])e[t]=""+e[t];else if(b(e[t]))for(var r=0,n=e[t].length;r=0;a--){var s=t[a],u=s.handler;if(u.events&&u.events[i]){if(u.events[i].apply(u,n)!==!0)return;o=!0}}if(!o&&!r)throw new Error("Nothing handled the event '"+i+"'.")}function l(e,r){var i,o={all:{},changed:{},removed:{}};t(o.all,r);var a=!1;n(e),n(r);for(i in e)e.hasOwnProperty(i)&&(r.hasOwnProperty(i)||(a=!0,o.removed[i]=e[i]));for(i in r)if(r.hasOwnProperty(i))if(b(e[i])&&b(r[i]))if(e[i].length!==r[i].length)o.changed[i]=r[i],a=!0;else for(var s=0,u=e[i].length;s1)throw new Error("Second argument not supported");if("object"!=typeof e)throw new TypeError("Argument must be an object");return i.prototype=e,new i};e.o_create=u}),e("vertex",["exports"],function(e){"use strict";function t(e){this.name=e,this.incoming={},this.incomingNames=[],this.hasOutgoing=!1,this.value=null}e.default=t}),e("visit",["exports"],function(e){"use strict";function t(e,r,n,i){var o,a=e.name,s=e.incoming,u=e.incomingNames,l=u.length;if(n||(n={}),i||(i=[]),!n.hasOwnProperty(a)){for(i.push(a),n[a]=!0,o=0;o=500&&e<600}function x(e){var t=parseInt(e,10);return t>=200&&t<300||304===t}e.AjaxError=r,e.InvalidError=n,e.UnauthorizedError=i,e.ForbiddenError=o,e.BadRequestError=a,e.NotFoundError=s,e.TimeoutError=u,e.AbortError=l,e.ConflictError=c,e.ServerError=f,e.isAjaxError=d,e.isUnauthorizedError=p,e.isForbiddenError=h,e.isInvalidError=m,e.isBadRequestError=v,e.isNotFoundError=b,e.isTimeoutError=g,e.isAbortError=y,e.isConflictError=_,e.isServerError=w,e.isSuccess=x;var k=t.default.Error;r.prototype=Object.create(k.prototype),n.prototype=Object.create(r.prototype),i.prototype=Object.create(r.prototype),o.prototype=Object.create(r.prototype),a.prototype=Object.create(r.prototype),s.prototype=Object.create(r.prototype),u.prototype=Object.create(r.prototype),l.prototype=Object.create(r.prototype),c.prototype=Object.create(r.prototype),f.prototype=Object.create(r.prototype)}),define("ember-ajax/index",["exports","ember-ajax/request"],function(e,t){"use strict";Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})}),define("ember-ajax/mixins/ajax-request",["exports","ember","ember-ajax/errors","ember-ajax/utils/parse-response-headers","ember-ajax/utils/url-helpers","ember-ajax/utils/ajax"],function(e,t,r,n,i,o){"use strict";function a(e){return!w(e)&&0===e.indexOf(T)}function s(e){return"/"===e.charAt(0)}function u(e){return"/"===e.charAt(e.length-1)}function l(e){return s(e)&&(e=e.substring(1)),u(e)&&(e=e.slice(0,-1)),e}function c(e){return"object"==typeof e}function f(e){return"string"==typeof e}var d=t.default.$,p=t.default.A,h=t.default.Error,m=t.default.Logger,v=t.default.Mixin,b=t.default.RSVP.Promise,g=t.default.Test,y=t.default.get,_=t.default.isArray,w=t.default.isNone,x=t.default.merge,k=t.default.run,E=t.default.runInDebug,C=t.default.testing,O=t.default.warn,T="application/vnd.api+json",N=0;C&&g.registerWaiter(function(){return 0===N}),e.default=v.create({contentType:"application/x-www-form-urlencoded; charset=UTF-8",headers:{},request:function(e,t){var r=this,n=this.options(e,t);return new b(function(t,i){r._makeRequest(e,n).then(function(e){var r=e.response;t(r)}).catch(function(e){var t=e.response;i(t)})},"ember-ajax: "+n.type+" "+n.url+" response")},raw:function(e,t){var r=this.options(e,t);return this._makeRequest(e,r)},_makeRequest:function(e,t){var i=this,s={type:t.type,url:t.url};return a(t.headers["Content-Type"])&&"GET"!==s.type&&"object"==typeof t.data&&(t.data=JSON.stringify(t.data)),new b(function(a,u){t.success=function(e,t,o){var l=i.handleResponse(o.status,(0,n.default)(o.getAllResponseHeaders()),e,s);N-=1,(0,r.isAjaxError)(l)?k.join(null,u,{payload:e,textStatus:t,jqXHR:o,response:l}):k.join(null,a,{payload:e,textStatus:t,jqXHR:o,response:l})},t.error=function(t,o,a){E(function(){var r="The server returned an empty string for "+s.type+" "+e+", which cannot be parsed into a valid JSON. Return either null or {}.",n=!("parsererror"===o&&""===t.responseText);O(r,n,{id:"ds.adapter.returned-empty-string-as-JSON"})});var l=i.parseErrorResponse(t.responseText)||a,c=void 0;c=a instanceof Error?a:"timeout"===o?new r.TimeoutError:"abort"===o?new r.AbortError:i.handleResponse(t.status,(0,n.default)(t.getAllResponseHeaders()),l,s),N-=1,k.join(null,u,{payload:l,textStatus:o,jqXHR:t,errorThrown:a,response:c})},N+=1,(0,o.default)(t)},"ember-ajax: "+t.type+" "+t.url)},post:function(e,t){return this.request(e,this._addTypeToOptionsFor(t,"POST"))},put:function(e,t){return this.request(e,this._addTypeToOptionsFor(t,"PUT"))},patch:function(e,t){return this.request(e,this._addTypeToOptionsFor(t,"PATCH"))},del:function(e,t){return this.request(e,this._addTypeToOptionsFor(t,"DELETE"))},delete:function(){return this.del.apply(this,arguments)},get:function(e){if(arguments.length>1||"/"===e.charAt(0))throw new h("It seems you tried to use `.get` to make a request! Use the `.request` method instead.");return this._super.apply(this,arguments)},_addTypeToOptionsFor:function(e,t){return e=e||{},e.type=t,e},_getFullHeadersHash:function(e){var t=y(this,"headers"),r=x({},t);return x(r,e)},options:function(e){var t=arguments.length<=1||void 0===arguments[1]?{}:arguments[1];return t.url=this._buildURL(e,t),t.type=t.type||"GET",t.dataType=t.dataType||"json",t.contentType=t.contentType||y(this,"contentType"),this._shouldSendHeaders(t)?t.headers=this._getFullHeadersHash(t.headers):t.headers=t.headers||{},t},_buildURL:function(e){var t=arguments.length<=1||void 0===arguments[1]?{}:arguments[1],r=new i.RequestURL(e);if(r.isComplete)return r.href;var n=t.host||y(this,"host"),o=t.namespace||y(this,"namespace");o&&(o=l(o));var a="";return n&&(a+=n),o&&(u(a)||(a+="/"),a+=o),e&&(s(e)||(a+="/"),a+=e),a},handleResponse:function(e,t,n,i){n=null===n||void 0===n?{}:n;var o=this.normalizeErrorResponse(e,t,n);if(this.isSuccess(e,t,n))return n;if(this.isUnauthorizedError(e,t,n))return new r.UnauthorizedError(o);if(this.isForbiddenError(e,t,n))return new r.ForbiddenError(o);if(this.isInvalidError(e,t,n))return new r.InvalidError(o);if(this.isBadRequestError(e,t,n))return new r.BadRequestError(o);if(this.isNotFoundError(e,t,n))return new r.NotFoundError(o);if(this.isAbortError(e,t,n))return new r.AbortError(o);if(this.isConflictError(e,t,n))return new r.ConflictError(o);if(this.isServerError(e,t,n))return new r.ServerError(o);var a=this.generateDetailedMessage(e,t,n,i);return new r.AjaxError(o,a)},_matchHosts:function(e,t){return t.constructor===RegExp?t.test(e):"string"==typeof t?t===e:(m.warn("trustedHosts only handles strings or regexes.",t,"is neither."),!1)},_shouldSendHeaders:function(e){var t=this,r=e.url,n=e.host;r=r||"",n=n||y(this,"host")||"";var o=new i.RequestURL(r),a=y(this,"trustedHosts")||p();if(!o.isComplete)return!0;if(a.find(function(e){return t._matchHosts(o.hostname,e)}))return!0;var s=new i.RequestURL(n);return o.sameHost(s)},generateDetailedMessage:function(e,t,r,n){var i=void 0,o=t["Content-Type"]||"Empty Content-Type";i="text/html"===o&&r.length>250?"[Omitted Lengthy HTML]":JSON.stringify(r);var a=n.type+" "+n.url,s="Payload ("+o+")";return["Ember AJAX Request "+a+" returned a "+e,s,i].join("\n")},isUnauthorizedError:function(e){return(0,r.isUnauthorizedError)(e)},isForbiddenError:function(e){return(0,r.isForbiddenError)(e)},isInvalidError:function(e){return(0,r.isInvalidError)(e)},isBadRequestError:function(e){return(0,r.isBadRequestError)(e)},isNotFoundError:function(e){return(0,r.isNotFoundError)(e)},isAbortError:function(e){return(0,r.isAbortError)(e)},isConflictError:function(e){return(0,r.isConflictError)(e)},isServerError:function(e){return(0,r.isServerError)(e)},isSuccess:function(e){return(0,r.isSuccess)(e)},parseErrorResponse:function(e){try{return d.parseJSON(e)}catch(t){return e}},normalizeErrorResponse:function(e,t,r){return _(r.errors)?r.errors.map(function(t){if(c(t)){var r=x({},t);return r.status=""+t.status,r}return{status:""+e,title:t}}):_(r)?r.map(function(t){return c(t)?{status:""+e,title:t.title||"The backend responded with an error",detail:t}:{status:""+e,title:""+t}}):f(r)?[{status:""+e,title:r}]:[{status:""+e,title:r.title||"The backend responded with an error",detail:r}]}})}),define("ember-ajax/mixins/ajax-support",["exports","ember"],function(e,t){"use strict";var r=t.default.Mixin,n=t.default.inject.service,i=t.default.computed.alias;e.default=r.create({ajaxService:n("ajax"),host:i("ajaxService.host"),namespace:i("ajaxService.namespace"),headers:i("ajaxService.headers"),ajax:function(e,t,r){return r=this.ajaxOptions.apply(this,arguments),this.get("ajaxService").request(e,r)},ajaxOptions:function(e,t){var r=arguments.length<=2||void 0===arguments[2]?{}:arguments[2];return r.type=t,this.get("ajaxService").options(e,r)}})}),define("ember-ajax/raw",["exports","ember-ajax/ajax-request"],function(e,t){"use strict";function r(){var e=new t.default;return e.raw.apply(e,arguments)}e.default=r}),define("ember-ajax/request",["exports","ember-ajax/ajax-request"],function(e,t){"use strict";function r(){var e=new t.default;return e.request.apply(e,arguments)}e.default=r}),define("ember-ajax/services/ajax",["exports","ember","ember-ajax/mixins/ajax-request"],function(e,t,r){"use strict";var n=t.default.Service;e.default=n.extend(r.default)}),define("ember-ajax/utils/ajax",["exports","ember","ember-ajax/utils/is-fastboot"],function(e,t,r){"use strict";var n=t.default.$;e.default=r.default?najax:n.ajax}),define("ember-ajax/utils/is-fastboot",["exports"],function(e){"use strict";var t="undefined"!=typeof FastBoot;e.default=t}),define("ember-ajax/utils/parse-response-headers",["exports"],function(e){"use strict";function t(e){return Array.isArray(e)?e:Array.from(e)}function r(e){var r={};if(!e)return r;var i=e.split(n);return i.forEach(function(e){var n=e.split(":"),i=t(n),o=i[0],a=i.slice(1);o=o.trim(),a=a.join(":").trim(),a&&(r[o]=a)}),r}e.default=r;var n="\r\n"}),define("ember-ajax/utils/url-helpers",["exports","ember-ajax/utils/is-fastboot"],function(e,t){"use strict";function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function n(){return t.default?URL:s?require("url"):document.createElement("a")}function i(e){var r=void 0;s||t.default?r=u.parse(e):(u.href=e,r=u);var n={};return n.href=r.href,n.protocol=r.protocol,n.hostname=r.hostname,n.port=r.port,n.pathname=r.pathname,n.search=r.search,n.hash=r.hash,n}var o=function(){function e(e,t){for(var r=0;r_&&(n=t[y-1],b=n[0],!b.test(e));y--);return n=n||[],b=n[0],i=n[1],o=e.replace(b,i)}},e.default=i}),define("ember-inflector/lib/system/string",["exports","ember-inflector/lib/system/inflector"],function(e,t){"use strict";function r(e){return t.default.inflector.pluralize(e)}function n(e){return t.default.inflector.singularize(e)}e.pluralize=r,e.singularize=n}),define("ember-inflector/lib/utils/make-helper",["exports","ember"],function(e,t){"use strict";function r(e){return t.default.Helper?t.default.Helper.helper(e):t.default.HTMLBars?t.default.HTMLBars.makeBoundHelper(e):t.default.Handlebars.makeBoundHelper(e)}e.default=r}),define("ember-load-initializers/index",["exports","ember"],function(e,t){"use strict";e.default=function(e,r){var n=new RegExp("^"+r+"/((?:instance-)?initializers)/"),i=Object.keys||t.default.keys;i(requirejs._eak_seen).map(function(e){return{moduleName:e,matches:n.exec(e)}}).filter(function(e){return e.matches&&2===e.matches.length}).forEach(function(r){var n=r.moduleName,i=require(n,null,null,!0);if(!i)throw new Error(n+" must export an initializer.");var o=t.default.String.camelize(r.matches[1].substring(0,r.matches[1].length-1)),a=i.default;if(!a.name){var s=n.match(/[^\/]+\/?$/)[0];a.name=s}e[o]&&e[o](a)})}}),define("ember-resolver/container-debug-adapter",["exports","ember","ember-resolver/utils/module-registry"],function(e,t,r){"use strict";function n(e,t,r){var n=t.match(new RegExp("^/?"+r+"/(.+)/"+e+"$"));if(n)return n[1]}var i=t.default.ContainerDebugAdapter,o=null;"undefined"!=typeof i&&(o=i.extend({_moduleRegistry:null,init:function(){this._super.apply(this,arguments),this._moduleRegistry||(this._moduleRegistry=new r.default)},canCatalogEntriesByType:function(){return!0},catalogEntriesByType:function(e){for(var r=this._moduleRegistry.moduleNames(),i=t.default.A(),o=this.namespace.modulePrefix,a=0,s=r.length;a1?r[0]+":"+t.default.String.dasherize(r[1].replace(/\./g,"/")):e},pluralize:function(e){return this.pluralizedTypes[e]||(this.pluralizedTypes[e]=e+"s")},podBasedLookupWithPrefix:function(e,t){var r=t.fullNameWithoutType;return"template"===t.type&&(r=r.replace(/^components\//,"")),e+"/"+r+"/"+t.type},podBasedModuleName:function(e){var t=this.namespace.podModulePrefix||this.namespace.modulePrefix;return this.podBasedLookupWithPrefix(t,e)},podBasedComponentsInSubdir:function(e){var t=this.namespace.podModulePrefix||this.namespace.modulePrefix;if(t+="/components","component"===e.type||e.fullNameWithoutType.match(/^components/))return this.podBasedLookupWithPrefix(t,e)},mainModuleName:function(e){var t=e.prefix+"/"+e.type;if("main"===e.fullNameWithoutType)return t},defaultModuleName:function(e){return e.prefix+"/"+this.pluralize(e.type)+"/"+e.fullNameWithoutType},prefix:function(e){var t=this.namespace.modulePrefix;return this.namespace[e.type+"Prefix"]&&(t=this.namespace[e.type+"Prefix"]),t},moduleNameLookupPatterns:t.default.computed(function(){return[this.podBasedModuleName,this.podBasedComponentsInSubdir,this.mainModuleName,this.defaultModuleName]}),findModuleName:function(e,t){for(var r,n=this.get("moduleNameLookupPatterns"),i=0,o=n.length;i60?".":new Array(60-r.fullName.length).join("."),n||(n=this.lookupDescription(r)),t.default.Logger.info(i,r.fullName,o,n)}},knownForType:function(e){for(var t=this._moduleRegistry.moduleNames(),r=(0,i.default)(),n=0,o=t.length;nn.length+i.length)return e+":"+t.slice(o+n.length,a);var s=this.pluralize(e),u=r+"/"+s+"/";return 0===t.indexOf(u)&&t.length>u.length?e+":"+t.slice(u.length):void 0},_extractDefaultExport:function(e){var t=require(e,null,null,!0);return t&&t.default&&(t=t.default),t}});d.reopenClass({moduleBasedResolver:!0}),e.default=d}),define("ember-resolver/utils/class-factory",["exports"],function(e){"use strict";function t(e){return{create:function(t){return"function"==typeof e.extend?e.extend(t):e}}}e.default=t}),define("ember-resolver/utils/create",["exports","ember"],function(e,t){"use strict";var r=Object.create||t.default.create;if(!r||r(null).hasOwnProperty)throw new Error("This browser does not support Object.create(null), please polyfil with es5-sham: http://git.io/yBU2rg");e.default=r}),define("ember-resolver/utils/make-dictionary",["exports","ember-resolver/utils/create"],function(e,t){"use strict";function r(){var e=(0,t.default)(null);return e._dict=null,delete e._dict,e}e.default=r}),define("ember-resolver/utils/module-registry",["exports","ember"],function(e,t){"use strict";function r(e){this._entries=e||requirejs.entries}"undefined"==typeof requirejs.entries&&(requirejs.entries=requirejs._eak_seen),r.prototype.moduleNames=function(){return(Object.keys||t.default.keys)(this._entries)},r.prototype.has=function(e){return e in this._entries},r.prototype.get=function(e){var t=arguments.length<=1||void 0===arguments[1]?"default":arguments[1],r=require(e);return r&&r[t]},e.default=r}); \ No newline at end of file diff --git a/bench/implementations/ember-2.6.3/dist/assets/vendor-7b5c98520910afa58d74e05ec86cd873.css b/bench/implementations/ember-2.6.3/dist/assets/vendor-7b5c98520910afa58d74e05ec86cd873.css new file mode 100644 index 0000000..3f5cff9 --- /dev/null +++ b/bench/implementations/ember-2.6.3/dist/assets/vendor-7b5c98520910afa58d74e05ec86cd873.css @@ -0,0 +1 @@ +#issue-count,.hidden,label[for=toggle-all]{display:none}#footer,#info,#todoapp h1,#toggle-all{text-align:center}hr{margin:20px 0;border:0;border-top:1px dashed #c5c5c5;border-bottom:1px dashed #f7f7f7}.learn a{font-weight:400;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 p:after,.quote p:before{font-size:50px;opacity:.15;position:absolute}.quote{border:none;margin:20px 0 60px}.quote p{font-style:italic}.quote p:before{content:'“';top:-20px;left:3px}.quote p:after{content:'”';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)}.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:.5s}#main,#new-todo,#todo-list li,#todoapp,.edit{position:relative}@media (min-width:899px){.learn-bar{width:auto;padding-left:300px}.learn-bar>.learn{left:8px}}body,button,html{padding:0;margin:0}button{border:0;background:0 0;font-size:100%;vertical-align:baseline;font-family:inherit;font-weight:inherit;color:inherit;-webkit-appearance:none;appearance:none;-webkit-font-smoothing:antialiased;-moz-font-smoothing:antialiased;font-smoothing:antialiased}body{font:14px 'Helvetica Neue',Helvetica,Arial,sans-serif;line-height:1.4em;background:#f5f5f5;color:#4d4d4d;min-width:230px;max-width:550px;margin:0 auto;-webkit-font-smoothing:antialiased;-moz-font-smoothing:antialiased;font-smoothing:antialiased;font-weight:300}button,input[type=checkbox]{outline:0}#todoapp{background:#fff;margin:130px 0 40px;box-shadow:0 2px 4px 0 rgba(0,0,0,.2),0 25px 50px 0 rgba(0,0,0,.1)}#todoapp input::-webkit-input-placeholder{font-style:italic;font-weight:300;color:#e6e6e6}#todoapp input::-moz-placeholder{font-style:italic;font-weight:300;color:#e6e6e6}#todoapp input::input-placeholder{font-style:italic;font-weight:300;color:#e6e6e6}#todoapp h1{position:absolute;top:-155px;width:100%;font-size:100px;font-weight:100;color:rgba(175,47,47,.15);-webkit-text-rendering:optimizeLegibility;-moz-text-rendering:optimizeLegibility;text-rendering:optimizeLegibility}#new-todo,.edit{margin:0;width:100%;font-size:24px;font-family:inherit;font-weight:inherit;line-height:1.4em;outline:0;color:inherit;padding:6px;border:1px solid #999;box-shadow:inset 0 -1px 5px 0 rgba(0,0,0,.2);box-sizing:border-box;-webkit-font-smoothing:antialiased;-moz-font-smoothing:antialiased;font-smoothing:antialiased}#new-todo{padding:16px 16px 16px 60px;border:none;background:rgba(0,0,0,.003);box-shadow:inset 0 -2px 1px rgba(0,0,0,.03)}#main{z-index:2;border-top:1px solid #e6e6e6}#toggle-all{position:absolute;top:-55px;left:-12px;width:60px;height:34px;border:none}#toggle-all:before{content:'❯';font-size:22px;color:#e6e6e6;padding:10px 27px}#toggle-all:checked:before{color:#737373}#todo-list{margin:0;padding:0;list-style:none}#todo-list li{font-size:24px;border-bottom:1px solid #ededed}#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;margin:0 0 0 43px}#todo-list li.editing .view{display:none}#todo-list li .toggle{text-align:center;width:40px;height:auto;position:absolute;top:0;bottom:0;margin:auto 0;border:none;-webkit-appearance:none;appearance:none}#todo-list li .toggle:after{content:url('data:image/svg+xml;utf8,')}#todo-list li .toggle:checked:after{content:url('data:image/svg+xml;utf8,')}#todo-list li label{white-space:pre;word-break:break-word;padding:15px 60px 15px 15px;margin-left:45px;display:block;line-height:1.2;transition:color .4s}#todo-list li.completed label{color:#d9d9d9;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 11px;font-size:30px;color:#cc9a9a;transition:color .2s ease-out}#filters,#footer:before{position:absolute;right:0;left:0}#todo-list li .destroy:hover{color:#af5b5e}#filters li a,#info a{color:inherit;text-decoration:none}#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:10px 15px;height:20px;border-top:1px solid #e6e6e6}#footer:before{content:'';bottom:0;height:50px;overflow:hidden;box-shadow:0 1px 1px rgba(0,0,0,.2),0 8px 0 -3px #f6f6f6,0 9px 1px -3px rgba(0,0,0,.2),0 16px 0 -6px #f6f6f6,0 17px 2px -6px rgba(0,0,0,.2)}#todo-count{float:left;text-align:left}#todo-count strong{font-weight:300}#filters{margin:0;padding:0;list-style:none}#filters li{display:inline}#filters li a{margin:3px;padding:3px 7px;border:1px solid transparent;border-radius:3px}#filters li a.selected,#filters li a:hover{border-color:rgba(175,47,47,.1)}#filters li a.selected{border-color:rgba(175,47,47,.2)}#clear-completed,html #clear-completed:active{float:right;line-height:20px;text-decoration:none;cursor:pointer;position:relative}#clear-completed:hover,#info a:hover{text-decoration:underline}#info{margin:65px auto 0;color:#bfbfbf;font-size:10px;text-shadow:0 1px 0 rgba(255,255,255,.5)}#info p{line-height:1}#info a{font-weight:400}@media screen and (-webkit-min-device-pixel-ratio:0){#todo-list li .toggle,#toggle-all{background:0 0}#todo-list li .toggle{height:40px}#toggle-all{-webkit-transform:rotate(90deg);transform:rotate(90deg);-webkit-appearance:none;appearance:none}}@media (max-width:430px){#footer{height:50px}#filters{bottom:10px}} \ No newline at end of file diff --git a/bench/implementations/ember-2.6.3/dist/crossdomain.xml b/bench/implementations/ember-2.6.3/dist/crossdomain.xml new file mode 100755 index 0000000..0c16a7a --- /dev/null +++ b/bench/implementations/ember-2.6.3/dist/crossdomain.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/bench/implementations/ember-2.6.3/dist/index.html b/bench/implementations/ember-2.6.3/dist/index.html new file mode 100644 index 0000000..c8ff116 --- /dev/null +++ b/bench/implementations/ember-2.6.3/dist/index.html @@ -0,0 +1,25 @@ + + + + + + Todomvc + + + + + + + + + + + + + + + + + + + diff --git a/bench/implementations/ember-2.6.3/dist/robots.txt b/bench/implementations/ember-2.6.3/dist/robots.txt new file mode 100755 index 0000000..f591645 --- /dev/null +++ b/bench/implementations/ember-2.6.3/dist/robots.txt @@ -0,0 +1,3 @@ +# http://www.robotstxt.org +User-agent: * +Disallow: diff --git a/bench/implementations/ember-2.6.3/ember-cli-build.js b/bench/implementations/ember-2.6.3/ember-cli-build.js new file mode 100755 index 0000000..f030642 --- /dev/null +++ b/bench/implementations/ember-2.6.3/ember-cli-build.js @@ -0,0 +1,26 @@ +/*jshint node:true*/ +/* global require, module */ +var EmberApp = require('ember-cli/lib/broccoli/ember-app'); + +module.exports = function (defaults) { + var app = new EmberApp(defaults, { + // Add options here + }); + + app.import('vendor/base.css'); + app.import('vendor/index.css'); + // Use `app.import` to add additional libraries to the generated + // output files. + // + // If you need to use different assets in different + // environments, specify an object as the first parameter. That + // object's keys should be the environment name and the values + // should be the asset to use in that environment. + // + // If the library that you are including contains AMD or ES6 + // modules that you would like to import into your application + // please specify an object with the list of modules as keys + // along with the exports of each module as its value. + + return app.toTree(); +}; diff --git a/bench/implementations/ember-2.6.3/package.json b/bench/implementations/ember-2.6.3/package.json new file mode 100755 index 0000000..3deaaa7 --- /dev/null +++ b/bench/implementations/ember-2.6.3/package.json @@ -0,0 +1,44 @@ +{ + "name": "todomvc", + "version": "0.0.0", + "description": "Small description for todomvc goes here", + "private": true, + "directories": { + "doc": "doc", + "test": "tests" + }, + "scripts": { + "build": "ember build", + "start": "ember server", + "test": "ember test", + "make": "bower install && ember build -prod" + }, + "repository": "", + "engines": { + "node": ">= 0.10.0" + }, + "author": "", + "license": "MIT", + "devDependencies": { + "bower": "*", + "broccoli-asset-rev": "^2.4.2", + "ember-ajax": "^2.0.1", + "ember-cli": "2.6.3", + "ember-cli-app-version": "^1.0.0", + "ember-cli-babel": "^5.1.6", + "ember-cli-dependency-checker": "^1.2.0", + "ember-cli-htmlbars": "^1.0.3", + "ember-cli-htmlbars-inline-precompile": "^0.3.1", + "ember-cli-inject-live-reload": "^1.4.0", + "ember-cli-jshint": "^1.0.0", + "ember-cli-qunit": "^1.4.0", + "ember-cli-release": "^0.2.9", + "ember-cli-sri": "^2.1.0", + "ember-cli-uglify": "^1.2.0", + "ember-export-application-global": "^1.0.5", + "ember-inflector": "1.9.4", + "ember-load-initializers": "^0.5.1", + "ember-resolver": "^2.0.3", + "loader.js": "^4.0.1" + } +} diff --git a/bench/implementations/ember-2.6.3/public/crossdomain.xml b/bench/implementations/ember-2.6.3/public/crossdomain.xml new file mode 100755 index 0000000..0c16a7a --- /dev/null +++ b/bench/implementations/ember-2.6.3/public/crossdomain.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/bench/implementations/ember-2.6.3/public/robots.txt b/bench/implementations/ember-2.6.3/public/robots.txt new file mode 100755 index 0000000..f591645 --- /dev/null +++ b/bench/implementations/ember-2.6.3/public/robots.txt @@ -0,0 +1,3 @@ +# http://www.robotstxt.org +User-agent: * +Disallow: diff --git a/bench/implementations/ember-2.6.3/testem.js b/bench/implementations/ember-2.6.3/testem.js new file mode 100755 index 0000000..7564502 --- /dev/null +++ b/bench/implementations/ember-2.6.3/testem.js @@ -0,0 +1,13 @@ +/*jshint node:true*/ +module.exports = { + framework: 'qunit', + test_page: 'tests/index.html?hidepassed', + disable_watching: true, + launch_in_ci: [ + 'PhantomJS' + ], + launch_in_dev: [ + 'PhantomJS', + 'Chrome' + ] +}; diff --git a/bench/implementations/ember-2.6.3/vendor/base.css b/bench/implementations/ember-2.6.3/vendor/base.css new file mode 100755 index 0000000..da65968 --- /dev/null +++ b/bench/implementations/ember-2.6.3/vendor/base.css @@ -0,0 +1,141 @@ +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; +} + +#issue-count { + display: none; +} + +.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); +} + +.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) { + .learn-bar { + width: auto; + padding-left: 300px; + } + + .learn-bar > .learn { + left: 8px; + } +} diff --git a/bench/implementations/ember-2.6.3/vendor/index.css b/bench/implementations/ember-2.6.3/vendor/index.css new file mode 100755 index 0000000..54d89ab --- /dev/null +++ b/bench/implementations/ember-2.6.3/vendor/index.css @@ -0,0 +1,378 @@ +html, +body { + margin: 0; + padding: 0; +} + +button { + margin: 0; + padding: 0; + border: 0; + background: none; + font-size: 100%; + vertical-align: baseline; + font-family: inherit; + font-weight: inherit; + color: inherit; + -webkit-appearance: none; + appearance: none; + -webkit-font-smoothing: antialiased; + -moz-font-smoothing: antialiased; + font-smoothing: antialiased; +} + +body { + font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif; + line-height: 1.4em; + background: #f5f5f5; + color: #4d4d4d; + min-width: 230px; + max-width: 550px; + margin: 0 auto; + -webkit-font-smoothing: antialiased; + -moz-font-smoothing: antialiased; + font-smoothing: antialiased; + font-weight: 300; +} + +button, +input[type="checkbox"] { + outline: none; +} + +.hidden { + display: none; +} + +#todoapp { + background: #fff; + margin: 130px 0 40px 0; + position: relative; + box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), + 0 25px 50px 0 rgba(0, 0, 0, 0.1); +} + +#todoapp input::-webkit-input-placeholder { + font-style: italic; + font-weight: 300; + color: #e6e6e6; +} + +#todoapp input::-moz-placeholder { + font-style: italic; + font-weight: 300; + color: #e6e6e6; +} + +#todoapp input::input-placeholder { + font-style: italic; + font-weight: 300; + color: #e6e6e6; +} + +#todoapp h1 { + position: absolute; + top: -155px; + width: 100%; + font-size: 100px; + font-weight: 100; + text-align: center; + color: rgba(175, 47, 47, 0.15); + -webkit-text-rendering: optimizeLegibility; + -moz-text-rendering: optimizeLegibility; + text-rendering: optimizeLegibility; +} + +#new-todo, +.edit { + position: relative; + margin: 0; + width: 100%; + font-size: 24px; + font-family: inherit; + font-weight: 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); + box-sizing: border-box; + -webkit-font-smoothing: antialiased; + -moz-font-smoothing: antialiased; + font-smoothing: antialiased; +} + +#new-todo { + padding: 16px 16px 16px 60px; + border: none; + background: rgba(0, 0, 0, 0.003); + box-shadow: inset 0 -2px 1px rgba(0,0,0,0.03); +} + +#main { + position: relative; + z-index: 2; + border-top: 1px solid #e6e6e6; +} + +label[for='toggle-all'] { + display: none; +} + +#toggle-all { + position: absolute; + top: -55px; + left: -12px; + width: 60px; + height: 34px; + text-align: center; + border: none; /* Mobile Safari */ +} + +#toggle-all:before { + content: '❯'; + font-size: 22px; + color: #e6e6e6; + padding: 10px 27px 10px 27px; +} + +#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 solid #ededed; +} + +#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; + appearance: none; +} + +#todo-list li .toggle:after { + content: url('data:image/svg+xml;utf8,'); +} + +#todo-list li .toggle:checked:after { + content: url('data:image/svg+xml;utf8,'); +} + +#todo-list li label { + white-space: pre; + word-break: break-word; + padding: 15px 60px 15px 15px; + margin-left: 45px; + display: block; + line-height: 1.2; + transition: color 0.4s; +} + +#todo-list li.completed label { + color: #d9d9d9; + 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: 30px; + color: #cc9a9a; + margin-bottom: 11px; + transition: color 0.2s ease-out; +} + +#todo-list li .destroy:hover { + color: #af5b5e; +} + +#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: 10px 15px; + height: 20px; + text-align: center; + border-top: 1px solid #e6e6e6; +} + +#footer:before { + content: ''; + position: absolute; + right: 0; + bottom: 0; + left: 0; + height: 50px; + overflow: hidden; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), + 0 8px 0 -3px #f6f6f6, + 0 9px 1px -3px rgba(0, 0, 0, 0.2), + 0 16px 0 -6px #f6f6f6, + 0 17px 2px -6px rgba(0, 0, 0, 0.2); +} + +#todo-count { + float: left; + text-align: left; +} + +#todo-count strong { + font-weight: 300; +} + +#filters { + margin: 0; + padding: 0; + list-style: none; + position: absolute; + right: 0; + left: 0; +} + +#filters li { + display: inline; +} + +#filters li a { + color: inherit; + margin: 3px; + padding: 3px 7px; + text-decoration: none; + border: 1px solid transparent; + border-radius: 3px; +} + +#filters li a.selected, +#filters li a:hover { + border-color: rgba(175, 47, 47, 0.1); +} + +#filters li a.selected { + border-color: rgba(175, 47, 47, 0.2); +} + +#clear-completed, +html #clear-completed:active { + float: right; + position: relative; + line-height: 20px; + text-decoration: none; + cursor: pointer; + position: relative; +} + +#clear-completed:hover { + text-decoration: underline; +} + +#info { + margin: 65px auto 0; + color: #bfbfbf; + font-size: 10px; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + text-align: center; +} + +#info p { + line-height: 1; +} + +#info a { + color: inherit; + text-decoration: none; + font-weight: 400; +} + +#info a:hover { + text-decoration: underline; +} + +/* + Hack to remove background from Mobile Safari. + Can't use it globally since it destroys checkboxes in Firefox +*/ +@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 { + -webkit-transform: rotate(90deg); + transform: rotate(90deg); + -webkit-appearance: none; + appearance: none; + } +} + +@media (max-width: 430px) { + #footer { + height: 50px; + } + + #filters { + bottom: 10px; + } +} diff --git a/bench/implementations/inferno/dist/bundle.js b/bench/implementations/inferno/dist/bundle.js new file mode 100644 index 0000000..12a233a --- /dev/null +++ b/bench/implementations/inferno/dist/bundle.js @@ -0,0 +1,3248 @@ +/******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; + +/******/ // The require function +/******/ function __webpack_require__(moduleId) { + +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; + +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false +/******/ }; + +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); + +/******/ // Flag the module as loaded +/******/ module.loaded = true; + +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } + + +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; + +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; + +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = "dist"; + +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, exports, __webpack_require__) { + + 'use strict'; + + var _inferno = __webpack_require__(1); + + var _inferno2 = _interopRequireDefault(_inferno); + + var _infernoComponent = __webpack_require__(3); + + var _infernoComponent2 = _interopRequireDefault(_infernoComponent); + + var _share = __webpack_require__(5); + + var _base = __webpack_require__(6); + + var _model = __webpack_require__(7); + + var _model2 = _interopRequireDefault(_model); + + var _item = __webpack_require__(8); + + var _item2 = _interopRequireDefault(_item); + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + + function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + + function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + + var render = _inferno2.default.render; + + var model = new _model2.default(); + + var App = function (_Component) { + _inherits(App, _Component); + + function App() { + var _temp, _this, _ret; + + _classCallCheck(this, App); + + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + return _ret = (_temp = (_this = _possibleConstructorReturn(this, _Component.call.apply(_Component, [this].concat(args))), _this), _this.state = { + route: (0, _share.read)(), + todos: model.get() + }, _this.update = function (arr) { + return _this.setState({ todos: arr }); + }, _this.componentWillMount = function () { + window.onhashchange = function () { + return _this.setState({ route: (0, _share.read)() }); + }; + }, _this.add = function (e) { + if (e.which !== _share.ENTER) return; + + var val = e.target.value.trim(); + if (!val) return; + + e.target.value = ''; + _this.update(model.add(val)); + }, _this.edit = function (todo, val) { + val = val.trim(); + if (val.length) { + _this.update(model.put(todo, { title: val, editing: 0 })); + } else { + _this.remove(todo); + } + }, _this.focus = function (todo) { + return _this.update(model.put(todo, { editing: 1 })); + }, _this.blur = function (todo) { + return _this.update(model.put(todo, { editing: 0 })); + }, _this.remove = function (todo) { + return _this.update(model.del(todo)); + }, _this.toggleOne = function (todo) { + return _this.update(model.toggle(todo)); + }, _this.toggleAll = function (ev) { + return _this.update(model.toggleAll(ev.target.checked)); + }, _this.clearCompleted = function () { + return _this.update(model.clearCompleted()); + }, _temp), _possibleConstructorReturn(_this, _ret); + } + + App.prototype.render = function render(_, _ref) { + var _this2 = this; + + var todos = _ref.todos, + route = _ref.route; + + var num = todos.length; + var shown = todos.filter(_share.filters[route]); + var numDone = todos.filter(_share.filters.completed).length; + var numAct = num - numDone; + + return _inferno2.default.createVNode(2, 'div', null, [_inferno2.default.createVNode(16, _base.Head, { + 'onEnter': this.add + }), num ? _inferno2.default.createVNode(2, 'section', { + 'className': 'main' + }, [_inferno2.default.createVNode(512, 'input', { + 'className': 'toggle-all', + 'type': 'checkbox', + 'checked': numAct === 0 + }, null, { + 'onClick': this.toggleAll + }), _inferno2.default.createVNode(2, 'ul', { + 'className': 'todo-list' + }, shown.map(function (t) { + return _inferno2.default.createVNode(16, _item2.default, { + 'data': t, + 'onBlur': function onBlur() { + return _this2.blur(t); + }, + 'onFocus': function onFocus() { + return _this2.focus(t); + }, + 'doDelete': function doDelete() { + return _this2.remove(t); + }, + 'doSave': function doSave(val) { + return _this2.edit(t, val); + }, + 'doToggle': function doToggle() { + return _this2.toggleOne(t); + } + }); + }))]) : null, numAct || numDone ? _inferno2.default.createVNode(16, _base.Foot, { + 'onClear': this.clearCompleted, + 'left': numAct, + 'done': numDone, + 'route': route + }) : null]); + }; + + return App; + }(_infernoComponent2.default); + + render(_inferno2.default.createVNode(16, App), document.getElementById('app')); + +/***/ }), +/* 1 */ +/***/ (function(module, exports, __webpack_require__) { + + module.exports = __webpack_require__(2); + + +/***/ }), +/* 2 */ +/***/ (function(module, exports, __webpack_require__) { + + /*! + * inferno v1.0.0-beta32 + * (c) 2016 Dominic Gannaway + * Released under the MIT License. + */ + (function (global, factory) { + true ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.Inferno = global.Inferno || {}))); + }(this, (function (exports) { 'use strict'; + + var NO_OP = '$NO_OP'; + var ERROR_MSG = 'a runtime error occured! Use Inferno in development environment to find the error.'; + var isBrowser = typeof window !== 'undefined' && window.document; + + // this is MUCH faster than .constructor === Array and instanceof Array + // in Node 7 and the later versions of V8, slower in older versions though + var isArray = Array.isArray; + function isStatefulComponent(o) { + return !isUndefined(o.prototype) && !isUndefined(o.prototype.render); + } + function isStringOrNumber(obj) { + return isString(obj) || isNumber(obj); + } + function isNullOrUndef(obj) { + return isUndefined(obj) || isNull(obj); + } + function isInvalid(obj) { + return isNull(obj) || obj === false || isTrue(obj) || isUndefined(obj); + } + function isFunction(obj) { + return typeof obj === 'function'; + } + function isAttrAnEvent(attr) { + return attr[0] === 'o' && attr[1] === 'n' && attr.length > 3; + } + function isString(obj) { + return typeof obj === 'string'; + } + function isNumber(obj) { + return typeof obj === 'number'; + } + function isNull(obj) { + return obj === null; + } + function isTrue(obj) { + return obj === true; + } + function isUndefined(obj) { + return obj === undefined; + } + function isObject(o) { + return typeof o === 'object'; + } + function throwError(message) { + if (!message) { + message = ERROR_MSG; + } + throw new Error(("Inferno Error: " + message)); + } + function warning(condition, message) { + if (!condition) { + console.error(message); + } + } + var EMPTY_OBJ = {}; + + function cloneVNode(vNodeToClone, props) { + var _children = [], len = arguments.length - 2; + while ( len-- > 0 ) _children[ len ] = arguments[ len + 2 ]; + + var children = _children; + if (_children.length > 0 && !isNull(_children[0])) { + if (!props) { + props = {}; + } + if (_children.length === 1) { + children = _children[0]; + } + if (isUndefined(props.children)) { + props.children = children; + } + else { + if (isArray(children)) { + if (isArray(props.children)) { + props.children = props.children.concat(children); + } + else { + props.children = [props.children].concat(children); + } + } + else { + if (isArray(props.children)) { + props.children.push(children); + } + else { + props.children = [props.children]; + props.children.push(children); + } + } + } + } + children = null; + var flags = vNodeToClone.flags; + var events = vNodeToClone.events || (props && props.events) || null; + var newVNode; + if (isArray(vNodeToClone)) { + newVNode = vNodeToClone.map(function (vNode) { return cloneVNode(vNode); }); + } + else if (isNullOrUndef(props) && isNullOrUndef(children)) { + newVNode = Object.assign({}, vNodeToClone); + } + else { + var key = !isNullOrUndef(vNodeToClone.key) ? vNodeToClone.key : props.key; + var ref = vNodeToClone.ref || props.ref; + if (flags & 28 /* Component */) { + newVNode = createVNode(flags, vNodeToClone.type, Object.assign({}, vNodeToClone.props, props), null, events, key, ref, true); + } + else if (flags & 3970 /* Element */) { + children = (props && props.children) || vNodeToClone.children; + newVNode = createVNode(flags, vNodeToClone.type, Object.assign({}, vNodeToClone.props, props), children, events, key, ref, !children); + } + } + if (flags & 28 /* Component */) { + var newProps = newVNode.props; + if (newProps) { + var newChildren = newProps.children; + // we need to also clone component children that are in props + // as the children may also have been hoisted + if (newChildren) { + if (isArray(newChildren)) { + for (var i = 0; i < newChildren.length; i++) { + var child = newChildren[i]; + if (!isInvalid(child) && isVNode(child)) { + newProps.children[i] = cloneVNode(child); + } + } + } + else if (isVNode(newChildren)) { + newProps.children = cloneVNode(newChildren); + } + } + } + newVNode.children = null; + } + newVNode.dom = null; + return newVNode; + } + + function _normalizeVNodes(nodes, result, i) { + for (; i < nodes.length; i++) { + var n = nodes[i]; + if (!isInvalid(n)) { + if (Array.isArray(n)) { + _normalizeVNodes(n, result, 0); + } + else { + if (isStringOrNumber(n)) { + n = createTextVNode(n); + } + else if (isVNode(n) && n.dom) { + n = cloneVNode(n); + } + result.push(n); + } + } + } + } + function normalizeVNodes(nodes) { + var newNodes; + // we assign $ which basically means we've flagged this array for future note + // if it comes back again, we need to clone it, as people are using it + // in an immutable way + // tslint:disable + if (nodes['$']) { + nodes = nodes.slice(); + } + else { + nodes['$'] = true; + } + // tslint:enable + for (var i = 0; i < nodes.length; i++) { + var n = nodes[i]; + if (isInvalid(n)) { + if (!newNodes) { + newNodes = nodes.slice(0, i); + } + newNodes.push(n); + } + else if (Array.isArray(n)) { + var result = (newNodes || nodes).slice(0, i); + _normalizeVNodes(nodes, result, i); + return result; + } + else if (isStringOrNumber(n)) { + if (!newNodes) { + newNodes = nodes.slice(0, i); + } + newNodes.push(createTextVNode(n)); + } + else if (isVNode(n) && n.dom) { + if (!newNodes) { + newNodes = nodes.slice(0, i); + } + newNodes.push(cloneVNode(n)); + } + else if (newNodes) { + newNodes.push(cloneVNode(n)); + } + } + return newNodes || nodes; + } + function normalizeChildren(children) { + if (isArray(children)) { + return normalizeVNodes(children); + } + else if (isVNode(children) && children.dom) { + return cloneVNode(children); + } + return children; + } + function normalizeProps(vNode, props, children) { + if (!(vNode.flags & 28 /* Component */) && isNullOrUndef(children) && !isNullOrUndef(props.children)) { + vNode.children = props.children; + } + if (props.ref) { + vNode.ref = props.ref; + } + if (props.events) { + vNode.events = props.events; + } + if (!isNullOrUndef(props.key)) { + vNode.key = props.key; + } + } + function normalize(vNode) { + var props = vNode.props; + var children = vNode.children; + // convert a wrongly created type back to element + if (isString(vNode.type) && (vNode.flags & 28 /* Component */)) { + vNode.flags = 3970 /* Element */; + } + if (props) { + normalizeProps(vNode, props, children); + } + if (!isInvalid(children)) { + vNode.children = normalizeChildren(children); + } + if (props && !isInvalid(props.children)) { + props.children = normalizeChildren(props.children); + } + } + function createVNode(flags, type, props, children, events, key, ref, noNormalise) { + if (flags & 16 /* ComponentUnknown */) { + flags = isStatefulComponent(type) ? 4 /* ComponentClass */ : 8 /* ComponentFunction */; + } + var vNode = { + children: isUndefined(children) ? null : children, + dom: null, + events: events || null, + flags: flags || 0, + key: key === undefined ? null : key, + props: props || null, + ref: ref || null, + type: type + }; + if (!noNormalise) { + normalize(vNode); + } + return vNode; + } + function createVoidVNode() { + return createVNode(4096 /* Void */); + } + function createTextVNode(text) { + return createVNode(1 /* Text */, null, null, text); + } + function isVNode(o) { + return !!o.flags; + } + + var devToolsStatus = { + connected: false + }; + var internalIncrementer = { + id: 0 + }; + var componentIdMap = new Map(); + function getIncrementalId() { + return internalIncrementer.id++; + } + function sendToDevTools(global, data) { + var event = new CustomEvent('inferno.client.message', { + detail: JSON.stringify(data, function (key, val) { + if (!isNull(val) && !isUndefined(val)) { + if (key === '_vComponent' || !isUndefined(val.nodeType)) { + return; + } + else if (isFunction(val)) { + return ("$$f:" + (val.name)); + } + } + return val; + }) + }); + global.dispatchEvent(event); + } + function rerenderRoots() { + for (var i = 0; i < roots.length; i++) { + var root = roots[i]; + render(root.input, root.dom); + } + } + function initDevToolsHooks(global) { + global.__INFERNO_DEVTOOLS_GLOBAL_HOOK__ = roots; + global.addEventListener('inferno.devtools.message', function (message) { + var detail = JSON.parse(message.detail); + var type = detail.type; + switch (type) { + case 'get-roots': + if (!devToolsStatus.connected) { + devToolsStatus.connected = true; + rerenderRoots(); + sendRoots(global); + } + break; + default: + // TODO:? + break; + } + }); + } + function sendRoots(global) { + sendToDevTools(global, { type: 'roots', data: roots }); + } + + var Lifecycle = function Lifecycle() { + this.listeners = []; + this.fastUnmount = true; + }; + Lifecycle.prototype.addListener = function addListener (callback) { + this.listeners.push(callback); + }; + Lifecycle.prototype.trigger = function trigger () { + var this$1 = this; + + for (var i = 0; i < this.listeners.length; i++) { + this$1.listeners[i](); + } + }; + + function constructDefaults(string, object, value) { + /* eslint no-return-assign: 0 */ + string.split(',').forEach(function (i) { return object[i] = value; }); + } + var xlinkNS = 'http://www.w3.org/1999/xlink'; + var xmlNS = 'http://www.w3.org/XML/1998/namespace'; + var svgNS = 'http://www.w3.org/2000/svg'; + var strictProps = {}; + var booleanProps = {}; + var namespaces = {}; + var isUnitlessNumber = {}; + var skipProps = {}; + var dehyphenProps = { + textAnchor: 'text-anchor' + }; + var delegatedProps = {}; + constructDefaults('xlink:href,xlink:arcrole,xlink:actuate,xlink:role,xlink:titlef,xlink:type', namespaces, xlinkNS); + constructDefaults('xml:base,xml:lang,xml:space', namespaces, xmlNS); + constructDefaults('volume,defaultValue,defaultChecked', strictProps, true); + constructDefaults('children,ref,key,selected,checked,value,multiple', skipProps, true); + constructDefaults('onClick,onMouseDown,onMouseUp,onMouseMove', delegatedProps, true); + constructDefaults('muted,scoped,loop,open,checked,default,capture,disabled,readonly,required,autoplay,controls,seamless,reversed,allowfullscreen,novalidate', booleanProps, true); + constructDefaults('animationIterationCount,borderImageOutset,borderImageSlice,borderImageWidth,boxFlex,boxFlexGroup,boxOrdinalGroup,columnCount,flex,flexGrow,flexPositive,flexShrink,flexNegative,flexOrder,gridRow,gridColumn,fontWeight,lineClamp,lineHeight,opacity,order,orphans,tabSize,widows,zIndex,zoom,fillOpacity,floodOpacity,stopOpacity,strokeDasharray,strokeDashoffset,strokeMiterlimit,strokeOpacity,strokeWidth,', isUnitlessNumber, true); + + var delegatedEvents = new Map(); + function handleEvent(name, lastEvent, nextEvent, dom) { + var delegatedRoots = delegatedEvents.get(name); + if (nextEvent) { + if (!delegatedRoots) { + delegatedRoots = { items: new Map(), count: 0, docEvent: null }; + var docEvent = attachEventToDocument(name, delegatedRoots); + delegatedRoots.docEvent = docEvent; + delegatedEvents.set(name, delegatedRoots); + } + if (!lastEvent) { + delegatedRoots.count++; + } + delegatedRoots.items.set(dom, nextEvent); + } + else if (delegatedRoots) { + if (delegatedRoots.items.has(dom)) { + delegatedRoots.count--; + delegatedRoots.items.delete(dom); + if (delegatedRoots.count === 0) { + document.removeEventListener(normalizeEventName(name), delegatedRoots.docEvent); + delegatedEvents.delete(name); + } + } + } + } + function dispatchEvent(event, dom, items, count, eventData) { + var eventsToTrigger = items.get(dom); + if (eventsToTrigger) { + count--; + // linkEvent object + eventData.dom = dom; + if (eventsToTrigger.event) { + eventsToTrigger.event(eventsToTrigger.data, event); + } + else { + eventsToTrigger(event); + } + if (eventData.stopPropagation) { + return; + } + } + var parentDom = dom.parentNode; + if (count > 0 && (parentDom || parentDom === document.body)) { + dispatchEvent(event, parentDom, items, count, eventData); + } + } + function normalizeEventName(name) { + return name.substr(2).toLowerCase(); + } + function attachEventToDocument(name, delegatedRoots) { + var docEvent = function (event) { + var eventData = { + stopPropagation: false, + dom: document + }; + // we have to do this as some browsers recycle the same Event between calls + // so we need to make the property configurable + Object.defineProperty(event, 'currentTarget', { + configurable: true, + get: function get() { + return eventData.dom; + } + }); + event.stopPropagation = function () { + eventData.stopPropagation = true; + }; + var count = delegatedRoots.count; + if (count > 0) { + dispatchEvent(event, event.target, delegatedRoots.items, count, eventData); + } + }; + document.addEventListener(normalizeEventName(name), docEvent); + return docEvent; + } + + function isCheckedType(type) { + return type === 'checkbox' || type === 'radio'; + } + function isControlled(props) { + var usesChecked = isCheckedType(props.type); + return usesChecked ? !isNullOrUndef(props.checked) : !isNullOrUndef(props.value); + } + function onTextInputChange(e) { + var vNode = this.vNode; + var events = vNode.events || EMPTY_OBJ; + var dom = vNode.dom; + if (events.onInput) { + events.onInput(e); + } + else if (events.oninput) { + events.oninput(e); + } + // the user may have updated the vNode from the above onInput events + // so we need to get it from the context of `this` again + applyValue(this.vNode, dom); + } + function onCheckboxChange(e) { + var vNode = this.vNode; + var events = vNode.events || EMPTY_OBJ; + var dom = vNode.dom; + if (events.onClick) { + events.onClick(e); + } + else if (events.onclick) { + events.onclick(e); + } + // the user may have updated the vNode from the above onClick events + // so we need to get it from the context of `this` again + applyValue(this.vNode, dom); + } + function handleAssociatedRadioInputs(name) { + var inputs = document.querySelectorAll(("input[type=\"radio\"][name=\"" + name + "\"]")); + [].forEach.call(inputs, function (dom) { + var inputWrapper = wrappers.get(dom); + if (inputWrapper) { + var props = inputWrapper.vNode.props; + if (props) { + dom.checked = inputWrapper.vNode.props.checked; + } + } + }); + } + function processInput(vNode, dom) { + var props = vNode.props || EMPTY_OBJ; + applyValue(vNode, dom); + if (isControlled(props)) { + var inputWrapper = wrappers.get(dom); + if (!inputWrapper) { + inputWrapper = { + vNode: vNode + }; + if (isCheckedType(props.type)) { + dom.onclick = onCheckboxChange.bind(inputWrapper); + dom.onclick.wrapped = true; + } + else { + dom.oninput = onTextInputChange.bind(inputWrapper); + dom.oninput.wrapped = true; + } + wrappers.set(dom, inputWrapper); + } + inputWrapper.vNode = vNode; + } + } + function applyValue(vNode, dom) { + var props = vNode.props || EMPTY_OBJ; + var type = props.type; + var value = props.value; + var checked = props.checked; + if (type !== dom.type && type) { + dom.type = type; + } + if (props.multiple !== dom.multiple) { + dom.multiple = props.multiple; + } + if (isCheckedType(type)) { + if (!isNullOrUndef(value)) { + dom.value = value; + } + dom.checked = checked; + if (type === 'radio' && props.name) { + handleAssociatedRadioInputs(props.name); + } + } + else { + if (!isNullOrUndef(value) && dom.value !== value) { + dom.value = value; + } + else if (!isNullOrUndef(checked)) { + dom.checked = checked; + } + } + } + + function isControlled$1(props) { + return !isNullOrUndef(props.value); + } + function updateChildOption(vNode, value) { + var props = vNode.props || EMPTY_OBJ; + var dom = vNode.dom; + // we do this as multiple may have changed + dom.value = props.value; + if ((isArray(value) && value.indexOf(props.value) !== -1) || props.value === value) { + dom.selected = true; + } + else { + dom.selected = props.selected || false; + } + } + function onSelectChange(e) { + var vNode = this.vNode; + var events = vNode.events || EMPTY_OBJ; + var dom = vNode.dom; + if (events.onChange) { + events.onChange(e); + } + else if (events.onchange) { + events.onchange(e); + } + // the user may have updated the vNode from the above onChange events + // so we need to get it from the context of `this` again + applyValue$1(this.vNode, dom); + } + function processSelect(vNode, dom) { + var props = vNode.props || EMPTY_OBJ; + applyValue$1(vNode, dom); + if (isControlled$1(props)) { + var selectWrapper = wrappers.get(dom); + if (!selectWrapper) { + selectWrapper = { + vNode: vNode + }; + dom.onchange = onSelectChange.bind(selectWrapper); + dom.onchange.wrapped = true; + wrappers.set(dom, selectWrapper); + } + selectWrapper.vNode = vNode; + } + } + function applyValue$1(vNode, dom) { + var props = vNode.props || EMPTY_OBJ; + if (props.multiple !== dom.multiple) { + dom.multiple = props.multiple; + } + var children = vNode.children; + var value = props.value; + if (isArray(children)) { + for (var i = 0; i < children.length; i++) { + updateChildOption(children[i], value); + } + } + else if (isVNode(children)) { + updateChildOption(children, value); + } + } + + function isControlled$2(props) { + return !isNullOrUndef(props.value); + } + function onTextareaInputChange(e) { + var vNode = this.vNode; + var events = vNode.events || EMPTY_OBJ; + var dom = vNode.dom; + if (events.onInput) { + events.onInput(e); + } + else if (events.oninput) { + events.oninput(e); + } + // the user may have updated the vNode from the above onInput events + // so we need to get it from the context of `this` again + applyValue$2(this.vNode, dom); + } + function processTextarea(vNode, dom) { + var props = vNode.props || EMPTY_OBJ; + applyValue$2(vNode, dom); + var textareaWrapper = wrappers.get(dom); + if (isControlled$2(props)) { + if (!textareaWrapper) { + textareaWrapper = { + vNode: vNode + }; + dom.oninput = onTextareaInputChange.bind(textareaWrapper); + dom.oninput.wrapped = true; + wrappers.set(dom, textareaWrapper); + } + textareaWrapper.vNode = vNode; + } + } + function applyValue$2(vNode, dom) { + var props = vNode.props || EMPTY_OBJ; + var value = props.value; + if (dom.value !== value) { + dom.value = value; + } + } + + var wrappers = new Map(); + function processElement(flags, vNode, dom) { + if (flags & 512 /* InputElement */) { + processInput(vNode, dom); + } + else if (flags & 2048 /* SelectElement */) { + processSelect(vNode, dom); + } + else if (flags & 1024 /* TextareaElement */) { + processTextarea(vNode, dom); + } + } + + function unmount(vNode, parentDom, lifecycle, canRecycle, shallowUnmount, isRecycling) { + var flags = vNode.flags; + if (flags & 28 /* Component */) { + unmountComponent(vNode, parentDom, lifecycle, canRecycle, shallowUnmount, isRecycling); + } + else if (flags & 3970 /* Element */) { + unmountElement(vNode, parentDom, lifecycle, canRecycle, shallowUnmount, isRecycling); + } + else if (flags & (1 /* Text */ | 4096 /* Void */)) { + unmountVoidOrText(vNode, parentDom); + } + } + function unmountVoidOrText(vNode, parentDom) { + if (parentDom) { + removeChild(parentDom, vNode.dom); + } + } + function unmountComponent(vNode, parentDom, lifecycle, canRecycle, shallowUnmount, isRecycling) { + var instance = vNode.children; + var flags = vNode.flags; + var isStatefulComponent$$1 = flags & 4; + var ref = vNode.ref; + var dom = vNode.dom; + if (!isRecycling) { + if (!shallowUnmount) { + if (isStatefulComponent$$1) { + var subLifecycle = instance._lifecycle; + if (!subLifecycle.fastUnmount) { + unmount(instance._lastInput, null, lifecycle, false, shallowUnmount, isRecycling); + } + } + else { + if (!lifecycle.fastUnmount) { + unmount(instance, null, lifecycle, false, shallowUnmount, isRecycling); + } + } + } + if (isStatefulComponent$$1) { + instance._ignoreSetState = true; + instance.componentWillUnmount(); + if (ref && !isRecycling) { + ref(null); + } + instance._unmounted = true; + findDOMNodeEnabled && componentToDOMNodeMap.delete(instance); + } + else if (!isNullOrUndef(ref)) { + if (!isNullOrUndef(ref.onComponentWillUnmount)) { + ref.onComponentWillUnmount(dom); + } + } + } + if (parentDom) { + var lastInput = instance._lastInput; + if (isNullOrUndef(lastInput)) { + lastInput = instance; + } + removeChild(parentDom, dom); + } + if (recyclingEnabled && !isStatefulComponent$$1 && (parentDom || canRecycle)) { + poolComponent(vNode); + } + } + function unmountElement(vNode, parentDom, lifecycle, canRecycle, shallowUnmount, isRecycling) { + var dom = vNode.dom; + var ref = vNode.ref; + var events = vNode.events; + if (!shallowUnmount && !lifecycle.fastUnmount) { + if (ref && !isRecycling) { + unmountRef(ref); + } + var children = vNode.children; + if (!isNullOrUndef(children)) { + unmountChildren$1(children, lifecycle, shallowUnmount, isRecycling); + } + } + if (!isNull(events)) { + for (var name in events) { + // do not add a hasOwnProperty check here, it affects performance + patchEvent(name, events[name], null, dom, lifecycle); + events[name] = null; + } + } + if (parentDom) { + removeChild(parentDom, dom); + } + if (recyclingEnabled && (parentDom || canRecycle)) { + poolElement(vNode); + } + } + function unmountChildren$1(children, lifecycle, shallowUnmount, isRecycling) { + if (isArray(children)) { + for (var i = 0; i < children.length; i++) { + var child = children[i]; + if (!isInvalid(child) && isObject(child)) { + unmount(child, null, lifecycle, false, shallowUnmount, isRecycling); + } + } + } + else if (isObject(children)) { + unmount(children, null, lifecycle, false, shallowUnmount, isRecycling); + } + } + function unmountRef(ref) { + if (isFunction(ref)) { + ref(null); + } + else { + if (isInvalid(ref)) { + return; + } + if (false) { + throwError('string "refs" are not supported in Inferno 1.0. Use callback "refs" instead.'); + } + throwError(); + } + } + + function patch(lastVNode, nextVNode, parentDom, lifecycle, context, isSVG, isRecycling) { + if (lastVNode !== nextVNode) { + var lastFlags = lastVNode.flags; + var nextFlags = nextVNode.flags; + if (nextFlags & 28 /* Component */) { + if (lastFlags & 28 /* Component */) { + patchComponent(lastVNode, nextVNode, parentDom, lifecycle, context, isSVG, nextFlags & 4 /* ComponentClass */, isRecycling); + } + else { + replaceVNode(parentDom, mountComponent(nextVNode, null, lifecycle, context, isSVG, nextFlags & 4 /* ComponentClass */), lastVNode, lifecycle, isRecycling); + } + } + else if (nextFlags & 3970 /* Element */) { + if (lastFlags & 3970 /* Element */) { + patchElement(lastVNode, nextVNode, parentDom, lifecycle, context, isSVG, isRecycling); + } + else { + replaceVNode(parentDom, mountElement(nextVNode, null, lifecycle, context, isSVG), lastVNode, lifecycle, isRecycling); + } + } + else if (nextFlags & 1 /* Text */) { + if (lastFlags & 1 /* Text */) { + patchText(lastVNode, nextVNode); + } + else { + replaceVNode(parentDom, mountText(nextVNode, null), lastVNode, lifecycle, isRecycling); + } + } + else if (nextFlags & 4096 /* Void */) { + if (lastFlags & 4096 /* Void */) { + patchVoid(lastVNode, nextVNode); + } + else { + replaceVNode(parentDom, mountVoid(nextVNode, null), lastVNode, lifecycle, isRecycling); + } + } + else { + // Error case: mount new one replacing old one + replaceLastChildAndUnmount(lastVNode, nextVNode, parentDom, lifecycle, context, isSVG, isRecycling); + } + } + } + function unmountChildren(children, dom, lifecycle, isRecycling) { + if (isVNode(children)) { + unmount(children, dom, lifecycle, true, false, isRecycling); + } + else if (isArray(children)) { + removeAllChildren(dom, children, lifecycle, false, isRecycling); + } + else { + dom.textContent = ''; + } + } + function patchElement(lastVNode, nextVNode, parentDom, lifecycle, context, isSVG, isRecycling) { + var nextTag = nextVNode.type; + var lastTag = lastVNode.type; + if (lastTag !== nextTag) { + replaceWithNewNode(lastVNode, nextVNode, parentDom, lifecycle, context, isSVG, isRecycling); + } + else { + var dom = lastVNode.dom; + var lastProps = lastVNode.props; + var nextProps = nextVNode.props; + var lastChildren = lastVNode.children; + var nextChildren = nextVNode.children; + var lastFlags = lastVNode.flags; + var nextFlags = nextVNode.flags; + var lastRef = lastVNode.ref; + var nextRef = nextVNode.ref; + var lastEvents = lastVNode.events; + var nextEvents = nextVNode.events; + nextVNode.dom = dom; + if (isSVG || (nextFlags & 128 /* SvgElement */)) { + isSVG = true; + } + if (lastChildren !== nextChildren) { + patchChildren(lastFlags, nextFlags, lastChildren, nextChildren, dom, lifecycle, context, isSVG, isRecycling); + } + if (!(nextFlags & 2 /* HtmlElement */)) { + processElement(nextFlags, nextVNode, dom); + } + if (lastProps !== nextProps) { + patchProps(lastProps, nextProps, dom, lifecycle, context, isSVG); + } + if (lastEvents !== nextEvents) { + patchEvents(lastEvents, nextEvents, dom, lifecycle); + } + if (nextRef) { + if (lastRef !== nextRef || isRecycling) { + mountRef(dom, nextRef, lifecycle); + } + } + } + } + function patchChildren(lastFlags, nextFlags, lastChildren, nextChildren, dom, lifecycle, context, isSVG, isRecycling) { + var patchArray = false; + var patchKeyed = false; + if (nextFlags & 64 /* HasNonKeyedChildren */) { + patchArray = true; + } + else if ((lastFlags & 32 /* HasKeyedChildren */) && (nextFlags & 32 /* HasKeyedChildren */)) { + patchKeyed = true; + patchArray = true; + } + else if (isInvalid(nextChildren)) { + unmountChildren(lastChildren, dom, lifecycle, isRecycling); + } + else if (isInvalid(lastChildren)) { + if (isStringOrNumber(nextChildren)) { + setTextContent(dom, nextChildren); + } + else { + if (isArray(nextChildren)) { + mountArrayChildren(nextChildren, dom, lifecycle, context, isSVG); + } + else { + mount(nextChildren, dom, lifecycle, context, isSVG); + } + } + } + else if (isStringOrNumber(nextChildren)) { + if (isStringOrNumber(lastChildren)) { + updateTextContent(dom, nextChildren); + } + else { + unmountChildren(lastChildren, dom, lifecycle, isRecycling); + setTextContent(dom, nextChildren); + } + } + else if (isArray(nextChildren)) { + if (isArray(lastChildren)) { + patchArray = true; + if (isKeyed(lastChildren, nextChildren)) { + patchKeyed = true; + } + } + else { + unmountChildren(lastChildren, dom, lifecycle, isRecycling); + mountArrayChildren(nextChildren, dom, lifecycle, context, isSVG); + } + } + else if (isArray(lastChildren)) { + removeAllChildren(dom, lastChildren, lifecycle, false, isRecycling); + mount(nextChildren, dom, lifecycle, context, isSVG); + } + else if (isVNode(nextChildren)) { + if (isVNode(lastChildren)) { + patch(lastChildren, nextChildren, dom, lifecycle, context, isSVG, isRecycling); + } + else { + unmountChildren(lastChildren, dom, lifecycle, isRecycling); + mount(nextChildren, dom, lifecycle, context, isSVG); + } + } + else if (isVNode(lastChildren)) { + } + else { + } + if (patchArray) { + if (patchKeyed) { + patchKeyedChildren(lastChildren, nextChildren, dom, lifecycle, context, isSVG, isRecycling); + } + else { + patchNonKeyedChildren(lastChildren, nextChildren, dom, lifecycle, context, isSVG, isRecycling); + } + } + } + function patchComponent(lastVNode, nextVNode, parentDom, lifecycle, context, isSVG, isClass, isRecycling) { + var lastType = lastVNode.type; + var nextType = nextVNode.type; + var nextProps = nextVNode.props || EMPTY_OBJ; + var lastKey = lastVNode.key; + var nextKey = nextVNode.key; + if (lastType !== nextType) { + if (isClass) { + replaceWithNewNode(lastVNode, nextVNode, parentDom, lifecycle, context, isSVG, isRecycling); + } + else { + var lastInput = lastVNode.children._lastInput || lastVNode.children; + var nextInput = createStatelessComponentInput(nextVNode, nextType, nextProps, context); + patch(lastInput, nextInput, parentDom, lifecycle, context, isSVG, isRecycling); + var dom = nextVNode.dom = nextInput.dom; + nextVNode.children = nextInput; + mountStatelessComponentCallbacks(nextVNode.ref, dom, lifecycle); + unmount(lastVNode, null, lifecycle, false, true, isRecycling); + } + } + else { + if (isClass) { + if (lastKey !== nextKey) { + replaceWithNewNode(lastVNode, nextVNode, parentDom, lifecycle, context, isSVG, isRecycling); + return false; + } + var instance = lastVNode.children; + if (instance._unmounted) { + if (isNull(parentDom)) { + return true; + } + replaceChild(parentDom, mountComponent(nextVNode, null, lifecycle, context, isSVG, nextVNode.flags & 4 /* ComponentClass */), lastVNode.dom); + } + else { + var defaultProps = nextType.defaultProps; + var lastProps = instance.props; + if (instance._devToolsStatus.connected && !instance._devToolsId) { + componentIdMap.set(instance._devToolsId = getIncrementalId(), instance); + } + lifecycle.fastUnmount = false; + if (!isUndefined(defaultProps)) { + copyPropsTo(lastProps, nextProps); + nextVNode.props = nextProps; + } + var lastState = instance.state; + var nextState = instance.state; + var childContext = instance.getChildContext(); + nextVNode.children = instance; + instance._isSVG = isSVG; + if (!isNullOrUndef(childContext)) { + childContext = Object.assign({}, context, childContext); + } + else { + childContext = context; + } + var lastInput$1 = instance._lastInput; + var nextInput$1 = instance._updateComponent(lastState, nextState, lastProps, nextProps, context, false); + var didUpdate = true; + instance._childContext = childContext; + if (isInvalid(nextInput$1)) { + nextInput$1 = createVoidVNode(); + } + else if (isArray(nextInput$1)) { + if (false) { + throwError('a valid Inferno VNode (or null) must be returned from a component render. You may have returned an array or an invalid object.'); + } + throwError(); + } + else if (nextInput$1 === NO_OP) { + nextInput$1 = lastInput$1; + didUpdate = false; + } + else if (isObject(nextInput$1) && nextInput$1.dom) { + nextInput$1 = cloneVNode(nextInput$1); + } + if (nextInput$1.flags & 28 /* Component */) { + nextInput$1.parentVNode = nextVNode; + } + else if (lastInput$1.flags & 28 /* Component */) { + lastInput$1.parentVNode = nextVNode; + } + instance._lastInput = nextInput$1; + instance._vNode = nextVNode; + if (didUpdate) { + var fastUnmount = lifecycle.fastUnmount; + var subLifecycle = instance._lifecycle; + lifecycle.fastUnmount = subLifecycle.fastUnmount; + patch(lastInput$1, nextInput$1, parentDom, lifecycle, childContext, isSVG, isRecycling); + subLifecycle.fastUnmount = lifecycle.unmount; + lifecycle.fastUnmount = fastUnmount; + instance.componentDidUpdate(lastProps, lastState); + findDOMNodeEnabled && componentToDOMNodeMap.set(instance, nextInput$1.dom); + } + nextVNode.dom = nextInput$1.dom; + } + } + else { + var shouldUpdate = true; + var lastProps$1 = lastVNode.props; + var nextHooks = nextVNode.ref; + var nextHooksDefined = !isNullOrUndef(nextHooks); + var lastInput$2 = lastVNode.children; + var nextInput$2 = lastInput$2; + nextVNode.dom = lastVNode.dom; + nextVNode.children = lastInput$2; + if (lastKey !== nextKey) { + shouldUpdate = true; + } + else { + if (nextHooksDefined && !isNullOrUndef(nextHooks.onComponentShouldUpdate)) { + shouldUpdate = nextHooks.onComponentShouldUpdate(lastProps$1, nextProps); + } + } + if (shouldUpdate !== false) { + if (nextHooksDefined && !isNullOrUndef(nextHooks.onComponentWillUpdate)) { + lifecycle.fastUnmount = false; + nextHooks.onComponentWillUpdate(lastProps$1, nextProps); + } + nextInput$2 = nextType(nextProps, context); + if (isInvalid(nextInput$2)) { + nextInput$2 = createVoidVNode(); + } + else if (isArray(nextInput$2)) { + if (false) { + throwError('a valid Inferno VNode (or null) must be returned from a component render. You may have returned an array or an invalid object.'); + } + throwError(); + } + else if (isObject(nextInput$2) && nextInput$2.dom) { + nextInput$2 = cloneVNode(nextInput$2); + } + if (nextInput$2 !== NO_OP) { + patch(lastInput$2, nextInput$2, parentDom, lifecycle, context, isSVG, isRecycling); + nextVNode.children = nextInput$2; + if (nextHooksDefined && !isNullOrUndef(nextHooks.onComponentDidUpdate)) { + lifecycle.fastUnmount = false; + nextHooks.onComponentDidUpdate(lastProps$1, nextProps); + } + nextVNode.dom = nextInput$2.dom; + } + } + if (nextInput$2.flags & 28 /* Component */) { + nextInput$2.parentVNode = nextVNode; + } + else if (lastInput$2.flags & 28 /* Component */) { + lastInput$2.parentVNode = nextVNode; + } + } + } + return false; + } + function patchText(lastVNode, nextVNode) { + var nextText = nextVNode.children; + var dom = lastVNode.dom; + nextVNode.dom = dom; + if (lastVNode.children !== nextText) { + dom.nodeValue = nextText; + } + } + function patchVoid(lastVNode, nextVNode) { + nextVNode.dom = lastVNode.dom; + } + function patchNonKeyedChildren(lastChildren, nextChildren, dom, lifecycle, context, isSVG, isRecycling) { + var lastChildrenLength = lastChildren.length; + var nextChildrenLength = nextChildren.length; + var commonLength = lastChildrenLength > nextChildrenLength ? nextChildrenLength : lastChildrenLength; + var i; + var nextNode = null; + var newNode; + // Loop backwards so we can use insertBefore + if (lastChildrenLength < nextChildrenLength) { + for (i = nextChildrenLength - 1; i >= commonLength; i--) { + var child = nextChildren[i]; + if (!isInvalid(child)) { + if (child.dom) { + nextChildren[i] = child = cloneVNode(child); + } + newNode = mount(child, null, lifecycle, context, isSVG); + insertOrAppend(dom, newNode, nextNode); + nextNode = newNode; + } + } + } + else if (nextChildrenLength === 0) { + removeAllChildren(dom, lastChildren, lifecycle, false, isRecycling); + } + else if (lastChildrenLength > nextChildrenLength) { + for (i = commonLength; i < lastChildrenLength; i++) { + var child$1 = lastChildren[i]; + if (!isInvalid(child$1)) { + unmount(lastChildren[i], dom, lifecycle, false, false, isRecycling); + } + } + } + for (i = commonLength - 1; i >= 0; i--) { + var lastChild = lastChildren[i]; + var nextChild = nextChildren[i]; + if (isInvalid(nextChild)) { + if (!isInvalid(lastChild)) { + unmount(lastChild, dom, lifecycle, true, false, isRecycling); + } + } + else { + if (nextChild.dom) { + nextChildren[i] = nextChild = cloneVNode(nextChild); + } + if (isInvalid(lastChild)) { + newNode = mount(nextChild, null, lifecycle, context, isSVG); + insertOrAppend(dom, newNode, nextNode); + nextNode = newNode; + } + else { + patch(lastChild, nextChild, dom, lifecycle, context, isSVG, isRecycling); + nextNode = nextChild.dom; + } + } + } + } + function patchKeyedChildren(a, b, dom, lifecycle, context, isSVG, isRecycling) { + var aLength = a.length; + var bLength = b.length; + var aEnd = aLength - 1; + var bEnd = bLength - 1; + var aStart = 0; + var bStart = 0; + var i; + var j; + var aNode; + var bNode; + var nextNode; + var nextPos; + var node; + if (aLength === 0) { + if (bLength !== 0) { + mountArrayChildren(b, dom, lifecycle, context, isSVG); + } + return; + } + else if (bLength === 0) { + removeAllChildren(dom, a, lifecycle, false, isRecycling); + return; + } + var aStartNode = a[aStart]; + var bStartNode = b[bStart]; + var aEndNode = a[aEnd]; + var bEndNode = b[bEnd]; + if (bStartNode.dom) { + b[bStart] = bStartNode = cloneVNode(bStartNode); + } + if (bEndNode.dom) { + b[bEnd] = bEndNode = cloneVNode(bEndNode); + } + // Step 1 + /* eslint no-constant-condition: 0 */ + outer: while (true) { + // Sync nodes with the same key at the beginning. + while (aStartNode.key === bStartNode.key) { + patch(aStartNode, bStartNode, dom, lifecycle, context, isSVG, isRecycling); + aStart++; + bStart++; + if (aStart > aEnd || bStart > bEnd) { + break outer; + } + aStartNode = a[aStart]; + bStartNode = b[bStart]; + if (bStartNode.dom) { + b[bStart] = bStartNode = cloneVNode(bStartNode); + } + } + // Sync nodes with the same key at the end. + while (aEndNode.key === bEndNode.key) { + patch(aEndNode, bEndNode, dom, lifecycle, context, isSVG, isRecycling); + aEnd--; + bEnd--; + if (aStart > aEnd || bStart > bEnd) { + break outer; + } + aEndNode = a[aEnd]; + bEndNode = b[bEnd]; + if (bEndNode.dom) { + b[bEnd] = bEndNode = cloneVNode(bEndNode); + } + } + // Move and sync nodes from right to left. + if (aEndNode.key === bStartNode.key) { + patch(aEndNode, bStartNode, dom, lifecycle, context, isSVG, isRecycling); + insertOrAppend(dom, bStartNode.dom, aStartNode.dom); + aEnd--; + bStart++; + aEndNode = a[aEnd]; + bStartNode = b[bStart]; + if (bStartNode.dom) { + b[bStart] = bStartNode = cloneVNode(bStartNode); + } + continue; + } + // Move and sync nodes from left to right. + if (aStartNode.key === bEndNode.key) { + patch(aStartNode, bEndNode, dom, lifecycle, context, isSVG, isRecycling); + nextPos = bEnd + 1; + nextNode = nextPos < b.length ? b[nextPos].dom : null; + insertOrAppend(dom, bEndNode.dom, nextNode); + aStart++; + bEnd--; + aStartNode = a[aStart]; + bEndNode = b[bEnd]; + if (bEndNode.dom) { + b[bEnd] = bEndNode = cloneVNode(bEndNode); + } + continue; + } + break; + } + if (aStart > aEnd) { + if (bStart <= bEnd) { + nextPos = bEnd + 1; + nextNode = nextPos < b.length ? b[nextPos].dom : null; + while (bStart <= bEnd) { + node = b[bStart]; + if (node.dom) { + b[bStart] = node = cloneVNode(node); + } + bStart++; + insertOrAppend(dom, mount(node, null, lifecycle, context, isSVG), nextNode); + } + } + } + else if (bStart > bEnd) { + while (aStart <= aEnd) { + unmount(a[aStart++], dom, lifecycle, false, false, isRecycling); + } + } + else { + aLength = aEnd - aStart + 1; + bLength = bEnd - bStart + 1; + var aNullable = a; + var sources = new Array(bLength); + // Mark all nodes as inserted. + for (i = 0; i < bLength; i++) { + sources[i] = -1; + } + var moved = false; + var pos = 0; + var patched = 0; + if ((bLength <= 4) || (aLength * bLength <= 16)) { + for (i = aStart; i <= aEnd; i++) { + aNode = a[i]; + if (patched < bLength) { + for (j = bStart; j <= bEnd; j++) { + bNode = b[j]; + if (aNode.key === bNode.key) { + sources[j - bStart] = i; + if (pos > j) { + moved = true; + } + else { + pos = j; + } + if (bNode.dom) { + b[j] = bNode = cloneVNode(bNode); + } + patch(aNode, bNode, dom, lifecycle, context, isSVG, isRecycling); + patched++; + aNullable[i] = null; + break; + } + } + } + } + } + else { + var keyIndex = new Map(); + for (i = bStart; i <= bEnd; i++) { + node = b[i]; + keyIndex.set(node.key, i); + } + for (i = aStart; i <= aEnd; i++) { + aNode = a[i]; + if (patched < bLength) { + j = keyIndex.get(aNode.key); + if (!isUndefined(j)) { + bNode = b[j]; + sources[j - bStart] = i; + if (pos > j) { + moved = true; + } + else { + pos = j; + } + if (bNode.dom) { + b[j] = bNode = cloneVNode(bNode); + } + patch(aNode, bNode, dom, lifecycle, context, isSVG, isRecycling); + patched++; + aNullable[i] = null; + } + } + } + } + if (aLength === a.length && patched === 0) { + removeAllChildren(dom, a, lifecycle, false, isRecycling); + while (bStart < bLength) { + node = b[bStart]; + if (node.dom) { + b[bStart] = node = cloneVNode(node); + } + bStart++; + insertOrAppend(dom, mount(node, null, lifecycle, context, isSVG), null); + } + } + else { + i = aLength - patched; + while (i > 0) { + aNode = aNullable[aStart++]; + if (!isNull(aNode)) { + unmount(aNode, dom, lifecycle, false, false, isRecycling); + i--; + } + } + if (moved) { + var seq = lis_algorithm(sources); + j = seq.length - 1; + for (i = bLength - 1; i >= 0; i--) { + if (sources[i] === -1) { + pos = i + bStart; + node = b[pos]; + if (node.dom) { + b[pos] = node = cloneVNode(node); + } + nextPos = pos + 1; + nextNode = nextPos < b.length ? b[nextPos].dom : null; + insertOrAppend(dom, mount(node, dom, lifecycle, context, isSVG), nextNode); + } + else { + if (j < 0 || i !== seq[j]) { + pos = i + bStart; + node = b[pos]; + nextPos = pos + 1; + nextNode = nextPos < b.length ? b[nextPos].dom : null; + insertOrAppend(dom, node.dom, nextNode); + } + else { + j--; + } + } + } + } + else if (patched !== bLength) { + for (i = bLength - 1; i >= 0; i--) { + if (sources[i] === -1) { + pos = i + bStart; + node = b[pos]; + if (node.dom) { + b[pos] = node = cloneVNode(node); + } + nextPos = pos + 1; + nextNode = nextPos < b.length ? b[nextPos].dom : null; + insertOrAppend(dom, mount(node, null, lifecycle, context, isSVG), nextNode); + } + } + } + } + } + } + // // https://en.wikipedia.org/wiki/Longest_increasing_subsequence + function lis_algorithm(a) { + var p = a.slice(0); + var result = []; + result.push(0); + var i; + var j; + var u; + var v; + var c; + for (i = 0; i < a.length; i++) { + if (a[i] === -1) { + continue; + } + j = result[result.length - 1]; + if (a[j] < a[i]) { + p[i] = j; + result.push(i); + continue; + } + u = 0; + v = result.length - 1; + while (u < v) { + c = ((u + v) / 2) | 0; + if (a[result[c]] < a[i]) { + u = c + 1; + } + else { + v = c; + } + } + if (a[i] < a[result[u]]) { + if (u > 0) { + p[i] = result[u - 1]; + } + result[u] = i; + } + } + u = result.length; + v = result[u - 1]; + while (u-- > 0) { + result[u] = v; + v = p[v]; + } + return result; + } + function patchProp(prop, lastValue, nextValue, dom, isSVG, lifecycle) { + if (skipProps[prop]) { + return; + } + if (booleanProps[prop]) { + dom[prop] = nextValue ? true : false; + } + else if (strictProps[prop]) { + var value = isNullOrUndef(nextValue) ? '' : nextValue; + if (dom[prop] !== value) { + dom[prop] = value; + } + } + else if (isAttrAnEvent(prop)) { + patchEvent(prop, lastValue, nextValue, dom, lifecycle); + } + else if (lastValue !== nextValue) { + if (isNullOrUndef(nextValue)) { + dom.removeAttribute(prop); + } + else if (prop === 'className') { + if (isSVG) { + dom.setAttribute('class', nextValue); + } + else { + dom.className = nextValue; + } + } + else if (prop === 'style') { + patchStyle(lastValue, nextValue, dom); + } + else if (prop === 'dangerouslySetInnerHTML') { + var lastHtml = lastValue && lastValue.__html; + var nextHtml = nextValue && nextValue.__html; + if (lastHtml !== nextHtml) { + if (!isNullOrUndef(nextHtml)) { + dom.innerHTML = nextHtml; + } + } + } + else if (prop !== 'childrenType' && prop !== 'ref' && prop !== 'key') { + var dehyphenProp = dehyphenProps[prop]; + var ns = namespaces[prop]; + if (ns) { + dom.setAttributeNS(ns, dehyphenProp || prop, nextValue); + } + else { + dom.setAttribute(dehyphenProp || prop, nextValue); + } + } + } + } + function patchEvents(lastEvents, nextEvents, dom, lifecycle) { + lastEvents = lastEvents || EMPTY_OBJ; + nextEvents = nextEvents || EMPTY_OBJ; + if (nextEvents !== EMPTY_OBJ) { + for (var name in nextEvents) { + // do not add a hasOwnProperty check here, it affects performance + patchEvent(name, lastEvents[name], nextEvents[name], dom, lifecycle); + } + } + if (lastEvents !== EMPTY_OBJ) { + for (var name$1 in lastEvents) { + // do not add a hasOwnProperty check here, it affects performance + if (isNullOrUndef(nextEvents[name$1])) { + patchEvent(name$1, lastEvents[name$1], null, dom, lifecycle); + } + } + } + } + function patchEvent(name, lastValue, nextValue, dom, lifecycle) { + if (lastValue !== nextValue) { + var nameLowerCase = name.toLowerCase(); + var domEvent = dom[nameLowerCase]; + // if the function is wrapped, that means it's been controlled by a wrapper + if (domEvent && domEvent.wrapped) { + return; + } + if (delegatedProps[name]) { + lifecycle.fastUnmount = false; + handleEvent(name, lastValue, nextValue, dom); + } + else { + dom[nameLowerCase] = nextValue; + } + } + } + function patchProps(lastProps, nextProps, dom, lifecycle, context, isSVG) { + lastProps = lastProps || EMPTY_OBJ; + nextProps = nextProps || EMPTY_OBJ; + if (nextProps !== EMPTY_OBJ) { + for (var prop in nextProps) { + // do not add a hasOwnProperty check here, it affects performance + var nextValue = nextProps[prop]; + var lastValue = lastProps[prop]; + if (isNullOrUndef(nextValue)) { + removeProp(prop, dom); + } + else { + patchProp(prop, lastValue, nextValue, dom, isSVG, lifecycle); + } + } + } + if (lastProps !== EMPTY_OBJ) { + for (var prop$1 in lastProps) { + // do not add a hasOwnProperty check here, it affects performance + if (isNullOrUndef(nextProps[prop$1])) { + removeProp(prop$1, dom); + } + } + } + } + // We are assuming here that we come from patchProp routine + // -nextAttrValue cannot be null or undefined + function patchStyle(lastAttrValue, nextAttrValue, dom) { + if (isString(nextAttrValue)) { + dom.style.cssText = nextAttrValue; + return; + } + for (var style in nextAttrValue) { + // do not add a hasOwnProperty check here, it affects performance + var value = nextAttrValue[style]; + if (isNumber(value) && !isUnitlessNumber[style]) { + dom.style[style] = value + 'px'; + } + else { + dom.style[style] = value; + } + } + if (!isNullOrUndef(lastAttrValue)) { + for (var style$1 in lastAttrValue) { + if (isNullOrUndef(nextAttrValue[style$1])) { + dom.style[style$1] = ''; + } + } + } + } + function removeProp(prop, dom) { + if (prop === 'className') { + dom.removeAttribute('class'); + } + else if (prop === 'value') { + dom.value = ''; + } + else if (prop === 'style') { + dom.style.cssText = null; + dom.removeAttribute('style'); + } + else if (delegatedProps[prop]) { + handleEvent(prop, null, null, dom); + } + else { + dom.removeAttribute(prop); + } + } + + var recyclingEnabled = true; + var componentPools = new Map(); + var elementPools = new Map(); + function disableRecycling() { + recyclingEnabled = false; + componentPools.clear(); + elementPools.clear(); + } + + function recycleElement(vNode, lifecycle, context, isSVG) { + var tag = vNode.type; + var key = vNode.key; + var pools = elementPools.get(tag); + if (!isUndefined(pools)) { + var pool = key === null ? pools.nonKeyed : pools.keyed.get(key); + if (!isUndefined(pool)) { + var recycledVNode = pool.pop(); + if (!isUndefined(recycledVNode)) { + patchElement(recycledVNode, vNode, null, lifecycle, context, isSVG, true); + return vNode.dom; + } + } + } + return null; + } + function poolElement(vNode) { + var tag = vNode.type; + var key = vNode.key; + var pools = elementPools.get(tag); + if (isUndefined(pools)) { + pools = { + nonKeyed: [], + keyed: new Map() + }; + elementPools.set(tag, pools); + } + if (isNull(key)) { + pools.nonKeyed.push(vNode); + } + else { + var pool = pools.keyed.get(key); + if (isUndefined(pool)) { + pool = []; + pools.keyed.set(key, pool); + } + pool.push(vNode); + } + } + function recycleComponent(vNode, lifecycle, context, isSVG) { + var type = vNode.type; + var key = vNode.key; + var pools = componentPools.get(type); + if (!isUndefined(pools)) { + var pool = key === null ? pools.nonKeyed : pools.keyed.get(key); + if (!isUndefined(pool)) { + var recycledVNode = pool.pop(); + if (!isUndefined(recycledVNode)) { + var flags = vNode.flags; + var failed = patchComponent(recycledVNode, vNode, null, lifecycle, context, isSVG, flags & 4 /* ComponentClass */, true); + if (!failed) { + return vNode.dom; + } + } + } + } + return null; + } + function poolComponent(vNode) { + var type = vNode.type; + var key = vNode.key; + var hooks = vNode.ref; + var nonRecycleHooks = hooks && (hooks.onComponentWillMount || + hooks.onComponentWillUnmount || + hooks.onComponentDidMount || + hooks.onComponentWillUpdate || + hooks.onComponentDidUpdate); + if (nonRecycleHooks) { + return; + } + var pools = componentPools.get(type); + if (isUndefined(pools)) { + pools = { + nonKeyed: [], + keyed: new Map() + }; + componentPools.set(type, pools); + } + if (isNull(key)) { + pools.nonKeyed.push(vNode); + } + else { + var pool = pools.keyed.get(key); + if (isUndefined(pool)) { + pool = []; + pools.keyed.set(key, pool); + } + pool.push(vNode); + } + } + + function mount(vNode, parentDom, lifecycle, context, isSVG) { + var flags = vNode.flags; + if (flags & 3970 /* Element */) { + return mountElement(vNode, parentDom, lifecycle, context, isSVG); + } + else if (flags & 28 /* Component */) { + return mountComponent(vNode, parentDom, lifecycle, context, isSVG, flags & 4 /* ComponentClass */); + } + else if (flags & 4096 /* Void */) { + return mountVoid(vNode, parentDom); + } + else if (flags & 1 /* Text */) { + return mountText(vNode, parentDom); + } + else { + if (false) { + throwError(("mount() expects a valid VNode, instead it received an object with the type \"" + (typeof vNode) + "\".")); + } + throwError(); + } + } + function mountText(vNode, parentDom) { + var dom = document.createTextNode(vNode.children); + vNode.dom = dom; + if (parentDom) { + appendChild(parentDom, dom); + } + return dom; + } + function mountVoid(vNode, parentDom) { + var dom = document.createTextNode(''); + vNode.dom = dom; + if (parentDom) { + appendChild(parentDom, dom); + } + return dom; + } + function mountElement(vNode, parentDom, lifecycle, context, isSVG) { + if (recyclingEnabled) { + var dom$1 = recycleElement(vNode, lifecycle, context, isSVG); + if (!isNull(dom$1)) { + if (!isNull(parentDom)) { + appendChild(parentDom, dom$1); + } + return dom$1; + } + } + var tag = vNode.type; + var flags = vNode.flags; + if (isSVG || (flags & 128 /* SvgElement */)) { + isSVG = true; + } + var dom = documentCreateElement(tag, isSVG); + var children = vNode.children; + var props = vNode.props; + var events = vNode.events; + var ref = vNode.ref; + vNode.dom = dom; + if (!isNull(children)) { + if (isStringOrNumber(children)) { + setTextContent(dom, children); + } + else if (isArray(children)) { + mountArrayChildren(children, dom, lifecycle, context, isSVG); + } + else if (isVNode(children)) { + mount(children, dom, lifecycle, context, isSVG); + } + } + if (!(flags & 2 /* HtmlElement */)) { + processElement(flags, vNode, dom); + } + if (!isNull(props)) { + for (var prop in props) { + // do not add a hasOwnProperty check here, it affects performance + patchProp(prop, null, props[prop], dom, isSVG, lifecycle); + } + } + if (!isNull(events)) { + for (var name in events) { + // do not add a hasOwnProperty check here, it affects performance + patchEvent(name, null, events[name], dom, lifecycle); + } + } + if (!isNull(ref)) { + mountRef(dom, ref, lifecycle); + } + if (!isNull(parentDom)) { + appendChild(parentDom, dom); + } + return dom; + } + function mountArrayChildren(children, dom, lifecycle, context, isSVG) { + for (var i = 0; i < children.length; i++) { + var child = children[i]; + if (!isInvalid(child)) { + if (child.dom) { + children[i] = child = cloneVNode(child); + } + mount(children[i], dom, lifecycle, context, isSVG); + } + } + } + function mountComponent(vNode, parentDom, lifecycle, context, isSVG, isClass) { + if (recyclingEnabled) { + var dom$1 = recycleComponent(vNode, lifecycle, context, isSVG); + if (!isNull(dom$1)) { + if (!isNull(parentDom)) { + appendChild(parentDom, dom$1); + } + return dom$1; + } + } + var type = vNode.type; + var props = vNode.props || EMPTY_OBJ; + var ref = vNode.ref; + var dom; + if (isClass) { + var defaultProps = type.defaultProps; + lifecycle.fastUnmount = false; + if (!isUndefined(defaultProps)) { + copyPropsTo(defaultProps, props); + vNode.props = props; + } + var instance = createStatefulComponentInstance(vNode, type, props, context, isSVG, devToolsStatus); + var input = instance._lastInput; + var fastUnmount = lifecycle.fastUnmount; + // we store the fastUnmount value, but we set it back to true on the lifecycle + // we do this so we can determine if the component render has a fastUnmount or not + lifecycle.fastUnmount = true; + instance._vNode = vNode; + vNode.dom = dom = mount(input, null, lifecycle, instance._childContext, isSVG); + // we now create a lifecycle for this component and store the fastUnmount value + var subLifecycle = instance._lifecycle = new Lifecycle(); + subLifecycle.fastUnmount = lifecycle.fastUnmount; + // we then set the lifecycle fastUnmount value back to what it was before the mount + lifecycle.fastUnmount = fastUnmount; + if (!isNull(parentDom)) { + appendChild(parentDom, dom); + } + mountStatefulComponentCallbacks(ref, instance, lifecycle); + findDOMNodeEnabled && componentToDOMNodeMap.set(instance, dom); + vNode.children = instance; + } + else { + var input$1 = createStatelessComponentInput(vNode, type, props, context); + vNode.dom = dom = mount(input$1, null, lifecycle, context, isSVG); + vNode.children = input$1; + mountStatelessComponentCallbacks(ref, dom, lifecycle); + if (!isNull(parentDom)) { + appendChild(parentDom, dom); + } + } + return dom; + } + function mountStatefulComponentCallbacks(ref, instance, lifecycle) { + if (ref) { + if (isFunction(ref)) { + ref(instance); + } + else { + if (false) { + throwError('string "refs" are not supported in Inferno 1.0. Use callback "refs" instead.'); + } + throwError(); + } + } + if (!isNull(instance.componentDidMount)) { + lifecycle.addListener(function () { + instance.componentDidMount(); + }); + } + } + function mountStatelessComponentCallbacks(ref, dom, lifecycle) { + if (ref) { + if (!isNullOrUndef(ref.onComponentWillMount)) { + lifecycle.fastUnmount = false; + ref.onComponentWillMount(); + } + if (!isNullOrUndef(ref.onComponentDidMount)) { + lifecycle.fastUnmount = false; + lifecycle.addListener(function () { return ref.onComponentDidMount(dom); }); + } + } + } + function mountRef(dom, value, lifecycle) { + if (isFunction(value)) { + lifecycle.fastUnmount = false; + lifecycle.addListener(function () { return value(dom); }); + } + else { + if (isInvalid(value)) { + return; + } + if (false) { + throwError('string "refs" are not supported in Inferno 1.0. Use callback "refs" instead.'); + } + throwError(); + } + } + + function copyPropsTo(copyFrom, copyTo) { + for (var prop in copyFrom) { + if (isUndefined(copyTo[prop])) { + copyTo[prop] = copyFrom[prop]; + } + } + } + function createStatefulComponentInstance(vNode, Component, props, context, isSVG, devToolsStatus) { + if (isUndefined(context)) { + context = {}; + } + var instance = new Component(props, context); + instance.context = context; + if (instance.props === EMPTY_OBJ) { + instance.props = props; + } + instance._patch = patch; + instance._devToolsStatus = devToolsStatus; + if (findDOMNodeEnabled) { + instance._componentToDOMNodeMap = componentToDOMNodeMap; + } + var childContext = instance.getChildContext(); + if (!isNullOrUndef(childContext)) { + instance._childContext = Object.assign({}, context, childContext); + } + else { + instance._childContext = context; + } + instance._unmounted = false; + instance._pendingSetState = true; + instance._isSVG = isSVG; + instance.componentWillMount(); + instance._beforeRender && instance._beforeRender(); + var input = instance.render(props, instance.state, context); + instance._afterRender && instance._afterRender(); + if (isArray(input)) { + if (false) { + throwError('a valid Inferno VNode (or null) must be returned from a component render. You may have returned an array or an invalid object.'); + } + throwError(); + } + else if (isInvalid(input)) { + input = createVoidVNode(); + } + else { + if (input.dom) { + input = cloneVNode(input); + } + if (input.flags & 28 /* Component */) { + // if we have an input that is also a component, we run into a tricky situation + // where the root vNode needs to always have the correct DOM entry + // so we break monomorphism on our input and supply it our vNode as parentVNode + // we can optimise this in the future, but this gets us out of a lot of issues + input.parentVNode = vNode; + } + } + instance._pendingSetState = false; + instance._lastInput = input; + return instance; + } + function replaceLastChildAndUnmount(lastInput, nextInput, parentDom, lifecycle, context, isSVG, isRecycling) { + replaceVNode(parentDom, mount(nextInput, null, lifecycle, context, isSVG), lastInput, lifecycle, isRecycling); + } + function replaceVNode(parentDom, dom, vNode, lifecycle, isRecycling) { + var shallowUnmount = false; + // we cannot cache nodeType here as vNode might be re-assigned below + if (vNode.flags & 28 /* Component */) { + // if we are accessing a stateful or stateless component, we want to access their last rendered input + // accessing their DOM node is not useful to us here + unmount(vNode, null, lifecycle, false, false, isRecycling); + vNode = vNode.children._lastInput || vNode.children; + shallowUnmount = true; + } + replaceChild(parentDom, dom, vNode.dom); + unmount(vNode, null, lifecycle, false, shallowUnmount, isRecycling); + } + function createStatelessComponentInput(vNode, component, props, context) { + var input = component(props, context); + if (isArray(input)) { + if (false) { + throwError('a valid Inferno VNode (or null) must be returned from a component render. You may have returned an array or an invalid object.'); + } + throwError(); + } + else if (isInvalid(input)) { + input = createVoidVNode(); + } + else { + if (input.dom) { + input = cloneVNode(input); + } + if (input.flags & 28 /* Component */) { + // if we have an input that is also a component, we run into a tricky situation + // where the root vNode needs to always have the correct DOM entry + // so we break monomorphism on our input and supply it our vNode as parentVNode + // we can optimise this in the future, but this gets us out of a lot of issues + input.parentVNode = vNode; + } + } + return input; + } + function setTextContent(dom, text) { + if (text !== '') { + dom.textContent = text; + } + else { + dom.appendChild(document.createTextNode('')); + } + } + function updateTextContent(dom, text) { + dom.firstChild.nodeValue = text; + } + function appendChild(parentDom, dom) { + parentDom.appendChild(dom); + } + function insertOrAppend(parentDom, newNode, nextNode) { + if (isNullOrUndef(nextNode)) { + appendChild(parentDom, newNode); + } + else { + parentDom.insertBefore(newNode, nextNode); + } + } + function documentCreateElement(tag, isSVG) { + if (isSVG === true) { + return document.createElementNS(svgNS, tag); + } + else { + return document.createElement(tag); + } + } + function replaceWithNewNode(lastNode, nextNode, parentDom, lifecycle, context, isSVG, isRecycling) { + unmount(lastNode, null, lifecycle, false, false, isRecycling); + var dom = mount(nextNode, null, lifecycle, context, isSVG); + nextNode.dom = dom; + replaceChild(parentDom, dom, lastNode.dom); + } + function replaceChild(parentDom, nextDom, lastDom) { + if (!parentDom) { + parentDom = lastDom.parentNode; + } + parentDom.replaceChild(nextDom, lastDom); + } + function removeChild(parentDom, dom) { + parentDom.removeChild(dom); + } + function removeAllChildren(dom, children, lifecycle, shallowUnmount, isRecycling) { + dom.textContent = ''; + if (!lifecycle.fastUnmount) { + removeChildren(null, children, lifecycle, shallowUnmount, isRecycling); + } + } + function removeChildren(dom, children, lifecycle, shallowUnmount, isRecycling) { + for (var i = 0; i < children.length; i++) { + var child = children[i]; + if (!isInvalid(child)) { + unmount(child, dom, lifecycle, true, shallowUnmount, isRecycling); + } + } + } + function isKeyed(lastChildren, nextChildren) { + return nextChildren.length && !isNullOrUndef(nextChildren[0]) && !isNullOrUndef(nextChildren[0].key) + && lastChildren.length && !isNullOrUndef(lastChildren[0]) && !isNullOrUndef(lastChildren[0].key); + } + + function normaliseChildNodes(dom) { + var rawChildNodes = dom.childNodes; + var length = rawChildNodes.length; + var i = 0; + while (i < length) { + var rawChild = rawChildNodes[i]; + if (rawChild.nodeType === 8) { + if (rawChild.data === '!') { + var placeholder = document.createTextNode(''); + dom.replaceChild(placeholder, rawChild); + i++; + } + else { + dom.removeChild(rawChild); + length--; + } + } + else { + i++; + } + } + } + function hydrateComponent(vNode, dom, lifecycle, context, isSVG, isClass) { + var type = vNode.type; + var props = vNode.props || {}; + var ref = vNode.ref; + vNode.dom = dom; + if (isClass) { + var _isSVG = dom.namespaceURI === svgNS; + var defaultProps = type.defaultProps; + lifecycle.fastUnmount = false; + if (!isUndefined(defaultProps)) { + copyPropsTo(defaultProps, props); + vNode.props = props; + } + var instance = createStatefulComponentInstance(vNode, type, props, context, _isSVG, devToolsStatus); + var input = instance._lastInput; + var fastUnmount = lifecycle.fastUnmount; + // we store the fastUnmount value, but we set it back to true on the lifecycle + // we do this so we can determine if the component render has a fastUnmount or not + lifecycle.fastUnmount = true; + instance._vComponent = vNode; + instance._vNode = vNode; + hydrate(input, dom, lifecycle, instance._childContext, _isSVG); + var subLifecycle = instance._lifecycle = new Lifecycle(); + subLifecycle.fastUnmount = lifecycle.fastUnmount; + // we then set the lifecycle fastUnmount value back to what it was before the mount + lifecycle.fastUnmount = fastUnmount; + mountStatefulComponentCallbacks(ref, instance, lifecycle); + findDOMNodeEnabled && componentToDOMNodeMap.set(instance, dom); + vNode.children = instance; + } + else { + var input$1 = createStatelessComponentInput(vNode, type, props, context); + hydrate(input$1, dom, lifecycle, context, isSVG); + vNode.children = input$1; + vNode.dom = input$1.dom; + mountStatelessComponentCallbacks(ref, dom, lifecycle); + } + } + function hydrateElement(vNode, dom, lifecycle, context, isSVG) { + var tag = vNode.type; + var children = vNode.children; + var props = vNode.props; + var events = vNode.events; + var flags = vNode.flags; + if (isSVG || (flags & 128 /* SvgElement */)) { + isSVG = true; + } + if (dom.nodeType !== 1 || dom.tagName.toLowerCase() !== tag) { + var newDom = mountElement(vNode, null, lifecycle, context, isSVG); + vNode.dom = newDom; + replaceChild(dom.parentNode, newDom, dom); + } + else { + vNode.dom = dom; + if (children) { + hydrateChildren(children, dom, lifecycle, context, isSVG); + } + if (!(flags & 2 /* HtmlElement */)) { + processElement(flags, vNode, dom); + } + for (var prop in props) { + patchProp(prop, null, props[prop], dom, isSVG, lifecycle); + } + for (var name in events) { + patchEvent(name, null, events[name], dom, lifecycle); + } + } + } + function hydrateChildren(children, dom, lifecycle, context, isSVG) { + normaliseChildNodes(dom); + var domNodes = Array.prototype.slice.call(dom.childNodes); + var childNodeIndex = 0; + if (isArray(children)) { + for (var i = 0; i < children.length; i++) { + var child = children[i]; + if (isObject(child) && !isNull(child)) { + hydrate(child, domNodes[childNodeIndex++], lifecycle, context, isSVG); + } + } + } + else if (isObject(children)) { + hydrate(children, dom.firstChild, lifecycle, context, isSVG); + } + } + function hydrateText(vNode, dom) { + if (dom.nodeType === 3) { + var newDom = mountText(vNode, null); + vNode.dom = newDom; + replaceChild(dom.parentNode, newDom, dom); + } + else { + vNode.dom = dom; + } + } + function hydrateVoid(vNode, dom) { + vNode.dom = dom; + } + function hydrate(vNode, dom, lifecycle, context, isSVG) { + if (false) { + if (isInvalid(dom)) { + throwError("failed to hydrate. The server-side render doesn't match client side."); + } + } + var flags = vNode.flags; + if (flags & 28 /* Component */) { + return hydrateComponent(vNode, dom, lifecycle, context, isSVG, flags & 4 /* ComponentClass */); + } + else if (flags & 3970 /* Element */) { + return hydrateElement(vNode, dom, lifecycle, context, isSVG); + } + else if (flags & 1 /* Text */) { + return hydrateText(vNode, dom); + } + else if (flags & 4096 /* Void */) { + return hydrateVoid(vNode, dom); + } + else { + if (false) { + throwError(("hydrate() expects a valid VNode, instead it received an object with the type \"" + (typeof vNode) + "\".")); + } + throwError(); + } + } + function hydrateRoot(input, parentDom, lifecycle) { + if (parentDom && parentDom.nodeType === 1 && parentDom.firstChild) { + hydrate(input, parentDom.firstChild, lifecycle, {}, false); + return true; + } + return false; + } + + // rather than use a Map, like we did before, we can use an array here + // given there shouldn't be THAT many roots on the page, the difference + // in performance is huge: https://esbench.com/bench/5802a691330ab09900a1a2da + var roots = []; + var componentToDOMNodeMap = new Map(); + var findDOMNodeEnabled = false; + function enableFindDOMNode() { + findDOMNodeEnabled = true; + } + function findDOMNode(ref) { + if (!findDOMNodeEnabled) { + if (false) { + throwError('findDOMNode() has been disabled, use enableFindDOMNode() enabled findDOMNode(). Warning this can significantly impact performance!'); + } + throwError(); + } + var dom = ref && ref.nodeType ? ref : null; + return componentToDOMNodeMap.get(ref) || dom; + } + function getRoot(dom) { + for (var i = 0; i < roots.length; i++) { + var root = roots[i]; + if (root.dom === dom) { + return root; + } + } + return null; + } + function setRoot(dom, input, lifecycle) { + roots.push({ + dom: dom, + input: input, + lifecycle: lifecycle + }); + } + function removeRoot(root) { + for (var i = 0; i < roots.length; i++) { + if (roots[i] === root) { + roots.splice(i, 1); + return; + } + } + } + var documentBody = isBrowser ? document.body : null; + function render(input, parentDom) { + if (documentBody === parentDom) { + if (false) { + throwError('you cannot render() to the "document.body". Use an empty element as a container instead.'); + } + throwError(); + } + if (input === NO_OP) { + return; + } + var root = getRoot(parentDom); + if (isNull(root)) { + var lifecycle = new Lifecycle(); + if (!isInvalid(input)) { + if (input.dom) { + input = cloneVNode(input); + } + if (!hydrateRoot(input, parentDom, lifecycle)) { + mount(input, parentDom, lifecycle, {}, false); + } + lifecycle.trigger(); + setRoot(parentDom, input, lifecycle); + } + } + else { + var lifecycle$1 = root.lifecycle; + lifecycle$1.listeners = []; + if (isNullOrUndef(input)) { + unmount(root.input, parentDom, lifecycle$1, false, false, false); + removeRoot(root); + } + else { + if (input.dom) { + input = cloneVNode(input); + } + patch(root.input, input, parentDom, lifecycle$1, {}, false, false); + } + lifecycle$1.trigger(); + root.input = input; + } + if (devToolsStatus.connected) { + sendRoots(window); + } + } + function createRenderer() { + var parentDom; + return function renderer(lastInput, nextInput) { + if (!parentDom) { + parentDom = lastInput; + } + render(nextInput, parentDom); + }; + } + + function linkEvent(data, event) { + return { data: data, event: event }; + } + + if (isBrowser) { + window.process = { + env: { + NODE_ENV: 'development' + } + }; + initDevToolsHooks(window); + } + + if (false) { + var testFunc = function testFn() {}; + warning( + (testFunc.name || testFunc.toString()).indexOf('testFn') !== -1, + 'It looks like you\'re using a minified copy of the development build ' + + 'of Inferno. When deploying Inferno apps to production, make sure to use ' + + 'the production build which skips development warnings and is faster. ' + + 'See http://infernojs.org for more details.' + ); + } + + // we duplicate it so it plays nicely with different module loading systems + var index = { + linkEvent: linkEvent, + // core shapes + createVNode: createVNode, + + // cloning + cloneVNode: cloneVNode, + + // used to shared common items between Inferno libs + NO_OP: NO_OP, + EMPTY_OBJ: EMPTY_OBJ, + + //DOM + render: render, + findDOMNode: findDOMNode, + createRenderer: createRenderer, + disableRecycling: disableRecycling, + enableFindDOMNode: enableFindDOMNode + }; + + exports['default'] = index; + exports.linkEvent = linkEvent; + exports.createVNode = createVNode; + exports.cloneVNode = cloneVNode; + exports.NO_OP = NO_OP; + exports.EMPTY_OBJ = EMPTY_OBJ; + exports.render = render; + exports.findDOMNode = findDOMNode; + exports.createRenderer = createRenderer; + exports.disableRecycling = disableRecycling; + exports.enableFindDOMNode = enableFindDOMNode; + + Object.defineProperty(exports, '__esModule', { value: true }); + + }))); + + +/***/ }), +/* 3 */ +/***/ (function(module, exports, __webpack_require__) { + + module.exports = __webpack_require__(4); + + +/***/ }), +/* 4 */ +/***/ (function(module, exports, __webpack_require__) { + + /*! + * inferno-component v1.0.0-beta32 + * (c) 2016 Dominic Gannaway + * Released under the MIT License. + */ + (function (global, factory) { + true ? module.exports = factory(__webpack_require__(2)) : + typeof define === 'function' && define.amd ? define(['inferno'], factory) : + (global.Inferno = global.Inferno || {}, global.Inferno.Component = factory(global.Inferno)); + }(this, (function (inferno) { 'use strict'; + + var ERROR_MSG = 'a runtime error occured! Use Inferno in development environment to find the error.'; + + + // this is MUCH faster than .constructor === Array and instanceof Array + // in Node 7 and the later versions of V8, slower in older versions though + var isArray = Array.isArray; + + + function isNullOrUndef(obj) { + return isUndefined(obj) || isNull(obj); + } + function isInvalid(obj) { + return isNull(obj) || obj === false || isTrue(obj) || isUndefined(obj); + } + function isFunction(obj) { + return typeof obj === 'function'; + } + + + + function isNull(obj) { + return obj === null; + } + function isTrue(obj) { + return obj === true; + } + function isUndefined(obj) { + return obj === undefined; + } + + function throwError(message) { + if (!message) { + message = ERROR_MSG; + } + throw new Error(("Inferno Error: " + message)); + } + + var Lifecycle = function Lifecycle() { + this.listeners = []; + this.fastUnmount = true; + }; + Lifecycle.prototype.addListener = function addListener (callback) { + this.listeners.push(callback); + }; + Lifecycle.prototype.trigger = function trigger () { + var this$1 = this; + + for (var i = 0; i < this.listeners.length; i++) { + this$1.listeners[i](); + } + }; + + var noOp = ERROR_MSG; + if (false) { + noOp = 'Inferno Error: Can only update a mounted or mounting component. This usually means you called setState() or forceUpdate() on an unmounted component. This is a no-op.'; + } + var componentCallbackQueue = new Map(); + // when a components root VNode is also a component, we can run into issues + // this will recursively look for vNode.parentNode if the VNode is a component + function updateParentComponentVNodes(vNode, dom) { + if (vNode.flags & 28 /* Component */) { + var parentVNode = vNode.parentVNode; + if (parentVNode) { + parentVNode.dom = dom; + updateParentComponentVNodes(parentVNode, dom); + } + } + } + // this is in shapes too, but we don't want to import from shapes as it will pull in a duplicate of createVNode + function createVoidVNode() { + return inferno.createVNode(4096 /* Void */); + } + function addToQueue(component, force, callback) { + // TODO this function needs to be revised and improved on + var queue = componentCallbackQueue.get(component); + if (!queue) { + queue = []; + componentCallbackQueue.set(component, queue); + Promise.resolve().then(function () { + applyState(component, force, function () { + for (var i = 0; i < queue.length; i++) { + queue[i](); + } + }); + componentCallbackQueue.delete(component); + component._processingSetState = false; + }); + } + if (callback) { + queue.push(callback); + } + } + function queueStateChanges(component, newState, callback) { + if (isFunction(newState)) { + newState = newState(component.state); + } + for (var stateKey in newState) { + component._pendingState[stateKey] = newState[stateKey]; + } + if (!component._pendingSetState) { + if (component._processingSetState || callback) { + addToQueue(component, false, callback); + } + else { + component._pendingSetState = true; + component._processingSetState = true; + applyState(component, false, callback); + component._processingSetState = false; + } + } + else { + component.state = Object.assign({}, component.state, component._pendingState); + component._pendingState = {}; + } + } + function applyState(component, force, callback) { + if ((!component._deferSetState || force) && !component._blockRender) { + component._pendingSetState = false; + var pendingState = component._pendingState; + var prevState = component.state; + var nextState = Object.assign({}, prevState, pendingState); + var props = component.props; + var context = component.context; + component._pendingState = {}; + var nextInput = component._updateComponent(prevState, nextState, props, props, context, force); + var didUpdate = true; + if (isInvalid(nextInput)) { + nextInput = createVoidVNode(); + } + else if (isArray(nextInput)) { + if (false) { + throwError('a valid Inferno VNode (or null) must be returned from a component render. You may have returned an array or an invalid object.'); + } + throwError(); + } + else if (nextInput === inferno.NO_OP) { + nextInput = component._lastInput; + didUpdate = false; + } + var lastInput = component._lastInput; + var parentDom = lastInput.dom.parentNode; + component._lastInput = nextInput; + if (didUpdate) { + var subLifecycle = component._lifecycle; + if (!subLifecycle) { + subLifecycle = new Lifecycle(); + } + else { + subLifecycle.listeners = []; + } + component._lifecycle = subLifecycle; + var childContext = component.getChildContext(); + if (!isNullOrUndef(childContext)) { + childContext = Object.assign({}, context, component._childContext, childContext); + } + else { + childContext = Object.assign({}, context, component._childContext); + } + component._patch(lastInput, nextInput, parentDom, subLifecycle, childContext, component._isSVG, false); + subLifecycle.trigger(); + component.componentDidUpdate(props, prevState); + } + var vNode = component._vNode; + var dom = vNode.dom = nextInput.dom; + var componentToDOMNodeMap = component._componentToDOMNodeMap; + componentToDOMNodeMap && componentToDOMNodeMap.set(component, nextInput.dom); + updateParentComponentVNodes(vNode, dom); + if (!isNullOrUndef(callback)) { + callback(); + } + } + } + var Component$1 = function Component$1(props, context) { + this.state = {}; + this.refs = {}; + this._processingSetState = false; + this._blockRender = false; + this._ignoreSetState = false; + this._blockSetState = false; + this._deferSetState = false; + this._pendingSetState = false; + this._pendingState = {}; + this._lastInput = null; + this._vNode = null; + this._unmounted = true; + this._devToolsStatus = null; + this._devToolsId = null; + this._lifecycle = null; + this._childContext = null; + this._patch = null; + this._isSVG = false; + this._componentToDOMNodeMap = null; + /** @type {object} */ + this.props = props || inferno.EMPTY_OBJ; + /** @type {object} */ + this.context = context || {}; + if (!this.componentDidMount) { + this.componentDidMount = null; + } + }; + Component$1.prototype.render = function render (nextProps, nextState, nextContext) { + }; + Component$1.prototype.forceUpdate = function forceUpdate (callback) { + if (this._unmounted) { + throw Error(noOp); + } + applyState(this, true, callback); + }; + Component$1.prototype.setState = function setState (newState, callback) { + if (this._unmounted) { + throw Error(noOp); + } + if (!this._blockSetState) { + if (!this._ignoreSetState) { + queueStateChanges(this, newState, callback); + } + } + else { + if (false) { + throwError('cannot update state via setState() in componentWillUpdate().'); + } + throwError(); + } + }; + Component$1.prototype.componentWillMount = function componentWillMount () { + }; + Component$1.prototype.componentDidMount = function componentDidMount () { + }; + Component$1.prototype.componentWillUnmount = function componentWillUnmount () { + }; + Component$1.prototype.componentDidUpdate = function componentDidUpdate (prevProps, prevState, prevContext) { + }; + Component$1.prototype.shouldComponentUpdate = function shouldComponentUpdate (nextProps, nextState, context) { + return true; + }; + Component$1.prototype.componentWillReceiveProps = function componentWillReceiveProps (nextProps, context) { + }; + Component$1.prototype.componentWillUpdate = function componentWillUpdate (nextProps, nextState, nextContext) { + }; + Component$1.prototype.getChildContext = function getChildContext () { + }; + Component$1.prototype._updateComponent = function _updateComponent (prevState, nextState, prevProps, nextProps, context, force) { + if (this._unmounted === true) { + if (false) { + throwError(noOp); + } + throwError(); + } + if ((prevProps !== nextProps || nextProps === inferno.EMPTY_OBJ) || prevState !== nextState || force) { + if (prevProps !== nextProps || nextProps === inferno.EMPTY_OBJ) { + this._blockRender = true; + this.componentWillReceiveProps(nextProps, context); + this._blockRender = false; + if (this._pendingSetState) { + nextState = Object.assign({}, nextState, this._pendingState); + this._pendingSetState = false; + this._pendingState = {}; + } + } + var shouldUpdate = this.shouldComponentUpdate(nextProps, nextState, context); + if (shouldUpdate !== false || force) { + this._blockSetState = true; + this.componentWillUpdate(nextProps, nextState, context); + this._blockSetState = false; + this.props = nextProps; + var state = this.state = nextState; + this.context = context; + this._beforeRender && this._beforeRender(); + var render = this.render(nextProps, state, context); + this._afterRender && this._afterRender(); + return render; + } + } + return inferno.NO_OP; + }; + + return Component$1; + + }))); + + +/***/ }), +/* 5 */ +/***/ (function(module, exports) { + + 'use strict'; + + exports.__esModule = true; + exports.read = read; + exports.assign = assign; + exports.isEqual = isEqual; + /** + * Shared funcs/values + */ + + var ENTER = exports.ENTER = 13; + var ESCAPE = exports.ESCAPE = 27; + + var filters = exports.filters = { + all: function all(t) { + return true; + }, + active: function active(t) { + return !t.completed; + }, + completed: function completed(t) { + return t.completed; + } + }; + + /** + * Read the `location.hash` value + * @return {String} + */ + function read() { + return location.hash.replace('#/', '') || 'all'; + } + + /** + * Modified `Object.assign` shim + * - always writes to new object + * @return {Object} + */ + function assign() { + var src = void 0; + var tar = {}; + for (var s = 0; s < arguments.length; s++) { + src = Object(arguments[s]); + for (var k in src) { + tar[k] = src[k]; + } + } + return tar; + } + + /** + * Are two Objects equal values? + * @param {Object} a + * @param {Object} b + * @return {Boolean} + */ + function isEqual(a, b) { + // Create arrays of property names + var aProps = Object.getOwnPropertyNames(a); + var bProps = Object.getOwnPropertyNames(b); + + if (aProps.length !== bProps.length) return false; + + for (var i = 0; i < aProps.length; i++) { + var k = aProps[i]; + if (a[k] !== b[k]) return false; + } + + return true; + } + +/***/ }), +/* 6 */ +/***/ (function(module, exports, __webpack_require__) { + + 'use strict'; + + exports.__esModule = true; + exports.links = undefined; + exports.Head = Head; + exports.Foot = Foot; + + var _inferno = __webpack_require__(1); + + var _inferno2 = _interopRequireDefault(_inferno); + + var _share = __webpack_require__(5); + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + + /** + * Stateless Header component + */ + function Head(_ref) { + var onEnter = _ref.onEnter; + + return _inferno2.default.createVNode(2, 'header', { + 'className': 'header' + }, [_inferno2.default.createVNode(2, 'h1', null, 'todos'), _inferno2.default.createVNode(512, 'input', { + 'className': 'new-todo', + 'autofocus': true, + 'autocomplete': 'off', + 'placeholder': 'What needs to be done?' + }, null, { + 'onkeydown': onEnter + })]); + } + + var links = exports.links = [{ hash: '#/', name: 'All' }, { hash: '#/active', name: 'Active' }, { hash: '#/completed', name: 'Completed' }]; + + /** + * Stateless Footer component + */ + function Foot(_ref2) { + var left = _ref2.left, + done = _ref2.done, + route = _ref2.route, + onClear = _ref2.onClear; + + return _inferno2.default.createVNode(2, 'footer', { + 'className': 'footer' + }, [_inferno2.default.createVNode(2, 'span', { + 'className': 'todo-count' + }, [_inferno2.default.createVNode(2, 'strong', null, left), ' ', left > 1 ? 'items' : 'item', ' left']), _inferno2.default.createVNode(2, 'ul', { + 'className': 'filters' + }, links.map(function (_ref3) { + var hash = _ref3.hash, + name = _ref3.name; + return _inferno2.default.createVNode(2, 'li', null, _inferno2.default.createVNode(2, 'a', { + 'href': hash, + 'className': name.toLowerCase() === route ? 'selected' : '' + }, name)); + })), done > 0 ? _inferno2.default.createVNode(2, 'button', { + 'className': 'clear-completed' + }, 'Clear completed', { + 'onClick': onClear + }) : null]); + } + +/***/ }), +/* 7 */ +/***/ (function(module, exports, __webpack_require__) { + + 'use strict'; + + exports.__esModule = true; + + var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + + var _share = __webpack_require__(5); + + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + + var STOR = window.localStorage; + var STOR_ID = 'todos-inferno'; + + var Model = function Model() { + var _this = this; + + _classCallCheck(this, Model); + + this.get = function () { + return _this.data = JSON.parse(STOR.getItem(STOR_ID) || '[]'); + }; + + this.set = function (arr) { + _this.data = arr || _this.data || []; + STOR.setItem(STOR_ID, JSON.stringify(_this.data)); + return _this.data; + }; + + this.add = function (str) { + return _this.set(_this.data.concat({ title: str, completed: false })); + }; + + this.put = function (todo, obj) { + return _this.set(_this.data.map(function (t) { + return (0, _share.isEqual)(t, todo) ? (0, _share.assign)(todo, obj) : t; + })); + }; + + this.del = function (todo) { + return _this.set(_this.data.filter(function (t) { + return !(0, _share.isEqual)(t, todo); + })); + }; + + this.toggle = function (todo) { + return _this.put(todo, { completed: !todo.completed }); + }; + + this.toggleAll = function (completed) { + return _this.set(_this.data.map(function (t) { + return _extends({}, t, { completed: completed }); + })); + }; + + this.clearCompleted = function () { + return _this.set(_this.data.filter(function (t) { + return !t.completed; + })); + }; + }; + + exports.default = Model; + +/***/ }), +/* 8 */ +/***/ (function(module, exports, __webpack_require__) { + + 'use strict'; + + exports.__esModule = true; + + var _inferno = __webpack_require__(1); + + var _inferno2 = _interopRequireDefault(_inferno); + + var _infernoComponent = __webpack_require__(3); + + var _infernoComponent2 = _interopRequireDefault(_infernoComponent); + + var _share = __webpack_require__(5); + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + + function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } + + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + + function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + + function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + + var Item = function (_Component) { + _inherits(Item, _Component); + + function Item(_ref) { + var data = _ref.data, + props = _objectWithoutProperties(_ref, ['data']); + + _classCallCheck(this, Item); + + var _this = _possibleConstructorReturn(this, _Component.call(this, props)); + + _initialiseProps.call(_this); + + _this.todo = data; + _this.state = { text: data.title }; + _this.editor = null; + return _this; + } + + Item.prototype.render = function render(_ref2, _ref3) { + var _this2 = this; + + var doToggle = _ref2.doToggle, + doDelete = _ref2.doDelete, + doSave = _ref2.doSave, + onBlur = _ref2.onBlur, + onFocus = _ref2.onFocus; + var text = _ref3.text; + var _todo = this.todo, + title = _todo.title, + completed = _todo.completed, + editing = _todo.editing; + + + var cls = []; + editing && cls.push('editing'); + completed && cls.push('completed'); + + var handleKeydown = function handleKeydown(e) { + if (e.which === _share.ESCAPE) return onBlur(); + if (e.which === _share.ENTER) return doSave(text); + }; + + // tmp fix + var handleBlur = function handleBlur() { + return doSave(text); + }; + var handleInput = function handleInput(e) { + return _this2.setText(e.target.value); + }; + + return _inferno2.default.createVNode(2, 'li', { + 'className': cls.join(' ') + }, [_inferno2.default.createVNode(2, 'div', { + 'className': 'view' + }, [_inferno2.default.createVNode(512, 'input', { + 'className': 'toggle', + 'type': 'checkbox', + 'checked': completed + }, null, { + 'onClick': doToggle + }), _inferno2.default.createVNode(2, 'label', null, title, { + 'ondblclick': onFocus + }), _inferno2.default.createVNode(2, 'button', { + 'className': 'destroy' + }, null, { + 'onClick': doDelete + })]), _inferno2.default.createVNode(512, 'input', { + 'className': 'edit', + 'value': editing && text + }, null, { + 'onblur': handleBlur, + 'oninput': handleInput, + 'onkeydown': handleKeydown + }, null, function (el) { + _this2.editor = el; + })]); + }; + + return Item; + }(_infernoComponent2.default); + + var _initialiseProps = function _initialiseProps() { + var _this3 = this; + + this.componentWillReceiveProps = function (_ref4) { + var data = _ref4.data; + return _this3.setText(data.title); + }; + + this.shouldComponentUpdate = function (_ref5, _ref6) { + var data = _ref5.data; + var text = _ref6.text; + return !((0, _share.isEqual)(data, _this3.todo) && text === _this3.state.text); + }; + + this.componentWillUpdate = function (_ref7) { + var data = _ref7.data; + return _this3.todo = data; + }; + + this.componentDidUpdate = function () { + return _this3.editor.focus(); + }; + + this.setText = function (text) { + return _this3.setState({ text: text }); + }; + }; + + exports.default = Item; + +/***/ }) +/******/ ]); \ No newline at end of file diff --git a/bench/implementations/inferno/index.html b/bench/implementations/inferno/index.html new file mode 100644 index 0000000..eac678f --- /dev/null +++ b/bench/implementations/inferno/index.html @@ -0,0 +1,20 @@ + + + + + Inferno • TodoMVC + + + + +
+ + + + + + diff --git a/bench/implementations/inferno/package.json b/bench/implementations/inferno/package.json new file mode 100644 index 0000000..075ed52 --- /dev/null +++ b/bench/implementations/inferno/package.json @@ -0,0 +1,24 @@ +{ + "private": true, + "scripts": { + "dev": "webpack-dev-server", + "build": "webpack -p", + "test": "cd test && npm test" + }, + "dependencies": { + "inferno": "beta32", + "inferno-component": "beta32", + "todomvc-app-css": "^2.0.0", + "todomvc-common": "^1.0.0" + }, + "devDependencies": { + "babel-core": "^6.5.2", + "babel-loader": "^6.2.1", + "babel-plugin-inferno": "beta13", + "babel-preset-es2015": "^6.5.0", + "babel-preset-es2015-loose": "^7.0.0", + "babel-preset-stage-0": "^6.5.0", + "webpack": "^1.12.14", + "webpack-dev-server": "^1.14.1" + } +} diff --git a/bench/implementations/inferno/src/base.js b/bench/implementations/inferno/src/base.js new file mode 100644 index 0000000..c517d91 --- /dev/null +++ b/bench/implementations/inferno/src/base.js @@ -0,0 +1,49 @@ +import Inferno from 'inferno'; +import { states } from './share'; + +/** + * Stateless Header component + */ +export function Head({onEnter}) { + return ( +
+

todos

+ +
+ ); +} + +export const links = [ + {hash: '#/', name: 'All'}, + {hash: '#/active', name: 'Active'}, + {hash: '#/completed', name: 'Completed'} +]; + +/** + * Stateless Footer component + */ +export function Foot({left, done, route, onClear}) { + return ( +
+ + { left } { left > 1 ? 'items' : 'item' } left + + + { done > 0 ? ( + + ) : null } +
+ ); +} diff --git a/bench/implementations/inferno/src/index.js b/bench/implementations/inferno/src/index.js new file mode 100644 index 0000000..a805ae3 --- /dev/null +++ b/bench/implementations/inferno/src/index.js @@ -0,0 +1,112 @@ +import Inferno from 'inferno'; +import Component from 'inferno-component'; +import { ENTER, filters, read } from './share'; +import { Head, Foot } from './base'; +import Model from './model'; +import Item from './item'; + +const { render } = Inferno; +const model = new Model(); + +class App extends Component { + state = { + route: read(), + todos: model.get() + }; + + update = arr => this.setState({todos: arr}); + + componentWillMount = () => { + window.onhashchange = () => this.setState({route: read()}); + }; + + add = e => { + if (e.which !== ENTER) return; + + const val = e.target.value.trim(); + if (!val) return; + + e.target.value = ''; + this.update( + model.add(val) + ); + }; + + edit = (todo, val) => { + val = val.trim(); + if (val.length) { + this.update( + model.put(todo, {title: val, editing: 0}) + ); + } else { + this.remove(todo); + } + }; + + focus = todo => this.update( + model.put(todo, {editing: 1}) + ); + + blur = todo => this.update( + model.put(todo, {editing: 0}) + ); + + remove = todo => this.update( + model.del(todo) + ); + + toggleOne = todo => this.update( + model.toggle(todo) + ); + + toggleAll = ev => this.update( + model.toggleAll(ev.target.checked) + ); + + clearCompleted = () => this.update( + model.clearCompleted() + ); + + render(_, {todos, route}) { + const num = todos.length; + const shown = todos.filter(filters[route]); + const numDone = todos.filter(filters.completed).length; + const numAct = num - numDone; + + return ( +
+ + + { num ? ( +
+ + +
    + { + shown.map(t => + this.blur(t) } + onFocus={ () => this.focus(t) } + doDelete={ () => this.remove(t) } + doSave={ val => this.edit(t, val) } + doToggle={ () => this.toggleOne(t) } + /> + ) + } +
+
+ ) : null } + + { (numAct || numDone) ? ( + + ) : null } +
+ ) + } +} + +render(, document.getElementById('app')); diff --git a/bench/implementations/inferno/src/item.js b/bench/implementations/inferno/src/item.js new file mode 100644 index 0000000..5b97227 --- /dev/null +++ b/bench/implementations/inferno/src/item.js @@ -0,0 +1,58 @@ +import Inferno from 'inferno'; +import Component from 'inferno-component'; +import { ESCAPE, ENTER, isEqual } from './share'; + +export default class Item extends Component { + constructor({data, ...props}) { + super(props); + this.todo = data; + this.state = {text: data.title}; + this.editor = null; + } + + componentWillReceiveProps = ({data}) => this.setText(data.title); + shouldComponentUpdate = ({data}, {text}) => !(isEqual(data, this.todo) && text === this.state.text); + componentWillUpdate = ({data}) => (this.todo = data); + componentDidUpdate = () => this.editor.focus(); + + setText = text => this.setState({text}); + + render({doToggle, doDelete, doSave, onBlur, onFocus}, {text}) { + const {title, completed, editing} = this.todo; + + const cls = []; + editing && cls.push('editing'); + completed && cls.push('completed'); + + const handleKeydown = e => { + if (e.which === ESCAPE) return onBlur(); + if (e.which === ENTER) return doSave(text); + }; + + // tmp fix + const handleBlur = () => doSave(text); + const handleInput = e => this.setText(e.target.value); + + return ( +
  • +
    + + + + + +
    + + { this.editor = el }} + value={ editing && text } + onblur={ handleBlur } + oninput={ handleInput } + onkeydown={ handleKeydown } + /> +
  • + ); + } +} diff --git a/bench/implementations/inferno/src/model.js b/bench/implementations/inferno/src/model.js new file mode 100644 index 0000000..1d73064 --- /dev/null +++ b/bench/implementations/inferno/src/model.js @@ -0,0 +1,36 @@ +import { assign, isEqual } from './share'; + +const STOR = window.localStorage; +const STOR_ID = 'todos-inferno'; + +export default class Model { + get = () => (this.data = JSON.parse(STOR.getItem(STOR_ID) || '[]')) + + set = arr => { + this.data = arr || this.data || []; + STOR.setItem(STOR_ID, JSON.stringify(this.data)); + return this.data; + } + + add = str => this.set( + this.data.concat({title: str, completed: false}) + ) + + put = (todo, obj) => this.set( + this.data.map(t => isEqual(t, todo) ? assign(todo, obj) : t) + ) + + del = todo => this.set( + this.data.filter(t => !isEqual(t, todo)) + ) + + toggle = todo => this.put(todo, {completed: !todo.completed}) + + toggleAll = completed => this.set( + this.data.map(t => ({...t, completed})) + ) + + clearCompleted = () => this.set( + this.data.filter(t => !t.completed) + ) +} diff --git a/bench/implementations/inferno/src/share.js b/bench/implementations/inferno/src/share.js new file mode 100644 index 0000000..89ff4a7 --- /dev/null +++ b/bench/implementations/inferno/src/share.js @@ -0,0 +1,58 @@ +/** + * Shared funcs/values + */ + +export const ENTER = 13; +export const ESCAPE = 27; + +export const filters = { + all: t => true, + active: t => !t.completed, + completed: t => t.completed +} + +/** + * Read the `location.hash` value + * @return {String} + */ +export function read() { + return location.hash.replace('#/', '') || 'all'; +} + +/** + * Modified `Object.assign` shim + * - always writes to new object + * @return {Object} + */ +export function assign() { + let src; + let tar = {}; + for (let s = 0; s < arguments.length; s++) { + src = Object(arguments[s]); + for (const k in src) { + tar[k] = src[k]; + } + } + return tar; +} + +/** + * Are two Objects equal values? + * @param {Object} a + * @param {Object} b + * @return {Boolean} + */ +export function isEqual(a, b) { + // Create arrays of property names + const aProps = Object.getOwnPropertyNames(a); + const bProps = Object.getOwnPropertyNames(b); + + if (aProps.length !== bProps.length) return false; + + for (let i = 0; i < aProps.length; i++) { + const k = aProps[i]; + if (a[k] !== b[k]) return false; + } + + return true; +} diff --git a/bench/implementations/inferno/test/.gitignore b/bench/implementations/inferno/test/.gitignore new file mode 100644 index 0000000..93f1361 --- /dev/null +++ b/bench/implementations/inferno/test/.gitignore @@ -0,0 +1,2 @@ +node_modules +npm-debug.log diff --git a/bench/implementations/inferno/test/README.md b/bench/implementations/inferno/test/README.md new file mode 100644 index 0000000..6488647 --- /dev/null +++ b/bench/implementations/inferno/test/README.md @@ -0,0 +1,189 @@ +# TodoMVC Browser Tests + +The TodoMVC project has a great many implementations of exactly the same app using different MV* frameworks. Each app should be functionally identical. The goal of these tests is to provide a fully automated browser-based test that can be used to ensure that the specification is being followed by each and every TodoMVC app. + + +## Todo + +- [ ] Complete the test implementation (27 out of 28 are now complete). The only test that I am struggling with is to test that the delete button becomes visible on hover. +- [ ] Make it work with PhantomJS. In practice, Phantom is only a little bit faster, but it should work. Currently there are a few Phantom specific failures. +- [ ] Allow testing of apps that require a server (see: https://github.com/tastejs/todomvc/pull/821/files#r9377070) + + +## Running the tests + +These tests use Selenium 2 (WebDriver), via the JavaScript API (WebdriverJS). In order to run the tests, you will need to install the dependencies. npm must be version 2.0.0 or greater, so upgrade it first with `npm install -g npm` if `npm --version` outputs anything less than 2.0.0. Run the following command from within the `tests` folder: + +```sh +$ npm install +``` + +If you haven't already run `npm install` in the root directory, execute `npm install` there as well. + +You need to run a local server for the tests. Start the test server using: + +```sh +$ gulp test-server +``` + +To run the tests for all TodoMVC implementations, run the following: + +```sh +$ npm run test +``` + +In order to run tests for a single TodoMVC implementation, supply a framework argument as follows: + +```sh +$ npm run test -- --framework=angularjs +``` + +N.B. Remember the extra -- to separate the script arguments from the npm arguments. + +In order to run a specific test, use the mocha 'grep' function. For example: + +``` +$ npm run test -- --framework=jquery --grep 'should trim entered text' + + TodoMVC - jquery + Editing + ✓ should trim entered text (1115ms) + + + 1 passing (3s) +``` + +### Specifying the browser + +You can also specify the browser that will be used to execute the tests via the `---browser` argument. The tests default to using Chrome. For example, to run against phantomjs, use the following: + +```sh +$ npm run test -- --browser=phantomjs +``` + +You must install phantomjs first of course! + +Valid browser names can be found within webdriver via the `webdriver.Browser` enumeration. + + +## Reporting against known issues + +The `knownIssues.js` file details the currently known issues with the TodoMVC implementations. You can run the tests and compare against these issues using the `mocha-known-issues-reporter`: + +```sh +$ npm run test -- --reporter=mocha-known-issues-reporter +``` + +When run via grunt the suite supports exactly the same command line arguments. + +An example output with the known issues reporter is shown below: + +``` +$ npm run test -- --reporter=mocha-known-issues-reporter --framework=jquery +... +Running "simplemocha:files" (simplemocha) task +(1 of 27) pass: TodoMVC - jquery, No Todos, should hide #main and #footer +[...] +(17 of 27) pass: TodoMVC - jquery, Editing, should remove the item if an empty text string was entered +(18 of 27) known issue: TodoMVC - jquery, Editing, should cancel edits on escape -- error: undefined +(19 of 27) pass: TodoMVC - jquery, Counter, should display the current number of todo items +(20 of 27) pass: TodoMVC - jquery, Clear completed button, should display the number of completed items +(21 of 27) pass: TodoMVC - jquery, Clear completed button, should remove completed items when clicked +(22 of 27) pass: TodoMVC - jquery, Clear completed button, should be hidden when there are no items that are completed +(23 of 27) pass: TodoMVC - jquery, Persistence, should persist its data +(24 of 27) known issue: TodoMVC - jquery, Routing, should allow me to display active items -- error: Cannot call method 'click' of undefined +(25 of 27) known issue: TodoMVC - jquery, Routing, should allow me to display completed items -- error: Cannot call method 'click' of undefined +(26 of 27) known issue: TodoMVC - jquery, Routing, should allow me to display all items -- error: Cannot call method 'click' of undefined +(27 of 27) known issue: TodoMVC - jquery, Routing, should highlight the currently applied filter -- error: Cannot call method 'getAttribute' of undefined + +passed: 22/27 +failed: 5/27 +new issues: 0 +resolved issues: 0 +``` + +The reporter indicates the number of passes, failed, new and resolved issues. This makes it ideal for regression testing. + +### Example output + +A test run with the 'spec' reporter looks something like the following: + +``` +$ npm run test -- --framework=angularjs + + angularjs + TodoMVC + No Todos + ✓ should hide #main and #footer (201ms) + New Todo + ✓ should allow me to add todo items (548ms) + ✓ should clear text input field when an item is added (306ms) + ✓ should trim text input (569ms) + ✓ should show #main and #footer when items added (405ms) + Mark all as completed + ✓ should allow me to mark all items as completed (1040ms) + ✓ should allow me to clear the completion state of all items (1014ms) + ✓ complete all checkbox should update state when items are completed (1413ms) + Item + ✓ should allow me to mark items as complete (843ms) + ✓ should allow me to un-mark items as complete (978ms) + ✓ should allow me to edit an item (1155ms) + ✓ should show the remove button on hover + Editing + ✓ should hide other controls when editing (718ms) + ✓ should save edits on enter (1093ms) + ✓ should save edits on blur (1256ms) + ✓ should trim entered text (1163ms) + ✓ should remove the item if an empty text string was entered (1033ms) + ✓ should cancel edits on escape (1115ms) + Counter + ✓ should display the current number of todo items (462ms) + Clear completed button + ✓ should display the number of completed items (873ms) + ✓ should remove completed items when clicked (898ms) + ✓ should be hidden when there are no items that are completed (893ms) + Persistence + ✓ should persist its data (3832ms) + Routing + ✓ should allow me to display active items (871ms) + ✓ should allow me to display completed items (960ms) + ✓ should allow me to display all items (1192ms) + ✓ should highlight the currently applied filter (1095ms) + + + 27 passing (1m) +``` + + +## Speed mode + +In order to keep each test case fully isolated, the browser is closed then re-opened in between each test. This does mean that the tests can take quite a long time to run. If you don't mind the risk of side-effects you can run the tests in speed mode by adding the `--speedMode` argument. + +```sh +$ npm run test -- --speedMode +``` + +Before each test, all the todo items are checked as completed and the 'clear complete' button pressed. This makes the tests run in around half the time, but with the obvious risk that the tear-down code may fail. + + +## Lax mode + +There are certain implementations (e.g. GWT and Dojo) where the constraints of the framework mean that it is not possible to match exactly the HTML specification for TodoMVC. In these cases, the tests can be run in a 'lax' mode where the XPath queries used to locate DOM elements are more general. For example, rather than looking for a checkbox `input` element with a class of `toggle`, in lax mode it simply looks for any `input` elements of type `checkbox`. To run the tests in lax mode, simply use the `--laxMode` argument: + + +```sh +$ npm run test -- --laxMode +``` + + +## Test design + +Very briefly, the tests are designed as follows: + +- `page.js` - provides an abstraction layer for the HTML template. All the code required to access elements from the DOM is found within this file. The XPaths used to locate elements are based on the TodoMVC specification, using the required element classes / ids. +- `pageLaxMode.js` - extends the above in order to relax the XPath constraints. +- `testOperations.js` - provides common assertions and operations. +- `test.js` - Erm … the tests! These are written to closely match the TodoMVC spec. +- `allTest.js` - A simple file that locates all of the framework examples, and runs the tests for each. + +**NOTE:** All of the WebdriverJS methods return promises and are executed asynchronously. However, you do not have to 'chain' them using `then`, they are instead automagically added to a queue, then executed. This means that if you add non-WebdriverJS operations (asserts, log messages) these will not be executed at the point you might expect. This is why `TestOperations.js` uses an explicit `then` each time it asserts. diff --git a/bench/implementations/inferno/test/index.js b/bench/implementations/inferno/test/index.js new file mode 100644 index 0000000..962374e --- /dev/null +++ b/bench/implementations/inferno/test/index.js @@ -0,0 +1,414 @@ +'use strict'; + +var webdriver = require('selenium-webdriver'); +var chrome = require('selenium-webdriver/chrome'); +var test = require('selenium-webdriver/testing'); +var Page = require('./page'); +var PageLaxMode = require('./pageLaxMode'); +var TestOperations = require('./testOperations'); + +var argv = require('optimist').default('laxMode', false).default('browser', 'chrome').argv; + +function todoMVCTest(baseUrl, speedMode, laxMode, browserName) { + test.describe('TodoMVC: ', function () { + + var TODO_ITEM_ONE = 'buy some cheese'; + var TODO_ITEM_TWO = 'feed the cat'; + var TODO_ITEM_THREE = 'book a doctors appointment'; + var browser, testOps, page; + + // a number of tests use this set of ToDo items. + function createStandardItems(done) { + page.enterItem(TODO_ITEM_ONE); + page.enterItem(TODO_ITEM_TWO); + return page.enterItem(TODO_ITEM_THREE) + .then(function () { + if (done instanceof Function) { + done(); + } + }); + } + + function launchBrowser(done) { + var chromeOptions = new chrome.Options(); + chromeOptions.addArguments('no-sandbox'); + + if (process.env.CHROME_PATH !== undefined) { + chromeOptions.setChromeBinaryPath(process.env.CHROME_PATH); + } + + browser = new webdriver.Builder() + .withCapabilities({browserName: browserName}) + .setChromeOptions(chromeOptions) + .build(); + + browser.get(baseUrl); + + page = laxMode ? new PageLaxMode(browser) : new Page(browser); + testOps = new TestOperations(page); + + return page.ensureAppIsVisibleAndLoaded() + .then(function () { + if (done instanceof Function) { + done(); + } + }); + } + + function printCapturedLogs() { + var logs = browser.manage().logs(); + + return logs.get('browser') + .then(function (entries) { + if (entries && entries.length) { + console.log(entries); + } + }); + } + + function closeBrowser(done) { + return browser + .quit() + .then(function () { + if (done instanceof Function) { done(); } + }); + } + + if (speedMode) { + test.before(launchBrowser); + test.after(closeBrowser); + test.afterEach(function (done) { + return browser.executeScript('window.localStorage && localStorage.clear(); location.reload(true);') + .then(function () { done(); }); + }); + } else { + test.beforeEach(launchBrowser); + test.afterEach(function (done) { + printCapturedLogs() + .then(function () { + return closeBrowser(done); + }); + }); + } + + test.describe('When page is initially opened', function () { + + test.it('should focus on the todo input field', function (done) { + testOps.assertNewInputFocused() + .then(function () { done(); }); + }); + + }); + + test.describe('No Todos', function () { + + test.it('should hide #main and #footer', function (done) { + testOps.assertItemCount(0); + testOps.assertMainSectionVisibility(false); + testOps.assertFooterVisibility(false) + .then(function () { done(); }); + }); + + }); + + test.describe('New Todo', function () { + + test.it('should allow me to add todo items', function (done) { + page.enterItem(TODO_ITEM_ONE); + testOps.assertItems([TODO_ITEM_ONE]); + page.enterItem(TODO_ITEM_TWO); + testOps.assertItems([TODO_ITEM_ONE, TODO_ITEM_TWO]) + .then(function () { done(); }); + }); + + test.it('should clear text input field when an item is added', function (done) { + page.enterItem(TODO_ITEM_ONE); + testOps.assertNewItemInputFieldText('') + .then(function () { done(); }); + }); + + test.it('should append new items to the bottom of the list', function (done) { + createStandardItems(); + testOps.assertItemCount(3); + testOps.assertItemText(0, TODO_ITEM_ONE); + testOps.assertItemText(1, TODO_ITEM_TWO); + testOps.assertItemText(2, TODO_ITEM_THREE) + .then(function () { done(); }); + }); + + test.it('should trim text input', function (done) { + page.enterItem(' ' + TODO_ITEM_ONE + ' '); + testOps.assertItemText(0, TODO_ITEM_ONE) + .then(function () { done(); }); + }); + + test.it('should show #main and #footer when items added', function (done) { + page.enterItem(TODO_ITEM_ONE); + testOps.assertMainSectionVisibility(true); + testOps.assertFooterVisibility(true) + .then(function () { done(); }); + }); + + }); + + test.describe('Mark all as completed', function () { + + test.beforeEach(createStandardItems); + + test.it('should allow me to mark all items as completed', function (done) { + page.clickMarkAllCompletedCheckBox(); + testOps.assertItemCompletedStates([true, true, true]) + .then(function () { done(); }); + }); + + test.it('should correctly update the complete all checked state', function (done) { + // manually check all items + page.toggleItemAtIndex(0); + page.toggleItemAtIndex(1); + page.toggleItemAtIndex(2); + + // ensure checkall is in the correct state + testOps.assertCompleteAllCheckedStatus(true) + .then(function () { done(); }); + }); + + test.it('should allow me to clear the completion state of all items', function (done) { + page.clickMarkAllCompletedCheckBox(); + page.clickMarkAllCompletedCheckBox(); + + testOps.assertItemCompletedStates([false, false, false]) + .then(function () { done(); }); + }); + + test.it('complete all checkbox should update state when items are completed / cleared', function (done) { + page.clickMarkAllCompletedCheckBox(); + testOps.assertCompleteAllCheckedStatus(true); + + // all items are complete, now mark one as not-complete + page.toggleItemAtIndex(0); + testOps.assertCompleteAllCheckedStatus(false); + + // now mark as complete, so that once again all items are completed + page.toggleItemAtIndex(0); + testOps.assertCompleteAllCheckedStatus(true) + .then(function () { done(); }); + }); + + }); + + test.describe('Item', function () { + + test.it('should allow me to mark items as complete', function (done) { + page.enterItem(TODO_ITEM_ONE); + page.enterItem(TODO_ITEM_TWO); + + page.toggleItemAtIndex(0); + testOps.assertItemCompletedStates([true, false]); + + page.toggleItemAtIndex(1); + testOps.assertItemCompletedStates([true, true]) + .then(function () { done(); }); + }); + + test.it('should allow me to un-mark items as complete', function (done) { + page.enterItem(TODO_ITEM_ONE); + page.enterItem(TODO_ITEM_TWO); + + page.toggleItemAtIndex(0); + testOps.assertItemCompletedStates([true, false]); + + page.toggleItemAtIndex(0); + testOps.assertItemCompletedStates([false, false]) + .then(function () { done(); }); + }); + + }); + + test.describe('Editing', function () { + + test.beforeEach(function (done) { + createStandardItems(); + page.doubleClickItemAtIndex(1) + .then(function () { done(); }); + }); + + test.it('should focus the input', function (done) { + testOps.assertItemInputFocused(); + testOps.assertNewInputBlurred() // Unnecessary? The HTML spec dictates that only one element can be focused. + .then(function () { done(); }); + }); + + test.it('should hide other controls when editing', function (done) { + testOps.assertItemToggleIsHidden(1); + testOps.assertItemLabelIsHidden(1) + .then(function () { done(); }); + }); + + test.it('should save edits on enter', function (done) { + page.editItemAtIndex(1, 'buy some sausages' + webdriver.Key.ENTER); + testOps.assertItems([TODO_ITEM_ONE, 'buy some sausages', TODO_ITEM_THREE]) + .then(function () { done(); }); + }); + + test.it('should save edits on blur', function (done) { + page.editItemAtIndex(1, 'buy some sausages'); + // click a toggle button so that the blur() event is fired + page.toggleItemAtIndex(0); + testOps.assertItems([TODO_ITEM_ONE, 'buy some sausages', TODO_ITEM_THREE]) + .then(function () { done(); }); + }); + + test.it('should trim entered text', function (done) { + page.editItemAtIndex(1, ' buy some sausages ' + webdriver.Key.ENTER); + testOps.assertItems([TODO_ITEM_ONE, 'buy some sausages', TODO_ITEM_THREE]) + .then(function () { done(); }); + }); + + test.it('should remove the item if an empty text string was entered', function (done) { + page.editItemAtIndex(1, webdriver.Key.ENTER); + testOps.assertItems([TODO_ITEM_ONE, TODO_ITEM_THREE]) + .then(function () { done(); }); + }); + + test.it('should cancel edits on escape', function (done) { + page.editItemAtIndex(1, 'foo' + webdriver.Key.ESCAPE); + testOps.assertItems([TODO_ITEM_ONE, TODO_ITEM_TWO, TODO_ITEM_THREE]) + .then(function () { done(); }); + }); + + }); + + test.describe('Counter', function () { + + test.it('should display the current number of todo items', function (done) { + page.enterItem(TODO_ITEM_ONE); + testOps.assertItemCountText('1 item left'); + page.enterItem(TODO_ITEM_TWO); + testOps.assertItemCountText('2 items left') + .then(function () { done(); }); + }); + + }); + + test.describe('Clear completed button', function () { + + test.beforeEach(createStandardItems); + + test.it('should display the correct text', function (done) { + page.toggleItemAtIndex(1); + testOps.assertClearCompleteButtonText('Clear completed') + .then(function () { done(); }); + }); + + test.it('should remove completed items when clicked', function (done) { + page.toggleItemAtIndex(1); + page.clickClearCompleteButton(); + testOps.assertItemCount(2); + testOps.assertItems([TODO_ITEM_ONE, TODO_ITEM_THREE]) + .then(function () { done(); }); + }); + + test.it('should be hidden when there are no items that are completed', function (done) { + page.toggleItemAtIndex(1); + testOps.assertClearCompleteButtonVisibility(true); + page.clickClearCompleteButton(); + testOps.assertClearCompleteButtonVisibility(false) + .then(function () { done(); }); + }); + + }); + + test.describe('Persistence', function () { + + test.it('should persist its data', function (done) { + function stateTest() { + testOps.assertItemCount(2); + testOps.assertItems([TODO_ITEM_ONE, TODO_ITEM_TWO]); + return testOps.assertItemCompletedStates([false, true]); + } + + // set up state + page.enterItem(TODO_ITEM_ONE); + page.enterItem(TODO_ITEM_TWO); + page.toggleItemAtIndex(1); + stateTest(); + + // navigate away and back again + browser.get('about:blank'); + browser.get(baseUrl); + + // repeat the state test + stateTest() + .then(function () { done(); }); + }); + + }); + + test.describe('Routing', function () { + + test.beforeEach(createStandardItems); + + test.it('should allow me to display active items', function (done) { + page.toggleItemAtIndex(1); + page.filterByActiveItems(); + testOps.assertItems([TODO_ITEM_ONE, page.ITEM_HIDDEN_OR_REMOVED, TODO_ITEM_THREE]) + .then(function () { return done(); }); + }); + + test.it('should respect the back button', function (done) { + page.toggleItemAtIndex(1); + page.filterByActiveItems(); + page.filterByCompletedItems(); + testOps.assertItems([page.ITEM_HIDDEN_OR_REMOVED, TODO_ITEM_TWO]); // should show completed items + page.back(); // then active items + testOps.assertItems([TODO_ITEM_ONE, page.ITEM_HIDDEN_OR_REMOVED, TODO_ITEM_THREE]); + page.back(); // then all items + testOps.assertItems([TODO_ITEM_ONE, TODO_ITEM_TWO, TODO_ITEM_THREE]) + .then(function () { done(); }); + }); + + test.it('should allow me to display completed items', function (done) { + page.toggleItemAtIndex(1); + page.filterByCompletedItems(); + testOps.assertItems([page.ITEM_HIDDEN_OR_REMOVED, TODO_ITEM_TWO]); + page.filterByAllItems() // TODO: why + .then(function () { done(); }); + }); + + test.it('should allow me to display all items', function (done) { + page.toggleItemAtIndex(1); + + // apply the other filters first, before returning to the 'all' state + page.filterByActiveItems(); + page.filterByCompletedItems(); + page.filterByAllItems(); + testOps.assertItems([TODO_ITEM_ONE, TODO_ITEM_TWO, TODO_ITEM_THREE]) + .then(function () { done(); }); + }); + + test.it('should highlight the currently applied filter', function (done) { + // initially 'all' should be selected + testOps.assertFilterAtIndexIsSelected(0); + page.filterByActiveItems(); + testOps.assertFilterAtIndexIsSelected(1); + page.filterByCompletedItems(); + testOps.assertFilterAtIndexIsSelected(2) + .then(function () { done(); }); + }); + + }); + + }); +}; + +'use strict'; + +/** + * Init test + */ +todoMVCTest( + 'http://localhost:8000/index.html', + argv.speedMode, + argv.laxMode, + argv.browser +); diff --git a/bench/implementations/inferno/test/knownIssues.js b/bench/implementations/inferno/test/knownIssues.js new file mode 100644 index 0000000..65ed345 --- /dev/null +++ b/bench/implementations/inferno/test/knownIssues.js @@ -0,0 +1,131 @@ +module.exports = [ + + // durandal routing is very very slow. + // see: https://github.com/tastejs/todomvc/issues/831 + 'TodoMVC - durandal, Routing, should allow me to display active items', + 'TodoMVC - durandal, Routing, should allow me to display completed items', + 'TodoMVC - durandal, Routing, should allow me to display all items', + 'TodoMVC - durandal, Routing, should highlight the currently applied filter', + + // https://github.com/tastejs/todomvc/issues/828 + // routing should default to all + 'TodoMVC - sammyjs, Routing, should highlight the currently applied filter', + + // https://github.com/tastejs/todomvc/issues/824 + // this implementation has numerous edit experience issues + 'TodoMVC - angularjs_require, Mark all as completed, should allow me to mark all items as completed', + 'TodoMVC - angularjs_require, Mark all as completed, should allow me to clear the completion state of all items', + // jscs:disable + 'TodoMVC - angularjs_require, Mark all as completed, complete all checkbox should update state when items are completed / cleared', + + // jscs:enable + // https://github.com/tastejs/todomvc/issues/815 + // does not hide other controls while editing + 'TodoMVC - dojo, Editing, should hide other controls when editing', + + // https://github.com/tastejs/todomvc/issues/816 + // atma does not hide the main section, instead it hides the toggle-all checkbox + 'TodoMVC - atmajs, No Todos, should hide #main and #footer', + + // https://github.com/tastejs/todomvc/issues/819 + // the edit experience with soma is quite broken. You can + // get multiple elements into an edit state + 'TodoMVC - somajs_require, Editing, should remove the item if an empty text string was entered', + 'TodoMVC - somajs_require, Editing, should cancel edits on escape', + + // the following are covered by the following issue: + // https://github.com/tastejs/todomvc/issues/789 + 'TodoMVC - closure, Editing, should cancel edits on escape', + 'TodoMVC - ariatemplates, Editing, should cancel edits on escape', + 'TodoMVC - dermis, Editing, should cancel edits on escape', + 'TodoMVC - duel, Editing, should cancel edits on escape', + 'TodoMVC - extjs_deftjs, Editing, should cancel edits on escape', + 'TodoMVC - olives, Editing, should cancel edits on escape', + 'TodoMVC - rappidjs, Editing, should cancel edits on escape', + 'TodoMVC - serenadejs, Editing, should cancel edits on escape', + 'TodoMVC - typescript-angular, Editing, should cancel edits on escape', + 'TodoMVC - flight, Editing, should cancel edits on escape', + 'TodoMVC - backbone_require, Editing, should cancel edits on escape', + 'TodoMVC - dijon, Editing, should cancel edits on escape', + 'TodoMVC - knockoutjs_require, Editing, should cancel edits on escape', + + // all the following are covered by this issue: + // https://github.com/tastejs/todomvc/issues/856 + 'TodoMVC - knockoutjs, Routing, should respect the back button', + 'TodoMVC - spine, Routing, should respect the back button', + 'TodoMVC - serenadejs, Routing, should respect the back button', + 'TodoMVC - flight, Routing, should respect the back button', + 'TodoMVC - lavaca_require, Routing, should respect the back button', + 'TodoMVC - somajs_require, Routing, should respect the back button', + + // the following implementations do not support routing + 'TodoMVC - extjs_deftjs, Routing, should allow me to display active items', + 'TodoMVC - extjs_deftjs, Routing, should allow me to display completed items', + 'TodoMVC - extjs_deftjs, Routing, should allow me to display all items', + 'TodoMVC - extjs_deftjs, Routing, should highlight the currently applied filter', + 'TodoMVC - extjs_deftjs, Routing, should respect the back button', + 'TodoMVC - olives, Routing, should allow me to display active items', + 'TodoMVC - olives, Routing, should allow me to display completed items', + 'TodoMVC - olives, Routing, should allow me to display all items', + 'TodoMVC - olives, Routing, should highlight the currently applied filter', + 'TodoMVC - olives, Routing, should respect the back button', + 'TodoMVC - dijon, Routing, should allow me to display active items', + 'TodoMVC - dijon, Routing, should allow me to display completed items', + 'TodoMVC - dijon, Routing, should allow me to display all items', + 'TodoMVC - dijon, Routing, should highlight the currently applied filter', + 'TodoMVC - dijon, Routing, should respect the back button', + 'TodoMVC - duel, Routing, should allow me to display active items', + 'TodoMVC - duel, Routing, should allow me to display completed items', + 'TodoMVC - duel, Routing, should allow me to display all items', + 'TodoMVC - duel, Routing, should highlight the currently applied filter', + 'TodoMVC - duel, Routing, should respect the back button', + 'TodoMVC - knockoutjs_require, Routing, should allow me to display active items', + 'TodoMVC - knockoutjs_require, Routing, should allow me to display completed items', + 'TodoMVC - knockoutjs_require, Routing, should allow me to display all items', + 'TodoMVC - knockoutjs_require, Routing, should highlight the currently applied filter', + 'TodoMVC - knockoutjs_require, Routing, should respect the back button', + 'TodoMVC - angular-dart, Routing, should allow me to display active items', + 'TodoMVC - angular-dart, Routing, should allow me to display completed items', + 'TodoMVC - angular-dart, Routing, should allow me to display all items', + 'TodoMVC - angular-dart, Routing, should highlight the currently applied filter', + 'TodoMVC - angular-dart, Routing, should respect the back button', + 'TodoMVC - typescript-backbone, Routing, should allow me to display active items', + 'TodoMVC - typescript-backbone, Routing, should allow me to display completed items', + 'TodoMVC - typescript-backbone, Routing, should allow me to display all items', + 'TodoMVC - typescript-backbone, Routing, should highlight the currently applied filter', + 'TodoMVC - typescript-backbone, Routing, should respect the back button', + + // EXTJS is not spec compliant (by a long way!) + 'TodoMVC - extjs, New Todo, should show #main and #footer when items added', + 'TodoMVC - extjs, Mark all as completed, should allow me to mark all items as completed', + 'TodoMVC - extjs, Mark all as completed, complete all checkbox should update state when items are completed / cleared', + 'TodoMVC - extjs, Item, should allow me to mark items as complete', + 'TodoMVC - extjs, Item, should allow me to un-mark items as complete', + 'TodoMVC - extjs, Editing, should save edits on blur', + 'TodoMVC - extjs, Editing, should cancel edits on escape', + 'TodoMVC - extjs, Counter, should display the current number of todo items', + 'TodoMVC - extjs, Clear completed button, should display the number of completed items', + 'TodoMVC - extjs, Clear completed button, should remove completed items when clicked', + 'TodoMVC - extjs, Clear completed button, should be hidden when there are no items that are completed', + 'TodoMVC - extjs, Persistence, should persist its data', + 'TodoMVC - extjs, Routing, should allow me to display active items', + 'TodoMVC - extjs, Routing, should allow me to display completed items', + 'TodoMVC - extjs, Routing, should allow me to display all items', + 'TodoMVC - extjs, Routing, should highlight the currently applied filter', + 'TodoMVC - extjs, Routing, should respect the back button', + + // ----------------- Test framework issues ----------- + + // for some reason the persistence test fails for knockout, even though persistence is working + // just fine. Perhaps there is something asynchronous going on that is causing the assert + // to be executed early? + 'TodoMVC - knockoutjs, Persistence, should persist its data', + + // chaplin edit tests fail with the following: + // StaleElementReferenceError: stale element reference: element is not attached to the page document + 'TodoMVC - chaplin-brunch, Editing, should save edits on enter', + 'TodoMVC - chaplin-brunch, Editing, should save edits on blur', + 'TodoMVC - chaplin-brunch, Editing, should trim entered text', + 'TodoMVC - chaplin-brunch, Editing, should remove the item if an empty text string was entered', + 'TodoMVC - chaplin-brunch, Editing, should cancel edits on escape' +]; diff --git a/bench/implementations/inferno/test/learn.json b/bench/implementations/inferno/test/learn.json new file mode 100644 index 0000000..48de203 --- /dev/null +++ b/bench/implementations/inferno/test/learn.json @@ -0,0 +1,5 @@ +{ + "templates": { + "todomvc": "

    <%= name %>

    <% if (typeof examples !== 'undefined') { %> <% examples.forEach(function (example) { %>
    <%= example.name %>
    <% if (!location.href.match(example.url + '/')) { %> \" href=\"<%= example.url %>\">Demo, <% } if (example.type === 'backend') { %>\"><% } else { %>\"><% } %>Source <% }); %> <% } %>

    <%= description %>

    <% if (typeof link_groups !== 'undefined') { %>
    <% link_groups.forEach(function (link_group) { %>

    <%= link_group.heading %>

    <% }); %> <% } %>

    If you have other helpful links to share, or find any of the links above no longer work, please let us know.
    " + } +} diff --git a/bench/implementations/inferno/test/memory-exceptions.json b/bench/implementations/inferno/test/memory-exceptions.json new file mode 100644 index 0000000..acbdc39 --- /dev/null +++ b/bench/implementations/inferno/test/memory-exceptions.json @@ -0,0 +1,6 @@ +{ + "humble": { + "nodes": 30, + "listeners": 0 + } +} diff --git a/bench/implementations/inferno/test/memory.js b/bench/implementations/inferno/test/memory.js new file mode 100644 index 0000000..5d60410 --- /dev/null +++ b/bench/implementations/inferno/test/memory.js @@ -0,0 +1,99 @@ +'use strict'; + +var drool = require('drool'); +var exceptions = require('./memory-exceptions.json'); +var argv = require('optimist').default('laxMode', false).default('browser', 'chrome').argv; +var driverConfig = { + chromeOptions: 'no-sandbox' +}; + +if (typeof process.env.CHROME_PATH !== 'undefined') { + driverConfig.chromeBinaryPath = process.env.CHROME_PATH; +} + +var driver = drool.start(driverConfig); + +function idApp() { + return driver.findElement(drool.webdriver.By.css('#todoapp')) + .then(function () { return true; }) + .thenCatch(function () { return false; }); +} + +function newTodoSelector() { + return idApp().then(function (isId) { + if (isId) { + return '#new-todo'; + } + + return '.new-todo'; + }); +} + +function listSelector() { + return idApp().then(function (isId) { + if (isId) { + return '#todo-list li'; + } + + return '.todo-list li'; + }); +} + +/** + * Init + */ +drool.flow({ + repeatCount: 5, + setup: function () { + driver.get('http://localhost:8000/index.html'); + }, + action: function (name) { + driver.wait(function () { + driver.sleep(500); + return driver.findElement(drool.webdriver.By.css(newTodoSelector(name))) + .sendKeys('find magical goats', drool.webdriver.Key.ENTER) + .thenCatch(function () { + return false; + }) + .then(function () { + return driver.findElement(drool.webdriver.By.css(listSelector(name))).isDisplayed() + .then(function () { + return true; + }); + }); + }, 10000); + + driver.wait(function () { + return driver.findElement(drool.webdriver.By.css(listSelector(name))).click() + .thenCatch(function () { + return false; + }) + .then(function () { + return true; + }); + }); + + driver.findElement(drool.webdriver.By.css('.destroy')).click(); + }.bind(null, 'inferno'), + assert: function (after, initial) { + var nodeIncrease = (after.nodes - initial.nodes); + var listenerIncrease = (after.jsEventListeners - initial.jsEventListeners); + var memoryExceptions = exceptions['inferno'] || {}; + + console.log(this + ', ' + nodeIncrease + ', ' + + (after.jsHeapSizeUsed - initial.jsHeapSizeUsed) + ', ' + listenerIncrease); + + //https://code.google.com/p/chromium/issues/detail?id=516153 + if (nodeIncrease > memoryExceptions.nodes || 0) { + throw new Error('Node Count leak detected!'); + } + + if (listenerIncrease > memoryExceptions.listeners || 0) { + throw new Error('Event Listener leak detected!'); + } + + }.bind('inferno') +}, driver); + +driver.quit(); + diff --git a/bench/implementations/inferno/test/package.json b/bench/implementations/inferno/test/package.json new file mode 100644 index 0000000..f56e1c8 --- /dev/null +++ b/bench/implementations/inferno/test/package.json @@ -0,0 +1,15 @@ +{ + "private": true, + "devDependencies": { + "chromedriver": "^2.18.0", + "drool": "0.4.0", + "express": "^4.10", + "mocha": "*", + "mocha-known-issues-reporter": "git+https://github.com/ColinEberhardt/mocha-known-issues-reporter.git#v0.0.0", + "optimist": "^0.6.1", + "selenium-webdriver": "~2.53.1" + }, + "scripts": { + "test": "node server & mocha index.js --no-timeouts --reporter spec" + } +} diff --git a/bench/implementations/inferno/test/page.js b/bench/implementations/inferno/test/page.js new file mode 100644 index 0000000..7cb0866 --- /dev/null +++ b/bench/implementations/inferno/test/page.js @@ -0,0 +1,269 @@ +'use strict'; + +var webdriver = require('selenium-webdriver'); +var until = require('selenium-webdriver/lib/until'); + +var idSelectors = true; +var classOrId = idSelectors ? '#' : '.'; + +var DEFAULT_TIMEOUT = 3000; +var REMOVED_TIMEOUT = 100; + +var REMOVE_TEXT_KEY_SEQ = Array(51).join(webdriver.Key.BACK_SPACE + webdriver.Key.DELETE); + +// Unique symbols +var ELEMENT_MISSING = Object.freeze({}); +var ITEM_HIDDEN_OR_REMOVED = Object.freeze({}); + +module.exports = function Page(browser) { + // CSS ELEMENT SELECTORS + + this.getMainSectionCss = function () { return classOrId + 'main'; }; + + this.getFooterSectionCss = function () { return 'footer' + classOrId + 'footer'; }; + + this.getClearCompletedButtonCss = function () { return 'button' + classOrId + 'clear-completed'; }; + + this.getNewInputCss = function () { return 'input' + classOrId + 'new-todo'; }; + + this.getToggleAllCss = function () { return 'input' + classOrId + 'toggle-all'; }; + + this.getItemCountCss = function () { return 'span' + classOrId + 'todo-count'; }; + + this.getFilterCss = function (index) { + return classOrId + 'filters li:nth-of-type(' + (index + 1) + ') a, ' + + classOrId + 'filters a:nth-of-type(' + (index + 1) + ')'; + }; + + this.getSelectedFilterCss = function (index) { return this.getFilterCss(index) + '.selected'; }; + + this.getFilterAllCss = function () { return this.getFilterCss(0); }; + + this.getFilterActiveCss = function () { return this.getFilterCss(1); }; + + this.getFilterCompletedCss = function () { return this.getFilterCss(2); }; + + this.getListCss = function (suffixCss) { return 'ul' + classOrId + 'todo-list' + (suffixCss || ''); }; + + this.getListItemCss = function (index, suffixCss, excludeParentSelector) { + suffixCss = (index === undefined ? '' : ':nth-of-type(' + (index + 1) + ')') + (suffixCss || ''); + return excludeParentSelector ? 'li' + suffixCss : this.getListCss(' li' + suffixCss); + }; + + this.getListItemToggleCss = function (index) { return this.getListItemCss(index, ' input.toggle'); }; + + this.getListItemLabelCss = function (index) { return this.getListItemCss(index, ' label'); }; + + this.getLastListItemLabelCss = function (index) { return this.getListItemCss(index, ':last-of-type label'); }; + + this.getListItemInputCss = function (index) { return this.getListItemCss(index, ' input.edit'); }; + + this.getEditingListItemInputCss = function () { return this.getListItemCss(undefined, '.editing input.edit'); }; + + // This CSS selector returns the _last_ element of a list that exactly matches the provided list of completed states + // It is used as a boolean test of the item states + this.getListItemsWithCompletedStatesCss = function (completedStates) { + var suffixCss = ' ' + completedStates.map(function (completed, i) { + return this.getListItemCss(i, completed ? '.completed' : ':not(.completed)', true); + }, this).join(' + '); + return this.getListCss(suffixCss); + }; + + // PUBLIC SYMBOLS + + this.ITEM_HIDDEN_OR_REMOVED = ITEM_HIDDEN_OR_REMOVED; + + // NAVIGATION + + this.back = function () { + return browser.navigate().back(); + }; + + // ELEMENT RETREIVAL + // wait* methods guarantees to return an element, or throw an exception + // get* methods may return nothing at all, or in the case of element lists, an older version of the list + + this.getElements = function (css) { + return browser.findElements(webdriver.By.css(css)); + }; + + this.waitForElement = function (css, failMsg, timeout) { + return browser.wait(until.elementLocated(webdriver.By.css(css)), timeout || DEFAULT_TIMEOUT, failMsg); + }; + + this.waitForFocusedElement = function (css, failMsg) { + return this.waitForElement(css + ':focus', failMsg); + }; + + this.waitForBlurredElement = function (css, failMsg) { + return this.waitForElement(css + ':not(:focus)', failMsg); + }; + + this.waitForListItemCount = function (count) { + var self = this; + return browser.wait(function () { + return self.waitForElement(self.getListCss()) + .then(function (listElement) { + return listElement.findElements(webdriver.By.css(self.getListItemCss(undefined, undefined, true))); + }) + .then(function (listItems) { + return listItems.length === count; + }); + }, DEFAULT_TIMEOUT, 'Expected item list to contain ' + count + ' item' + (count === 1 ? '' : 's')); + }; + + this.waitForClearCompleteButton = function () { + return this.waitForElement(this.getClearCompletedButtonCss()); + }; + + this.waitForToggleForItem = function (index) { + return this.waitForElement(this.getListItemToggleCss(index)); + }; + + this.waitForItemLabel = function (index) { + return this.waitForElement(this.getListItemLabelCss(index)); + }; + + this.waitForNewItemInputField = function () { + return this.waitForElement(this.getNewInputCss()); + }; + + this.waitForMarkAllCompletedCheckBox = function () { + return this.waitForElement(this.getToggleAllCss()); + }; + + this.getListItems = function () { + return this.getElements(this.getListItemCss()); + }; + + this.waitForVisibility = function (shouldBeVisible, css, failMsg) { + if (shouldBeVisible) { + return this.waitForElement(css, failMsg) + .then(function (element) { + return browser.wait(until.elementIsVisible(element), DEFAULT_TIMEOUT, failMsg); + }); + } else { + return this.waitForElement(css, undefined, REMOVED_TIMEOUT) + .catch(function () { return ELEMENT_MISSING; }) + .then(function (elementOrError) { + return elementOrError === ELEMENT_MISSING ? + ELEMENT_MISSING : // Returning a value will resolve the promise + browser.wait(until.elementIsNotVisible(elementOrError), DEFAULT_TIMEOUT, failMsg); + }); + } + }; + + this.waitForMainSectionRemovedOrEmpty = function () { + return this.waitForElement(this.getMainSectionCss(), undefined, REMOVED_TIMEOUT) + .catch(function () { return ELEMENT_MISSING; }) + .then(function (elementOrError) { + return elementOrError === ELEMENT_MISSING ? ELEMENT_MISSING : this.waitForListItemCount(0); + }.bind(this)); + }; + + this.waitForCheckedStatus = function (shouldBeChecked, failMsg, element) { + var condition = shouldBeChecked ? 'elementIsSelected' : 'elementIsNotSelected'; + return browser.wait(until[condition](element), DEFAULT_TIMEOUT, failMsg); + }; + + this.waitForTextContent = function (text, failMsg, element) { + return browser.wait(until.elementTextIs(element, text), DEFAULT_TIMEOUT, failMsg); + }; + + // PAGE ACTIONS + + this.ensureAppIsVisibleAndLoaded = function () { + return this.waitForVisibility(false, this.getFooterSectionCss(), 'Footer is not hidden') + .then(this.waitForElement.bind( + this, '.new-todo, #new-todo', 'Could not find new todo input field', undefined)) + .then(function (newTodoElement) { + return newTodoElement.getAttribute('id'); + }) + .then(function (newTodoElementId) { + if (newTodoElementId === 'new-todo') { return; } + idSelectors = false; + classOrId = idSelectors ? '#' : '.'; + }); + }; + + this.clickMarkAllCompletedCheckBox = function () { + return this.waitForMarkAllCompletedCheckBox().click(); + }; + + this.clickClearCompleteButton = function () { + return this.waitForVisibility(true, this.getClearCompletedButtonCss(), + 'Expected clear completed items button to be visible') + .then(function (clearCompleteButton) { + clearCompleteButton.click(); + }); + }; + + this.enterItem = function (itemText) { + var self = this; + var nItems; + return self.getListItems() + .then(function (items) { + nItems = items.length; + }) + .then(this.waitForNewItemInputField.bind(this)) + .then(function (newItemInput) { + return newItemInput.sendKeys(itemText).then(function () { return newItemInput; }); + }) + .then(function (newItemInput) { + return browser.wait(function () { + // Hit Enter repeatedly until the text goes away + return newItemInput.sendKeys(webdriver.Key.ENTER) + .then(newItemInput.getAttribute.bind(newItemInput, 'value')) + .then(function (newItemInputValue) { + return newItemInputValue.length === 0; + }); + }, DEFAULT_TIMEOUT); + }) + .then(function () { + return self.waitForElement(self.getLastListItemLabelCss(nItems)); + }) + .then(this.waitForTextContent.bind(this, itemText.trim(), + 'Expected new item label to read ' + itemText.trim())); + }; + + this.toggleItemAtIndex = function (index) { + return this.waitForToggleForItem(index).click(); + }; + + this.editItemAtIndex = function (index, itemText) { + return this.waitForElement(this.getListItemInputCss(index)) + .then(function (itemEditField) { + return itemEditField.sendKeys(REMOVE_TEXT_KEY_SEQ, itemText); + }); + }; + + this.doubleClickItemAtIndex = function (index) { + return this.waitForItemLabel(index).then(function (itemLabel) { + // double click is not 'natively' supported, so we need to send the event direct to the element, see: + // jscs:disable + // http://stackoverflow.com/questions/3982442/selenium-2-webdriver-how-to-double-click-a-table-row-which-opens-a-new-window + // jscs:enable + return browser.executeScript('var evt = document.createEvent("MouseEvents");' + + 'evt.initMouseEvent("dblclick",true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0,null);' + + 'arguments[0].dispatchEvent(evt);', itemLabel); + }); + }; + + this.filterBy = function (filterCss) { + return this.waitForElement(filterCss) + .click() + .then(this.waitForElement.bind(this, filterCss + '.selected', undefined, undefined)); + }; + + this.filterByActiveItems = function () { + return this.filterBy(this.getFilterActiveCss()); + }; + + this.filterByCompletedItems = function () { + return this.filterBy(this.getFilterCompletedCss()); + }; + + this.filterByAllItems = function () { + return this.filterBy(this.getFilterAllCss()); + }; +}; diff --git a/bench/implementations/inferno/test/pageLaxMode.js b/bench/implementations/inferno/test/pageLaxMode.js new file mode 100644 index 0000000..0830aec --- /dev/null +++ b/bench/implementations/inferno/test/pageLaxMode.js @@ -0,0 +1,73 @@ +'use strict'; + +var Page = require('./page'); + +module.exports = function PageLaxMode() { + + Page.apply(this, arguments); + + this.getMainSectionCss = function () { + return 'section section'; + }; + + this.getFooterSectionCss = function () { + return 'section footer'; + }; + + this.getListCss = function (suffixCss) { + return [ + 'section > ul', + 'section > div > ul', + 'ul#todo-list' + ].map(function (listCss) { + return listCss + (suffixCss || ''); + }).join(', '); + }; + + this.getToggleAllCss = function () { + return [ + 'section > input[type="checkbox"]', + 'section > * > input[type="checkbox"]', + 'input#toggle-all' + ].join(', '); + }; + + this.getClearCompletedButtonCss = function () { + return [ + 'footer > button', + 'footer > * > button', + 'button#clear-completed' + ].join(', '); + }; + + this.getItemCountCss = function () { + return [ + 'footer > span', + 'footer > * > span' + ].join(', '); + }; + + this.getFilterCss = function (index) { + return 'footer ul li:nth-child(' + (index + 1) + ') a'; + }; + + this.getNewInputCss = function () { + return [ + 'header > input', + 'header > * > input', + 'input#new-todo' + ].join(', '); + }; + + this.getListItemToggleCss = function (index) { + return this.getListItemCss(index, ' input[type="checkbox"]'); + }; + + this.getListItemInputCss = function (index) { + return [ + this.getListItemCss(index, ' input.edit'), + this.getListItemCss(index, ' input[type="text"]') + ].join(', '); + }; + +}; diff --git a/bench/implementations/inferno/test/run.sh b/bench/implementations/inferno/test/run.sh new file mode 100755 index 0000000..694bbb4 --- /dev/null +++ b/bench/implementations/inferno/test/run.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +args="$@" + +npm i && \ +eval "node memory.js $args" && \ +eval "npm test -- $args" diff --git a/bench/implementations/inferno/test/server.js b/bench/implementations/inferno/test/server.js new file mode 100644 index 0000000..d3efaf3 --- /dev/null +++ b/bench/implementations/inferno/test/server.js @@ -0,0 +1,15 @@ +const fs = require('fs'); +const path = require('path'); +const express = require('express'); +const learnJson = require('./learn.json'); + +const learner = require.resolve('./learn.json'); + +const app = express(); +const dir = path.resolve(__dirname, '..'); + +app.use(express.static(dir)); +app.use('/learn.json', express.static(learner)); +app.use('/favicon.ico', function () {}); + +app.listen(8000); diff --git a/bench/implementations/inferno/test/testOperations.js b/bench/implementations/inferno/test/testOperations.js new file mode 100644 index 0000000..447171d --- /dev/null +++ b/bench/implementations/inferno/test/testOperations.js @@ -0,0 +1,103 @@ +'use strict'; + +function TestOperations(page) { + + this.assertItemInputFocused = function () { + return page.waitForFocusedElement(page.getEditingListItemInputCss(), 'Expected the item input to be focused'); + }; + + this.assertNewInputFocused = function () { + return page.waitForFocusedElement(page.getNewInputCss()); + }; + + this.assertNewInputBlurred = function () { + return page.waitForBlurredElement(page.getNewInputCss()); + }; + + this.assertItemCount = function (itemCount) { + return itemCount === 0 ? + page.waitForMainSectionRemovedOrEmpty() : + page.waitForListItemCount(itemCount); + }; + + this.assertClearCompleteButtonText = function (buttonText) { + return page.waitForClearCompleteButton() + .then(page.waitForTextContent.bind(page, buttonText, 'Expected clear button text to be ' + buttonText)); + }; + + this.assertClearCompleteButtonVisibility = function (shouldBeVisible) { + var failMsg = 'Expected the clear completed items button to be ' + (shouldBeVisible ? 'visible' : 'hidden'); + return page.waitForVisibility(shouldBeVisible, page.getClearCompletedButtonCss(), failMsg); + }; + + this.assertMainSectionVisibility = function (shouldBeVisible) { + var failMsg = 'Expected main section to be ' + (shouldBeVisible ? 'visible' : 'hidden'); + return page.waitForVisibility(shouldBeVisible, page.getMainSectionCss(), failMsg); + }; + + this.assertFooterVisibility = function (shouldBeVisible) { + var failMsg = 'Expected footer to be ' + (shouldBeVisible ? 'visible' : 'hidden'); + return page.waitForVisibility(shouldBeVisible, page.getFooterSectionCss(), failMsg); + }; + + this.assertItemToggleIsHidden = function (index) { + return page.waitForVisibility(false, page.getListItemToggleCss(index), + 'Expected the item toggle button to be hidden'); + }; + + this.assertItemLabelIsHidden = function (index) { + return page.waitForVisibility(false, page.getListItemLabelCss(index), 'Expected the item label to be hidden'); + }; + + this.assertNewItemInputFieldText = function (text) { + return page.waitForNewItemInputField() + .then(page.waitForTextContent.bind(page, text, + 'Expected the new item input text field contents to be ' + text)); + }; + + this.assertItemText = function (itemIndex, text) { + return page.waitForItemLabel(itemIndex) + .then(page.waitForTextContent.bind(page, text, 'Expected the item label to be ' + text)); + }; + + this.assertItems = function (textArray) { + return page.getListItems().then(function (items) { + if (items.length < textArray.length) { + // This means that the framework removes rather than hides list items + textArray = textArray.filter(function (item) { return item !== page.ITEM_HIDDEN_OR_REMOVED; }); + } + var ret; + textArray.forEach(function (text, i) { + if (text === page.ITEM_HIDDEN_OR_REMOVED) { return; } + var promise = page.waitForTextContent(text, 'Expected item text to be ' + text, items[i]); + ret = ret ? ret.then(promise) : promise; + }); + return ret; + }); + }; + + this.assertItemCountText = function (text) { + return page.waitForElement(page.getItemCountCss()) + .then(page.waitForTextContent.bind(page, text, 'Expected item count text to be ' + text)); + }; + + this.assertItemCompletedStates = function (completedStates) { + return page.waitForElement( + page.getListItemsWithCompletedStatesCss(completedStates), + 'Item completed states were incorrect'); + }; + + this.assertFilterAtIndexIsSelected = function (selectedIndex) { + return page.waitForElement( + page.getSelectedFilterCss(selectedIndex), + 'Expexted the filter / route at index ' + selectedIndex + ' to be selected'); + }; + + this.assertCompleteAllCheckedStatus = function (shouldBeChecked) { + var failMsg = 'Expected the mark-all-completed checkbox to be ' + shouldBeChecked ? 'checked' : 'unchecked'; + return page.waitForMarkAllCompletedCheckBox() + .then(page.waitForCheckedStatus.bind(page, shouldBeChecked, failMsg)); + }; +} + +module.exports = TestOperations; diff --git a/bench/implementations/inferno/test/yarn.lock b/bench/implementations/inferno/test/yarn.lock new file mode 100644 index 0000000..2e5eefe --- /dev/null +++ b/bench/implementations/inferno/test/yarn.lock @@ -0,0 +1,581 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +abbrev@1: + version "1.0.9" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" + +accepts@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.3.tgz#c3ca7434938648c3e0d9c1e328dd68b622c284ca" + dependencies: + mime-types "~2.1.11" + negotiator "0.6.1" + +adm-zip@0.4.4: + version "0.4.4" + resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.4.tgz#a61ed5ae6905c3aea58b3a657d25033091052736" + +adm-zip@^0.4.7: + version "0.4.7" + resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.7.tgz#8606c2cbf1c426ce8c8ec00174447fd49b6eafc1" + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + +balanced-match@^0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" + +brace-expansion@^1.0.0: + version "1.1.6" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.6.tgz#7197d7eaa9b87e648390ea61fc66c84427420df9" + dependencies: + balanced-match "^0.4.1" + concat-map "0.0.1" + +browser-stdout@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" + +chromedriver@^2.18.0: + version "2.25.2" + resolved "https://registry.yarnpkg.com/chromedriver/-/chromedriver-2.25.2.tgz#20bfcf1f84ede626be39abf94454a87c1a2ef0b5" + dependencies: + adm-zip "^0.4.7" + kew "^0.5.0" + mkdirp "^0.5.0" + npmconf "^2.1.1" + rimraf "^2.0.3" + +commander@2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" + dependencies: + graceful-readlink ">= 1.0.0" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + +config-chain@~1.1.8: + version "1.1.11" + resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.11.tgz#aba09747dfbe4c3e70e766a6e41586e1859fc6f2" + dependencies: + ini "^1.3.4" + proto-list "~1.2.1" + +content-disposition@0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.1.tgz#87476c6a67c8daa87e32e87616df883ba7fb071b" + +content-type@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.2.tgz#b7d113aee7a8dd27bd21133c4dc2529df1721eed" + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + +cookie@0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" + +debug@2.2.0, debug@~2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" + dependencies: + ms "0.7.1" + +depd@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.0.tgz#e1bd82c6aab6ced965b97b88b17ed3e528ca18c3" + +destroy@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" + +diff@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-1.4.0.tgz#7f28d2eb9ee7b15a97efd89ce63dcfdaa3ccbabf" + +drool@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/drool/-/drool-0.4.0.tgz#bc60d33b46a956e756d78e995f44a6b3233401dc" + dependencies: + selenium-webdriver "2.53.1" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + +encodeurl@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.1.tgz#79e3d58655346909fe6f0f45a5de68103b294d20" + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + +escape-string-regexp@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + +etag@~1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.7.0.tgz#03d30b5f67dd6e632d2945d30d6652731a34d5d8" + +express@^4.10: + version "4.14.0" + resolved "https://registry.yarnpkg.com/express/-/express-4.14.0.tgz#c1ee3f42cdc891fb3dc650a8922d51ec847d0d66" + dependencies: + accepts "~1.3.3" + array-flatten "1.1.1" + content-disposition "0.5.1" + content-type "~1.0.2" + cookie "0.3.1" + cookie-signature "1.0.6" + debug "~2.2.0" + depd "~1.1.0" + encodeurl "~1.0.1" + escape-html "~1.0.3" + etag "~1.7.0" + finalhandler "0.5.0" + fresh "0.3.0" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "~2.3.0" + parseurl "~1.3.1" + path-to-regexp "0.1.7" + proxy-addr "~1.1.2" + qs "6.2.0" + range-parser "~1.2.0" + send "0.14.1" + serve-static "~1.11.1" + type-is "~1.6.13" + utils-merge "1.0.0" + vary "~1.1.0" + +finalhandler@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-0.5.0.tgz#e9508abece9b6dba871a6942a1d7911b91911ac7" + dependencies: + debug "~2.2.0" + escape-html "~1.0.3" + on-finished "~2.3.0" + statuses "~1.3.0" + unpipe "~1.0.0" + +forwarded@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.0.tgz#19ef9874c4ae1c297bcf078fde63a09b66a84363" + +fresh@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.3.0.tgz#651f838e22424e7566de161d8358caa199f83d4f" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + +glob@7.0.5, glob@^7.0.5: + version "7.0.5" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.0.5.tgz#b4202a69099bbb4d292a7c1b95b6682b67ebdc95" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.2" + once "^1.3.0" + path-is-absolute "^1.0.0" + +"graceful-readlink@>= 1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" + +growl@1.9.2: + version "1.9.2" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" + +has-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" + +http-errors@~1.5.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.5.1.tgz#788c0d2c1de2c81b9e6e8c01843b6b97eb920750" + dependencies: + inherits "2.0.3" + setprototypeof "1.0.2" + statuses ">= 1.3.1 < 2" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.3, inherits@~2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + +ini@^1.2.0, ini@^1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" + +ipaddr.js@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.1.1.tgz#c791d95f52b29c1247d5df80ada39b8a73647230" + +json3@3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" + +kew@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/kew/-/kew-0.5.0.tgz#ece11cb5d8d01a81f8ce804c8d0bba06e6b25ca2" + +lodash._baseassign@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e" + dependencies: + lodash._basecopy "^3.0.0" + lodash.keys "^3.0.0" + +lodash._basecopy@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" + +lodash._basecreate@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz#1bc661614daa7fc311b7d03bf16806a0213cf821" + +lodash._getnative@^3.0.0: + version "3.9.1" + resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" + +lodash._isiterateecall@^3.0.0: + version "3.0.9" + resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" + +lodash.create@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/lodash.create/-/lodash.create-3.1.1.tgz#d7f2849f0dbda7e04682bb8cd72ab022461debe7" + dependencies: + lodash._baseassign "^3.0.0" + lodash._basecreate "^3.0.0" + lodash._isiterateecall "^3.0.0" + +lodash.isarguments@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" + +lodash.isarray@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" + +lodash.keys@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" + dependencies: + lodash._getnative "^3.0.0" + lodash.isarguments "^3.0.0" + lodash.isarray "^3.0.0" + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + +mime-db@~1.25.0: + version "1.25.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.25.0.tgz#c18dbd7c73a5dbf6f44a024dc0d165a1e7b1c392" + +mime-types@~2.1.11, mime-types@~2.1.13: + version "2.1.13" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.13.tgz#e07aaa9c6c6b9a7ca3012c69003ad25a39e92a88" + dependencies: + mime-db "~1.25.0" + +mime@1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53" + +minimatch@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774" + dependencies: + brace-expansion "^1.0.0" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + +minimist@~0.0.1: + version "0.0.10" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" + +mkdirp@0.5.1, mkdirp@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + dependencies: + minimist "0.0.8" + +"mocha-known-issues-reporter@git+https://github.com/ColinEberhardt/mocha-known-issues-reporter.git#v0.0.0": + version "0.0.0" + resolved "git+https://github.com/ColinEberhardt/mocha-known-issues-reporter.git#8aea16b3e9596ee794295abbed8cdb95fb379e93" + +mocha@*: + version "3.2.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.2.0.tgz#7dc4f45e5088075171a68896814e6ae9eb7a85e3" + dependencies: + browser-stdout "1.3.0" + commander "2.9.0" + debug "2.2.0" + diff "1.4.0" + escape-string-regexp "1.0.5" + glob "7.0.5" + growl "1.9.2" + json3 "3.3.2" + lodash.create "3.1.1" + mkdirp "0.5.1" + supports-color "3.1.2" + +ms@0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" + +negotiator@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" + +nopt@~3.0.1: + version "3.0.6" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" + dependencies: + abbrev "1" + +npmconf@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/npmconf/-/npmconf-2.1.2.tgz#66606a4a736f1e77a059aa071a79c94ab781853a" + dependencies: + config-chain "~1.1.8" + inherits "~2.0.0" + ini "^1.2.0" + mkdirp "^0.5.0" + nopt "~3.0.1" + once "~1.3.0" + osenv "^0.1.0" + semver "2 || 3 || 4" + uid-number "0.0.5" + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + dependencies: + ee-first "1.1.1" + +once@^1.3.0, once@~1.3.0: + version "1.3.3" + resolved "https://registry.yarnpkg.com/once/-/once-1.3.3.tgz#b2e261557ce4c314ec8304f3fa82663e4297ca20" + dependencies: + wrappy "1" + +optimist@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" + dependencies: + minimist "~0.0.1" + wordwrap "~0.0.2" + +options@>=0.0.5: + version "0.0.6" + resolved "https://registry.yarnpkg.com/options/-/options-0.0.6.tgz#ec22d312806bb53e731773e7cdaefcf1c643128f" + +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + +os-tmpdir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + +osenv@^0.1.0: + version "0.1.3" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.3.tgz#83cf05c6d6458fc4d5ac6362ea325d92f2754217" + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.0" + +parseurl@~1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.1.tgz#c8ab8c9223ba34888aa64a297b28853bec18da56" + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + +proto-list@~1.2.1: + version "1.2.4" + resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" + +proxy-addr@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-1.1.2.tgz#b4cc5f22610d9535824c123aef9d3cf73c40ba37" + dependencies: + forwarded "~0.1.0" + ipaddr.js "1.1.1" + +qs@6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.2.0.tgz#3b7848c03c2dece69a9522b0fae8c4126d745f3b" + +range-parser@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" + +rimraf@^2.0.3, rimraf@^2.2.8: + version "2.5.4" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.5.4.tgz#96800093cbf1a0c86bd95b4625467535c29dfa04" + dependencies: + glob "^7.0.5" + +sax@0.6.x: + version "0.6.1" + resolved "https://registry.yarnpkg.com/sax/-/sax-0.6.1.tgz#563b19c7c1de892e09bfc4f2fc30e3c27f0952b9" + +selenium-webdriver@2.53.1: + version "2.53.1" + resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-2.53.1.tgz#b50673955dc03b9164c07773a86b25ea7161dbd9" + dependencies: + adm-zip "0.4.4" + rimraf "^2.2.8" + tmp "0.0.24" + ws "^1.0.1" + xml2js "0.4.4" + +selenium-webdriver@~2.53.1: + version "2.53.3" + resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-2.53.3.tgz#d29ff5a957dff1a1b49dc457756e4e4bfbdce085" + dependencies: + adm-zip "0.4.4" + rimraf "^2.2.8" + tmp "0.0.24" + ws "^1.0.1" + xml2js "0.4.4" + +"semver@2 || 3 || 4": + version "4.3.6" + resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da" + +send@0.14.1: + version "0.14.1" + resolved "https://registry.yarnpkg.com/send/-/send-0.14.1.tgz#a954984325392f51532a7760760e459598c89f7a" + dependencies: + debug "~2.2.0" + depd "~1.1.0" + destroy "~1.0.4" + encodeurl "~1.0.1" + escape-html "~1.0.3" + etag "~1.7.0" + fresh "0.3.0" + http-errors "~1.5.0" + mime "1.3.4" + ms "0.7.1" + on-finished "~2.3.0" + range-parser "~1.2.0" + statuses "~1.3.0" + +serve-static@~1.11.1: + version "1.11.1" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.11.1.tgz#d6cce7693505f733c759de57befc1af76c0f0805" + dependencies: + encodeurl "~1.0.1" + escape-html "~1.0.3" + parseurl "~1.3.1" + send "0.14.1" + +setprototypeof@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.2.tgz#81a552141ec104b88e89ce383103ad5c66564d08" + +"statuses@>= 1.3.1 < 2", statuses@~1.3.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" + +supports-color@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5" + dependencies: + has-flag "^1.0.0" + +tmp@0.0.24: + version "0.0.24" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.24.tgz#d6a5e198d14a9835cc6f2d7c3d9e302428c8cf12" + +type-is@~1.6.13: + version "1.6.14" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.14.tgz#e219639c17ded1ca0789092dd54a03826b817cb2" + dependencies: + media-typer "0.3.0" + mime-types "~2.1.13" + +uid-number@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.5.tgz#5a3db23ef5dbd55b81fce0ec9a2ac6fccdebb81e" + +ultron@1.0.x: + version "1.0.2" + resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.0.2.tgz#ace116ab557cd197386a4e88f4685378c8b2e4fa" + +unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + +utils-merge@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.0.tgz#0294fb922bb9375153541c4f7096231f287c8af8" + +vary@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.0.tgz#e1e5affbbd16ae768dd2674394b9ad3022653140" + +wordwrap@~0.0.2: + version "0.0.3" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + +ws@^1.0.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-1.1.1.tgz#082ddb6c641e85d4bb451f03d52f06eabdb1f018" + dependencies: + options ">=0.0.5" + ultron "1.0.x" + +xml2js@0.4.4: + version "0.4.4" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.4.tgz#3111010003008ae19240eba17497b57c729c555d" + dependencies: + sax "0.6.x" + xmlbuilder ">=1.0.0" + +xmlbuilder@>=1.0.0: + version "8.2.2" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-8.2.2.tgz#69248673410b4ba42e1a6136551d2922335aa773" diff --git a/bench/implementations/inferno/webpack.config.js b/bench/implementations/inferno/webpack.config.js new file mode 100644 index 0000000..f1a91aa --- /dev/null +++ b/bench/implementations/inferno/webpack.config.js @@ -0,0 +1,31 @@ +const webpack = require('webpack'); + +module.exports = { + entry: './src/index.js', + output: { + path: './dist', + publicPath: 'dist', + filename: 'bundle.js' + }, + module: { + loaders: [{ + test: /\.jsx?$/, + exclude: /node_modules/, + loader: 'babel', + query: { + presets: ['es2015-loose', 'stage-0'], + plugins: ['syntax-jsx', 'inferno'] + } + }] + }, + plugins: [ + new webpack.DefinePlugin({ + 'process.env': { + 'NODE_ENV': JSON.stringify('production') + } + }), + ], + devServer: { + port: process.env.PORT || 8000 + } +}; diff --git a/bench/implementations/inferno/yarn.lock b/bench/implementations/inferno/yarn.lock new file mode 100644 index 0000000..3ad2f2a --- /dev/null +++ b/bench/implementations/inferno/yarn.lock @@ -0,0 +1,2597 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +abbrev@1: + version "1.0.9" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" + +accepts@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.3.tgz#c3ca7434938648c3e0d9c1e328dd68b622c284ca" + dependencies: + mime-types "~2.1.11" + negotiator "0.6.1" + +acorn@^3.0.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" + +align-text@^0.1.1, align-text@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" + dependencies: + kind-of "^3.0.2" + longest "^1.0.1" + repeat-string "^1.5.2" + +amdefine@>=0.0.4: + version "1.0.1" + resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + +ansi-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.0.0.tgz#c5061b6e0ef8a81775e50f5d66151bf6bf371107" + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + +anymatch@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.0.tgz#a3e52fa39168c825ff57b0248126ce5a8ff95507" + dependencies: + arrify "^1.0.0" + micromatch "^2.1.5" + +aproba@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.0.4.tgz#2713680775e7614c8ba186c065d4e2e52d1072c0" + +are-we-there-yet@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.2.tgz#80e470e95a084794fe1899262c5667c6e88de1b3" + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.0 || ^1.1.13" + +arr-diff@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" + dependencies: + arr-flatten "^1.0.1" + +arr-flatten@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.0.1.tgz#e5ffe54d45e19f32f216e91eb99c8ce892bb604b" + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + +array-unique@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" + +arrify@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + +asn1@~0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" + +assert-plus@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" + +assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + +assert@^1.1.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91" + dependencies: + util "0.10.3" + +async-each@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" + +async@^0.9.0: + version "0.9.2" + resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" + +async@^1.3.0: + version "1.5.2" + resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" + +async@~0.2.6: + version "0.2.10" + resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + +aws-sign2@~0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" + +aws4@^1.2.1: + version "1.5.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.5.0.tgz#0a29ffb79c31c9e712eeb087e8e7a64b4a56d755" + +babel-code-frame@^6.16.0: + version "6.16.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.16.0.tgz#f90e60da0862909d3ce098733b5d3987c97cb8de" + dependencies: + chalk "^1.1.0" + esutils "^2.0.2" + js-tokens "^2.0.0" + +babel-core@^6.18.0, babel-core@^6.5.2: + version "6.18.2" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.18.2.tgz#d8bb14dd6986fa4f3566a26ceda3964fa0e04e5b" + dependencies: + babel-code-frame "^6.16.0" + babel-generator "^6.18.0" + babel-helpers "^6.16.0" + babel-messages "^6.8.0" + babel-register "^6.18.0" + babel-runtime "^6.9.1" + babel-template "^6.16.0" + babel-traverse "^6.18.0" + babel-types "^6.18.0" + babylon "^6.11.0" + convert-source-map "^1.1.0" + debug "^2.1.1" + json5 "^0.5.0" + lodash "^4.2.0" + minimatch "^3.0.2" + path-is-absolute "^1.0.0" + private "^0.1.6" + slash "^1.0.0" + source-map "^0.5.0" + +babel-generator@^6.18.0: + version "6.19.0" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.19.0.tgz#9b2f244204777a3d6810ec127c673c87b349fac5" + dependencies: + babel-messages "^6.8.0" + babel-runtime "^6.9.0" + babel-types "^6.19.0" + detect-indent "^4.0.0" + jsesc "^1.3.0" + lodash "^4.2.0" + source-map "^0.5.0" + +babel-helper-bindify-decorators@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.18.0.tgz#fc00c573676a6e702fffa00019580892ec8780a5" + dependencies: + babel-runtime "^6.0.0" + babel-traverse "^6.18.0" + babel-types "^6.18.0" + +babel-helper-builder-binary-assignment-operator-visitor@^6.8.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.18.0.tgz#8ae814989f7a53682152e3401a04fabd0bb333a6" + dependencies: + babel-helper-explode-assignable-expression "^6.18.0" + babel-runtime "^6.0.0" + babel-types "^6.18.0" + +babel-helper-call-delegate@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.18.0.tgz#05b14aafa430884b034097ef29e9f067ea4133bd" + dependencies: + babel-helper-hoist-variables "^6.18.0" + babel-runtime "^6.0.0" + babel-traverse "^6.18.0" + babel-types "^6.18.0" + +babel-helper-define-map@^6.18.0, babel-helper-define-map@^6.8.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.18.0.tgz#8d6c85dc7fbb4c19be3de40474d18e97c3676ec2" + dependencies: + babel-helper-function-name "^6.18.0" + babel-runtime "^6.9.0" + babel-types "^6.18.0" + lodash "^4.2.0" + +babel-helper-explode-assignable-expression@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.18.0.tgz#14b8e8c2d03ad735d4b20f1840b24cd1f65239fe" + dependencies: + babel-runtime "^6.0.0" + babel-traverse "^6.18.0" + babel-types "^6.18.0" + +babel-helper-explode-class@^6.8.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-helper-explode-class/-/babel-helper-explode-class-6.18.0.tgz#c44f76f4fa23b9c5d607cbac5d4115e7a76f62cb" + dependencies: + babel-helper-bindify-decorators "^6.18.0" + babel-runtime "^6.0.0" + babel-traverse "^6.18.0" + babel-types "^6.18.0" + +babel-helper-function-name@^6.18.0, babel-helper-function-name@^6.8.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.18.0.tgz#68ec71aeba1f3e28b2a6f0730190b754a9bf30e6" + dependencies: + babel-helper-get-function-arity "^6.18.0" + babel-runtime "^6.0.0" + babel-template "^6.8.0" + babel-traverse "^6.18.0" + babel-types "^6.18.0" + +babel-helper-get-function-arity@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.18.0.tgz#a5b19695fd3f9cdfc328398b47dafcd7094f9f24" + dependencies: + babel-runtime "^6.0.0" + babel-types "^6.18.0" + +babel-helper-hoist-variables@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.18.0.tgz#a835b5ab8b46d6de9babefae4d98ea41e866b82a" + dependencies: + babel-runtime "^6.0.0" + babel-types "^6.18.0" + +babel-helper-optimise-call-expression@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.18.0.tgz#9261d0299ee1a4f08a6dd28b7b7c777348fd8f0f" + dependencies: + babel-runtime "^6.0.0" + babel-types "^6.18.0" + +babel-helper-regex@^6.8.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.18.0.tgz#ae0ebfd77de86cb2f1af258e2cc20b5fe893ecc6" + dependencies: + babel-runtime "^6.9.0" + babel-types "^6.18.0" + lodash "^4.2.0" + +babel-helper-remap-async-to-generator@^6.16.0, babel-helper-remap-async-to-generator@^6.16.2: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.18.0.tgz#336cdf3cab650bb191b02fc16a3708e7be7f9ce5" + dependencies: + babel-helper-function-name "^6.18.0" + babel-runtime "^6.0.0" + babel-template "^6.16.0" + babel-traverse "^6.18.0" + babel-types "^6.18.0" + +babel-helper-replace-supers@^6.18.0, babel-helper-replace-supers@^6.8.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.18.0.tgz#28ec69877be4144dbd64f4cc3a337e89f29a924e" + dependencies: + babel-helper-optimise-call-expression "^6.18.0" + babel-messages "^6.8.0" + babel-runtime "^6.0.0" + babel-template "^6.16.0" + babel-traverse "^6.18.0" + babel-types "^6.18.0" + +babel-helpers@^6.16.0: + version "6.16.0" + resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.16.0.tgz#1095ec10d99279460553e67eb3eee9973d3867e3" + dependencies: + babel-runtime "^6.0.0" + babel-template "^6.16.0" + +babel-loader@^6.2.1: + version "6.2.9" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-6.2.9.tgz#2bce6a1c29b47afa90b937ba1fb1f87084d61c61" + dependencies: + find-cache-dir "^0.1.1" + loader-utils "^0.2.11" + mkdirp "^0.5.1" + object-assign "^4.0.1" + +babel-messages@^6.8.0: + version "6.8.0" + resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.8.0.tgz#bf504736ca967e6d65ef0adb5a2a5f947c8e0eb9" + dependencies: + babel-runtime "^6.0.0" + +babel-plugin-check-es2015-constants@^6.3.13: + version "6.8.0" + resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.8.0.tgz#dbf024c32ed37bfda8dee1e76da02386a8d26fe7" + dependencies: + babel-runtime "^6.0.0" + +babel-plugin-inferno@beta13: + version "1.2.0-beta13" + resolved "https://registry.yarnpkg.com/babel-plugin-inferno/-/babel-plugin-inferno-1.2.0-beta13.tgz#3a5beb856ea75e7b2891e692aeda861dcbfb190d" + dependencies: + babel-plugin-syntax-jsx "^6.18.0" + +babel-plugin-syntax-async-functions@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" + +babel-plugin-syntax-async-generators@^6.5.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz#6bc963ebb16eccbae6b92b596eb7f35c342a8b9a" + +babel-plugin-syntax-class-constructor-call@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz#9cb9d39fe43c8600bec8146456ddcbd4e1a76416" + +babel-plugin-syntax-class-properties@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de" + +babel-plugin-syntax-decorators@^6.13.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz#312563b4dbde3cc806cee3e416cceeaddd11ac0b" + +babel-plugin-syntax-do-expressions@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz#5747756139aa26d390d09410b03744ba07e4796d" + +babel-plugin-syntax-dynamic-import@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz#8d6a26229c83745a9982a441051572caa179b1da" + +babel-plugin-syntax-exponentiation-operator@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" + +babel-plugin-syntax-export-extensions@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz#70a1484f0f9089a4e84ad44bac353c95b9b12721" + +babel-plugin-syntax-function-bind@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz#48c495f177bdf31a981e732f55adc0bdd2601f46" + +babel-plugin-syntax-jsx@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" + +babel-plugin-syntax-object-rest-spread@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" + +babel-plugin-syntax-trailing-function-commas@^6.3.13: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.13.0.tgz#2b84b7d53dd744f94ff1fad7669406274b23f541" + +babel-plugin-transform-async-generator-functions@^6.17.0: + version "6.17.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.17.0.tgz#d0b5a2b2f0940f2b245fa20a00519ed7bc6cae54" + dependencies: + babel-helper-remap-async-to-generator "^6.16.2" + babel-plugin-syntax-async-generators "^6.5.0" + babel-runtime "^6.0.0" + +babel-plugin-transform-async-to-generator@^6.16.0: + version "6.16.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.16.0.tgz#19ec36cb1486b59f9f468adfa42ce13908ca2999" + dependencies: + babel-helper-remap-async-to-generator "^6.16.0" + babel-plugin-syntax-async-functions "^6.8.0" + babel-runtime "^6.0.0" + +babel-plugin-transform-class-constructor-call@^6.3.13: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.18.0.tgz#80855e38a1ab47b8c6c647f8ea1bcd2c00ca3aae" + dependencies: + babel-plugin-syntax-class-constructor-call "^6.18.0" + babel-runtime "^6.0.0" + babel-template "^6.8.0" + +babel-plugin-transform-class-properties@^6.18.0: + version "6.19.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.19.0.tgz#1274b349abaadc835164e2004f4a2444a2788d5f" + dependencies: + babel-helper-function-name "^6.18.0" + babel-plugin-syntax-class-properties "^6.8.0" + babel-runtime "^6.9.1" + babel-template "^6.15.0" + +babel-plugin-transform-decorators@^6.13.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.13.0.tgz#82d65c1470ae83e2d13eebecb0a1c2476d62da9d" + dependencies: + babel-helper-define-map "^6.8.0" + babel-helper-explode-class "^6.8.0" + babel-plugin-syntax-decorators "^6.13.0" + babel-runtime "^6.0.0" + babel-template "^6.8.0" + babel-types "^6.13.0" + +babel-plugin-transform-do-expressions@^6.3.13: + version "6.8.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.8.0.tgz#fda692af339835cc255bb7544efb8f7c1306c273" + dependencies: + babel-plugin-syntax-do-expressions "^6.8.0" + babel-runtime "^6.0.0" + +babel-plugin-transform-es2015-arrow-functions@^6.3.13: + version "6.8.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.8.0.tgz#5b63afc3181bdc9a8c4d481b5a4f3f7d7fef3d9d" + dependencies: + babel-runtime "^6.0.0" + +babel-plugin-transform-es2015-block-scoped-functions@^6.3.13: + version "6.8.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.8.0.tgz#ed95d629c4b5a71ae29682b998f70d9833eb366d" + dependencies: + babel-runtime "^6.0.0" + +babel-plugin-transform-es2015-block-scoping@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.18.0.tgz#3bfdcfec318d46df22525cdea88f1978813653af" + dependencies: + babel-runtime "^6.9.0" + babel-template "^6.15.0" + babel-traverse "^6.18.0" + babel-types "^6.18.0" + lodash "^4.2.0" + +babel-plugin-transform-es2015-classes@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.18.0.tgz#ffe7a17321bf83e494dcda0ae3fc72df48ffd1d9" + dependencies: + babel-helper-define-map "^6.18.0" + babel-helper-function-name "^6.18.0" + babel-helper-optimise-call-expression "^6.18.0" + babel-helper-replace-supers "^6.18.0" + babel-messages "^6.8.0" + babel-runtime "^6.9.0" + babel-template "^6.14.0" + babel-traverse "^6.18.0" + babel-types "^6.18.0" + +babel-plugin-transform-es2015-computed-properties@^6.3.13: + version "6.8.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.8.0.tgz#f51010fd61b3bd7b6b60a5fdfd307bb7a5279870" + dependencies: + babel-helper-define-map "^6.8.0" + babel-runtime "^6.0.0" + babel-template "^6.8.0" + +babel-plugin-transform-es2015-destructuring@^6.18.0: + version "6.19.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.19.0.tgz#ff1d911c4b3f4cab621bd66702a869acd1900533" + dependencies: + babel-runtime "^6.9.0" + +babel-plugin-transform-es2015-duplicate-keys@^6.6.0: + version "6.8.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.8.0.tgz#fd8f7f7171fc108cc1c70c3164b9f15a81c25f7d" + dependencies: + babel-runtime "^6.0.0" + babel-types "^6.8.0" + +babel-plugin-transform-es2015-for-of@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.18.0.tgz#4c517504db64bf8cfc119a6b8f177211f2028a70" + dependencies: + babel-runtime "^6.0.0" + +babel-plugin-transform-es2015-function-name@^6.9.0: + version "6.9.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.9.0.tgz#8c135b17dbd064e5bba56ec511baaee2fca82719" + dependencies: + babel-helper-function-name "^6.8.0" + babel-runtime "^6.9.0" + babel-types "^6.9.0" + +babel-plugin-transform-es2015-literals@^6.3.13: + version "6.8.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.8.0.tgz#50aa2e5c7958fc2ab25d74ec117e0cc98f046468" + dependencies: + babel-runtime "^6.0.0" + +babel-plugin-transform-es2015-modules-amd@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.18.0.tgz#49a054cbb762bdf9ae2d8a807076cfade6141e40" + dependencies: + babel-plugin-transform-es2015-modules-commonjs "^6.18.0" + babel-runtime "^6.0.0" + babel-template "^6.8.0" + +babel-plugin-transform-es2015-modules-commonjs@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.18.0.tgz#c15ae5bb11b32a0abdcc98a5837baa4ee8d67bcc" + dependencies: + babel-plugin-transform-strict-mode "^6.18.0" + babel-runtime "^6.0.0" + babel-template "^6.16.0" + babel-types "^6.18.0" + +babel-plugin-transform-es2015-modules-systemjs@^6.18.0: + version "6.19.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.19.0.tgz#50438136eba74527efa00a5b0fefaf1dc4071da6" + dependencies: + babel-helper-hoist-variables "^6.18.0" + babel-runtime "^6.11.6" + babel-template "^6.14.0" + +babel-plugin-transform-es2015-modules-umd@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.18.0.tgz#23351770ece5c1f8e83ed67cb1d7992884491e50" + dependencies: + babel-plugin-transform-es2015-modules-amd "^6.18.0" + babel-runtime "^6.0.0" + babel-template "^6.8.0" + +babel-plugin-transform-es2015-object-super@^6.3.13: + version "6.8.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.8.0.tgz#1b858740a5a4400887c23dcff6f4d56eea4a24c5" + dependencies: + babel-helper-replace-supers "^6.8.0" + babel-runtime "^6.0.0" + +babel-plugin-transform-es2015-parameters@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.18.0.tgz#9b2cfe238c549f1635ba27fc1daa858be70608b1" + dependencies: + babel-helper-call-delegate "^6.18.0" + babel-helper-get-function-arity "^6.18.0" + babel-runtime "^6.9.0" + babel-template "^6.16.0" + babel-traverse "^6.18.0" + babel-types "^6.18.0" + +babel-plugin-transform-es2015-shorthand-properties@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.18.0.tgz#e2ede3b7df47bf980151926534d1dd0cbea58f43" + dependencies: + babel-runtime "^6.0.0" + babel-types "^6.18.0" + +babel-plugin-transform-es2015-spread@^6.3.13: + version "6.8.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.8.0.tgz#0217f737e3b821fa5a669f187c6ed59205f05e9c" + dependencies: + babel-runtime "^6.0.0" + +babel-plugin-transform-es2015-sticky-regex@^6.3.13: + version "6.8.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.8.0.tgz#e73d300a440a35d5c64f5c2a344dc236e3df47be" + dependencies: + babel-helper-regex "^6.8.0" + babel-runtime "^6.0.0" + babel-types "^6.8.0" + +babel-plugin-transform-es2015-template-literals@^6.6.0: + version "6.8.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.8.0.tgz#86eb876d0a2c635da4ec048b4f7de9dfc897e66b" + dependencies: + babel-runtime "^6.0.0" + +babel-plugin-transform-es2015-typeof-symbol@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.18.0.tgz#0b14c48629c90ff47a0650077f6aa699bee35798" + dependencies: + babel-runtime "^6.0.0" + +babel-plugin-transform-es2015-unicode-regex@^6.3.13: + version "6.11.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.11.0.tgz#6298ceabaad88d50a3f4f392d8de997260f6ef2c" + dependencies: + babel-helper-regex "^6.8.0" + babel-runtime "^6.0.0" + regexpu-core "^2.0.0" + +babel-plugin-transform-exponentiation-operator@^6.3.13: + version "6.8.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.8.0.tgz#db25742e9339eade676ca9acec46f955599a68a4" + dependencies: + babel-helper-builder-binary-assignment-operator-visitor "^6.8.0" + babel-plugin-syntax-exponentiation-operator "^6.8.0" + babel-runtime "^6.0.0" + +babel-plugin-transform-export-extensions@^6.3.13: + version "6.8.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.8.0.tgz#fa80ff655b636549431bfd38f6b817bd82e47f5b" + dependencies: + babel-plugin-syntax-export-extensions "^6.8.0" + babel-runtime "^6.0.0" + +babel-plugin-transform-function-bind@^6.3.13: + version "6.8.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.8.0.tgz#e7f334ce69f50d28fe850a822eaaab9fa4f4d821" + dependencies: + babel-plugin-syntax-function-bind "^6.8.0" + babel-runtime "^6.0.0" + +babel-plugin-transform-object-rest-spread@^6.16.0: + version "6.19.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.19.0.tgz#f6ac428ee3cb4c6aa00943ed1422ce813603b34c" + dependencies: + babel-plugin-syntax-object-rest-spread "^6.8.0" + babel-runtime "^6.0.0" + +babel-plugin-transform-regenerator@^6.16.0: + version "6.16.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.16.1.tgz#a75de6b048a14154aae14b0122756c5bed392f59" + dependencies: + babel-runtime "^6.9.0" + babel-types "^6.16.0" + private "~0.1.5" + +babel-plugin-transform-strict-mode@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.18.0.tgz#df7cf2991fe046f44163dcd110d5ca43bc652b9d" + dependencies: + babel-runtime "^6.0.0" + babel-types "^6.18.0" + +babel-preset-es2015-loose@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/babel-preset-es2015-loose/-/babel-preset-es2015-loose-7.0.0.tgz#fd80c85d3b20cbf309bd0ce30a36380c5784bf06" + dependencies: + modify-babel-preset "^1.0.0" + +babel-preset-es2015@^6.5.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.18.0.tgz#b8c70df84ec948c43dcf2bf770e988eb7da88312" + dependencies: + babel-plugin-check-es2015-constants "^6.3.13" + babel-plugin-transform-es2015-arrow-functions "^6.3.13" + babel-plugin-transform-es2015-block-scoped-functions "^6.3.13" + babel-plugin-transform-es2015-block-scoping "^6.18.0" + babel-plugin-transform-es2015-classes "^6.18.0" + babel-plugin-transform-es2015-computed-properties "^6.3.13" + babel-plugin-transform-es2015-destructuring "^6.18.0" + babel-plugin-transform-es2015-duplicate-keys "^6.6.0" + babel-plugin-transform-es2015-for-of "^6.18.0" + babel-plugin-transform-es2015-function-name "^6.9.0" + babel-plugin-transform-es2015-literals "^6.3.13" + babel-plugin-transform-es2015-modules-amd "^6.18.0" + babel-plugin-transform-es2015-modules-commonjs "^6.18.0" + babel-plugin-transform-es2015-modules-systemjs "^6.18.0" + babel-plugin-transform-es2015-modules-umd "^6.18.0" + babel-plugin-transform-es2015-object-super "^6.3.13" + babel-plugin-transform-es2015-parameters "^6.18.0" + babel-plugin-transform-es2015-shorthand-properties "^6.18.0" + babel-plugin-transform-es2015-spread "^6.3.13" + babel-plugin-transform-es2015-sticky-regex "^6.3.13" + babel-plugin-transform-es2015-template-literals "^6.6.0" + babel-plugin-transform-es2015-typeof-symbol "^6.18.0" + babel-plugin-transform-es2015-unicode-regex "^6.3.13" + babel-plugin-transform-regenerator "^6.16.0" + +babel-preset-stage-0@^6.5.0: + version "6.16.0" + resolved "https://registry.yarnpkg.com/babel-preset-stage-0/-/babel-preset-stage-0-6.16.0.tgz#f5a263c420532fd57491f1a7315b3036e428f823" + dependencies: + babel-plugin-transform-do-expressions "^6.3.13" + babel-plugin-transform-function-bind "^6.3.13" + babel-preset-stage-1 "^6.16.0" + +babel-preset-stage-1@^6.16.0: + version "6.16.0" + resolved "https://registry.yarnpkg.com/babel-preset-stage-1/-/babel-preset-stage-1-6.16.0.tgz#9d31fbbdae7b17c549fd3ac93e3cf6902695e479" + dependencies: + babel-plugin-transform-class-constructor-call "^6.3.13" + babel-plugin-transform-export-extensions "^6.3.13" + babel-preset-stage-2 "^6.16.0" + +babel-preset-stage-2@^6.16.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-preset-stage-2/-/babel-preset-stage-2-6.18.0.tgz#9eb7bf9a8e91c68260d5ba7500493caaada4b5b5" + dependencies: + babel-plugin-syntax-dynamic-import "^6.18.0" + babel-plugin-transform-class-properties "^6.18.0" + babel-plugin-transform-decorators "^6.13.0" + babel-preset-stage-3 "^6.17.0" + +babel-preset-stage-3@^6.17.0: + version "6.17.0" + resolved "https://registry.yarnpkg.com/babel-preset-stage-3/-/babel-preset-stage-3-6.17.0.tgz#b6638e46db6e91e3f889013d8ce143917c685e39" + dependencies: + babel-plugin-syntax-trailing-function-commas "^6.3.13" + babel-plugin-transform-async-generator-functions "^6.17.0" + babel-plugin-transform-async-to-generator "^6.16.0" + babel-plugin-transform-exponentiation-operator "^6.3.13" + babel-plugin-transform-object-rest-spread "^6.16.0" + +babel-register@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.18.0.tgz#892e2e03865078dd90ad2c715111ec4449b32a68" + dependencies: + babel-core "^6.18.0" + babel-runtime "^6.11.6" + core-js "^2.4.0" + home-or-tmp "^2.0.0" + lodash "^4.2.0" + mkdirp "^0.5.1" + source-map-support "^0.4.2" + +babel-runtime@^6.0.0, babel-runtime@^6.11.6, babel-runtime@^6.9.0, babel-runtime@^6.9.1: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.18.0.tgz#0f4177ffd98492ef13b9f823e9994a02584c9078" + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.9.5" + +babel-template@^6.14.0, babel-template@^6.15.0, babel-template@^6.16.0, babel-template@^6.8.0: + version "6.16.0" + resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.16.0.tgz#e149dd1a9f03a35f817ddbc4d0481988e7ebc8ca" + dependencies: + babel-runtime "^6.9.0" + babel-traverse "^6.16.0" + babel-types "^6.16.0" + babylon "^6.11.0" + lodash "^4.2.0" + +babel-traverse@^6.16.0, babel-traverse@^6.18.0: + version "6.19.0" + resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.19.0.tgz#68363fb821e26247d52a519a84b2ceab8df4f55a" + dependencies: + babel-code-frame "^6.16.0" + babel-messages "^6.8.0" + babel-runtime "^6.9.0" + babel-types "^6.19.0" + babylon "^6.11.0" + debug "^2.2.0" + globals "^9.0.0" + invariant "^2.2.0" + lodash "^4.2.0" + +babel-types@^6.13.0, babel-types@^6.16.0, babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.8.0, babel-types@^6.9.0: + version "6.19.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.19.0.tgz#8db2972dbed01f1192a8b602ba1e1e4c516240b9" + dependencies: + babel-runtime "^6.9.1" + esutils "^2.0.2" + lodash "^4.2.0" + to-fast-properties "^1.0.1" + +babylon@^6.11.0: + version "6.14.1" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.14.1.tgz#956275fab72753ad9b3435d7afe58f8bf0a29815" + +balanced-match@^0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" + +base64-js@^1.0.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.0.tgz#a39992d723584811982be5e290bb6a53d86700f1" + +batch@0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/batch/-/batch-0.5.3.tgz#3f3414f380321743bfc1042f9a83ff1d5824d464" + +bcrypt-pbkdf@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.0.tgz#3ca76b85241c7170bf7d9703e7b9aa74630040d4" + dependencies: + tweetnacl "^0.14.3" + +big.js@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.1.3.tgz#4cada2193652eb3ca9ec8e55c9015669c9806978" + +binary-extensions@^1.0.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.8.0.tgz#48ec8d16df4377eae5fa5884682480af4d95c774" + +block-stream@*: + version "0.0.9" + resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" + dependencies: + inherits "~2.0.0" + +boom@2.x.x: + version "2.10.1" + resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" + dependencies: + hoek "2.x.x" + +brace-expansion@^1.0.0: + version "1.1.6" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.6.tgz#7197d7eaa9b87e648390ea61fc66c84427420df9" + dependencies: + balanced-match "^0.4.1" + concat-map "0.0.1" + +braces@^1.8.2: + version "1.8.5" + resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" + dependencies: + expand-range "^1.8.1" + preserve "^0.2.0" + repeat-element "^1.1.2" + +browserify-aes@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-0.4.0.tgz#067149b668df31c4b58533e02d01e806d8608e2c" + dependencies: + inherits "^2.0.1" + +browserify-zlib@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.1.4.tgz#bb35f8a519f600e0fa6b8485241c979d0141fb2d" + dependencies: + pako "~0.2.0" + +buffer-shims@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51" + +buffer@^4.9.0: + version "4.9.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + isarray "^1.0.0" + +builtin-status-codes@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-2.0.0.tgz#6f22003baacf003ccd287afe6872151fddc58579" + +bytes@2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.3.0.tgz#d5b680a165b6201739acb611542aabc2d8ceb070" + +camelcase@^1.0.2: + version "1.2.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" + +caseless@~0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.11.0.tgz#715b96ea9841593cc33067923f5ec60ebda4f7d7" + +center-align@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad" + dependencies: + align-text "^0.1.3" + lazy-cache "^1.0.3" + +chalk@^1.1.0, chalk@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chokidar@^1.0.0: + version "1.6.1" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.6.1.tgz#2f4447ab5e96e50fb3d789fd90d4c72e0e4c70c2" + dependencies: + anymatch "^1.3.0" + async-each "^1.0.0" + glob-parent "^2.0.0" + inherits "^2.0.1" + is-binary-path "^1.0.0" + is-glob "^2.0.0" + path-is-absolute "^1.0.0" + readdirp "^2.0.0" + optionalDependencies: + fsevents "^1.0.0" + +cliui@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" + dependencies: + center-align "^0.1.1" + right-align "^0.1.1" + wordwrap "0.0.2" + +clone@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.2.tgz#260b7a99ebb1edfe247538175f783243cb19d149" + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + +combined-stream@^1.0.5, combined-stream@~1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" + dependencies: + delayed-stream "~1.0.0" + +commander@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" + dependencies: + graceful-readlink ">= 1.0.0" + +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + +compressible@~2.0.8: + version "2.0.9" + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.9.tgz#6daab4e2b599c2770dd9e21e7a891b1c5a755425" + dependencies: + mime-db ">= 1.24.0 < 2" + +compression@^1.5.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/compression/-/compression-1.6.2.tgz#cceb121ecc9d09c52d7ad0c3350ea93ddd402bc3" + dependencies: + accepts "~1.3.3" + bytes "2.3.0" + compressible "~2.0.8" + debug "~2.2.0" + on-headers "~1.0.1" + vary "~1.1.0" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + +connect-history-api-fallback@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.3.0.tgz#e51d17f8f0ef0db90a64fdb47de3051556e9f169" + +console-browserify@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" + dependencies: + date-now "^0.1.4" + +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + +constants-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" + +content-disposition@0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.1.tgz#87476c6a67c8daa87e32e87616df883ba7fb071b" + +content-type@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.2.tgz#b7d113aee7a8dd27bd21133c4dc2529df1721eed" + +convert-source-map@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.3.0.tgz#e9f3e9c6e2728efc2676696a70eb382f73106a67" + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + +cookie@0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" + +core-js@^2.4.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.1.tgz#4de911e667b0eae9124e34254b53aea6fc618d3e" + +core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + +cryptiles@2.x.x: + version "2.0.5" + resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" + dependencies: + boom "2.x.x" + +crypto-browserify@3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.3.0.tgz#b9fc75bb4a0ed61dcf1cd5dae96eb30c9c3e506c" + dependencies: + browserify-aes "0.4.0" + pbkdf2-compat "2.0.1" + ripemd160 "0.2.0" + sha.js "2.2.6" + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + dependencies: + assert-plus "^1.0.0" + +date-now@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" + +debug@^2.1.1, debug@^2.2.0: + version "2.3.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.3.3.tgz#40c453e67e6e13c901ddec317af8986cda9eff8c" + dependencies: + ms "0.7.2" + +debug@~2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" + dependencies: + ms "0.7.1" + +decamelize@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + +deep-extend@~0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.1.tgz#efe4113d08085f4e6f9687759810f807469e2253" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + +depd@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.0.tgz#e1bd82c6aab6ced965b97b88b17ed3e528ca18c3" + +destroy@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" + +detect-indent@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" + dependencies: + repeating "^2.0.0" + +domain-browser@^1.1.1: + version "1.1.7" + resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.1.7.tgz#867aa4b093faa05f1de08c06f4d7b21fdf8698bc" + +ecc-jsbn@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" + dependencies: + jsbn "~0.1.0" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + +emojis-list@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" + +encodeurl@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.1.tgz#79e3d58655346909fe6f0f45a5de68103b294d20" + +enhanced-resolve@~0.9.0: + version "0.9.1" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz#4d6e689b3725f86090927ccc86cd9f1635b89e2e" + dependencies: + graceful-fs "^4.1.2" + memory-fs "^0.2.0" + tapable "^0.1.8" + +errno@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.4.tgz#b896e23a9e5e8ba33871fc996abd3635fc9a1c7d" + dependencies: + prr "~0.0.0" + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + +escape-string-regexp@^1.0.2: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + +esutils@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" + +etag@~1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.7.0.tgz#03d30b5f67dd6e632d2945d30d6652731a34d5d8" + +eventemitter3@1.x.x: + version "1.2.0" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.2.0.tgz#1c86991d816ad1e504750e73874224ecf3bec508" + +events@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" + +eventsource@~0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-0.1.6.tgz#0acede849ed7dd1ccc32c811bb11b944d4f29232" + dependencies: + original ">=0.0.5" + +expand-brackets@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" + dependencies: + is-posix-bracket "^0.1.0" + +expand-range@^1.8.1: + version "1.8.2" + resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" + dependencies: + fill-range "^2.1.0" + +express@^4.13.3: + version "4.14.0" + resolved "https://registry.yarnpkg.com/express/-/express-4.14.0.tgz#c1ee3f42cdc891fb3dc650a8922d51ec847d0d66" + dependencies: + accepts "~1.3.3" + array-flatten "1.1.1" + content-disposition "0.5.1" + content-type "~1.0.2" + cookie "0.3.1" + cookie-signature "1.0.6" + debug "~2.2.0" + depd "~1.1.0" + encodeurl "~1.0.1" + escape-html "~1.0.3" + etag "~1.7.0" + finalhandler "0.5.0" + fresh "0.3.0" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "~2.3.0" + parseurl "~1.3.1" + path-to-regexp "0.1.7" + proxy-addr "~1.1.2" + qs "6.2.0" + range-parser "~1.2.0" + send "0.14.1" + serve-static "~1.11.1" + type-is "~1.6.13" + utils-merge "1.0.0" + vary "~1.1.0" + +extend@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.0.tgz#5a474353b9f3353ddd8176dfd37b91c83a46f1d4" + +extglob@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" + dependencies: + is-extglob "^1.0.0" + +extsprintf@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.0.2.tgz#e1080e0658e300b06294990cc70e1502235fd550" + +faye-websocket@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.10.0.tgz#4e492f8d04dfb6f89003507f6edbf2d501e7c6f4" + dependencies: + websocket-driver ">=0.5.1" + +faye-websocket@~0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.0.tgz#d9ccf0e789e7db725d74bc4877d23aa42972ac50" + dependencies: + websocket-driver ">=0.5.1" + +filename-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.0.tgz#996e3e80479b98b9897f15a8a58b3d084e926775" + +fill-range@^2.1.0: + version "2.2.3" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723" + dependencies: + is-number "^2.1.0" + isobject "^2.0.0" + randomatic "^1.1.3" + repeat-element "^1.1.2" + repeat-string "^1.5.2" + +finalhandler@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-0.5.0.tgz#e9508abece9b6dba871a6942a1d7911b91911ac7" + dependencies: + debug "~2.2.0" + escape-html "~1.0.3" + on-finished "~2.3.0" + statuses "~1.3.0" + unpipe "~1.0.0" + +find-cache-dir@^0.1.1: + version "0.1.1" + resolved "http://registry.npmjs.org/find-cache-dir/-/find-cache-dir-0.1.1.tgz#c8defae57c8a52a8a784f9e31c57c742e993a0b9" + dependencies: + commondir "^1.0.1" + mkdirp "^0.5.1" + pkg-dir "^1.0.0" + +find-up@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + dependencies: + path-exists "^2.0.0" + pinkie-promise "^2.0.0" + +for-in@^0.1.5: + version "0.1.6" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-0.1.6.tgz#c9f96e89bfad18a545af5ec3ed352a1d9e5b4dc8" + +for-own@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.4.tgz#0149b41a39088c7515f51ebe1c1386d45f935072" + dependencies: + for-in "^0.1.5" + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + +form-data@~2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.2.tgz#89c3534008b97eada4cbb157d58f6f5df025eae4" + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.5" + mime-types "^2.1.12" + +forwarded@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.0.tgz#19ef9874c4ae1c297bcf078fde63a09b66a84363" + +fresh@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.3.0.tgz#651f838e22424e7566de161d8358caa199f83d4f" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + +fsevents@^1.0.0: + version "1.0.15" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.0.15.tgz#fa63f590f3c2ad91275e4972a6cea545fb0aae44" + dependencies: + nan "^2.3.0" + node-pre-gyp "^0.6.29" + +fstream-ignore@~1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/fstream-ignore/-/fstream-ignore-1.0.5.tgz#9c31dae34767018fe1d249b24dada67d092da105" + dependencies: + fstream "^1.0.0" + inherits "2" + minimatch "^3.0.0" + +fstream@^1.0.0, fstream@^1.0.2, fstream@~1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.10.tgz#604e8a92fe26ffd9f6fae30399d4984e1ab22822" + dependencies: + graceful-fs "^4.1.2" + inherits "~2.0.0" + mkdirp ">=0.5 0" + rimraf "2" + +gauge@~2.7.1: + version "2.7.2" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.2.tgz#15cecc31b02d05345a5d6b0e171cdb3ad2307774" + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + supports-color "^0.2.0" + wide-align "^1.1.0" + +generate-function@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74" + +generate-object-property@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" + dependencies: + is-property "^1.0.0" + +getpass@^0.1.1: + version "0.1.6" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.6.tgz#283ffd9fc1256840875311c1b60e8c40187110e6" + dependencies: + assert-plus "^1.0.0" + +glob-base@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" + dependencies: + glob-parent "^2.0.0" + is-glob "^2.0.0" + +glob-parent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" + dependencies: + is-glob "^2.0.0" + +glob@^7.0.5: + version "7.1.1" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.2" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^9.0.0: + version "9.14.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-9.14.0.tgz#8859936af0038741263053b39d0e76ca241e4034" + +graceful-fs@^4.1.2: + version "4.1.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" + +"graceful-readlink@>= 1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" + +har-validator@~2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-2.0.6.tgz#cdcbc08188265ad119b6a5a7c8ab70eecfb5d27d" + dependencies: + chalk "^1.1.1" + commander "^2.9.0" + is-my-json-valid "^2.12.4" + pinkie-promise "^2.0.0" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + dependencies: + ansi-regex "^2.0.0" + +has-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" + +has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + +hawk@~3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" + dependencies: + boom "2.x.x" + cryptiles "2.x.x" + hoek "2.x.x" + sntp "1.x.x" + +hoek@2.x.x: + version "2.16.3" + resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" + +home-or-tmp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.1" + +http-errors@~1.5.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.5.1.tgz#788c0d2c1de2c81b9e6e8c01843b6b97eb920750" + dependencies: + inherits "2.0.3" + setprototypeof "1.0.2" + statuses ">= 1.3.1 < 2" + +http-proxy-middleware@~0.17.1: + version "0.17.3" + resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.17.3.tgz#940382147149b856084f5534752d5b5a8168cd1d" + dependencies: + http-proxy "^1.16.2" + is-glob "^3.1.0" + lodash "^4.17.2" + micromatch "^2.3.11" + +http-proxy@^1.16.2: + version "1.16.2" + resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.16.2.tgz#06dff292952bf64dbe8471fa9df73066d4f37742" + dependencies: + eventemitter3 "1.x.x" + requires-port "1.x.x" + +http-signature@~1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" + dependencies: + assert-plus "^0.2.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +https-browserify@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-0.0.1.tgz#3f91365cabe60b77ed0ebba24b454e3e09d95a82" + +ieee754@^1.1.4: + version "1.1.8" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4" + +indexof@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" + +inferno-component@beta32: + version "1.0.0-beta32" + resolved "https://registry.yarnpkg.com/inferno-component/-/inferno-component-1.0.0-beta32.tgz#2bb0aac933c5033b186d809816e158f58a2590ed" + dependencies: + inferno "1.0.0-beta32" + +inferno@1.0.0-beta32, inferno@beta32: + version "1.0.0-beta32" + resolved "https://registry.yarnpkg.com/inferno/-/inferno-1.0.0-beta32.tgz#bd216a5117280da4a15ebcc4b4e1faf3603afc0d" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@~2.0.0, inherits@~2.0.1: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + +inherits@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" + +ini@~1.3.0: + version "1.3.4" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" + +interpret@^0.6.4: + version "0.6.6" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-0.6.6.tgz#fecd7a18e7ce5ca6abfb953e1f86213a49f1625b" + +invariant@^2.2.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" + dependencies: + loose-envify "^1.0.0" + +ipaddr.js@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.1.1.tgz#c791d95f52b29c1247d5df80ada39b8a73647230" + +is-binary-path@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + dependencies: + binary-extensions "^1.0.0" + +is-buffer@^1.0.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.4.tgz#cfc86ccd5dc5a52fa80489111c6920c457e2d98b" + +is-dotfile@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.2.tgz#2c132383f39199f8edc268ca01b9b007d205cc4d" + +is-equal-shallow@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" + dependencies: + is-primitive "^2.0.0" + +is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + +is-extglob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" + +is-extglob@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.0.tgz#33411a482b046bf95e6b0cb27ee2711af4cf15ad" + +is-finite@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + dependencies: + number-is-nan "^1.0.0" + +is-glob@^2.0.0, is-glob@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" + dependencies: + is-extglob "^1.0.0" + +is-glob@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" + dependencies: + is-extglob "^2.1.0" + +is-my-json-valid@^2.12.4: + version "2.15.0" + resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.15.0.tgz#936edda3ca3c211fd98f3b2d3e08da43f7b2915b" + dependencies: + generate-function "^2.0.0" + generate-object-property "^1.1.0" + jsonpointer "^4.0.0" + xtend "^4.0.0" + +is-number@^2.0.2, is-number@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" + dependencies: + kind-of "^3.0.2" + +is-posix-bracket@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" + +is-primitive@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" + +is-property@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" + +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + +isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + dependencies: + isarray "1.0.0" + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + +jodid25519@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/jodid25519/-/jodid25519-1.0.2.tgz#06d4912255093419477d425633606e0e90782967" + dependencies: + jsbn "~0.1.0" + +js-tokens@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-2.0.0.tgz#79903f5563ee778cc1162e6dcf1a0027c97f9cb5" + +jsbn@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.0.tgz#650987da0dd74f4ebf5a11377a2aa2d273e97dfd" + +jsesc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + +json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + +json3@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" + +json5@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" + +jsonpointer@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.0.tgz#6661e161d2fc445f19f98430231343722e1fcbd5" + +jsprim@^1.2.2: + version "1.3.1" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.3.1.tgz#2a7256f70412a29ee3670aaca625994c4dcff252" + dependencies: + extsprintf "1.0.2" + json-schema "0.2.3" + verror "1.3.6" + +kind-of@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.1.0.tgz#475d698a5e49ff5e53d14e3e732429dc8bf4cf47" + dependencies: + is-buffer "^1.0.2" + +lazy-cache@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" + +loader-utils@^0.2.11: + version "0.2.16" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.16.tgz#f08632066ed8282835dff88dfb52704765adee6d" + dependencies: + big.js "^3.1.3" + emojis-list "^2.0.0" + json5 "^0.5.0" + object-assign "^4.0.1" + +lodash@^4.17.2, lodash@^4.2.0: + version "4.17.2" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.2.tgz#34a3055babe04ce42467b607d700072c7ff6bf42" + +longest@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" + +loose-envify@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.0.tgz#6b26248c42f6d4fa4b0d8542f78edfcde35642a8" + dependencies: + js-tokens "^2.0.0" + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + +memory-fs@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.2.0.tgz#f2bb25368bc121e391c2520de92969caee0a0290" + +memory-fs@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.3.0.tgz#7bcc6b629e3a43e871d7e29aca6ae8a7f15cbb20" + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + +micromatch@^2.1.5, micromatch@^2.3.11: + version "2.3.11" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" + dependencies: + arr-diff "^2.0.0" + array-unique "^0.2.1" + braces "^1.8.2" + expand-brackets "^0.1.4" + extglob "^0.3.1" + filename-regex "^2.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.1" + kind-of "^3.0.2" + normalize-path "^2.0.1" + object.omit "^2.0.0" + parse-glob "^3.0.4" + regex-cache "^0.4.2" + +"mime-db@>= 1.24.0 < 2", mime-db@~1.25.0: + version "1.25.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.25.0.tgz#c18dbd7c73a5dbf6f44a024dc0d165a1e7b1c392" + +mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.13, mime-types@~2.1.7: + version "2.1.13" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.13.tgz#e07aaa9c6c6b9a7ca3012c69003ad25a39e92a88" + dependencies: + mime-db "~1.25.0" + +mime@1.3.4, mime@^1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53" + +minimatch@^3.0.0, minimatch@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774" + dependencies: + brace-expansion "^1.0.0" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + +minimist@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + +minimist@~0.0.1: + version "0.0.10" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" + +"mkdirp@>=0.5 0", mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + dependencies: + minimist "0.0.8" + +modify-babel-preset@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/modify-babel-preset/-/modify-babel-preset-1.2.0.tgz#d1b7c8c24896e19dbc4847347213e6b7144d1bc7" + dependencies: + require-relative "^0.8.7" + +ms@0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" + +ms@0.7.2: + version "0.7.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765" + +nan@^2.3.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.4.0.tgz#fb3c59d45fe4effe215f0b890f8adf6eb32d2232" + +negotiator@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" + +node-libs-browser@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-0.7.0.tgz#3e272c0819e308935e26674408d7af0e1491b83b" + dependencies: + assert "^1.1.1" + browserify-zlib "^0.1.4" + buffer "^4.9.0" + console-browserify "^1.1.0" + constants-browserify "^1.0.0" + crypto-browserify "3.3.0" + domain-browser "^1.1.1" + events "^1.0.0" + https-browserify "0.0.1" + os-browserify "^0.2.0" + path-browserify "0.0.0" + process "^0.11.0" + punycode "^1.2.4" + querystring-es3 "^0.2.0" + readable-stream "^2.0.5" + stream-browserify "^2.0.1" + stream-http "^2.3.1" + string_decoder "^0.10.25" + timers-browserify "^2.0.2" + tty-browserify "0.0.0" + url "^0.11.0" + util "^0.10.3" + vm-browserify "0.0.4" + +node-pre-gyp@^0.6.29: + version "0.6.32" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.32.tgz#fc452b376e7319b3d255f5f34853ef6fd8fe1fd5" + dependencies: + mkdirp "~0.5.1" + nopt "~3.0.6" + npmlog "^4.0.1" + rc "~1.1.6" + request "^2.79.0" + rimraf "~2.5.4" + semver "~5.3.0" + tar "~2.2.1" + tar-pack "~3.3.0" + +nopt@~3.0.6: + version "3.0.6" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" + dependencies: + abbrev "1" + +normalize-path@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.0.1.tgz#47886ac1662760d4261b7d979d241709d3ce3f7a" + +npmlog@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.0.1.tgz#d14f503b4cd79710375553004ba96e6662fbc0b8" + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.1" + set-blocking "~2.0.0" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + +oauth-sign@~0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" + +object-assign@^4.0.1, object-assign@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.0.tgz#7a3b3d0e98063d43f4c03f2e8ae6cd51a86883a0" + +object.omit@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" + dependencies: + for-own "^0.1.4" + is-extendable "^0.1.1" + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + dependencies: + ee-first "1.1.1" + +on-headers@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7" + +once@^1.3.0, once@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/once/-/once-1.3.3.tgz#b2e261557ce4c314ec8304f3fa82663e4297ca20" + dependencies: + wrappy "1" + +open@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/open/-/open-0.0.5.tgz#42c3e18ec95466b6bf0dc42f3a2945c3f0cad8fc" + +optimist@~0.6.0, optimist@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" + dependencies: + minimist "~0.0.1" + wordwrap "~0.0.2" + +original@>=0.0.5: + version "1.0.0" + resolved "https://registry.yarnpkg.com/original/-/original-1.0.0.tgz#9147f93fa1696d04be61e01bd50baeaca656bd3b" + dependencies: + url-parse "1.0.x" + +os-browserify@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.2.1.tgz#63fc4ccee5d2d7763d26bbf8601078e6c2e0044f" + +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + +os-tmpdir@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + +pako@~0.2.0: + version "0.2.9" + resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75" + +parse-glob@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" + dependencies: + glob-base "^0.3.0" + is-dotfile "^1.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.0" + +parseurl@~1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.1.tgz#c8ab8c9223ba34888aa64a297b28853bec18da56" + +path-browserify@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a" + +path-exists@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" + dependencies: + pinkie-promise "^2.0.0" + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + +pbkdf2-compat@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pbkdf2-compat/-/pbkdf2-compat-2.0.1.tgz#b6e0c8fa99494d94e0511575802a59a5c142f288" + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + +pkg-dir@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" + dependencies: + find-up "^1.0.0" + +preserve@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" + +private@^0.1.6, private@~0.1.5: + version "0.1.6" + resolved "https://registry.yarnpkg.com/private/-/private-0.1.6.tgz#55c6a976d0f9bafb9924851350fe47b9b5fbb7c1" + +process-nextick-args@~1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" + +process@^0.11.0: + version "0.11.9" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.9.tgz#7bd5ad21aa6253e7da8682264f1e11d11c0318c1" + +proxy-addr@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-1.1.2.tgz#b4cc5f22610d9535824c123aef9d3cf73c40ba37" + dependencies: + forwarded "~0.1.0" + ipaddr.js "1.1.1" + +prr@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/prr/-/prr-0.0.0.tgz#1a84b85908325501411853d0081ee3fa86e2926a" + +punycode@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" + +punycode@^1.2.4, punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + +qs@6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.2.0.tgz#3b7848c03c2dece69a9522b0fae8c4126d745f3b" + +qs@~6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.0.tgz#f403b264f23bc01228c74131b407f18d5ea5d442" + +querystring-es3@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" + +querystring@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" + +querystringify@0.0.x: + version "0.0.4" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-0.0.4.tgz#0cf7f84f9463ff0ae51c4c4b142d95be37724d9c" + +randomatic@^1.1.3: + version "1.1.6" + resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.6.tgz#110dcabff397e9dcff7c0789ccc0a49adf1ec5bb" + dependencies: + is-number "^2.0.2" + kind-of "^3.0.2" + +range-parser@^1.0.3, range-parser@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" + +rc@~1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.1.6.tgz#43651b76b6ae53b5c802f1151fa3fc3b059969c9" + dependencies: + deep-extend "~0.4.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~1.0.4" + +"readable-stream@^2.0.0 || ^1.1.13", readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.1.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.2.tgz#a9e6fec3c7dda85f8bb1b3ba7028604556fc825e" + dependencies: + buffer-shims "^1.0.0" + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "~1.0.0" + process-nextick-args "~1.0.6" + string_decoder "~0.10.x" + util-deprecate "~1.0.1" + +readable-stream@~2.1.4: + version "2.1.5" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.1.5.tgz#66fa8b720e1438b364681f2ad1a63c618448c9d0" + dependencies: + buffer-shims "^1.0.0" + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "~1.0.0" + process-nextick-args "~1.0.6" + string_decoder "~0.10.x" + util-deprecate "~1.0.1" + +readdirp@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78" + dependencies: + graceful-fs "^4.1.2" + minimatch "^3.0.2" + readable-stream "^2.0.2" + set-immediate-shim "^1.0.1" + +regenerate@^1.2.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.2.tgz#d1941c67bad437e1be76433add5b385f95b19260" + +regenerator-runtime@^0.9.5: + version "0.9.6" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.9.6.tgz#d33eb95d0d2001a4be39659707c51b0cb71ce029" + +regex-cache@^0.4.2: + version "0.4.3" + resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.3.tgz#9b1a6c35d4d0dfcef5711ae651e8e9d3d7114145" + dependencies: + is-equal-shallow "^0.1.3" + is-primitive "^2.0.0" + +regexpu-core@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" + dependencies: + regenerate "^1.2.1" + regjsgen "^0.2.0" + regjsparser "^0.1.4" + +regjsgen@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" + +regjsparser@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" + dependencies: + jsesc "~0.5.0" + +repeat-element@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" + +repeat-string@^1.5.2: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + +repeating@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" + dependencies: + is-finite "^1.0.0" + +request@^2.79.0: + version "2.79.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de" + dependencies: + aws-sign2 "~0.6.0" + aws4 "^1.2.1" + caseless "~0.11.0" + combined-stream "~1.0.5" + extend "~3.0.0" + forever-agent "~0.6.1" + form-data "~2.1.1" + har-validator "~2.0.6" + hawk "~3.1.3" + http-signature "~1.1.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.7" + oauth-sign "~0.8.1" + qs "~6.3.0" + stringstream "~0.0.4" + tough-cookie "~2.3.0" + tunnel-agent "~0.4.1" + uuid "^3.0.0" + +require-relative@^0.8.7: + version "0.8.7" + resolved "https://registry.yarnpkg.com/require-relative/-/require-relative-0.8.7.tgz#7999539fc9e047a37928fa196f8e1563dabd36de" + +requires-port@1.0.x, requires-port@1.x.x: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + +right-align@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" + dependencies: + align-text "^0.1.1" + +rimraf@2, rimraf@~2.5.1, rimraf@~2.5.4: + version "2.5.4" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.5.4.tgz#96800093cbf1a0c86bd95b4625467535c29dfa04" + dependencies: + glob "^7.0.5" + +ripemd160@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-0.2.0.tgz#2bf198bde167cacfa51c0a928e84b68bbe171fce" + +semver@~5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" + +send@0.14.1: + version "0.14.1" + resolved "https://registry.yarnpkg.com/send/-/send-0.14.1.tgz#a954984325392f51532a7760760e459598c89f7a" + dependencies: + debug "~2.2.0" + depd "~1.1.0" + destroy "~1.0.4" + encodeurl "~1.0.1" + escape-html "~1.0.3" + etag "~1.7.0" + fresh "0.3.0" + http-errors "~1.5.0" + mime "1.3.4" + ms "0.7.1" + on-finished "~2.3.0" + range-parser "~1.2.0" + statuses "~1.3.0" + +serve-index@^1.7.2: + version "1.8.0" + resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.8.0.tgz#7c5d96c13fb131101f93c1c5774f8516a1e78d3b" + dependencies: + accepts "~1.3.3" + batch "0.5.3" + debug "~2.2.0" + escape-html "~1.0.3" + http-errors "~1.5.0" + mime-types "~2.1.11" + parseurl "~1.3.1" + +serve-static@~1.11.1: + version "1.11.1" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.11.1.tgz#d6cce7693505f733c759de57befc1af76c0f0805" + dependencies: + encodeurl "~1.0.1" + escape-html "~1.0.3" + parseurl "~1.3.1" + send "0.14.1" + +set-blocking@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + +set-immediate-shim@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" + +setimmediate@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + +setprototypeof@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.2.tgz#81a552141ec104b88e89ce383103ad5c66564d08" + +sha.js@2.2.6: + version "2.2.6" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.2.6.tgz#17ddeddc5f722fb66501658895461977867315ba" + +signal-exit@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + +slash@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" + +sntp@1.x.x: + version "1.0.9" + resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" + dependencies: + hoek "2.x.x" + +sockjs-client@^1.0.3: + version "1.1.1" + resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.1.1.tgz#284843e9a9784d7c474b1571b3240fca9dda4bb0" + dependencies: + debug "^2.2.0" + eventsource "~0.1.6" + faye-websocket "~0.11.0" + inherits "^2.0.1" + json3 "^3.3.2" + url-parse "^1.1.1" + +sockjs@^0.3.15: + version "0.3.18" + resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.18.tgz#d9b289316ca7df77595ef299e075f0f937eb4207" + dependencies: + faye-websocket "^0.10.0" + uuid "^2.0.2" + +source-list-map@~0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-0.1.7.tgz#d4b5ce2a46535c72c7e8527c71a77d250618172e" + +source-map-support@^0.4.2: + version "0.4.6" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.6.tgz#32552aa64b458392a85eab3b0b5ee61527167aeb" + dependencies: + source-map "^0.5.3" + +source-map@^0.5.0, source-map@^0.5.3, source-map@~0.5.1: + version "0.5.6" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" + +source-map@~0.4.1: + version "0.4.4" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" + dependencies: + amdefine ">=0.0.4" + +sshpk@^1.7.0: + version "1.10.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.10.1.tgz#30e1a5d329244974a1af61511339d595af6638b0" + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + dashdash "^1.12.0" + getpass "^0.1.1" + optionalDependencies: + bcrypt-pbkdf "^1.0.0" + ecc-jsbn "~0.1.1" + jodid25519 "^1.0.0" + jsbn "~0.1.0" + tweetnacl "~0.14.0" + +"statuses@>= 1.3.1 < 2", statuses@~1.3.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" + +stream-browserify@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db" + dependencies: + inherits "~2.0.1" + readable-stream "^2.0.2" + +stream-cache@~0.0.1: + version "0.0.2" + resolved "https://registry.yarnpkg.com/stream-cache/-/stream-cache-0.0.2.tgz#1ac5ad6832428ca55667dbdee395dad4e6db118f" + +stream-http@^2.3.1: + version "2.5.0" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.5.0.tgz#585eee513217ed98fe199817e7313b6f772a6802" + dependencies: + builtin-status-codes "^2.0.0" + inherits "^2.0.1" + readable-stream "^2.1.0" + to-arraybuffer "^1.0.0" + xtend "^4.0.0" + +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +string_decoder@^0.10.25, string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + +stringstream@~0.0.4: + version "0.0.5" + resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + dependencies: + ansi-regex "^2.0.0" + +strip-json-comments@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-1.0.4.tgz#1e15fbcac97d3ee99bf2d73b4c656b082bbafb91" + +supports-color@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-0.2.0.tgz#d92de2694eb3f67323973d7ae3d8b55b4c22190a" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + +supports-color@^3.1.0, supports-color@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5" + dependencies: + has-flag "^1.0.0" + +tapable@^0.1.8, tapable@~0.1.8: + version "0.1.10" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.1.10.tgz#29c35707c2b70e50d07482b5d202e8ed446dafd4" + +tar-pack@~3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.3.0.tgz#30931816418f55afc4d21775afdd6720cee45dae" + dependencies: + debug "~2.2.0" + fstream "~1.0.10" + fstream-ignore "~1.0.5" + once "~1.3.3" + readable-stream "~2.1.4" + rimraf "~2.5.1" + tar "~2.2.1" + uid-number "~0.0.6" + +tar@~2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" + dependencies: + block-stream "*" + fstream "^1.0.2" + inherits "2" + +timers-browserify@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.2.tgz#ab4883cf597dcd50af211349a00fbca56ac86b86" + dependencies: + setimmediate "^1.0.4" + +to-arraybuffer@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" + +to-fast-properties@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.2.tgz#f3f5c0c3ba7299a7ef99427e44633257ade43320" + +todomvc-app-css@^2.0.0: + version "2.0.6" + resolved "https://registry.yarnpkg.com/todomvc-app-css/-/todomvc-app-css-2.0.6.tgz#0b3667c5e189f1568d9a9bf7947ebd928406961d" + +todomvc-common@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/todomvc-common/-/todomvc-common-1.0.3.tgz#cba1868109caa401b908ebf77794cc1014b74873" + +tough-cookie@~2.3.0: + version "2.3.2" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.2.tgz#f081f76e4c85720e6c37a5faced737150d84072a" + dependencies: + punycode "^1.4.1" + +tty-browserify@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" + +tunnel-agent@~0.4.1: + version "0.4.3" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.4" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.4.tgz#8c9dbfb52795686f166cd2023794bcf103d13c2b" + +type-is@~1.6.13: + version "1.6.14" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.14.tgz#e219639c17ded1ca0789092dd54a03826b817cb2" + dependencies: + media-typer "0.3.0" + mime-types "~2.1.13" + +uglify-js@~2.7.3: + version "2.7.5" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.7.5.tgz#4612c0c7baaee2ba7c487de4904ae122079f2ca8" + dependencies: + async "~0.2.6" + source-map "~0.5.1" + uglify-to-browserify "~1.0.0" + yargs "~3.10.0" + +uglify-to-browserify@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" + +uid-number@~0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" + +unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + +url-parse@1.0.x: + version "1.0.5" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.0.5.tgz#0854860422afdcfefeb6c965c662d4800169927b" + dependencies: + querystringify "0.0.x" + requires-port "1.0.x" + +url-parse@^1.1.1: + version "1.1.7" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.1.7.tgz#025cff999653a459ab34232147d89514cc87d74a" + dependencies: + querystringify "0.0.x" + requires-port "1.0.x" + +url@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" + dependencies: + punycode "1.3.2" + querystring "0.2.0" + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + +util@0.10.3, util@^0.10.3: + version "0.10.3" + resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" + dependencies: + inherits "2.0.1" + +utils-merge@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.0.tgz#0294fb922bb9375153541c4f7096231f287c8af8" + +uuid@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a" + +uuid@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.1.tgz#6544bba2dfda8c1cf17e629a3a305e2bb1fee6c1" + +vary@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.0.tgz#e1e5affbbd16ae768dd2674394b9ad3022653140" + +verror@1.3.6: + version "1.3.6" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.3.6.tgz#cff5df12946d297d2baaefaa2689e25be01c005c" + dependencies: + extsprintf "1.0.2" + +vm-browserify@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73" + dependencies: + indexof "0.0.1" + +watchpack@^0.2.1: + version "0.2.9" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-0.2.9.tgz#62eaa4ab5e5ba35fdfc018275626e3c0f5e3fb0b" + dependencies: + async "^0.9.0" + chokidar "^1.0.0" + graceful-fs "^4.1.2" + +webpack-core@~0.6.9: + version "0.6.9" + resolved "https://registry.yarnpkg.com/webpack-core/-/webpack-core-0.6.9.tgz#fc571588c8558da77be9efb6debdc5a3b172bdc2" + dependencies: + source-list-map "~0.1.7" + source-map "~0.4.1" + +webpack-dev-middleware@^1.4.0: + version "1.8.4" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-1.8.4.tgz#e8765c9122887ce9e3abd4cc9c3eb31b61e0948d" + dependencies: + memory-fs "~0.3.0" + mime "^1.3.4" + path-is-absolute "^1.0.0" + range-parser "^1.0.3" + +webpack-dev-server@^1.14.1: + version "1.16.2" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-1.16.2.tgz#8bebc2c4ce1c45a15c72dd769d9ba08db306a793" + dependencies: + compression "^1.5.2" + connect-history-api-fallback "^1.3.0" + express "^4.13.3" + http-proxy-middleware "~0.17.1" + open "0.0.5" + optimist "~0.6.1" + serve-index "^1.7.2" + sockjs "^0.3.15" + sockjs-client "^1.0.3" + stream-cache "~0.0.1" + strip-ansi "^3.0.0" + supports-color "^3.1.1" + webpack-dev-middleware "^1.4.0" + +webpack@^1.12.14: + version "1.14.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-1.14.0.tgz#54f1ffb92051a328a5b2057d6ae33c289462c823" + dependencies: + acorn "^3.0.0" + async "^1.3.0" + clone "^1.0.2" + enhanced-resolve "~0.9.0" + interpret "^0.6.4" + loader-utils "^0.2.11" + memory-fs "~0.3.0" + mkdirp "~0.5.0" + node-libs-browser "^0.7.0" + optimist "~0.6.0" + supports-color "^3.1.0" + tapable "~0.1.8" + uglify-js "~2.7.3" + watchpack "^0.2.1" + webpack-core "~0.6.9" + +websocket-driver@>=0.5.1: + version "0.6.5" + resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.6.5.tgz#5cb2556ceb85f4373c6d8238aa691c8454e13a36" + dependencies: + websocket-extensions ">=0.1.1" + +websocket-extensions@>=0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.1.tgz#76899499c184b6ef754377c2dbb0cd6cb55d29e7" + +wide-align@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.0.tgz#40edde802a71fea1f070da3e62dcda2e7add96ad" + dependencies: + string-width "^1.0.1" + +window-size@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" + +wordwrap@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" + +wordwrap@~0.0.2: + version "0.0.3" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + +xtend@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + +yargs@~3.10.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" + dependencies: + camelcase "^1.0.2" + cliui "^2.1.0" + decamelize "^1.0.0" + window-size "0.1.0" diff --git a/bench/implementations/nim-karax-comp-local/docs/docs.rst b/bench/implementations/nim-karax-comp-local/docs/docs.rst new file mode 100644 index 0000000..8298ba9 --- /dev/null +++ b/bench/implementations/nim-karax-comp-local/docs/docs.rst @@ -0,0 +1,58 @@ + +Virtual DOM +=========== + +The virtual dom is in the ``vdom`` module. + +The ``VNodeKind`` enum describes every tag that the HTML 5 spec includes +and some extensions that allow for an efficient component system. + +These extensions are: + +``VNodeKind.int`` + The node havs a single integer field. + +``VNodeKind.bool`` + The node has a single boolean field. + +``VNodeKint.vthunk`` + The node is a `virtual thunk`:idx:. This means there is a + function attached to it that produces the ``VNode`` structure + on demand. + +``VNodeKint.dthunk`` + The node is a `DOM thunk`:idx:. This means there is a + function attached to it that produces the ``Node`` DOM structure + on demand. + +For convenience of the resulting Nim DSL these tags have enum names +that differ from their HTML equivalent: + +================= ======================================================= +Enum value HTML +================= ======================================================= +``tdiv`` ``div`` (changed because ``div`` is a keyword in Nim) +``italic`` ``i`` +``bold`` ``b`` +``strikethrough`` ``s`` +``underlined`` ``u`` +================= ======================================================= + + +A virtual dom node also has a special field set called ``key``, an integer +that can be used as a data model specific key/id. It can be accessed in event +handlers to change the data model. See the todoapp for an example of how to +use it. + +**Note**: This is not a hint for the DOM diff algorithm, multipe nodes can +all have the same key value. + + +Event system +============ + +Karax does not abstract over the event system the DOM offers much: The same +``Event`` structure is used. Every callback has the +signature ``proc (ev: Event; n: VNode)``. + + diff --git a/bench/implementations/nim-karax-comp-local/examples/mediaplayer/mediaplayer.nim b/bench/implementations/nim-karax-comp-local/examples/mediaplayer/mediaplayer.nim new file mode 100644 index 0000000..18179c1 --- /dev/null +++ b/bench/implementations/nim-karax-comp-local/examples/mediaplayer/mediaplayer.nim @@ -0,0 +1,42 @@ + +import karax, karaxdsl, vdom, dom, components + +const + Play = 0 + Big = 1 + Small = 2 + Normal = 3 + +proc paused(n: Node): bool {.importcpp: "#.paused".} +proc play(n: Node) {.importcpp.} +proc pause(n: Node) {.importcpp.} +proc `width=`(n: Node, w: int) {.importcpp: "#.width = #".} + +proc mplayer*(id, resource: cstring): VNode {.component.} = + proc handler(ev: Event; n: VNode) = + let myVideo = document.getElementById(id) + case n.key + of Play: + if myVideo.paused: + myVideo.play() + else: + myVideo.pause() + of Big: myVideo.width = 560 + of Small: myVideo.width = 320 + of Normal: myVideo.width = 420 + else: discard + + result = buildHtml(tdiv): + button(onclick=handler, key=Play): + text "Play/Pause" + button(onclick=handler, key=Big): + text "Big" + button(onclick=handler, key=Small): + text "Small" + button(onclick=handler, key=Normal): + text "Normal" + br() + br() + video(id=id, width="420"): + source(src=resource, `type`="video/mp4"): + text "Your browser does not support HTML5 video." diff --git a/bench/implementations/nim-karax-comp-local/examples/mediaplayer/playerapp.html b/bench/implementations/nim-karax-comp-local/examples/mediaplayer/playerapp.html new file mode 100644 index 0000000..9e076e6 --- /dev/null +++ b/bench/implementations/nim-karax-comp-local/examples/mediaplayer/playerapp.html @@ -0,0 +1,15 @@ + + + + + Player app + + + + +
    + + + + + diff --git a/bench/implementations/nim-karax-comp-local/examples/mediaplayer/playerapp.nim b/bench/implementations/nim-karax-comp-local/examples/mediaplayer/playerapp.nim new file mode 100644 index 0000000..e611eec --- /dev/null +++ b/bench/implementations/nim-karax-comp-local/examples/mediaplayer/playerapp.nim @@ -0,0 +1,21 @@ +## Example app that shows how to write and embed a custom component. + +include karaxprelude +import mediaplayer + +const url = "https://www.w3schools.com/html/mov_bbb.mp4" + +proc createDom(): VNode = + result = buildHtml(table): + tr: + td: + mplayer("vid1", url) + td: + mplayer("vid2", url) + tr: + td: + mplayer("vid3", url) + td: + mplayer("vid4", url) + +setRenderer createDom diff --git a/bench/implementations/nim-karax-comp-local/examples/mediaplayer/playerapp.nims b/bench/implementations/nim-karax-comp-local/examples/mediaplayer/playerapp.nims new file mode 100644 index 0000000..9028ff1 --- /dev/null +++ b/bench/implementations/nim-karax-comp-local/examples/mediaplayer/playerapp.nims @@ -0,0 +1 @@ +--path: "../../src" diff --git a/bench/implementations/nim-karax-comp-local/examples/scrollapp/scrollapp.html b/bench/implementations/nim-karax-comp-local/examples/scrollapp/scrollapp.html new file mode 100644 index 0000000..1ff8b1b --- /dev/null +++ b/bench/implementations/nim-karax-comp-local/examples/scrollapp/scrollapp.html @@ -0,0 +1,15 @@ + + + + + Todo app + + + + +
    + + + + + diff --git a/bench/implementations/nim-karax-comp-local/examples/scrollapp/scrollapp.nim b/bench/implementations/nim-karax-comp-local/examples/scrollapp/scrollapp.nim new file mode 100644 index 0000000..e5ef9c1 --- /dev/null +++ b/bench/implementations/nim-karax-comp-local/examples/scrollapp/scrollapp.nim @@ -0,0 +1,24 @@ +## Example that shows how to accomplish an "infinitely scrolling" app. + +include karaxprelude +import jstrutils, dom + +var entries: seq[cstring] = @[] +for i in 1..500: + entries.add(cstring("Entry ") & &i) + +proc scrollEvent(ev: Event; n: VNode) = + let d = n.dom + if d != nil and inViewport(d.lastChild): + # "load" more data: + for i in 1..50: + entries.add(cstring("Loaded Entry ") & &i) + +proc createDom(): VNode = + result = buildHtml(): + tdiv(onscroll=scrollEvent, style="height: 400px; overflow: scroll"): + for x in entries: + tdiv: + text x + +setRenderer createDom diff --git a/bench/implementations/nim-karax-comp-local/examples/scrollapp/scrollapp.nims b/bench/implementations/nim-karax-comp-local/examples/scrollapp/scrollapp.nims new file mode 100644 index 0000000..9028ff1 --- /dev/null +++ b/bench/implementations/nim-karax-comp-local/examples/scrollapp/scrollapp.nims @@ -0,0 +1 @@ +--path: "../../src" diff --git a/bench/implementations/nim-karax-comp-local/examples/todoapp/index.html b/bench/implementations/nim-karax-comp-local/examples/todoapp/index.html new file mode 100644 index 0000000..488a3bf --- /dev/null +++ b/bench/implementations/nim-karax-comp-local/examples/todoapp/index.html @@ -0,0 +1,16 @@ + + + + + Todo app + + + + + +
    + + + + + diff --git a/bench/implementations/nim-karax-comp-local/examples/todoapp/style.css b/bench/implementations/nim-karax-comp-local/examples/todoapp/style.css new file mode 100644 index 0000000..ceaf090 --- /dev/null +++ b/bench/implementations/nim-karax-comp-local/examples/todoapp/style.css @@ -0,0 +1,378 @@ +html, +body { + margin: 0; + padding: 0; +} + +.todomvc-wrapper { + visibility: visible !important; +} + +button { + margin: 0; + padding: 0; + border: 0; + background: none; + font-size: 100%; + vertical-align: baseline; + font-family: inherit; + font-weight: inherit; + color: inherit; + -webkit-appearance: none; + appearance: none; + -webkit-font-smoothing: antialiased; + -moz-font-smoothing: antialiased; + font-smoothing: antialiased; +} + +body { + font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif; + line-height: 1.4em; + background: #f5f5f5; + color: #4d4d4d; + min-width: 230px; + max-width: 550px; + margin: 0 auto; + -webkit-font-smoothing: antialiased; + -moz-font-smoothing: antialiased; + font-smoothing: antialiased; + font-weight: 300; +} + +button, +input[type="checkbox"] { + outline: none; +} + +.hidden { + display: none; +} + +.todoapp { + background: #fff; + margin: 130px 0 40px 0; + position: relative; + box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), + 0 25px 50px 0 rgba(0, 0, 0, 0.1); +} + +.todoapp input::-webkit-input-placeholder { + font-style: italic; + font-weight: 300; + color: #e6e6e6; +} + +.todoapp input::-moz-placeholder { + font-style: italic; + font-weight: 300; + color: #e6e6e6; +} + +.todoapp input::input-placeholder { + font-style: italic; + font-weight: 300; + color: #e6e6e6; +} + +.todoapp h1 { + position: absolute; + top: -155px; + width: 100%; + font-size: 100px; + font-weight: 100; + text-align: center; + color: rgba(175, 47, 47, 0.15); + -webkit-text-rendering: optimizeLegibility; + -moz-text-rendering: optimizeLegibility; + text-rendering: optimizeLegibility; +} + +.new-todo, +.edit { + position: relative; + margin: 0; + width: 100%; + font-size: 24px; + font-family: inherit; + font-weight: 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); + box-sizing: border-box; + -webkit-font-smoothing: antialiased; + -moz-font-smoothing: antialiased; + font-smoothing: antialiased; +} + +.new-todo { + padding: 16px 16px 16px 60px; + border: none; + background: rgba(0, 0, 0, 0.003); + box-shadow: inset 0 -2px 1px rgba(0,0,0,0.03); +} + +.main { + position: relative; + z-index: 2; + border-top: 1px solid #e6e6e6; +} + +label[for='toggle-all'] { + display: none; +} + +.toggle-all { + position: absolute; + top: -55px; + left: -12px; + width: 60px; + height: 34px; + text-align: center; + border: none; /* Mobile Safari */ +} + +.toggle-all:before { + content: '>'; + font-size: 22px; + color: #e6e6e6; + padding: 10px 27px 10px 27px; +} + +.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 solid #ededed; +} + +.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; + appearance: none; +} + +.todo-list li .toggle:after { + content: url('data:image/svg+xml,'); +} + +.todo-list li .toggle:checked:after { + content: url('data:image/svg+xml,'); +} + +.todo-list li label { + white-space: pre-line; + word-break: break-all; + padding: 15px 60px 15px 15px; + margin-left: 45px; + display: block; + line-height: 1.2; + transition: color 0.4s; +} + +.todo-list li.completed label { + color: #d9d9d9; + 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: 30px; + color: #cc9a9a; + margin-bottom: 11px; + transition: color 0.2s ease-out; +} + +.todo-list li .destroy:hover { + color: #af5b5e; +} + +.todo-list li .destroy:after { + content: 'x'; +} + +.todo-list li:hover .destroy { + display: block; +} + +.todo-list li.editing:last-child { + margin-bottom: -1px; +} + +.footer { + color: #777; + padding: 10px 15px; + height: 20px; + text-align: center; + border-top: 1px solid #e6e6e6; +} + +.footer:before { + content: ''; + position: absolute; + right: 0; + bottom: 0; + left: 0; + height: 50px; + overflow: hidden; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), + 0 8px 0 -3px #f6f6f6, + 0 9px 1px -3px rgba(0, 0, 0, 0.2), + 0 16px 0 -6px #f6f6f6, + 0 17px 2px -6px rgba(0, 0, 0, 0.2); +} + +.todo-count { + float: left; + text-align: left; +} + +.todo-count strong { + font-weight: 300; +} + +.filters { + margin: 0; + padding: 0; + list-style: none; + position: absolute; + right: 0; + left: 0; +} + +.filters li { + display: inline; +} + +.filters li a { + color: inherit; + margin: 3px; + padding: 3px 7px; + text-decoration: none; + border: 1px solid transparent; + border-radius: 3px; +} + +.filters li a.selected, +.filters li a:hover { + border-color: rgba(175, 47, 47, 0.1); +} + +.filters li a.selected { + border-color: rgba(175, 47, 47, 0.2); +} + +.clear-completed, +html .clear-completed:active { + float: right; + position: relative; + line-height: 20px; + text-decoration: none; + cursor: pointer; + position: relative; +} + +.clear-completed:hover { + text-decoration: underline; +} + +.info { + margin: 65px auto 0; + color: #bfbfbf; + /* font-size: 10px; */ + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + text-align: center; +} + +.info p { + line-height: 1; +} + +.info a { + color: inherit; + text-decoration: none; + font-weight: 400; +} + +.info a:hover { + text-decoration: underline; +} + +/* + Hack to remove background from Mobile Safari. + Can't use it globally since it destroys checkboxes in Firefox +*/ +@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 { + -webkit-transform: rotate(90deg); + transform: rotate(90deg); + -webkit-appearance: none; + appearance: none; + } +} + +@media (max-width: 430px) { + .footer { + height: 50px; + } + + .filters { + bottom: 10px; + } +} \ No newline at end of file diff --git a/bench/implementations/nim-karax-comp-local/examples/todoapp/todoapp.nim b/bench/implementations/nim-karax-comp-local/examples/todoapp/todoapp.nim new file mode 100644 index 0000000..1ba06a6 --- /dev/null +++ b/bench/implementations/nim-karax-comp-local/examples/todoapp/todoapp.nim @@ -0,0 +1,155 @@ + +import vdom, karax, karaxdsl, jstrutils, components + +type + Filter = enum + all, active, completed + +var + selectedEntry = -1 + filter: Filter + entriesLen: int + +proc getItem(key : cstring ): cstring {.importc: "localStorage.getItem"} +proc setItem(key, value : cstring ) {.importc: "localStorage.setItem"} +proc clearEntries() {.importc: "localStorage.clear"} + +proc getEntryCstring(pos: int): cstring = + result = getItem(&pos & cstring"cstring") + if result == cstring"null": + result = nil + +proc isCompleted(pos: int): bool = + var value = getItem(cstring($pos & "bool")) + result = value == cstring"true" + +proc setEntryCstring(pos: int, value: cstring) = + setItem(cstring($pos & "cstring"), value) + +proc markAsCompleted(pos: int, value : bool) = + var val = cstring"true" + if not value: + val = cstring"false" + setItem(cstring($pos & "bool"), val) + +proc addEntry(str: cstring, bval : bool) = + setEntryCstring(entriesLen, str) + markAsCompleted(entriesLen, bval) + inc entriesLen + +proc updateEntry(pos: int, str: cstring, bval: bool) = + setEntryCstring(pos, str) + markAsCompleted(pos, bval) + +proc onTodoEnter(ev: Event; n: VNode) = + addEntry(n.value, false) + n.value = "" + +proc removeHandler(ev: Event; n: VNode) = + updateEntry(n.key, cstring(nil), false) + +proc editHandler(ev: Event; n: VNode) = + selectedEntry = n.key + +proc focusLost(ev: Event; n: VNode) = selectedEntry = -1 + +proc editEntry(ev: Event; n: VNode) = + setEntryCstring(n.key, n.value) + selectedEntry = -1 + +proc toggleEntry(ev: Event; n: VNode) = + let id = n.key + markAsCompleted(id, not isCompleted(id)) + +proc onAllDone(ev: Event; n: VNode) = + clearEntries() + selectedEntry = -1 + +proc clearCompleted(ev: Event, n: VNode) = + for i in 0.. + + + + Todo app + + + + +
    + + + + + diff --git a/bench/implementations/nim-karax-comp-local/experiments/example.nim b/bench/implementations/nim-karax-comp-local/experiments/example.nim new file mode 100644 index 0000000..3fe4000 --- /dev/null +++ b/bench/implementations/nim-karax-comp-local/experiments/example.nim @@ -0,0 +1,32 @@ + +import vdom, components, karax, karaxdsl, jdict, jstrutils + +var + images: seq[cstring] = @[cstring"a", "b", "c", "d"] + +proc carousel*(key: VKey): VNode {.component.} = + state: + var counter: int = 0 + + proc next(ev: Event; n: VNode) = + counter = (counter + 1) mod images.len + + result = buildHtml(tdiv(key=key)): + text images[counter] + button(onclick = next): + text "Next" + +proc createDom(): VNode = + result = buildHtml(table): + tr: + td: + carousel(0) + td: + carousel(1) + tr: + td: + carousel(2) + td: + carousel(3) + +setRenderer createDom diff --git a/bench/implementations/nim-karax-comp-local/experiments/example.nims b/bench/implementations/nim-karax-comp-local/experiments/example.nims new file mode 100644 index 0000000..532b206 --- /dev/null +++ b/bench/implementations/nim-karax-comp-local/experiments/example.nims @@ -0,0 +1 @@ +--path: "../src" diff --git a/bench/implementations/nim-karax-comp-local/experiments/oldwidgets.nim b/bench/implementations/nim-karax-comp-local/experiments/oldwidgets.nim new file mode 100644 index 0000000..c947d7f --- /dev/null +++ b/bench/implementations/nim-karax-comp-local/experiments/oldwidgets.nim @@ -0,0 +1,251 @@ +var + linkCounter: int + +proc link*(id: int): VNode = + result = newVNode(VNodeKind.anchor) + result.setAttr("href", "#") + inc linkCounter + result.setAttr("id", $linkCounter & ":" & $id) + +proc link*(action: EventHandler): VNode = + result = newVNode(VNodeKind.anchor) + result.setAttr("href", "#") + result.setOnclick action + +when false: + proc button*(caption: cstring; action: EventHandler; disabled=false): VNode = + result = newVNode(VNodeKind.button) + result.add text(caption) + if action != nil: + result.setOnClick action + if disabled: + result.setAttr("disabled", "true") + +proc select*(choices: openarray[cstring]): VNode = + result = newVNode(VNodeKind.select) + var i = 0 + for c in choices: + result.add tree(VNodeKind.option, [(cstring"value", toCstr(i))], text(c)) + inc i + +proc select*(choices: openarray[(int, cstring)]): VNode = + result = newVNode(VNodeKind.select) + for c in choices: + result.add tree(VNodeKind.option, [(cstring"value", toCstr(c[0]))], text(c[1])) + +var radioCounter: int + +proc radio*(choices: openarray[(int, cstring)]): VNode = + result = newVNode(VNodeKind.fieldset) + var i = 0 + inc radioCounter + for c in choices: + let id = cstring"radio_" & c[1] & toCstr(i) + var kid = tree(VNodeKind.input, [(cstring"type", cstring"radio"), + (cstring"id", id), (cstring"name", cstring"radio" & toCStr(radioCounter)), + (cstring"value", toCStr(c[0]))]) + if i == 0: + kid.setAttr(cstring"checked", cstring"checked") + var lab = tree(VNodeKind.label, [(cstring"for", id)], text(c[1])) + kid.add lab + result.add kid + inc i + +proc tag*(kind: VNodeKind; id=cstring(nil), class=cstring(nil)): VNode = + result = newVNode(kind) + result.id = id + result.class = class + +proc tdiv*(id=cstring(nil), class=cstring(nil)): VNode = tag(VNodeKind.tdiv, id, class) +proc span*(id=cstring(nil), class=cstring(nil)): VNode = tag(VNodeKind.span, id, class) + +proc valueAsInt*(e: Node): int = parseInt(e.value) + +proc th*(s: cstring): VNode = + result = newVNode(VNodeKind.th) + result.add text(s) + +proc td*(s: string): VNode = + result = newVNode(VNodeKind.td) + result.add text(s) + +proc td*(s: VNode): VNode = + result = newVNode(VNodeKind.td) + result.add s + +proc td*(class: cstring; s: VNode): VNode = + result = newVNode(VNodeKind.td) + result.add s + result.class = class + +proc table*(class=cstring(nil), kids: varargs[VNode]): VNode = + result = tag(VNodeKind.table, nil, class) + for k in kids: result.add k + +proc tr*(kids: varargs[VNode]): VNode = + result = newVNode(VNodeKind.tr) + for k in kids: + if k.kind in {VNodeKind.td, VNodeKind.th}: + result.add k + else: + result.add td(k) + +proc suffix*(s, prefix: cstring): cstring = + if s.startsWith(prefix): + result = s.substr(prefix.len) + else: + kout(cstring"bug! " & s & cstring" does not start with " & prefix) + +proc suffixAsInt*(s, prefix: cstring): int = parseInt(suffix(s, prefix)) + +#proc ceil(f: float): int {.importc: "Math.ceil", nodecl.} + +proc realtimeInput*(val: cstring; action: EventHandler): VNode = + var timer: Timeout + proc onkeyup(ev: Event; n: VNode) = + proc wrapper() = keyeventBody() + + if timer != nil: clearTimeout(timer) + timer = setTimeout(wrapper, 400) + result = tree(VNodeKind.input, [(cstring"type", cstring"text")]) + result.value = val + result.addEventListener(EventKind.onkeyup, onkeyup) + +proc enterInput*(id, val: cstring; action: EventHandler): VNode = + proc onkeyup(ev: Event; n: VNode) = + if ev.keyCode == 13: keyeventBody() + + result = tree(VNodeKind.input, [(cstring"type", cstring"text")]) + result.id = id + result.value = val + result.addEventListener(EventKind.onkeyup, onkeyup) + +proc setOnEnter*(n: VNode; action: EventHandler) = + proc onkeyup(ev: Event; n: VNode) = + if ev.keyCode == 13: keyeventBody() + n.addEventListener(EventKind.onkeyup, onkeyup) + +proc setOnscroll*(action: proc(min, max: VKey; diff: int)) = + var oldY = window.pageYOffset + + proc wrapper(ev: Event) = + let dir = window.pageYOffset - oldY + if dir == 0: return + + var a = VKey high(int) + var b = VKey 0 + var h, count: int + document.visibleKeys(a, b, h, count) + let avgh = h / count + let diff = toInt(dir.float / avgh) + if diff != 0: + oldY = window.pageYOffset + action(a, b, diff) + redraw() + + document.addEventListener("scroll", wrapper) + +when false: + var plugins {.exportc.}: seq[(string, proc())] = @[] + + proc onInput(val: cstring) = + kout val + if val == "dyn": + kout(plugins.len) + if plugins.len > 0: + plugins[0][1]() + +var + images: seq[cstring] = @[cstring"a", "b", "c", "d"] + +proc carousel*(): VNode = + var currentIndex = 0 + + proc next(ev: Event; n: VNode) = + currentIndex = (currentIndex + 1) mod images.len + + proc prev(ev: Event; n: VNode) = + currentIndex = (currentIndex - 1) mod images.len + + result = buildHtml(tdiv): + text images[currentIndex] + button(onclick = next): + text "Next" + button(onclick = prev): + text "Previous" + +#proc targetElem*(e: Event): Element = cast[Element](e.target) + +#proc getElementsByClassName*(cls: cstring): seq[Element] {.importc: +# "document.getElementsByClassName", nodecl.} +#proc textContent(e: Node): cstring {. +# importcpp: "#.textContent", nodecl.} + +proc isElementInViewport(el: Node; h: var int): bool = + let rect = el.getBoundingClientRect() + h = rect.bottom - rect.top + result = rect.top >= 0 and rect.left >= 0 and + rect.bottom <= clientHeight() and + rect.right <= clientWidth() + +proc visibleKeys(e: Node; a, b: var VKey; h, count: var int) = + # we only care about nodes that have a key: + var hh = 0 + # do not recurse if there is a 'key' field already: + if e.key >= 0: + if isElementInViewport(e, hh): + inc count + inc h, hh + a = min(a, e.key) + b = max(b, e.key) + else: + for i in 0.. + + + + Todo app + + + + + +
    + + + + + + diff --git a/bench/implementations/nim-karax-comp-local/experiments/scrollapp.nim b/bench/implementations/nim-karax-comp-local/experiments/scrollapp.nim new file mode 100644 index 0000000..f9c8ccb --- /dev/null +++ b/bench/implementations/nim-karax-comp-local/experiments/scrollapp.nim @@ -0,0 +1,142 @@ + +import vdom, karax, karaxdsl, jdict, jstrutils, components + +type + Filter = enum + all, active, completed + +var + entries: seq[(cstring, bool)] + visibleA = 0 + visibleB = 10 + selectedEntry = -1 + filter: Filter + +proc onTodoEnter(ev: Event; n: VNode) = + entries.add((n.value, false)) + n.value = "" + +proc removeHandler(ev: Event; n: VNode) = + entries[n.key] = (cstring(nil), false) + +proc editHandler(ev: Event; n: VNode) = + selectedEntry = n.key + +proc focusLost(ev: Event; n: VNode) = selectedEntry = -1 + +proc editEntry(ev: Event; n: VNode) = + entries[n.key][0] = n.value + selectedEntry = -1 + +proc toggleEntry(ev: Event; n: VNode) = + let id = n.key + entries[id][1] = not entries[id][1] + +proc onAllDone(ev: Event; n: VNode) = + entries = @[] + selectedEntry = -1 + +proc clearCompleted(ev: Event, n: VNode) = + for i in 0.. 0: + # scroll downwards: + visibleA = max(a-overshoot2, 0) + visibleB = min(b+diff+overshoot1, entries.len-1) + elif diff < 0: + # scroll upwards: + visibleA = max(a+diff-overshoot1, 0) + visibleB = min(b+overshoot2, entries.len-1) + ) + +setOnHashChange(proc(hash: cstring) = + if hash == cstring"#/": filter = all + elif hash == cstring"#/completed": filter = completed + elif hash == cstring"#/active": filter = active +) +setRenderer createDom + +proc onload(session: cstring) {.exportc.} = + for i in 0..visibleB: + entries.add((cstring"Entry " & &i, false)) + init() diff --git a/bench/implementations/nim-karax-comp-local/experiments/scrollapp.nims b/bench/implementations/nim-karax-comp-local/experiments/scrollapp.nims new file mode 100644 index 0000000..532b206 --- /dev/null +++ b/bench/implementations/nim-karax-comp-local/experiments/scrollapp.nims @@ -0,0 +1 @@ +--path: "../src" diff --git a/bench/implementations/nim-karax-comp-local/experiments/style.css b/bench/implementations/nim-karax-comp-local/experiments/style.css new file mode 100644 index 0000000..ceaf090 --- /dev/null +++ b/bench/implementations/nim-karax-comp-local/experiments/style.css @@ -0,0 +1,378 @@ +html, +body { + margin: 0; + padding: 0; +} + +.todomvc-wrapper { + visibility: visible !important; +} + +button { + margin: 0; + padding: 0; + border: 0; + background: none; + font-size: 100%; + vertical-align: baseline; + font-family: inherit; + font-weight: inherit; + color: inherit; + -webkit-appearance: none; + appearance: none; + -webkit-font-smoothing: antialiased; + -moz-font-smoothing: antialiased; + font-smoothing: antialiased; +} + +body { + font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif; + line-height: 1.4em; + background: #f5f5f5; + color: #4d4d4d; + min-width: 230px; + max-width: 550px; + margin: 0 auto; + -webkit-font-smoothing: antialiased; + -moz-font-smoothing: antialiased; + font-smoothing: antialiased; + font-weight: 300; +} + +button, +input[type="checkbox"] { + outline: none; +} + +.hidden { + display: none; +} + +.todoapp { + background: #fff; + margin: 130px 0 40px 0; + position: relative; + box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), + 0 25px 50px 0 rgba(0, 0, 0, 0.1); +} + +.todoapp input::-webkit-input-placeholder { + font-style: italic; + font-weight: 300; + color: #e6e6e6; +} + +.todoapp input::-moz-placeholder { + font-style: italic; + font-weight: 300; + color: #e6e6e6; +} + +.todoapp input::input-placeholder { + font-style: italic; + font-weight: 300; + color: #e6e6e6; +} + +.todoapp h1 { + position: absolute; + top: -155px; + width: 100%; + font-size: 100px; + font-weight: 100; + text-align: center; + color: rgba(175, 47, 47, 0.15); + -webkit-text-rendering: optimizeLegibility; + -moz-text-rendering: optimizeLegibility; + text-rendering: optimizeLegibility; +} + +.new-todo, +.edit { + position: relative; + margin: 0; + width: 100%; + font-size: 24px; + font-family: inherit; + font-weight: 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); + box-sizing: border-box; + -webkit-font-smoothing: antialiased; + -moz-font-smoothing: antialiased; + font-smoothing: antialiased; +} + +.new-todo { + padding: 16px 16px 16px 60px; + border: none; + background: rgba(0, 0, 0, 0.003); + box-shadow: inset 0 -2px 1px rgba(0,0,0,0.03); +} + +.main { + position: relative; + z-index: 2; + border-top: 1px solid #e6e6e6; +} + +label[for='toggle-all'] { + display: none; +} + +.toggle-all { + position: absolute; + top: -55px; + left: -12px; + width: 60px; + height: 34px; + text-align: center; + border: none; /* Mobile Safari */ +} + +.toggle-all:before { + content: '>'; + font-size: 22px; + color: #e6e6e6; + padding: 10px 27px 10px 27px; +} + +.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 solid #ededed; +} + +.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; + appearance: none; +} + +.todo-list li .toggle:after { + content: url('data:image/svg+xml,'); +} + +.todo-list li .toggle:checked:after { + content: url('data:image/svg+xml,'); +} + +.todo-list li label { + white-space: pre-line; + word-break: break-all; + padding: 15px 60px 15px 15px; + margin-left: 45px; + display: block; + line-height: 1.2; + transition: color 0.4s; +} + +.todo-list li.completed label { + color: #d9d9d9; + 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: 30px; + color: #cc9a9a; + margin-bottom: 11px; + transition: color 0.2s ease-out; +} + +.todo-list li .destroy:hover { + color: #af5b5e; +} + +.todo-list li .destroy:after { + content: 'x'; +} + +.todo-list li:hover .destroy { + display: block; +} + +.todo-list li.editing:last-child { + margin-bottom: -1px; +} + +.footer { + color: #777; + padding: 10px 15px; + height: 20px; + text-align: center; + border-top: 1px solid #e6e6e6; +} + +.footer:before { + content: ''; + position: absolute; + right: 0; + bottom: 0; + left: 0; + height: 50px; + overflow: hidden; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), + 0 8px 0 -3px #f6f6f6, + 0 9px 1px -3px rgba(0, 0, 0, 0.2), + 0 16px 0 -6px #f6f6f6, + 0 17px 2px -6px rgba(0, 0, 0, 0.2); +} + +.todo-count { + float: left; + text-align: left; +} + +.todo-count strong { + font-weight: 300; +} + +.filters { + margin: 0; + padding: 0; + list-style: none; + position: absolute; + right: 0; + left: 0; +} + +.filters li { + display: inline; +} + +.filters li a { + color: inherit; + margin: 3px; + padding: 3px 7px; + text-decoration: none; + border: 1px solid transparent; + border-radius: 3px; +} + +.filters li a.selected, +.filters li a:hover { + border-color: rgba(175, 47, 47, 0.1); +} + +.filters li a.selected { + border-color: rgba(175, 47, 47, 0.2); +} + +.clear-completed, +html .clear-completed:active { + float: right; + position: relative; + line-height: 20px; + text-decoration: none; + cursor: pointer; + position: relative; +} + +.clear-completed:hover { + text-decoration: underline; +} + +.info { + margin: 65px auto 0; + color: #bfbfbf; + /* font-size: 10px; */ + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + text-align: center; +} + +.info p { + line-height: 1; +} + +.info a { + color: inherit; + text-decoration: none; + font-weight: 400; +} + +.info a:hover { + text-decoration: underline; +} + +/* + Hack to remove background from Mobile Safari. + Can't use it globally since it destroys checkboxes in Firefox +*/ +@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 { + -webkit-transform: rotate(90deg); + transform: rotate(90deg); + -webkit-appearance: none; + appearance: none; + } +} + +@media (max-width: 430px) { + .footer { + height: 50px; + } + + .filters { + bottom: 10px; + } +} \ No newline at end of file diff --git a/bench/implementations/nim-karax-comp-local/karax.nimble b/bench/implementations/nim-karax-comp-local/karax.nimble new file mode 100644 index 0000000..be4879f --- /dev/null +++ b/bench/implementations/nim-karax-comp-local/karax.nimble @@ -0,0 +1,12 @@ +# Package + +version = "0.1.0" +author = "Araq" +description = "Karax is a framework for developing single page applications in Nim." +license = "MIT" + +# Dependencies + +requires "nim >= 0.16.1" + +skipDirs = @["examples/todoapp"] \ No newline at end of file diff --git a/bench/implementations/nim-karax-comp-local/readme.rst b/bench/implementations/nim-karax-comp-local/readme.rst new file mode 100644 index 0000000..907f016 --- /dev/null +++ b/bench/implementations/nim-karax-comp-local/readme.rst @@ -0,0 +1,38 @@ +Karax -- Single page applications in Nim +======================================== + +Karax is a framework for developing single page applications in Nim. +It's still in heavy development, so keep in mind that the API is subject +to change. + +To try it out, run:: + + nimble install # For first time + + cd examples/todoapp + nim js todoapp.nim + open todoapp.html + cd ../.. + + cd examples/mediaplayer + nim js playerapp.nim + open playerapp.html + +It uses a virtual DOM like React, but is much smaller than the existing +frameworks plus of course it's written in Nim for Nim. No external +dependencies! And thanks to Nim's whole program optimization only what +is used ends up in the generated JavaScript code. + + +Goals +===== + +- Leverage Nim's macro system to produce a framework that allows + for the development of applications that are boilerplate free. +- Keep it small, keep it fast, keep it flexible. + + +Todo +==== + +- Expose a nice API to do Ajax requests. diff --git a/bench/implementations/nim-karax-comp-local/src/components.nim b/bench/implementations/nim-karax-comp-local/src/components.nim new file mode 100644 index 0000000..b93742d --- /dev/null +++ b/bench/implementations/nim-karax-comp-local/src/components.nim @@ -0,0 +1,225 @@ +## Components in Karax are built by the ``.component`` macro annotation. + +import macros, jdict, dom, vdom, tables, strutils + +type + StateDict*[V] = ref object + defaultValue*: V + +proc get[V](d: StateDict[V], k: VKey): V {.importcpp: "#[#]".} +proc put[V](d: StateDict[V], k: VKey, v: V) {.importcpp: "#[#] = #".} + +proc contains*[V](d: StateDict[V], k: VKey): bool {.importcpp: "#.hasOwnProperty(#)".} +proc del*[V](d: StateDict[V], k: VKey) {.importcpp: "delete #[#]".} + +proc newStateDict*[V](): StateDict[V] {.importcpp: "{@}".} + +var + dirty = newStateDict[bool]() + someDirty*: bool + +proc markDirty*(key: VKey) = + dirty.put(key, true) + someDirty = true + +proc unmarkDirty*(key: VKey) = dirty.del key +proc isDirty*(key: VKey): bool = dirty.contains(key) + +proc `[]`*[V](d: StateDict[V], k: VKey): V = + if d.contains(k): result = d.get(k) + else: result = d.defaultValue + +proc `[]=`*[V](d: StateDict[V], k: VKey, v: V) = + d.put(k, v) + markDirty(k) + +var + vcomponents* = newJDict[cstring, proc(args: seq[VNode]): VNode]() + dcomponents* = newJDict[cstring, proc(args: seq[VNode]): Node]() + +type + ComponentKind* {.pure.} = enum + None, + Tag, + VNode, + Node + +var + allcomponents {.compileTime.} = initTable[string, ComponentKind]() + +proc isComponent*(x: string): ComponentKind {.compileTime.} = + allcomponents.getOrDefault(x) + +proc addTags() {.compileTime.} = + let x = (bindSym"VNodeKind").getTypeImpl + expectKind(x, nnkEnumTy) + for i in ord(VNodeKind.html)..ord(VNodeKind.high): + # +1 because of empty node at the start of the enum AST: + let tag = $x[i+1] + allcomponents[tag] = ComponentKind.Tag + +static: + addTags() + + +template toState(x): untyped = newIdentNode("state" & x) +proc accessState(sv: NimNode): NimNode {.compileTime.} = + newTree(nnkBracketExpr, sv, newIdentNode("key")) + +proc stateDecl(n: NimNode; names: TableRef[string, bool]; decl: NimNode) = + case n.kind + of nnkVarSection, nnkLetSection: + for c in n: + expectKind c, nnkIdentDefs + let typ = c[^2] + let val = c[^1] + let usedType = if typ.kind != nnkEmpty: typ else: newCall("type", val) + if usedType.kind == nnkEmpty: + error("cannot determine the variable's type", c) + for i in 0 .. c.len-3: + let v = $c[i] + let sv = toState v + decl.add quote do: + var `sv` = newStateDict[`usedType`]() + if val.kind != nnkEmpty: + decl.add newTree(nnkAsgn, newDotExpr(sv, newIdentNode"defaultValue"), + val) + else: + error("component state must have a primitive initializer") + names[v] = true + of nnkStmtList, nnkStmtListExpr: + for x in n: stateDecl(x, names, decl) + of nnkDo: + stateDecl(n.body, names, decl) + of nnkCommentStmt: discard + else: + error("invalid 'state' declaration", n) + +proc doState(n: NimNode; names: TableRef[string, bool]; + decl: NimNode): NimNode = + case n.kind + of nnkCallKinds: + # handle 'state' declaration and remove it from the AST: + if n.len == 2 and repr(n[0]) == "state": + stateDecl(n[1], names, decl) + return nil #newTree(nnkEmpty) + of nnkSym, nnkIdent: + let v = $n + if v in names: + let sv = toState v + return accessState(sv) + else: discard + result = copyNimNode(n) + for i in 0..`_. + +when not defined(js) and not defined(Nimdoc): + {.error: "This module only works on the JavaScript platform".} + +type + EventTarget* = ref EventTargetObj + EventTargetObj {.importc.} = object of RootObj + onabort*: proc (event: Event) {.nimcall.} + onblur*: proc (event: Event) {.nimcall.} + onchange*: proc (event: Event) {.nimcall.} + onclick*: proc (event: Event) {.nimcall.} + ondblclick*: proc (event: Event) {.nimcall.} + onerror*: proc (event: Event) {.nimcall.} + onfocus*: proc (event: Event) {.nimcall.} + onkeydown*: proc (event: Event) {.nimcall.} + onkeypress*: proc (event: Event) {.nimcall.} + onkeyup*: proc (event: Event) {.nimcall.} + onload*: proc (event: Event) {.nimcall.} + onmousedown*: proc (event: Event) {.nimcall.} + onmousemove*: proc (event: Event) {.nimcall.} + onmouseout*: proc (event: Event) {.nimcall.} + onmouseover*: proc (event: Event) {.nimcall.} + onmouseup*: proc (event: Event) {.nimcall.} + onreset*: proc (event: Event) {.nimcall.} + onselect*: proc (event: Event) {.nimcall.} + onsubmit*: proc (event: Event) {.nimcall.} + onunload*: proc (event: Event) {.nimcall.} + + Window* = ref WindowObj + WindowObj {.importc.} = object of EventTargetObj + document*: Document + event*: Event + history*: History + location*: Location + closed*: bool + defaultStatus*: cstring + innerHeight*, innerWidth*: int + locationbar*: ref LocationBar + menubar*: ref MenuBar + name*: cstring + outerHeight*, outerWidth*: int + pageXOffset*, pageYOffset*: int + personalbar*: ref PersonalBar + scrollbars*: ref ScrollBars + statusbar*: ref StatusBar + status*: cstring + toolbar*: ref ToolBar + frames*: seq[Frame] + + Frame* = ref FrameObj + FrameObj {.importc.} = object of WindowObj + + ClassList* = ref ClassListObj + ClassListObj {.importc.} = object of RootObj + + NodeType* = enum + ElementNode = 1, + AttributeNode, + TextNode, + CDATANode, + EntityRefNode, + EntityNode, + ProcessingInstructionNode, + CommentNode, + DocumentNode, + DocumentTypeNode, + DocumentFragmentNode, + NotationNode + + Node* = ref NodeObj + NodeObj {.importc.} = object of EventTargetObj + attributes*: seq[Node] + childNodes*: seq[Node] + children*: seq[Node] + data*: cstring + firstChild*: Node + lastChild*: Node + nextSibling*: Node + nodeName*: cstring + nodeType*: NodeType + nodeValue*: cstring + parentNode*: Node + previousSibling*: Node + innerHTML*: cstring + style*: Style + + Document* = ref DocumentObj + DocumentObj {.importc.} = object of NodeObj + alinkColor*: cstring + bgColor*: cstring + body*: Element + charset*: cstring + cookie*: cstring + defaultCharset*: cstring + fgColor*: cstring + head*: Element + lastModified*: cstring + linkColor*: cstring + referrer*: cstring + title*: cstring + URL*: cstring + vlinkColor*: cstring + anchors*: seq[AnchorElement] + forms*: seq[FormElement] + images*: seq[ImageElement] + applets*: seq[Element] + embeds*: seq[EmbedElement] + links*: seq[LinkElement] + + Element* = ref ElementObj + ElementObj {.importc.} = object of NodeObj + classList*: Classlist + checked*: bool + defaultChecked*: bool + defaultValue*: cstring + disabled*: bool + form*: FormElement + name*: cstring + readOnly*: bool + options*: seq[OptionElement] + + # https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement + HtmlElement* = ref object of Element + contentEditable*: string + isContentEditable*: bool + dir*: string + offsetHeight*: int + offsetWidth*: int + offsetLeft*: int + offsetTop*: int + + LinkElement* = ref LinkObj + LinkObj {.importc.} = object of ElementObj + target*: cstring + text*: cstring + x*: int + y*: int + + EmbedElement* = ref EmbedObj + EmbedObj {.importc.} = object of ElementObj + height*: int + hspace*: int + src*: cstring + width*: int + `type`*: cstring + vspace*: int + + AnchorElement* = ref AnchorObj + AnchorObj {.importc.} = object of ElementObj + text*: cstring + x*, y*: int + + OptionElement* = ref OptionObj + OptionObj {.importc.} = object of ElementObj + defaultSelected*: bool + selected*: bool + selectedIndex*: int + text*: cstring + value*: cstring + + FormElement* = ref FormObj + FormObj {.importc.} = object of ElementObj + action*: cstring + encoding*: cstring + `method`*: cstring + target*: cstring + elements*: seq[Element] + + ImageElement* = ref ImageObj + ImageObj {.importc.} = object of ElementObj + border*: int + complete*: bool + height*: int + hspace*: int + lowsrc*: cstring + src*: cstring + vspace*: int + width*: int + + Style = ref StyleObj + StyleObj {.importc.} = object of RootObj + background*: cstring + backgroundAttachment*: cstring + backgroundColor*: cstring + backgroundImage*: cstring + backgroundPosition*: cstring + backgroundRepeat*: cstring + border*: cstring + borderBottom*: cstring + borderBottomColor*: cstring + borderBottomStyle*: cstring + borderBottomWidth*: cstring + borderColor*: cstring + borderLeft*: cstring + borderLeftColor*: cstring + borderLeftStyle*: cstring + borderLeftWidth*: cstring + borderRight*: cstring + borderRightColor*: cstring + borderRightStyle*: cstring + borderRightWidth*: cstring + borderStyle*: cstring + borderTop*: cstring + borderTopColor*: cstring + borderTopStyle*: cstring + borderTopWidth*: cstring + borderWidth*: cstring + bottom*: cstring + captionSide*: cstring + clear*: cstring + clip*: cstring + color*: cstring + cursor*: cstring + direction*: cstring + display*: cstring + emptyCells*: cstring + cssFloat*: cstring + font*: cstring + fontFamily*: cstring + fontSize*: cstring + fontStretch*: cstring + fontStyle*: cstring + fontVariant*: cstring + fontWeight*: cstring + height*: cstring + left*: cstring + letterSpacing*: cstring + lineHeight*: cstring + listStyle*: cstring + listStyleImage*: cstring + listStylePosition*: cstring + listStyleType*: cstring + margin*: cstring + marginBottom*: cstring + marginLeft*: cstring + marginRight*: cstring + marginTop*: cstring + maxHeight*: cstring + maxWidth*: cstring + minHeight*: cstring + minWidth*: cstring + overflow*: cstring + padding*: cstring + paddingBottom*: cstring + paddingLeft*: cstring + paddingRight*: cstring + paddingTop*: cstring + pageBreakAfter*: cstring + pageBreakBefore*: cstring + position*: cstring + right*: cstring + scrollbar3dLightColor*: cstring + scrollbarArrowColor*: cstring + scrollbarBaseColor*: cstring + scrollbarDarkshadowColor*: cstring + scrollbarFaceColor*: cstring + scrollbarHighlightColor*: cstring + scrollbarShadowColor*: cstring + scrollbarTrackColor*: cstring + tableLayout*: cstring + textAlign*: cstring + textDecoration*: cstring + textIndent*: cstring + textTransform*: cstring + top*: cstring + verticalAlign*: cstring + visibility*: cstring + width*: cstring + wordSpacing*: cstring + zIndex*: int + + # TODO: A lot of the fields in Event belong to a more specific type of event. + # TODO: Should we clean this up? + Event* = ref EventObj + EventObj {.importc.} = object of RootObj + target*: Node + altKey*, ctrlKey*, shiftKey*: bool + button*: int + clientX*, clientY*: int + keyCode*: int + layerX*, layerY*: int + modifiers*: int + ALT_MASK*, CONTROL_MASK*, SHIFT_MASK*, META_MASK*: int + offsetX*, offsetY*: int + pageX*, pageY*: int + screenX*, screenY*: int + which*: int + `type`*: cstring + x*, y*: int + ABORT*: int + BLUR*: int + CHANGE*: int + CLICK*: int + DBLCLICK*: int + DRAGDROP*: int + ERROR*: int + FOCUS*: int + KEYDOWN*: int + KEYPRESS*: int + KEYUP*: int + LOAD*: int + MOUSEDOWN*: int + MOUSEMOVE*: int + MOUSEOUT*: int + MOUSEOVER*: int + MOUSEUP*: int + MOVE*: int + RESET*: int + RESIZE*: int + SELECT*: int + SUBMIT*: int + UNLOAD*: int + + TouchList* {.importc.} = ref object of RootObj + length*: int + + TouchEvent* {.importc.} = ref object of Event + changedTouches*, targetTouches*, touches*: TouchList + + Touch* {.importc.} = ref object of RootObj + identifier*: int + screenX*, screenY*, clientX*, clientY*, pageX*, pageY*: int + target*: Element + radiusX*, radiusY*: int + rotationAngle*: int + force*: float + + Location* = ref LocationObj + LocationObj {.importc.} = object of RootObj + hash*: cstring + host*: cstring + hostname*: cstring + href*: cstring + pathname*: cstring + port*: cstring + protocol*: cstring + search*: cstring + + History* = ref HistoryObj + HistoryObj {.importc.} = object of RootObj + length*: int + + Navigator* = ref NavigatorObj + NavigatorObj {.importc.} = object of RootObj + appCodeName*: cstring + appName*: cstring + appVersion*: cstring + cookieEnabled*: bool + language*: cstring + platform*: cstring + userAgent*: cstring + mimeTypes*: seq[ref MimeType] + + Plugin* {.importc.} = object of RootObj + description*: cstring + filename*: cstring + name*: cstring + + MimeType* {.importc.} = object of RootObj + description*: cstring + enabledPlugin*: ref Plugin + suffixes*: seq[cstring] + `type`*: cstring + + LocationBar* {.importc.} = object of RootObj + visible*: bool + MenuBar* = LocationBar + PersonalBar* = LocationBar + ScrollBars* = LocationBar + ToolBar* = LocationBar + StatusBar* = LocationBar + + Screen = ref ScreenObj + ScreenObj {.importc.} = object of RootObj + availHeight*: int + availWidth*: int + colorDepth*: int + height*: int + pixelDepth*: int + width*: int + + TimeOut* {.importc.} = ref object of RootObj + Interval* {.importc.} = object of RootObj + +proc len*(x: Node): int {.importcpp: "#.childNodes.length".} +proc `[]`*(x: Node; idx: int): Element {.importcpp: "#.childNodes[#]".} + +proc setTimeout*(action: proc(); ms: int): Timeout {.importc, nodecl.} +proc clearTimeout*(t: Timeout) {.importc, nodecl.} +proc getElementById*(id: cstring): Element {.importc: "document.getElementById", nodecl.} + +{.push importcpp.} + +# EventTarget "methods" +proc addEventListener*(et: EventTarget, ev: cstring, cb: proc(ev: Event), useCapture: bool = false) + +# Window "methods" +proc alert*(w: Window, msg: cstring) +proc back*(w: Window) +proc blur*(w: Window) +proc captureEvents*(w: Window, eventMask: int) {.deprecated.} +proc clearInterval*(w: Window, interval: ref Interval) +proc clearTimeout*(w: Window, timeout: TimeOut) +proc close*(w: Window) +proc confirm*(w: Window, msg: cstring): bool +proc disableExternalCapture*(w: Window) +proc enableExternalCapture*(w: Window) +proc find*(w: Window, text: cstring, caseSensitive = false, + backwards = false) +proc focus*(w: Window) +proc forward*(w: Window) +proc handleEvent*(w: Window, e: Event) +proc home*(w: Window) +proc moveBy*(w: Window, x, y: int) +proc moveTo*(w: Window, x, y: int) +proc open*(w: Window, uri, windowname: cstring, + properties: cstring = nil): Window +proc print*(w: Window) +proc prompt*(w: Window, text, default: cstring): cstring +proc releaseEvents*(w: Window, eventMask: int) {.deprecated.} +proc resizeBy*(w: Window, x, y: int) +proc resizeTo*(w: Window, x, y: int) +proc routeEvent*(w: Window, event: Event) +proc scrollBy*(w: Window, x, y: int) +proc scrollTo*(w: Window, x, y: int) +proc setInterval*(w: Window, code: cstring, pause: int): ref Interval +proc setInterval*(w: Window, function: proc (), pause: int): ref Interval +proc setTimeout*(w: Window, code: cstring, pause: int): TimeOut +proc setTimeout*(w: Window, function: proc (), pause: int): ref Interval +proc stop*(w: Window) +proc requestAnimationFrame*(w: Window, function: proc (time: float)): int +proc cancelAnimationFrame*(w: Window, id: int) + +# Node "methods" +proc appendChild*(n, child: Node) +proc appendData*(n: Node, data: cstring) +proc cloneNode*(n: Node, copyContent: bool): Node +proc deleteData*(n: Node, start, len: int) +proc getAttribute*(n: Node, attr: cstring): cstring +proc getAttributeNode*(n: Node, attr: cstring): Node +proc hasChildNodes*(n: Node): bool +proc insertBefore*(n, newNode, before: Node) +proc insertData*(n: Node, position: int, data: cstring) +proc removeAttribute*(n: Node, attr: cstring) +proc removeAttributeNode*(n, attr: Node) +proc removeChild*(n, child: Node) +proc replaceChild*(n, newNode, oldNode: Node) +proc replaceData*(n: Node, start, len: int, text: cstring) +proc scrollIntoView*(n: Node) +proc setAttribute*(n: Node, name, value: cstring) +proc setAttributeNode*(n: Node, attr: Node) + +# Document "methods" +proc captureEvents*(d: Document, eventMask: int) {.deprecated.} +proc createAttribute*(d: Document, identifier: cstring): Node +proc createElement*(d: Document, identifier: cstring): Element +proc createTextNode*(d: Document, identifier: cstring): Node +proc getElementById*(d: Document, id: cstring): Element +proc getElementsByName*(d: Document, name: cstring): seq[Element] +proc getElementsByTagName*(d: Document, name: cstring): seq[Element] +proc getElementsByClassName*(d: Document, name: cstring): seq[Element] +proc getSelection*(d: Document): cstring +proc handleEvent*(d: Document, event: Event) +proc open*(d: Document) +proc releaseEvents*(d: Document, eventMask: int) {.deprecated.} +proc routeEvent*(d: Document, event: Event) +proc write*(d: Document, text: cstring) +proc writeln*(d: Document, text: cstring) + +# Element "methods" +proc blur*(e: Element) +proc click*(e: Element) +proc focus*(e: Node) +proc handleEvent*(e: Element, event: Event) +proc select*(e: Element) +proc getElementsByTagName*(e: Element, name: cstring): seq[Element] +proc getElementsByClassName*(e: Element, name: cstring): seq[Element] + +# FormElement "methods" +proc reset*(f: FormElement) +proc submit*(f: FormElement) + +# EmbedElement "methods" +proc play*(e: EmbedElement) +proc stop*(e: EmbedElement) + +# Location "methods" +proc reload*(loc: Location) +proc replace*(loc: Location, s: cstring) + +# History "methods" +proc back*(h: History) +proc forward*(h: History) +proc go*(h: History, pagesToJump: int) + +# Navigator "methods" +proc javaEnabled*(h: Navigator): bool + +# ClassList "methods" +proc add*(c: ClassList, class: cstring) +proc remove*(c: ClassList, class: cstring) +proc contains*(c: ClassList, class: cstring):bool +proc toggle*(c: ClassList, class: cstring) + +# Style "methods" +proc getAttribute*(s: Style, attr: cstring, caseSensitive=false): cstring +proc removeAttribute*(s: Style, attr: cstring, caseSensitive=false) +proc setAttribute*(s: Style, attr, value: cstring, caseSensitive=false) + +# Event "methods" +proc preventDefault*(ev: Event) + +# TouchEvent "methods" +proc identifiedTouch*(list: TouchList): Touch +proc item*(list: TouchList, i: int): Touch + +{.pop.} + +proc setAttr*(n: Node; key, val: cstring) {.importcpp: "#.setAttribute(@)".} + +var + window* {.importc, nodecl.}: Window + document* {.importc, nodecl.}: Document + navigator* {.importc, nodecl.}: Navigator + screen* {.importc, nodecl.}: Screen + +proc decodeURI*(uri: cstring): cstring {.importc, nodecl.} +proc encodeURI*(uri: cstring): cstring {.importc, nodecl.} + +proc escape*(uri: cstring): cstring {.importc, nodecl.} +proc unescape*(uri: cstring): cstring {.importc, nodecl.} + +proc decodeURIComponent*(uri: cstring): cstring {.importc, nodecl.} +proc encodeURIComponent*(uri: cstring): cstring {.importc, nodecl.} +proc isFinite*(x: BiggestFloat): bool {.importc, nodecl.} +proc isNaN*(x: BiggestFloat): bool {.importc, nodecl.} +proc parseFloat*(s: cstring): BiggestFloat {.importc, nodecl.} +proc parseInt*(s: cstring): int {.importc, nodecl.} +proc parseInt*(s: cstring, radix: int):int {.importc, nodecl.} + + +proc id*(n: Node): cstring {.importcpp: "#.id", nodecl.} +proc `id=`*(n: Node; x: cstring) {.importcpp: "#.id = #", nodecl.} +proc class*(n: Node): cstring {.importcpp: "#.className", nodecl.} +proc `class=`*(n: Node; v: cstring) {.importcpp: "#.className = #", nodecl.} + +proc value*(n: Node): cstring {.importcpp: "#.value", nodecl.} +proc `value=`*(n: Node; v: cstring) {.importcpp: "#.value = #", nodecl.} + +proc `disabled=`*(n: Node; v: bool) {.importcpp: "#.disabled = #", nodecl.} + +proc getElementsByClass*(n: Node; name: cstring): seq[Node] {. + importcpp: "#.getElementsByClassName(#)", nodecl.} + + +type + BoundingRect* {.importc.} = object + top*, bottom*, left*, right*: int + +proc getBoundingClientRect*(e: Node): BoundingRect {. + importcpp: "getBoundingClientRect", nodecl.} +proc clientHeight*(): int {. + importcpp: "(window.innerHeight || document.documentElement.clientHeight)@", nodecl} +proc clientWidth*(): int {. + importcpp: "(window.innerWidth || document.documentElement.clientWidth)@", nodecl} + +proc inViewport*(el: Node): bool = + let rect = el.getBoundingClientRect() + result = rect.top >= 0 and rect.left >= 0 and + rect.bottom <= clientHeight() and + rect.right <= clientWidth() + +proc scrollTop*(e: Node): int {.importcpp: "#.scrollTop", nodecl.} +proc offsetHeight*(e: Node): int {.importcpp: "#.offsetHeight", nodecl.} +proc offsetTop*(e: Node): int {.importcpp: "#.offsetTop", nodecl.} diff --git a/bench/implementations/nim-karax-comp-local/src/jdict.nim b/bench/implementations/nim-karax-comp-local/src/jdict.nim new file mode 100644 index 0000000..0eecb58 --- /dev/null +++ b/bench/implementations/nim-karax-comp-local/src/jdict.nim @@ -0,0 +1,13 @@ + +type + JDict*[K, V] = ref object + +proc `[]`*[K, V](d: JDict[K, V], k: K): V {.importcpp: "#[#]".} +proc `[]=`*[K, V](d: JDict[K, V], k: K, v: V) {.importcpp: "#[#] = #".} + +proc newJDict*[K, V](): JDict[K, V] {.importcpp: "{@}".} + +proc contains*[K, V](d: JDict[K, V], k: K): bool {.importcpp: "#.hasOwnProperty(#)".} + +proc del*[K, V](d: JDict[K, V], k: K) {.importcpp: "delete #[#]".} + diff --git a/bench/implementations/nim-karax-comp-local/src/jstrutils.nim b/bench/implementations/nim-karax-comp-local/src/jstrutils.nim new file mode 100644 index 0000000..c69e2fa --- /dev/null +++ b/bench/implementations/nim-karax-comp-local/src/jstrutils.nim @@ -0,0 +1,23 @@ +# cstring handling utilities for performance + +proc split*(s, sep: cstring): seq[cstring] {.importcpp, nodecl.} + +proc split*(s, sep: cstring; max: int): seq[cstring] {.importcpp, nodecl.} + +proc startsWith*(a, b: cstring): bool {.importcpp: "startsWith", nodecl.} +proc contains*(a, b: cstring): bool {.importcpp: "(#.indexOf(#)>=0)", nodecl.} +proc substr*(s: cstring; start: int): cstring {.importcpp: "substr", nodecl.} +proc substr*(s: cstring; start, length: int): cstring {.importcpp: "substr", nodecl.} + +#proc len*(s: cstring): int {.importcpp: "#.length", nodecl.} +proc `&`*(a, b: cstring): cstring {.importcpp: "(# + #)", nodecl.} +proc toCstr*(s: int): cstring {.importcpp: "((#)+'')", nodecl.} +proc `&`*(s: int): cstring {.importcpp: "((#)+'')", nodecl.} +proc `&`*(s: bool): cstring {.importcpp: "((#)+'')", nodecl.} + +proc `&`*(s: cstring): cstring {.importcpp: "(#)", nodecl.} + +proc isInt*(s: cstring): bool {.asmNoStackFrame.} = + asm """ + return s.match(/^[0-9]+$/); + """ diff --git a/bench/implementations/nim-karax-comp-local/src/karax.nim b/bench/implementations/nim-karax-comp-local/src/karax.nim new file mode 100644 index 0000000..1908d6f --- /dev/null +++ b/bench/implementations/nim-karax-comp-local/src/karax.nim @@ -0,0 +1,345 @@ +## Karax -- Single page applications for Nim. + +import dom, vdom, jstrutils, components, jdict + +export dom.Event #, dom.cloneNode, dom + +proc kout*[T](x: T) {.importc: "console.log", varargs.} + ## the preferred way of debugging karax applications. + +proc hasProp(e: Node; prop: cstring): bool {.importcpp: "(#.hasOwnProperty(#))".} +proc rawkey(e: Node): VKey {.importcpp: "#.karaxKey", nodecl.} +proc key*(e: Node): VKey = + if e.hasProp"karaxKey": result = e.rawkey + else: result = -1 +proc `key=`*(e: Node; x: VKey) {.importcpp: "#.karaxKey = #", nodecl.} + +var + toFocus: Node + toFocusV: VNode + +proc setFocus*(n: VNode) = + toFocusV = n + +# ----------------- event wrapping --------------------------------------- + +template nativeValue(ev): cstring = cast[Element](ev.target).value +template setNativeValue(ev, val) = cast[Element](ev.target).value = val + +template keyeventBody() = + n.value = nativeValue(ev) + action(ev, n) + setNativeValue(ev, n.value) + # Do not call redraw() here! That is already done + # by ``karax.addEventHandler``. + +proc wrapEvent(d: Node; n: VNode; k: EventKind; action: EventHandler) = + proc stdWrapper(): (proc (ev: Event)) = + let action = action + let n = n + result = proc (ev: Event) = + action(ev, n) + + proc enterWrapper(): (proc (ev: Event)) = + let action = action + let n = n + result = proc (ev: Event) = + if ev.keyCode == 13: keyeventBody() + + proc laterWrapper(): (proc (ev: Event)) = + let action = action + let n = n + var timer: Timeout + result = proc (ev: Event) = + proc wrapper() = keyeventBody() + if timer != nil: clearTimeout(timer) + timer = setTimeout(wrapper, 400) + + case k + of EventKind.onkeyuplater: + d.addEventListener("keyup", laterWrapper()) + of EventKind.onkeyupenter: + d.addEventListener("keyup", enterWrapper()) + else: + d.addEventListener(toEventName[k], stdWrapper()) + +# --------------------- DOM diff ----------------------------------------- + +template detach(n: VNode) = n.dom = nil +template attach(n: Vnode) = n.dom = result + +proc vnodeToDom(n: VNode): Node = + if n.kind == VNodeKind.text: + result = document.createTextNode(n.text) + attach n + elif n.kind == VNodeKind.vthunk: + let x = callThunk(vcomponents[n.text], n) + result = vnodeToDom(x) + n.key = result.key + attach n + return result + elif n.kind == VNodeKind.dthunk: + result = callThunk(dcomponents[n.text], n) + n.key = result.key + attach n + return result + else: + result = document.createElement(toTag[n.kind]) + attach n + for k in n: + appendChild(result, vnodeToDom(k)) + # text is mapped to 'value': + if n.text != nil: + result.value = n.text + if n.id != nil: + result.id = n.id + if n.class != nil: + result.class = n.class + if n.key >= 0: + result.key = n.key + for k, v in attrs(n): + if v != nil: + result.setAttr(k, v) + for e, h in items(n.events): + wrapEvent(result, n, e, h) + if n == toFocusV and toFocus.isNil: + toFocus = result + +proc same(n: VNode, e: Node): bool = + if toTag[n.kind] == e.nodename: + result = true + if n.kind != VNodeKind.text: + if e.len != n.len: return false + for i in 0 ..< n.len: + if not same(n[i], e[i]): return false + +var + dorender: proc (): VNode {.closure.} + currentTree: VNode + +proc replaceById(id: cstring; newTree: Node) = + let x = document.getElementById(id) + x.parentNode.replaceChild(newTree, x) + #newTree.id = id + +proc equalsShallow(a, b: VNode): bool = + if a.kind != b.kind: return false + if a.id != b.id: return false + if a.key != b.key: return false + if a.kind == VNodeKind.text: + if a.text != b.text: return false + elif a.kind == VNodeKind.vthunk or a.kind == VNodeKind.dthunk: + if a.text != b.text: return false + if a.len != b.len: return false + for i in 0..= 0 and isDirty(newNode.key): + unmarkDirty(newNode.key) + let n = vnodeToDom(newNode) + if parent == nil: + replaceById("ROOT", n) + else: + parent.replaceChild(n, current) + elif newNode.kind != VNodeKind.text and newNode.kind != VNodeKind.vthunk and + newNode.kind != VNodeKind.dthunk: + for i in 0..newNode.len-1: + updateDirtyElements(current, current[i], newNode[i]) + # leave early if we know there cannot be anything left to do: + #if dirtyCount <= 0: return + +proc updateElement(parent, current: Node, newNode, oldNode: VNode) = + if not equalsShallow(newNode, oldNode): + detach(oldNode) + let n = vnodeToDom(newNode) + if parent == nil: + replaceById("ROOT", n) + else: + parent.replaceChild(n, current) + elif newNode.kind != VNodeKind.text: + let newLength = newNode.len + var oldLength = oldNode.len + let minLength = min(newLength, oldLength) + assert oldNode.kind == newNode.kind + when defined(simpleDiff): + for i in 0..min(newLength, oldLength)-1: + updateElement(current, current[i], newNode[i], oldNode[i]) + if newLength > oldLength: + for i in oldLength..newLength-1: + current.appendChild(vnodeToDom(newNode[i])) + elif oldLength > newLength: + for i in countdown(oldLength-1, newLength): + detach(oldNode[i]) + current.removeChild(current.lastChild) + else: + var commonPrefix = 0 + while commonPrefix < minLength and + equalsTree(newNode[commonPrefix], oldNode[commonPrefix]): + inc commonPrefix + + var oldPos = oldLength - 1 + var newPos = newLength - 1 + while oldPos >= commonPrefix and newPos >= commonPrefix and + equalsTree(newNode[newPos], oldNode[oldPos]): + dec oldPos + dec newPos + + var pos = min(oldPos, newPos) + 1 + for i in commonPrefix..pos-1: + updateElement(current, current.childNodes[i], newNode[i], oldNode[i]) + + var nextChildPos = oldPos + 1 + while pos <= newPos: + if nextChildPos == oldLength: + current.appendChild(vnodeToDom(newNode[pos])) + else: + current.insertBefore(vnodeToDom(newNode[pos]), current.childNodes[nextChildPos]) + # added new Node, so old state of VDOM have one more Node + inc oldLength + inc pos + inc nextChildPos + + for i in pos..oldPos: + detach(oldNode[i]) + current.removeChild(current.childNodes[pos]) + +when false: + var drawTimeout: Timeout + +proc dodraw() = + let newtree = dorender() + newtree.id = "ROOT" + toFocus = nil + if currentTree == nil: + currentTree = newtree + let asdom = vnodeToDom currentTree + replaceById("ROOT", asdom) + else: + let olddom = document.getElementById("ROOT") + updateElement(nil, olddom, newtree, currentTree) + #assert same(newtree, document.getElementById("ROOT")) + if someDirty: + updateDirtyElements(nil, olddom, newtree) + someDirty = false + currentTree = newtree + # now that it's part of the DOM, give it the focus: + if toFocus != nil: + toFocus.focus() + +proc reqFrame(callback: proc()) {.importc: "window.requestAnimationFrame".} + +proc redraw*() = + # we buffer redraw requests: + when false: + if drawTimeout != nil: + clearTimeout(drawTimeout) + drawTimeout = setTimeout(dodraw, 30) + elif true: + reqFrame(dodraw) + else: + dodraw() + +proc init(ev: Event) = + reqFrame(dodraw) + +proc setRenderer*(renderer: proc (): VNode) = + dorender = renderer + window.onload = init + +proc addEventHandler*(n: VNode; k: EventKind; action: EventHandler) = + ## Implements the foundation of Karax's event management. + ## Karax DSL transforms ``tag(onEvent = handler)`` to + ## ``tempNode.addEventHandler(tagNode, EventKind.onEvent, wrapper)`` + ## where ``wrapper`` calls the passed ``action`` and then triggers + ## a ``redraw``. + proc wrapper(ev: Event; n: VNode) = + action(ev, n) + redraw() + addEventListener(n, k, wrapper) + +proc setOnHashChange*(action: proc (hashPart: cstring)) = + var onhashChange {.importc: "window.onhashchange".}: proc() + var hashPart {.importc: "window.location.hash".}: cstring + proc wrapper() = + action(hashPart) + redraw() + onhashchange = wrapper + +proc ajax(meth, url: cstring; headers: openarray[(cstring, cstring)]; + data: cstring; + cont: proc (httpStatus: int; response: cstring)) = + proc setRequestHeader(a, b: cstring) {.importc: "ajax.setRequestHeader".} + {.emit: """ + var ajax = new XMLHttpRequest(); + ajax.open(`meth`,`url`,true);""".} + for a, b in items(headers): + setRequestHeader(a, b) + {.emit: """ + ajax.onreadystatechange = function(){ + if(this.readyState == 4){ + if(this.status == 200){ + `cont`(this.status, this.responseText); + } else { + `cont`(this.status, this.statusText); + } + } + } + ajax.send(`data`); + """.} + +proc ajaxPut*(url: string; headers: openarray[(cstring, cstring)]; + data: cstring; + cont: proc (httpStatus: int, response: cstring)) = + ajax("PUT", url, headers, data, cont) + +proc ajaxGet*(url: string; headers: openarray[(cstring, cstring)]; + cont: proc (httpStatus: int, response: cstring)) = + ajax("GET", url, headers, nil, cont) + +{.push stackTrace:off.} + +proc setupErrorHandler*(useAlert=false) = + ## Installs an error handler that transforms native JS unhandled + ## exceptions into Nim based stack traces. If `useAlert` is false, + ## the error message is put into the console, otherwise `alert` + ## is called. + proc stackTraceAsCstring(): cstring = cstring(getStackTrace()) + {.emit: """ + window.onerror = function(msg, url, line, col, error) { + var x = "Error: " + msg + "\n" + `stackTraceAsCstring`() + if (`useAlert`) + alert(x); + else + console.log(x); + var suppressErrorAlert = true; + return suppressErrorAlert; + };""".} + +{.pop.} + +proc prepend(parent, kid: Element) = + parent.insertBefore(kid, parent.firstChild) + +proc loadScript*(jsfilename: cstring) = + let body = getElementById("body") + let s = document.createElement("script") + s.setAttr "type", "text/javascript" + s.setAttr "src", jsfilename + body.prepend(s) + redraw() diff --git a/bench/implementations/nim-karax-comp-local/src/karaxdsl.nim b/bench/implementations/nim-karax-comp-local/src/karaxdsl.nim new file mode 100644 index 0000000..ade1c24 --- /dev/null +++ b/bench/implementations/nim-karax-comp-local/src/karaxdsl.nim @@ -0,0 +1,119 @@ + +import macros, karax, vdom, components +from strutils import startsWith, toLowerAscii + +const + StmtContext = ["kout", "inc", "echo", "dec", "!"] + SpecialAttrs = ["id", "class", "value", "key"] + +proc getName(n: NimNode): string = + case n.kind + of nnkIdent: + result = $n.ident + of nnkAccQuoted: + result = "" + for i in 0.. 0: + result[L-1] = tcall2(result[L-1], tmpContext) + of nnkStmtList, nnkStmtListExpr, nnkWhenStmt, nnkIfStmt, nnkCaseStmt, + nnkTryStmt, nnkFinally: + # recurse for every child: + result = copyNimNode(n) + for x in n: + result.add tcall2(x, tmpContext) + of nnkVarSection, nnkLetSection, nnkConstSection: + result = n + of nnkCallKinds: + let op = getName(n[0]) + let ck = isComponent(op) + if ck != ComponentKind.None: + let tmp = genSym(nskLet, "tmp") + let call = if ck == ComponentKind.Tag: + newCall(bindSym"tree", newDotExpr(bindSym"VNodeKind", n[0])) + elif ck == ComponentKind.VNode: + newCall(bindSym"vthunk", newLit(op)) + else: + newCall(bindSym"dthunk", newLit(op)) + result = newTree( + if tmpContext == nil: nnkStmtListExpr else: nnkStmtList, + newLetStmt(tmp, call)) + for i in 1 ..< n.len: + # named parameters are transformed into attributes or events: + let x = n[i] + if x.kind == nnkExprEqExpr: + let key = getName x[0] + if key.startsWith("on"): + result.add newCall(bindSym"addEventHandler", + tmp, newDotExpr(bindSym"EventKind", x[0]), x[1]) + elif key in SpecialAttrs: + result.add newDotAsgn(tmp, key, x[1]) + else: + result.add newCall(bindSym"setAttr", tmp, newLit(key), x[1]) + elif ck != ComponentKind.Tag: + call.add x + elif eqIdent(x, "setFocus"): + result.add newCall(x, tmp) + else: + result.add tcall2(x, tmp) + if tmpContext == nil: + result.add tmp + else: + result.add newCall(bindSym"add", tmpContext, tmp) + elif tmpContext != nil and op notin StmtContext: + result = newCall(bindSym"add", tmpContext, n) + elif op == "!" and n.len == 2: + result = n[1] + else: + result = n + else: + result = n + +macro buildHtml*(tag, children: untyped): VNode = + expectKind children, nnkDo + var call: NimNode + if tag.kind in nnkCallKinds: + call = tag + else: + call = newCall(tag) + call.add body(children) + result = tcall2(call, nil) + when defined(debugKaraxDsl): + echo repr result + +macro buildHtml*(children: untyped): VNode = + expectKind children, nnkDo + result = tcall2(body(children), nil) + when defined(debugKaraxDsl): + echo repr result diff --git a/bench/implementations/nim-karax-comp-local/src/karaxprelude.nim b/bench/implementations/nim-karax-comp-local/src/karaxprelude.nim new file mode 100644 index 0000000..285730a --- /dev/null +++ b/bench/implementations/nim-karax-comp-local/src/karaxprelude.nim @@ -0,0 +1,3 @@ +## Include file that contains the common imports for the Karax framework. + +import karax, karaxdsl, vdom, components diff --git a/bench/implementations/nim-karax-comp-local/src/shash.nim b/bench/implementations/nim-karax-comp-local/src/shash.nim new file mode 100644 index 0000000..c387e22 --- /dev/null +++ b/bench/implementations/nim-karax-comp-local/src/shash.nim @@ -0,0 +1,17 @@ +# Simple hashing for the JS target. + +type + Hash* = int + +{.push checks: off.} +proc sdbmHash(hash: Hash, c: int): Hash {.inline.} = + return Hash(c) + (hash shl 6) + (hash shl 16) - hash +{.pop.} + +proc charCodeAt(s: cstring; i: int): int {.importcpp: "#.charCodeAt(#)".} + +template `&=`*(x: var Hash, c: int) = x = sdbmHash(x, c) +template `&=`*(x: var Hash, s: cstring) = + for i in 0..\L" + if n.kind == VNodeKind.text: + result.add n.text + else: + if n.text != nil: + result.add " value = " + result.add n.text + for child in items(n): + toString(child, result, indent+2) + for i in 1..indent: result.add ' ' + result.add "\L" + +proc calcHash*(n: VNode) = + if n.validHash: return + n.validHash = true + var h: Hash = ord n.kind + if n.id != nil: + h &= "id" + h &= n.id + if n.class != nil: + h &= "class" + h &= n.class + if n.key >= 0: + h &= "k" + h &= n.key + for k, v in attrs(n): + h &= " " + h &= k + h &= "=" + h &= v + if n.kind == VNodeKind.text or n.text != nil: + h &= "t" + h &= n.text + else: + for child in items(n): + calcHash(child) + h &= child.hash + n.hash = h + +proc `$`*(n: VNode): cstring = + var res = "" + toString(n, res, 0) + result = cstring(res) diff --git a/bench/implementations/nim-karax-comp-local/tests/diffDomTests.html b/bench/implementations/nim-karax-comp-local/tests/diffDomTests.html new file mode 100644 index 0000000..5ecf130 --- /dev/null +++ b/bench/implementations/nim-karax-comp-local/tests/diffDomTests.html @@ -0,0 +1,19 @@ + + + + + Diff dom tests + + + + + +
    + + + + + + diff --git a/bench/implementations/nim-karax-comp-local/tests/diffDomTests.nim b/bench/implementations/nim-karax-comp-local/tests/diffDomTests.nim new file mode 100644 index 0000000..7fdcf85 --- /dev/null +++ b/bench/implementations/nim-karax-comp-local/tests/diffDomTests.nim @@ -0,0 +1,183 @@ + +import dom, vdom, times, karax, karaxdsl, jdict, jstrutils, parseutils, sequtils + +var + entries: seq[cstring] + results: seq[cstring] + timeout: Timeout + +proc reset() = + results.add cstring"reset started" + entries = @[cstring("0"), cstring("1"), cstring("2"), cstring("3"), cstring("4"), cstring("5") ] + redraw() + results.add cstring"reset finished" + +proc checkOrder(order : seq[int]): bool = + var ul = getElementById("ul") + if ul == nil or len(ul.children) != len(order): + return false + var pos = 0 + for child in ul.children: + if child.id != $order[pos]: + return false + inc pos + return true + +proc check1() = + let result = checkOrder(@[0, 1, 2, 3, 4, 7, 5]) + if result: + results.add cstring"test1 - OK" + else: + results.add cstring"test1 - FAIL" + +# result: 0 1 2 3 4 7 5 +proc test1() = + results.add cstring"test1 started" + entries = @[cstring("0"), cstring("1"), cstring("2"), cstring("3"), cstring("4"), cstring("5") ] + entries.insert(cstring("7"), 5) + redraw() + timeout = setTimeout(check1, 20) + +proc check2() = + let result = checkOrder(@[8, 0, 1, 2, 3, 4, 7, 5]) + if result: + results.add cstring"test1 - OK" + else: + results.add cstring"test2 - FAIL" + +# result: 8 0 1 2 3 4 7 5 +proc test2() = + results.add cstring"test2 started" + entries = @[cstring("0"), cstring("1"), cstring("2"), cstring("3"), cstring("4"), cstring("5") ] + entries.insert(cstring("7"), 5) + entries.insert(cstring("8"), 0) + redraw() + timeout = setTimeout(check2, 20) + +proc check3() = + let result = checkOrder(@[2, 3, 4, 1]) + if result: + results.add cstring"test3 - OK" + else: + results.add cstring"test3 - FAIL" + +# result: 2 3 4 1 +proc test3() = + results.add cstring"test3 started" + entries = @[cstring("2"), cstring("3"), cstring("4"), cstring("1") ] + redraw() + timeout = setTimeout(check3, 20) + +proc check4() = + let result = checkOrder(@[5, 6, 7, 8]) + if result: + results.add cstring"test4 - OK" + else: + results.add cstring"test4 - FAIL" + +# result: 5 6 7 8 +proc test4() = + results.add cstring"test4 started" + entries = @[cstring("5"), cstring("6"), cstring("7"), cstring("8") ] + redraw() + timeout = setTimeout(check4, 20) + +proc check5() = + let result = checkOrder(@[0, 1, 3, 5, 4, 5]) + if result: + results.add cstring"test5 - OK" + else: + results.add cstring"test5 - FAIL" + +# result: 0 1 3 5 4 5 +proc test5() = + results.add cstring"test5 started" + entries = @[cstring("0"), cstring("1"), cstring("3"), cstring("5"), cstring("4"), cstring("5") ] + redraw() + timeout = setTimeout(check5, 20) + +proc check6() = + let result = checkOrder(@[]) + if result: + results.add cstring"test6 - OK" + else: + results.add cstring"test6 - FAIL" + +# result: empty +proc test6() = + results.add cstring"test6 started" + entries = @[] + redraw() + timeout = setTimeout(check6, 20) + +proc check7() = + let result = checkOrder(@[2]) + if result: + results.add cstring"test7 - OK" + else: + results.add cstring"test7 - FAIL" + redraw() + +# result: 2 +proc test7() = + results.add cstring"test7 started" + entries = @[cstring("2")] + redraw() + timeout = setTimeout(check7, 20) + +proc createEntry(id: int): VNode = + result = buildHtml(): + button(id="" & $id): + text $id + +proc createDom(): VNode = + result = buildHtml(tdiv()): + ul(id="ul"): + for e in entries: + createEntry(parseInt(e)) + for r in results: + tdiv: + text r + +proc onload() = + for i in 0..5: # 0_000: + entries.add(cstring($i)) + + var dtReset = 100 + var dtTest = 500 + + var t = dtReset + timeout = setTimeout(test1, t) + t += dtTest + timeout = setTimeout(reset, t) + t += dtReset + + timeout = setTimeout(test2, t) + t += dtTest + timeout = setTimeout(reset, t) + t += dtReset + + timeout = setTimeout(test3, t) + t += dtTest + timeout = setTimeout(reset, t) + t += dtReset + + timeout = setTimeout(test4, t) + t += dtTest + timeout = setTimeout(reset, t) + t += dtReset + + timeout = setTimeout(test5, t) + t += dtTest + timeout = setTimeout(reset, t) + t += dtReset + + timeout = setTimeout(test6, t) + t += dtTest + timeout = setTimeout(reset, t) + t += dtReset + + timeout = setTimeout(test7, t) + +onload() +setRenderer createDom diff --git a/bench/implementations/nim-karax-comp-local/tests/diffDomTests.nims b/bench/implementations/nim-karax-comp-local/tests/diffDomTests.nims new file mode 100644 index 0000000..532b206 --- /dev/null +++ b/bench/implementations/nim-karax-comp-local/tests/diffDomTests.nims @@ -0,0 +1 @@ +--path: "../src" diff --git a/bench/implementations/nim-karax-comp/docs/docs.rst b/bench/implementations/nim-karax-comp/docs/docs.rst new file mode 100644 index 0000000..8298ba9 --- /dev/null +++ b/bench/implementations/nim-karax-comp/docs/docs.rst @@ -0,0 +1,58 @@ + +Virtual DOM +=========== + +The virtual dom is in the ``vdom`` module. + +The ``VNodeKind`` enum describes every tag that the HTML 5 spec includes +and some extensions that allow for an efficient component system. + +These extensions are: + +``VNodeKind.int`` + The node havs a single integer field. + +``VNodeKind.bool`` + The node has a single boolean field. + +``VNodeKint.vthunk`` + The node is a `virtual thunk`:idx:. This means there is a + function attached to it that produces the ``VNode`` structure + on demand. + +``VNodeKint.dthunk`` + The node is a `DOM thunk`:idx:. This means there is a + function attached to it that produces the ``Node`` DOM structure + on demand. + +For convenience of the resulting Nim DSL these tags have enum names +that differ from their HTML equivalent: + +================= ======================================================= +Enum value HTML +================= ======================================================= +``tdiv`` ``div`` (changed because ``div`` is a keyword in Nim) +``italic`` ``i`` +``bold`` ``b`` +``strikethrough`` ``s`` +``underlined`` ``u`` +================= ======================================================= + + +A virtual dom node also has a special field set called ``key``, an integer +that can be used as a data model specific key/id. It can be accessed in event +handlers to change the data model. See the todoapp for an example of how to +use it. + +**Note**: This is not a hint for the DOM diff algorithm, multipe nodes can +all have the same key value. + + +Event system +============ + +Karax does not abstract over the event system the DOM offers much: The same +``Event`` structure is used. Every callback has the +signature ``proc (ev: Event; n: VNode)``. + + diff --git a/bench/implementations/nim-karax-comp/examples/mediaplayer/mediaplayer.nim b/bench/implementations/nim-karax-comp/examples/mediaplayer/mediaplayer.nim new file mode 100644 index 0000000..18179c1 --- /dev/null +++ b/bench/implementations/nim-karax-comp/examples/mediaplayer/mediaplayer.nim @@ -0,0 +1,42 @@ + +import karax, karaxdsl, vdom, dom, components + +const + Play = 0 + Big = 1 + Small = 2 + Normal = 3 + +proc paused(n: Node): bool {.importcpp: "#.paused".} +proc play(n: Node) {.importcpp.} +proc pause(n: Node) {.importcpp.} +proc `width=`(n: Node, w: int) {.importcpp: "#.width = #".} + +proc mplayer*(id, resource: cstring): VNode {.component.} = + proc handler(ev: Event; n: VNode) = + let myVideo = document.getElementById(id) + case n.key + of Play: + if myVideo.paused: + myVideo.play() + else: + myVideo.pause() + of Big: myVideo.width = 560 + of Small: myVideo.width = 320 + of Normal: myVideo.width = 420 + else: discard + + result = buildHtml(tdiv): + button(onclick=handler, key=Play): + text "Play/Pause" + button(onclick=handler, key=Big): + text "Big" + button(onclick=handler, key=Small): + text "Small" + button(onclick=handler, key=Normal): + text "Normal" + br() + br() + video(id=id, width="420"): + source(src=resource, `type`="video/mp4"): + text "Your browser does not support HTML5 video." diff --git a/bench/implementations/nim-karax-comp/examples/mediaplayer/playerapp.html b/bench/implementations/nim-karax-comp/examples/mediaplayer/playerapp.html new file mode 100644 index 0000000..9e076e6 --- /dev/null +++ b/bench/implementations/nim-karax-comp/examples/mediaplayer/playerapp.html @@ -0,0 +1,15 @@ + + + + + Player app + + + + +
    + + + + + diff --git a/bench/implementations/nim-karax-comp/examples/mediaplayer/playerapp.nim b/bench/implementations/nim-karax-comp/examples/mediaplayer/playerapp.nim new file mode 100644 index 0000000..e611eec --- /dev/null +++ b/bench/implementations/nim-karax-comp/examples/mediaplayer/playerapp.nim @@ -0,0 +1,21 @@ +## Example app that shows how to write and embed a custom component. + +include karaxprelude +import mediaplayer + +const url = "https://www.w3schools.com/html/mov_bbb.mp4" + +proc createDom(): VNode = + result = buildHtml(table): + tr: + td: + mplayer("vid1", url) + td: + mplayer("vid2", url) + tr: + td: + mplayer("vid3", url) + td: + mplayer("vid4", url) + +setRenderer createDom diff --git a/bench/implementations/nim-karax-comp/examples/mediaplayer/playerapp.nims b/bench/implementations/nim-karax-comp/examples/mediaplayer/playerapp.nims new file mode 100644 index 0000000..9028ff1 --- /dev/null +++ b/bench/implementations/nim-karax-comp/examples/mediaplayer/playerapp.nims @@ -0,0 +1 @@ +--path: "../../src" diff --git a/bench/implementations/nim-karax-comp/examples/scrollapp/scrollapp.html b/bench/implementations/nim-karax-comp/examples/scrollapp/scrollapp.html new file mode 100644 index 0000000..1ff8b1b --- /dev/null +++ b/bench/implementations/nim-karax-comp/examples/scrollapp/scrollapp.html @@ -0,0 +1,15 @@ + + + + + Todo app + + + + +
    + + + + + diff --git a/bench/implementations/nim-karax-comp/examples/scrollapp/scrollapp.nim b/bench/implementations/nim-karax-comp/examples/scrollapp/scrollapp.nim new file mode 100644 index 0000000..e5ef9c1 --- /dev/null +++ b/bench/implementations/nim-karax-comp/examples/scrollapp/scrollapp.nim @@ -0,0 +1,24 @@ +## Example that shows how to accomplish an "infinitely scrolling" app. + +include karaxprelude +import jstrutils, dom + +var entries: seq[cstring] = @[] +for i in 1..500: + entries.add(cstring("Entry ") & &i) + +proc scrollEvent(ev: Event; n: VNode) = + let d = n.dom + if d != nil and inViewport(d.lastChild): + # "load" more data: + for i in 1..50: + entries.add(cstring("Loaded Entry ") & &i) + +proc createDom(): VNode = + result = buildHtml(): + tdiv(onscroll=scrollEvent, style="height: 400px; overflow: scroll"): + for x in entries: + tdiv: + text x + +setRenderer createDom diff --git a/bench/implementations/nim-karax-comp/examples/scrollapp/scrollapp.nims b/bench/implementations/nim-karax-comp/examples/scrollapp/scrollapp.nims new file mode 100644 index 0000000..9028ff1 --- /dev/null +++ b/bench/implementations/nim-karax-comp/examples/scrollapp/scrollapp.nims @@ -0,0 +1 @@ +--path: "../../src" diff --git a/bench/implementations/nim-karax-comp/examples/todoapp/index.html b/bench/implementations/nim-karax-comp/examples/todoapp/index.html new file mode 100644 index 0000000..488a3bf --- /dev/null +++ b/bench/implementations/nim-karax-comp/examples/todoapp/index.html @@ -0,0 +1,16 @@ + + + + + Todo app + + + + + +
    + + + + + diff --git a/bench/implementations/nim-karax-comp/examples/todoapp/style.css b/bench/implementations/nim-karax-comp/examples/todoapp/style.css new file mode 100644 index 0000000..ceaf090 --- /dev/null +++ b/bench/implementations/nim-karax-comp/examples/todoapp/style.css @@ -0,0 +1,378 @@ +html, +body { + margin: 0; + padding: 0; +} + +.todomvc-wrapper { + visibility: visible !important; +} + +button { + margin: 0; + padding: 0; + border: 0; + background: none; + font-size: 100%; + vertical-align: baseline; + font-family: inherit; + font-weight: inherit; + color: inherit; + -webkit-appearance: none; + appearance: none; + -webkit-font-smoothing: antialiased; + -moz-font-smoothing: antialiased; + font-smoothing: antialiased; +} + +body { + font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif; + line-height: 1.4em; + background: #f5f5f5; + color: #4d4d4d; + min-width: 230px; + max-width: 550px; + margin: 0 auto; + -webkit-font-smoothing: antialiased; + -moz-font-smoothing: antialiased; + font-smoothing: antialiased; + font-weight: 300; +} + +button, +input[type="checkbox"] { + outline: none; +} + +.hidden { + display: none; +} + +.todoapp { + background: #fff; + margin: 130px 0 40px 0; + position: relative; + box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), + 0 25px 50px 0 rgba(0, 0, 0, 0.1); +} + +.todoapp input::-webkit-input-placeholder { + font-style: italic; + font-weight: 300; + color: #e6e6e6; +} + +.todoapp input::-moz-placeholder { + font-style: italic; + font-weight: 300; + color: #e6e6e6; +} + +.todoapp input::input-placeholder { + font-style: italic; + font-weight: 300; + color: #e6e6e6; +} + +.todoapp h1 { + position: absolute; + top: -155px; + width: 100%; + font-size: 100px; + font-weight: 100; + text-align: center; + color: rgba(175, 47, 47, 0.15); + -webkit-text-rendering: optimizeLegibility; + -moz-text-rendering: optimizeLegibility; + text-rendering: optimizeLegibility; +} + +.new-todo, +.edit { + position: relative; + margin: 0; + width: 100%; + font-size: 24px; + font-family: inherit; + font-weight: 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); + box-sizing: border-box; + -webkit-font-smoothing: antialiased; + -moz-font-smoothing: antialiased; + font-smoothing: antialiased; +} + +.new-todo { + padding: 16px 16px 16px 60px; + border: none; + background: rgba(0, 0, 0, 0.003); + box-shadow: inset 0 -2px 1px rgba(0,0,0,0.03); +} + +.main { + position: relative; + z-index: 2; + border-top: 1px solid #e6e6e6; +} + +label[for='toggle-all'] { + display: none; +} + +.toggle-all { + position: absolute; + top: -55px; + left: -12px; + width: 60px; + height: 34px; + text-align: center; + border: none; /* Mobile Safari */ +} + +.toggle-all:before { + content: '>'; + font-size: 22px; + color: #e6e6e6; + padding: 10px 27px 10px 27px; +} + +.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 solid #ededed; +} + +.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; + appearance: none; +} + +.todo-list li .toggle:after { + content: url('data:image/svg+xml,'); +} + +.todo-list li .toggle:checked:after { + content: url('data:image/svg+xml,'); +} + +.todo-list li label { + white-space: pre-line; + word-break: break-all; + padding: 15px 60px 15px 15px; + margin-left: 45px; + display: block; + line-height: 1.2; + transition: color 0.4s; +} + +.todo-list li.completed label { + color: #d9d9d9; + 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: 30px; + color: #cc9a9a; + margin-bottom: 11px; + transition: color 0.2s ease-out; +} + +.todo-list li .destroy:hover { + color: #af5b5e; +} + +.todo-list li .destroy:after { + content: 'x'; +} + +.todo-list li:hover .destroy { + display: block; +} + +.todo-list li.editing:last-child { + margin-bottom: -1px; +} + +.footer { + color: #777; + padding: 10px 15px; + height: 20px; + text-align: center; + border-top: 1px solid #e6e6e6; +} + +.footer:before { + content: ''; + position: absolute; + right: 0; + bottom: 0; + left: 0; + height: 50px; + overflow: hidden; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), + 0 8px 0 -3px #f6f6f6, + 0 9px 1px -3px rgba(0, 0, 0, 0.2), + 0 16px 0 -6px #f6f6f6, + 0 17px 2px -6px rgba(0, 0, 0, 0.2); +} + +.todo-count { + float: left; + text-align: left; +} + +.todo-count strong { + font-weight: 300; +} + +.filters { + margin: 0; + padding: 0; + list-style: none; + position: absolute; + right: 0; + left: 0; +} + +.filters li { + display: inline; +} + +.filters li a { + color: inherit; + margin: 3px; + padding: 3px 7px; + text-decoration: none; + border: 1px solid transparent; + border-radius: 3px; +} + +.filters li a.selected, +.filters li a:hover { + border-color: rgba(175, 47, 47, 0.1); +} + +.filters li a.selected { + border-color: rgba(175, 47, 47, 0.2); +} + +.clear-completed, +html .clear-completed:active { + float: right; + position: relative; + line-height: 20px; + text-decoration: none; + cursor: pointer; + position: relative; +} + +.clear-completed:hover { + text-decoration: underline; +} + +.info { + margin: 65px auto 0; + color: #bfbfbf; + /* font-size: 10px; */ + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + text-align: center; +} + +.info p { + line-height: 1; +} + +.info a { + color: inherit; + text-decoration: none; + font-weight: 400; +} + +.info a:hover { + text-decoration: underline; +} + +/* + Hack to remove background from Mobile Safari. + Can't use it globally since it destroys checkboxes in Firefox +*/ +@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 { + -webkit-transform: rotate(90deg); + transform: rotate(90deg); + -webkit-appearance: none; + appearance: none; + } +} + +@media (max-width: 430px) { + .footer { + height: 50px; + } + + .filters { + bottom: 10px; + } +} \ No newline at end of file diff --git a/bench/implementations/nim-karax-comp/examples/todoapp/todoapp.nim b/bench/implementations/nim-karax-comp/examples/todoapp/todoapp.nim new file mode 100644 index 0000000..7fd6104 --- /dev/null +++ b/bench/implementations/nim-karax-comp/examples/todoapp/todoapp.nim @@ -0,0 +1,119 @@ + +import vdom, karax, karaxdsl, jstrutils, components + +type + Filter = enum + all, active, completed + +var + entries: seq[(cstring, bool)] + selectedEntry = -1 + filter: Filter + +proc onTodoEnter(ev: Event; n: VNode) = + entries.add((n.value, false)) + n.value = "" + +proc removeHandler(ev: Event; n: VNode) = + entries[n.key] = (cstring(nil), false) + +proc editHandler(ev: Event; n: VNode) = + selectedEntry = n.key + +proc focusLost(ev: Event; n: VNode) = selectedEntry = -1 + +proc editEntry(ev: Event; n: VNode) = + entries[n.key][0] = n.value + selectedEntry = -1 + +proc toggleEntry(ev: Event; n: VNode) = + let id = n.key + entries[id][1] = not entries[id][1] + +proc onAllDone(ev: Event; n: VNode) = + entries = @[] + selectedEntry = -1 + +proc clearCompleted(ev: Event, n: VNode) = + for i in 0.. + + + + Todo app + + + + +
    + + + + + diff --git a/bench/implementations/nim-karax-comp/experiments/example.nim b/bench/implementations/nim-karax-comp/experiments/example.nim new file mode 100644 index 0000000..3fe4000 --- /dev/null +++ b/bench/implementations/nim-karax-comp/experiments/example.nim @@ -0,0 +1,32 @@ + +import vdom, components, karax, karaxdsl, jdict, jstrutils + +var + images: seq[cstring] = @[cstring"a", "b", "c", "d"] + +proc carousel*(key: VKey): VNode {.component.} = + state: + var counter: int = 0 + + proc next(ev: Event; n: VNode) = + counter = (counter + 1) mod images.len + + result = buildHtml(tdiv(key=key)): + text images[counter] + button(onclick = next): + text "Next" + +proc createDom(): VNode = + result = buildHtml(table): + tr: + td: + carousel(0) + td: + carousel(1) + tr: + td: + carousel(2) + td: + carousel(3) + +setRenderer createDom diff --git a/bench/implementations/nim-karax-comp/experiments/example.nims b/bench/implementations/nim-karax-comp/experiments/example.nims new file mode 100644 index 0000000..532b206 --- /dev/null +++ b/bench/implementations/nim-karax-comp/experiments/example.nims @@ -0,0 +1 @@ +--path: "../src" diff --git a/bench/implementations/nim-karax-comp/experiments/oldwidgets.nim b/bench/implementations/nim-karax-comp/experiments/oldwidgets.nim new file mode 100644 index 0000000..c947d7f --- /dev/null +++ b/bench/implementations/nim-karax-comp/experiments/oldwidgets.nim @@ -0,0 +1,251 @@ +var + linkCounter: int + +proc link*(id: int): VNode = + result = newVNode(VNodeKind.anchor) + result.setAttr("href", "#") + inc linkCounter + result.setAttr("id", $linkCounter & ":" & $id) + +proc link*(action: EventHandler): VNode = + result = newVNode(VNodeKind.anchor) + result.setAttr("href", "#") + result.setOnclick action + +when false: + proc button*(caption: cstring; action: EventHandler; disabled=false): VNode = + result = newVNode(VNodeKind.button) + result.add text(caption) + if action != nil: + result.setOnClick action + if disabled: + result.setAttr("disabled", "true") + +proc select*(choices: openarray[cstring]): VNode = + result = newVNode(VNodeKind.select) + var i = 0 + for c in choices: + result.add tree(VNodeKind.option, [(cstring"value", toCstr(i))], text(c)) + inc i + +proc select*(choices: openarray[(int, cstring)]): VNode = + result = newVNode(VNodeKind.select) + for c in choices: + result.add tree(VNodeKind.option, [(cstring"value", toCstr(c[0]))], text(c[1])) + +var radioCounter: int + +proc radio*(choices: openarray[(int, cstring)]): VNode = + result = newVNode(VNodeKind.fieldset) + var i = 0 + inc radioCounter + for c in choices: + let id = cstring"radio_" & c[1] & toCstr(i) + var kid = tree(VNodeKind.input, [(cstring"type", cstring"radio"), + (cstring"id", id), (cstring"name", cstring"radio" & toCStr(radioCounter)), + (cstring"value", toCStr(c[0]))]) + if i == 0: + kid.setAttr(cstring"checked", cstring"checked") + var lab = tree(VNodeKind.label, [(cstring"for", id)], text(c[1])) + kid.add lab + result.add kid + inc i + +proc tag*(kind: VNodeKind; id=cstring(nil), class=cstring(nil)): VNode = + result = newVNode(kind) + result.id = id + result.class = class + +proc tdiv*(id=cstring(nil), class=cstring(nil)): VNode = tag(VNodeKind.tdiv, id, class) +proc span*(id=cstring(nil), class=cstring(nil)): VNode = tag(VNodeKind.span, id, class) + +proc valueAsInt*(e: Node): int = parseInt(e.value) + +proc th*(s: cstring): VNode = + result = newVNode(VNodeKind.th) + result.add text(s) + +proc td*(s: string): VNode = + result = newVNode(VNodeKind.td) + result.add text(s) + +proc td*(s: VNode): VNode = + result = newVNode(VNodeKind.td) + result.add s + +proc td*(class: cstring; s: VNode): VNode = + result = newVNode(VNodeKind.td) + result.add s + result.class = class + +proc table*(class=cstring(nil), kids: varargs[VNode]): VNode = + result = tag(VNodeKind.table, nil, class) + for k in kids: result.add k + +proc tr*(kids: varargs[VNode]): VNode = + result = newVNode(VNodeKind.tr) + for k in kids: + if k.kind in {VNodeKind.td, VNodeKind.th}: + result.add k + else: + result.add td(k) + +proc suffix*(s, prefix: cstring): cstring = + if s.startsWith(prefix): + result = s.substr(prefix.len) + else: + kout(cstring"bug! " & s & cstring" does not start with " & prefix) + +proc suffixAsInt*(s, prefix: cstring): int = parseInt(suffix(s, prefix)) + +#proc ceil(f: float): int {.importc: "Math.ceil", nodecl.} + +proc realtimeInput*(val: cstring; action: EventHandler): VNode = + var timer: Timeout + proc onkeyup(ev: Event; n: VNode) = + proc wrapper() = keyeventBody() + + if timer != nil: clearTimeout(timer) + timer = setTimeout(wrapper, 400) + result = tree(VNodeKind.input, [(cstring"type", cstring"text")]) + result.value = val + result.addEventListener(EventKind.onkeyup, onkeyup) + +proc enterInput*(id, val: cstring; action: EventHandler): VNode = + proc onkeyup(ev: Event; n: VNode) = + if ev.keyCode == 13: keyeventBody() + + result = tree(VNodeKind.input, [(cstring"type", cstring"text")]) + result.id = id + result.value = val + result.addEventListener(EventKind.onkeyup, onkeyup) + +proc setOnEnter*(n: VNode; action: EventHandler) = + proc onkeyup(ev: Event; n: VNode) = + if ev.keyCode == 13: keyeventBody() + n.addEventListener(EventKind.onkeyup, onkeyup) + +proc setOnscroll*(action: proc(min, max: VKey; diff: int)) = + var oldY = window.pageYOffset + + proc wrapper(ev: Event) = + let dir = window.pageYOffset - oldY + if dir == 0: return + + var a = VKey high(int) + var b = VKey 0 + var h, count: int + document.visibleKeys(a, b, h, count) + let avgh = h / count + let diff = toInt(dir.float / avgh) + if diff != 0: + oldY = window.pageYOffset + action(a, b, diff) + redraw() + + document.addEventListener("scroll", wrapper) + +when false: + var plugins {.exportc.}: seq[(string, proc())] = @[] + + proc onInput(val: cstring) = + kout val + if val == "dyn": + kout(plugins.len) + if plugins.len > 0: + plugins[0][1]() + +var + images: seq[cstring] = @[cstring"a", "b", "c", "d"] + +proc carousel*(): VNode = + var currentIndex = 0 + + proc next(ev: Event; n: VNode) = + currentIndex = (currentIndex + 1) mod images.len + + proc prev(ev: Event; n: VNode) = + currentIndex = (currentIndex - 1) mod images.len + + result = buildHtml(tdiv): + text images[currentIndex] + button(onclick = next): + text "Next" + button(onclick = prev): + text "Previous" + +#proc targetElem*(e: Event): Element = cast[Element](e.target) + +#proc getElementsByClassName*(cls: cstring): seq[Element] {.importc: +# "document.getElementsByClassName", nodecl.} +#proc textContent(e: Node): cstring {. +# importcpp: "#.textContent", nodecl.} + +proc isElementInViewport(el: Node; h: var int): bool = + let rect = el.getBoundingClientRect() + h = rect.bottom - rect.top + result = rect.top >= 0 and rect.left >= 0 and + rect.bottom <= clientHeight() and + rect.right <= clientWidth() + +proc visibleKeys(e: Node; a, b: var VKey; h, count: var int) = + # we only care about nodes that have a key: + var hh = 0 + # do not recurse if there is a 'key' field already: + if e.key >= 0: + if isElementInViewport(e, hh): + inc count + inc h, hh + a = min(a, e.key) + b = max(b, e.key) + else: + for i in 0.. + + + + Todo app + + + + + +
    + + + + + + diff --git a/bench/implementations/nim-karax-comp/experiments/scrollapp.nim b/bench/implementations/nim-karax-comp/experiments/scrollapp.nim new file mode 100644 index 0000000..f9c8ccb --- /dev/null +++ b/bench/implementations/nim-karax-comp/experiments/scrollapp.nim @@ -0,0 +1,142 @@ + +import vdom, karax, karaxdsl, jdict, jstrutils, components + +type + Filter = enum + all, active, completed + +var + entries: seq[(cstring, bool)] + visibleA = 0 + visibleB = 10 + selectedEntry = -1 + filter: Filter + +proc onTodoEnter(ev: Event; n: VNode) = + entries.add((n.value, false)) + n.value = "" + +proc removeHandler(ev: Event; n: VNode) = + entries[n.key] = (cstring(nil), false) + +proc editHandler(ev: Event; n: VNode) = + selectedEntry = n.key + +proc focusLost(ev: Event; n: VNode) = selectedEntry = -1 + +proc editEntry(ev: Event; n: VNode) = + entries[n.key][0] = n.value + selectedEntry = -1 + +proc toggleEntry(ev: Event; n: VNode) = + let id = n.key + entries[id][1] = not entries[id][1] + +proc onAllDone(ev: Event; n: VNode) = + entries = @[] + selectedEntry = -1 + +proc clearCompleted(ev: Event, n: VNode) = + for i in 0.. 0: + # scroll downwards: + visibleA = max(a-overshoot2, 0) + visibleB = min(b+diff+overshoot1, entries.len-1) + elif diff < 0: + # scroll upwards: + visibleA = max(a+diff-overshoot1, 0) + visibleB = min(b+overshoot2, entries.len-1) + ) + +setOnHashChange(proc(hash: cstring) = + if hash == cstring"#/": filter = all + elif hash == cstring"#/completed": filter = completed + elif hash == cstring"#/active": filter = active +) +setRenderer createDom + +proc onload(session: cstring) {.exportc.} = + for i in 0..visibleB: + entries.add((cstring"Entry " & &i, false)) + init() diff --git a/bench/implementations/nim-karax-comp/experiments/scrollapp.nims b/bench/implementations/nim-karax-comp/experiments/scrollapp.nims new file mode 100644 index 0000000..532b206 --- /dev/null +++ b/bench/implementations/nim-karax-comp/experiments/scrollapp.nims @@ -0,0 +1 @@ +--path: "../src" diff --git a/bench/implementations/nim-karax-comp/experiments/style.css b/bench/implementations/nim-karax-comp/experiments/style.css new file mode 100644 index 0000000..ceaf090 --- /dev/null +++ b/bench/implementations/nim-karax-comp/experiments/style.css @@ -0,0 +1,378 @@ +html, +body { + margin: 0; + padding: 0; +} + +.todomvc-wrapper { + visibility: visible !important; +} + +button { + margin: 0; + padding: 0; + border: 0; + background: none; + font-size: 100%; + vertical-align: baseline; + font-family: inherit; + font-weight: inherit; + color: inherit; + -webkit-appearance: none; + appearance: none; + -webkit-font-smoothing: antialiased; + -moz-font-smoothing: antialiased; + font-smoothing: antialiased; +} + +body { + font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif; + line-height: 1.4em; + background: #f5f5f5; + color: #4d4d4d; + min-width: 230px; + max-width: 550px; + margin: 0 auto; + -webkit-font-smoothing: antialiased; + -moz-font-smoothing: antialiased; + font-smoothing: antialiased; + font-weight: 300; +} + +button, +input[type="checkbox"] { + outline: none; +} + +.hidden { + display: none; +} + +.todoapp { + background: #fff; + margin: 130px 0 40px 0; + position: relative; + box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), + 0 25px 50px 0 rgba(0, 0, 0, 0.1); +} + +.todoapp input::-webkit-input-placeholder { + font-style: italic; + font-weight: 300; + color: #e6e6e6; +} + +.todoapp input::-moz-placeholder { + font-style: italic; + font-weight: 300; + color: #e6e6e6; +} + +.todoapp input::input-placeholder { + font-style: italic; + font-weight: 300; + color: #e6e6e6; +} + +.todoapp h1 { + position: absolute; + top: -155px; + width: 100%; + font-size: 100px; + font-weight: 100; + text-align: center; + color: rgba(175, 47, 47, 0.15); + -webkit-text-rendering: optimizeLegibility; + -moz-text-rendering: optimizeLegibility; + text-rendering: optimizeLegibility; +} + +.new-todo, +.edit { + position: relative; + margin: 0; + width: 100%; + font-size: 24px; + font-family: inherit; + font-weight: 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); + box-sizing: border-box; + -webkit-font-smoothing: antialiased; + -moz-font-smoothing: antialiased; + font-smoothing: antialiased; +} + +.new-todo { + padding: 16px 16px 16px 60px; + border: none; + background: rgba(0, 0, 0, 0.003); + box-shadow: inset 0 -2px 1px rgba(0,0,0,0.03); +} + +.main { + position: relative; + z-index: 2; + border-top: 1px solid #e6e6e6; +} + +label[for='toggle-all'] { + display: none; +} + +.toggle-all { + position: absolute; + top: -55px; + left: -12px; + width: 60px; + height: 34px; + text-align: center; + border: none; /* Mobile Safari */ +} + +.toggle-all:before { + content: '>'; + font-size: 22px; + color: #e6e6e6; + padding: 10px 27px 10px 27px; +} + +.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 solid #ededed; +} + +.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; + appearance: none; +} + +.todo-list li .toggle:after { + content: url('data:image/svg+xml,'); +} + +.todo-list li .toggle:checked:after { + content: url('data:image/svg+xml,'); +} + +.todo-list li label { + white-space: pre-line; + word-break: break-all; + padding: 15px 60px 15px 15px; + margin-left: 45px; + display: block; + line-height: 1.2; + transition: color 0.4s; +} + +.todo-list li.completed label { + color: #d9d9d9; + 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: 30px; + color: #cc9a9a; + margin-bottom: 11px; + transition: color 0.2s ease-out; +} + +.todo-list li .destroy:hover { + color: #af5b5e; +} + +.todo-list li .destroy:after { + content: 'x'; +} + +.todo-list li:hover .destroy { + display: block; +} + +.todo-list li.editing:last-child { + margin-bottom: -1px; +} + +.footer { + color: #777; + padding: 10px 15px; + height: 20px; + text-align: center; + border-top: 1px solid #e6e6e6; +} + +.footer:before { + content: ''; + position: absolute; + right: 0; + bottom: 0; + left: 0; + height: 50px; + overflow: hidden; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), + 0 8px 0 -3px #f6f6f6, + 0 9px 1px -3px rgba(0, 0, 0, 0.2), + 0 16px 0 -6px #f6f6f6, + 0 17px 2px -6px rgba(0, 0, 0, 0.2); +} + +.todo-count { + float: left; + text-align: left; +} + +.todo-count strong { + font-weight: 300; +} + +.filters { + margin: 0; + padding: 0; + list-style: none; + position: absolute; + right: 0; + left: 0; +} + +.filters li { + display: inline; +} + +.filters li a { + color: inherit; + margin: 3px; + padding: 3px 7px; + text-decoration: none; + border: 1px solid transparent; + border-radius: 3px; +} + +.filters li a.selected, +.filters li a:hover { + border-color: rgba(175, 47, 47, 0.1); +} + +.filters li a.selected { + border-color: rgba(175, 47, 47, 0.2); +} + +.clear-completed, +html .clear-completed:active { + float: right; + position: relative; + line-height: 20px; + text-decoration: none; + cursor: pointer; + position: relative; +} + +.clear-completed:hover { + text-decoration: underline; +} + +.info { + margin: 65px auto 0; + color: #bfbfbf; + /* font-size: 10px; */ + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + text-align: center; +} + +.info p { + line-height: 1; +} + +.info a { + color: inherit; + text-decoration: none; + font-weight: 400; +} + +.info a:hover { + text-decoration: underline; +} + +/* + Hack to remove background from Mobile Safari. + Can't use it globally since it destroys checkboxes in Firefox +*/ +@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 { + -webkit-transform: rotate(90deg); + transform: rotate(90deg); + -webkit-appearance: none; + appearance: none; + } +} + +@media (max-width: 430px) { + .footer { + height: 50px; + } + + .filters { + bottom: 10px; + } +} \ No newline at end of file diff --git a/bench/implementations/nim-karax-comp/karax.nimble b/bench/implementations/nim-karax-comp/karax.nimble new file mode 100644 index 0000000..be4879f --- /dev/null +++ b/bench/implementations/nim-karax-comp/karax.nimble @@ -0,0 +1,12 @@ +# Package + +version = "0.1.0" +author = "Araq" +description = "Karax is a framework for developing single page applications in Nim." +license = "MIT" + +# Dependencies + +requires "nim >= 0.16.1" + +skipDirs = @["examples/todoapp"] \ No newline at end of file diff --git a/bench/implementations/nim-karax-comp/readme.rst b/bench/implementations/nim-karax-comp/readme.rst new file mode 100644 index 0000000..907f016 --- /dev/null +++ b/bench/implementations/nim-karax-comp/readme.rst @@ -0,0 +1,38 @@ +Karax -- Single page applications in Nim +======================================== + +Karax is a framework for developing single page applications in Nim. +It's still in heavy development, so keep in mind that the API is subject +to change. + +To try it out, run:: + + nimble install # For first time + + cd examples/todoapp + nim js todoapp.nim + open todoapp.html + cd ../.. + + cd examples/mediaplayer + nim js playerapp.nim + open playerapp.html + +It uses a virtual DOM like React, but is much smaller than the existing +frameworks plus of course it's written in Nim for Nim. No external +dependencies! And thanks to Nim's whole program optimization only what +is used ends up in the generated JavaScript code. + + +Goals +===== + +- Leverage Nim's macro system to produce a framework that allows + for the development of applications that are boilerplate free. +- Keep it small, keep it fast, keep it flexible. + + +Todo +==== + +- Expose a nice API to do Ajax requests. diff --git a/bench/implementations/nim-karax-comp/src/components.nim b/bench/implementations/nim-karax-comp/src/components.nim new file mode 100644 index 0000000..b93742d --- /dev/null +++ b/bench/implementations/nim-karax-comp/src/components.nim @@ -0,0 +1,225 @@ +## Components in Karax are built by the ``.component`` macro annotation. + +import macros, jdict, dom, vdom, tables, strutils + +type + StateDict*[V] = ref object + defaultValue*: V + +proc get[V](d: StateDict[V], k: VKey): V {.importcpp: "#[#]".} +proc put[V](d: StateDict[V], k: VKey, v: V) {.importcpp: "#[#] = #".} + +proc contains*[V](d: StateDict[V], k: VKey): bool {.importcpp: "#.hasOwnProperty(#)".} +proc del*[V](d: StateDict[V], k: VKey) {.importcpp: "delete #[#]".} + +proc newStateDict*[V](): StateDict[V] {.importcpp: "{@}".} + +var + dirty = newStateDict[bool]() + someDirty*: bool + +proc markDirty*(key: VKey) = + dirty.put(key, true) + someDirty = true + +proc unmarkDirty*(key: VKey) = dirty.del key +proc isDirty*(key: VKey): bool = dirty.contains(key) + +proc `[]`*[V](d: StateDict[V], k: VKey): V = + if d.contains(k): result = d.get(k) + else: result = d.defaultValue + +proc `[]=`*[V](d: StateDict[V], k: VKey, v: V) = + d.put(k, v) + markDirty(k) + +var + vcomponents* = newJDict[cstring, proc(args: seq[VNode]): VNode]() + dcomponents* = newJDict[cstring, proc(args: seq[VNode]): Node]() + +type + ComponentKind* {.pure.} = enum + None, + Tag, + VNode, + Node + +var + allcomponents {.compileTime.} = initTable[string, ComponentKind]() + +proc isComponent*(x: string): ComponentKind {.compileTime.} = + allcomponents.getOrDefault(x) + +proc addTags() {.compileTime.} = + let x = (bindSym"VNodeKind").getTypeImpl + expectKind(x, nnkEnumTy) + for i in ord(VNodeKind.html)..ord(VNodeKind.high): + # +1 because of empty node at the start of the enum AST: + let tag = $x[i+1] + allcomponents[tag] = ComponentKind.Tag + +static: + addTags() + + +template toState(x): untyped = newIdentNode("state" & x) +proc accessState(sv: NimNode): NimNode {.compileTime.} = + newTree(nnkBracketExpr, sv, newIdentNode("key")) + +proc stateDecl(n: NimNode; names: TableRef[string, bool]; decl: NimNode) = + case n.kind + of nnkVarSection, nnkLetSection: + for c in n: + expectKind c, nnkIdentDefs + let typ = c[^2] + let val = c[^1] + let usedType = if typ.kind != nnkEmpty: typ else: newCall("type", val) + if usedType.kind == nnkEmpty: + error("cannot determine the variable's type", c) + for i in 0 .. c.len-3: + let v = $c[i] + let sv = toState v + decl.add quote do: + var `sv` = newStateDict[`usedType`]() + if val.kind != nnkEmpty: + decl.add newTree(nnkAsgn, newDotExpr(sv, newIdentNode"defaultValue"), + val) + else: + error("component state must have a primitive initializer") + names[v] = true + of nnkStmtList, nnkStmtListExpr: + for x in n: stateDecl(x, names, decl) + of nnkDo: + stateDecl(n.body, names, decl) + of nnkCommentStmt: discard + else: + error("invalid 'state' declaration", n) + +proc doState(n: NimNode; names: TableRef[string, bool]; + decl: NimNode): NimNode = + case n.kind + of nnkCallKinds: + # handle 'state' declaration and remove it from the AST: + if n.len == 2 and repr(n[0]) == "state": + stateDecl(n[1], names, decl) + return nil #newTree(nnkEmpty) + of nnkSym, nnkIdent: + let v = $n + if v in names: + let sv = toState v + return accessState(sv) + else: discard + result = copyNimNode(n) + for i in 0..`_. + +when not defined(js) and not defined(Nimdoc): + {.error: "This module only works on the JavaScript platform".} + +type + EventTarget* = ref EventTargetObj + EventTargetObj {.importc.} = object of RootObj + onabort*: proc (event: Event) {.nimcall.} + onblur*: proc (event: Event) {.nimcall.} + onchange*: proc (event: Event) {.nimcall.} + onclick*: proc (event: Event) {.nimcall.} + ondblclick*: proc (event: Event) {.nimcall.} + onerror*: proc (event: Event) {.nimcall.} + onfocus*: proc (event: Event) {.nimcall.} + onkeydown*: proc (event: Event) {.nimcall.} + onkeypress*: proc (event: Event) {.nimcall.} + onkeyup*: proc (event: Event) {.nimcall.} + onload*: proc (event: Event) {.nimcall.} + onmousedown*: proc (event: Event) {.nimcall.} + onmousemove*: proc (event: Event) {.nimcall.} + onmouseout*: proc (event: Event) {.nimcall.} + onmouseover*: proc (event: Event) {.nimcall.} + onmouseup*: proc (event: Event) {.nimcall.} + onreset*: proc (event: Event) {.nimcall.} + onselect*: proc (event: Event) {.nimcall.} + onsubmit*: proc (event: Event) {.nimcall.} + onunload*: proc (event: Event) {.nimcall.} + + Window* = ref WindowObj + WindowObj {.importc.} = object of EventTargetObj + document*: Document + event*: Event + history*: History + location*: Location + closed*: bool + defaultStatus*: cstring + innerHeight*, innerWidth*: int + locationbar*: ref LocationBar + menubar*: ref MenuBar + name*: cstring + outerHeight*, outerWidth*: int + pageXOffset*, pageYOffset*: int + personalbar*: ref PersonalBar + scrollbars*: ref ScrollBars + statusbar*: ref StatusBar + status*: cstring + toolbar*: ref ToolBar + frames*: seq[Frame] + + Frame* = ref FrameObj + FrameObj {.importc.} = object of WindowObj + + ClassList* = ref ClassListObj + ClassListObj {.importc.} = object of RootObj + + NodeType* = enum + ElementNode = 1, + AttributeNode, + TextNode, + CDATANode, + EntityRefNode, + EntityNode, + ProcessingInstructionNode, + CommentNode, + DocumentNode, + DocumentTypeNode, + DocumentFragmentNode, + NotationNode + + Node* = ref NodeObj + NodeObj {.importc.} = object of EventTargetObj + attributes*: seq[Node] + childNodes*: seq[Node] + children*: seq[Node] + data*: cstring + firstChild*: Node + lastChild*: Node + nextSibling*: Node + nodeName*: cstring + nodeType*: NodeType + nodeValue*: cstring + parentNode*: Node + previousSibling*: Node + innerHTML*: cstring + style*: Style + + Document* = ref DocumentObj + DocumentObj {.importc.} = object of NodeObj + alinkColor*: cstring + bgColor*: cstring + body*: Element + charset*: cstring + cookie*: cstring + defaultCharset*: cstring + fgColor*: cstring + head*: Element + lastModified*: cstring + linkColor*: cstring + referrer*: cstring + title*: cstring + URL*: cstring + vlinkColor*: cstring + anchors*: seq[AnchorElement] + forms*: seq[FormElement] + images*: seq[ImageElement] + applets*: seq[Element] + embeds*: seq[EmbedElement] + links*: seq[LinkElement] + + Element* = ref ElementObj + ElementObj {.importc.} = object of NodeObj + classList*: Classlist + checked*: bool + defaultChecked*: bool + defaultValue*: cstring + disabled*: bool + form*: FormElement + name*: cstring + readOnly*: bool + options*: seq[OptionElement] + + # https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement + HtmlElement* = ref object of Element + contentEditable*: string + isContentEditable*: bool + dir*: string + offsetHeight*: int + offsetWidth*: int + offsetLeft*: int + offsetTop*: int + + LinkElement* = ref LinkObj + LinkObj {.importc.} = object of ElementObj + target*: cstring + text*: cstring + x*: int + y*: int + + EmbedElement* = ref EmbedObj + EmbedObj {.importc.} = object of ElementObj + height*: int + hspace*: int + src*: cstring + width*: int + `type`*: cstring + vspace*: int + + AnchorElement* = ref AnchorObj + AnchorObj {.importc.} = object of ElementObj + text*: cstring + x*, y*: int + + OptionElement* = ref OptionObj + OptionObj {.importc.} = object of ElementObj + defaultSelected*: bool + selected*: bool + selectedIndex*: int + text*: cstring + value*: cstring + + FormElement* = ref FormObj + FormObj {.importc.} = object of ElementObj + action*: cstring + encoding*: cstring + `method`*: cstring + target*: cstring + elements*: seq[Element] + + ImageElement* = ref ImageObj + ImageObj {.importc.} = object of ElementObj + border*: int + complete*: bool + height*: int + hspace*: int + lowsrc*: cstring + src*: cstring + vspace*: int + width*: int + + Style = ref StyleObj + StyleObj {.importc.} = object of RootObj + background*: cstring + backgroundAttachment*: cstring + backgroundColor*: cstring + backgroundImage*: cstring + backgroundPosition*: cstring + backgroundRepeat*: cstring + border*: cstring + borderBottom*: cstring + borderBottomColor*: cstring + borderBottomStyle*: cstring + borderBottomWidth*: cstring + borderColor*: cstring + borderLeft*: cstring + borderLeftColor*: cstring + borderLeftStyle*: cstring + borderLeftWidth*: cstring + borderRight*: cstring + borderRightColor*: cstring + borderRightStyle*: cstring + borderRightWidth*: cstring + borderStyle*: cstring + borderTop*: cstring + borderTopColor*: cstring + borderTopStyle*: cstring + borderTopWidth*: cstring + borderWidth*: cstring + bottom*: cstring + captionSide*: cstring + clear*: cstring + clip*: cstring + color*: cstring + cursor*: cstring + direction*: cstring + display*: cstring + emptyCells*: cstring + cssFloat*: cstring + font*: cstring + fontFamily*: cstring + fontSize*: cstring + fontStretch*: cstring + fontStyle*: cstring + fontVariant*: cstring + fontWeight*: cstring + height*: cstring + left*: cstring + letterSpacing*: cstring + lineHeight*: cstring + listStyle*: cstring + listStyleImage*: cstring + listStylePosition*: cstring + listStyleType*: cstring + margin*: cstring + marginBottom*: cstring + marginLeft*: cstring + marginRight*: cstring + marginTop*: cstring + maxHeight*: cstring + maxWidth*: cstring + minHeight*: cstring + minWidth*: cstring + overflow*: cstring + padding*: cstring + paddingBottom*: cstring + paddingLeft*: cstring + paddingRight*: cstring + paddingTop*: cstring + pageBreakAfter*: cstring + pageBreakBefore*: cstring + position*: cstring + right*: cstring + scrollbar3dLightColor*: cstring + scrollbarArrowColor*: cstring + scrollbarBaseColor*: cstring + scrollbarDarkshadowColor*: cstring + scrollbarFaceColor*: cstring + scrollbarHighlightColor*: cstring + scrollbarShadowColor*: cstring + scrollbarTrackColor*: cstring + tableLayout*: cstring + textAlign*: cstring + textDecoration*: cstring + textIndent*: cstring + textTransform*: cstring + top*: cstring + verticalAlign*: cstring + visibility*: cstring + width*: cstring + wordSpacing*: cstring + zIndex*: int + + # TODO: A lot of the fields in Event belong to a more specific type of event. + # TODO: Should we clean this up? + Event* = ref EventObj + EventObj {.importc.} = object of RootObj + target*: Node + altKey*, ctrlKey*, shiftKey*: bool + button*: int + clientX*, clientY*: int + keyCode*: int + layerX*, layerY*: int + modifiers*: int + ALT_MASK*, CONTROL_MASK*, SHIFT_MASK*, META_MASK*: int + offsetX*, offsetY*: int + pageX*, pageY*: int + screenX*, screenY*: int + which*: int + `type`*: cstring + x*, y*: int + ABORT*: int + BLUR*: int + CHANGE*: int + CLICK*: int + DBLCLICK*: int + DRAGDROP*: int + ERROR*: int + FOCUS*: int + KEYDOWN*: int + KEYPRESS*: int + KEYUP*: int + LOAD*: int + MOUSEDOWN*: int + MOUSEMOVE*: int + MOUSEOUT*: int + MOUSEOVER*: int + MOUSEUP*: int + MOVE*: int + RESET*: int + RESIZE*: int + SELECT*: int + SUBMIT*: int + UNLOAD*: int + + TouchList* {.importc.} = ref object of RootObj + length*: int + + TouchEvent* {.importc.} = ref object of Event + changedTouches*, targetTouches*, touches*: TouchList + + Touch* {.importc.} = ref object of RootObj + identifier*: int + screenX*, screenY*, clientX*, clientY*, pageX*, pageY*: int + target*: Element + radiusX*, radiusY*: int + rotationAngle*: int + force*: float + + Location* = ref LocationObj + LocationObj {.importc.} = object of RootObj + hash*: cstring + host*: cstring + hostname*: cstring + href*: cstring + pathname*: cstring + port*: cstring + protocol*: cstring + search*: cstring + + History* = ref HistoryObj + HistoryObj {.importc.} = object of RootObj + length*: int + + Navigator* = ref NavigatorObj + NavigatorObj {.importc.} = object of RootObj + appCodeName*: cstring + appName*: cstring + appVersion*: cstring + cookieEnabled*: bool + language*: cstring + platform*: cstring + userAgent*: cstring + mimeTypes*: seq[ref MimeType] + + Plugin* {.importc.} = object of RootObj + description*: cstring + filename*: cstring + name*: cstring + + MimeType* {.importc.} = object of RootObj + description*: cstring + enabledPlugin*: ref Plugin + suffixes*: seq[cstring] + `type`*: cstring + + LocationBar* {.importc.} = object of RootObj + visible*: bool + MenuBar* = LocationBar + PersonalBar* = LocationBar + ScrollBars* = LocationBar + ToolBar* = LocationBar + StatusBar* = LocationBar + + Screen = ref ScreenObj + ScreenObj {.importc.} = object of RootObj + availHeight*: int + availWidth*: int + colorDepth*: int + height*: int + pixelDepth*: int + width*: int + + TimeOut* {.importc.} = ref object of RootObj + Interval* {.importc.} = object of RootObj + +proc len*(x: Node): int {.importcpp: "#.childNodes.length".} +proc `[]`*(x: Node; idx: int): Element {.importcpp: "#.childNodes[#]".} + +proc setTimeout*(action: proc(); ms: int): Timeout {.importc, nodecl.} +proc clearTimeout*(t: Timeout) {.importc, nodecl.} +proc getElementById*(id: cstring): Element {.importc: "document.getElementById", nodecl.} + +{.push importcpp.} + +# EventTarget "methods" +proc addEventListener*(et: EventTarget, ev: cstring, cb: proc(ev: Event), useCapture: bool = false) + +# Window "methods" +proc alert*(w: Window, msg: cstring) +proc back*(w: Window) +proc blur*(w: Window) +proc captureEvents*(w: Window, eventMask: int) {.deprecated.} +proc clearInterval*(w: Window, interval: ref Interval) +proc clearTimeout*(w: Window, timeout: TimeOut) +proc close*(w: Window) +proc confirm*(w: Window, msg: cstring): bool +proc disableExternalCapture*(w: Window) +proc enableExternalCapture*(w: Window) +proc find*(w: Window, text: cstring, caseSensitive = false, + backwards = false) +proc focus*(w: Window) +proc forward*(w: Window) +proc handleEvent*(w: Window, e: Event) +proc home*(w: Window) +proc moveBy*(w: Window, x, y: int) +proc moveTo*(w: Window, x, y: int) +proc open*(w: Window, uri, windowname: cstring, + properties: cstring = nil): Window +proc print*(w: Window) +proc prompt*(w: Window, text, default: cstring): cstring +proc releaseEvents*(w: Window, eventMask: int) {.deprecated.} +proc resizeBy*(w: Window, x, y: int) +proc resizeTo*(w: Window, x, y: int) +proc routeEvent*(w: Window, event: Event) +proc scrollBy*(w: Window, x, y: int) +proc scrollTo*(w: Window, x, y: int) +proc setInterval*(w: Window, code: cstring, pause: int): ref Interval +proc setInterval*(w: Window, function: proc (), pause: int): ref Interval +proc setTimeout*(w: Window, code: cstring, pause: int): TimeOut +proc setTimeout*(w: Window, function: proc (), pause: int): ref Interval +proc stop*(w: Window) +proc requestAnimationFrame*(w: Window, function: proc (time: float)): int +proc cancelAnimationFrame*(w: Window, id: int) + +# Node "methods" +proc appendChild*(n, child: Node) +proc appendData*(n: Node, data: cstring) +proc cloneNode*(n: Node, copyContent: bool): Node +proc deleteData*(n: Node, start, len: int) +proc getAttribute*(n: Node, attr: cstring): cstring +proc getAttributeNode*(n: Node, attr: cstring): Node +proc hasChildNodes*(n: Node): bool +proc insertBefore*(n, newNode, before: Node) +proc insertData*(n: Node, position: int, data: cstring) +proc removeAttribute*(n: Node, attr: cstring) +proc removeAttributeNode*(n, attr: Node) +proc removeChild*(n, child: Node) +proc replaceChild*(n, newNode, oldNode: Node) +proc replaceData*(n: Node, start, len: int, text: cstring) +proc scrollIntoView*(n: Node) +proc setAttribute*(n: Node, name, value: cstring) +proc setAttributeNode*(n: Node, attr: Node) + +# Document "methods" +proc captureEvents*(d: Document, eventMask: int) {.deprecated.} +proc createAttribute*(d: Document, identifier: cstring): Node +proc createElement*(d: Document, identifier: cstring): Element +proc createTextNode*(d: Document, identifier: cstring): Node +proc getElementById*(d: Document, id: cstring): Element +proc getElementsByName*(d: Document, name: cstring): seq[Element] +proc getElementsByTagName*(d: Document, name: cstring): seq[Element] +proc getElementsByClassName*(d: Document, name: cstring): seq[Element] +proc getSelection*(d: Document): cstring +proc handleEvent*(d: Document, event: Event) +proc open*(d: Document) +proc releaseEvents*(d: Document, eventMask: int) {.deprecated.} +proc routeEvent*(d: Document, event: Event) +proc write*(d: Document, text: cstring) +proc writeln*(d: Document, text: cstring) + +# Element "methods" +proc blur*(e: Element) +proc click*(e: Element) +proc focus*(e: Node) +proc handleEvent*(e: Element, event: Event) +proc select*(e: Element) +proc getElementsByTagName*(e: Element, name: cstring): seq[Element] +proc getElementsByClassName*(e: Element, name: cstring): seq[Element] + +# FormElement "methods" +proc reset*(f: FormElement) +proc submit*(f: FormElement) + +# EmbedElement "methods" +proc play*(e: EmbedElement) +proc stop*(e: EmbedElement) + +# Location "methods" +proc reload*(loc: Location) +proc replace*(loc: Location, s: cstring) + +# History "methods" +proc back*(h: History) +proc forward*(h: History) +proc go*(h: History, pagesToJump: int) + +# Navigator "methods" +proc javaEnabled*(h: Navigator): bool + +# ClassList "methods" +proc add*(c: ClassList, class: cstring) +proc remove*(c: ClassList, class: cstring) +proc contains*(c: ClassList, class: cstring):bool +proc toggle*(c: ClassList, class: cstring) + +# Style "methods" +proc getAttribute*(s: Style, attr: cstring, caseSensitive=false): cstring +proc removeAttribute*(s: Style, attr: cstring, caseSensitive=false) +proc setAttribute*(s: Style, attr, value: cstring, caseSensitive=false) + +# Event "methods" +proc preventDefault*(ev: Event) + +# TouchEvent "methods" +proc identifiedTouch*(list: TouchList): Touch +proc item*(list: TouchList, i: int): Touch + +{.pop.} + +proc setAttr*(n: Node; key, val: cstring) {.importcpp: "#.setAttribute(@)".} + +var + window* {.importc, nodecl.}: Window + document* {.importc, nodecl.}: Document + navigator* {.importc, nodecl.}: Navigator + screen* {.importc, nodecl.}: Screen + +proc decodeURI*(uri: cstring): cstring {.importc, nodecl.} +proc encodeURI*(uri: cstring): cstring {.importc, nodecl.} + +proc escape*(uri: cstring): cstring {.importc, nodecl.} +proc unescape*(uri: cstring): cstring {.importc, nodecl.} + +proc decodeURIComponent*(uri: cstring): cstring {.importc, nodecl.} +proc encodeURIComponent*(uri: cstring): cstring {.importc, nodecl.} +proc isFinite*(x: BiggestFloat): bool {.importc, nodecl.} +proc isNaN*(x: BiggestFloat): bool {.importc, nodecl.} +proc parseFloat*(s: cstring): BiggestFloat {.importc, nodecl.} +proc parseInt*(s: cstring): int {.importc, nodecl.} +proc parseInt*(s: cstring, radix: int):int {.importc, nodecl.} + + +proc id*(n: Node): cstring {.importcpp: "#.id", nodecl.} +proc `id=`*(n: Node; x: cstring) {.importcpp: "#.id = #", nodecl.} +proc class*(n: Node): cstring {.importcpp: "#.className", nodecl.} +proc `class=`*(n: Node; v: cstring) {.importcpp: "#.className = #", nodecl.} + +proc value*(n: Node): cstring {.importcpp: "#.value", nodecl.} +proc `value=`*(n: Node; v: cstring) {.importcpp: "#.value = #", nodecl.} + +proc `disabled=`*(n: Node; v: bool) {.importcpp: "#.disabled = #", nodecl.} + +proc getElementsByClass*(n: Node; name: cstring): seq[Node] {. + importcpp: "#.getElementsByClassName(#)", nodecl.} + + +type + BoundingRect* {.importc.} = object + top*, bottom*, left*, right*: int + +proc getBoundingClientRect*(e: Node): BoundingRect {. + importcpp: "getBoundingClientRect", nodecl.} +proc clientHeight*(): int {. + importcpp: "(window.innerHeight || document.documentElement.clientHeight)@", nodecl} +proc clientWidth*(): int {. + importcpp: "(window.innerWidth || document.documentElement.clientWidth)@", nodecl} + +proc inViewport*(el: Node): bool = + let rect = el.getBoundingClientRect() + result = rect.top >= 0 and rect.left >= 0 and + rect.bottom <= clientHeight() and + rect.right <= clientWidth() + +proc scrollTop*(e: Node): int {.importcpp: "#.scrollTop", nodecl.} +proc offsetHeight*(e: Node): int {.importcpp: "#.offsetHeight", nodecl.} +proc offsetTop*(e: Node): int {.importcpp: "#.offsetTop", nodecl.} diff --git a/bench/implementations/nim-karax-comp/src/jdict.nim b/bench/implementations/nim-karax-comp/src/jdict.nim new file mode 100644 index 0000000..0eecb58 --- /dev/null +++ b/bench/implementations/nim-karax-comp/src/jdict.nim @@ -0,0 +1,13 @@ + +type + JDict*[K, V] = ref object + +proc `[]`*[K, V](d: JDict[K, V], k: K): V {.importcpp: "#[#]".} +proc `[]=`*[K, V](d: JDict[K, V], k: K, v: V) {.importcpp: "#[#] = #".} + +proc newJDict*[K, V](): JDict[K, V] {.importcpp: "{@}".} + +proc contains*[K, V](d: JDict[K, V], k: K): bool {.importcpp: "#.hasOwnProperty(#)".} + +proc del*[K, V](d: JDict[K, V], k: K) {.importcpp: "delete #[#]".} + diff --git a/bench/implementations/nim-karax-comp/src/jstrutils.nim b/bench/implementations/nim-karax-comp/src/jstrutils.nim new file mode 100644 index 0000000..c69e2fa --- /dev/null +++ b/bench/implementations/nim-karax-comp/src/jstrutils.nim @@ -0,0 +1,23 @@ +# cstring handling utilities for performance + +proc split*(s, sep: cstring): seq[cstring] {.importcpp, nodecl.} + +proc split*(s, sep: cstring; max: int): seq[cstring] {.importcpp, nodecl.} + +proc startsWith*(a, b: cstring): bool {.importcpp: "startsWith", nodecl.} +proc contains*(a, b: cstring): bool {.importcpp: "(#.indexOf(#)>=0)", nodecl.} +proc substr*(s: cstring; start: int): cstring {.importcpp: "substr", nodecl.} +proc substr*(s: cstring; start, length: int): cstring {.importcpp: "substr", nodecl.} + +#proc len*(s: cstring): int {.importcpp: "#.length", nodecl.} +proc `&`*(a, b: cstring): cstring {.importcpp: "(# + #)", nodecl.} +proc toCstr*(s: int): cstring {.importcpp: "((#)+'')", nodecl.} +proc `&`*(s: int): cstring {.importcpp: "((#)+'')", nodecl.} +proc `&`*(s: bool): cstring {.importcpp: "((#)+'')", nodecl.} + +proc `&`*(s: cstring): cstring {.importcpp: "(#)", nodecl.} + +proc isInt*(s: cstring): bool {.asmNoStackFrame.} = + asm """ + return s.match(/^[0-9]+$/); + """ diff --git a/bench/implementations/nim-karax-comp/src/karax.nim b/bench/implementations/nim-karax-comp/src/karax.nim new file mode 100644 index 0000000..1908d6f --- /dev/null +++ b/bench/implementations/nim-karax-comp/src/karax.nim @@ -0,0 +1,345 @@ +## Karax -- Single page applications for Nim. + +import dom, vdom, jstrutils, components, jdict + +export dom.Event #, dom.cloneNode, dom + +proc kout*[T](x: T) {.importc: "console.log", varargs.} + ## the preferred way of debugging karax applications. + +proc hasProp(e: Node; prop: cstring): bool {.importcpp: "(#.hasOwnProperty(#))".} +proc rawkey(e: Node): VKey {.importcpp: "#.karaxKey", nodecl.} +proc key*(e: Node): VKey = + if e.hasProp"karaxKey": result = e.rawkey + else: result = -1 +proc `key=`*(e: Node; x: VKey) {.importcpp: "#.karaxKey = #", nodecl.} + +var + toFocus: Node + toFocusV: VNode + +proc setFocus*(n: VNode) = + toFocusV = n + +# ----------------- event wrapping --------------------------------------- + +template nativeValue(ev): cstring = cast[Element](ev.target).value +template setNativeValue(ev, val) = cast[Element](ev.target).value = val + +template keyeventBody() = + n.value = nativeValue(ev) + action(ev, n) + setNativeValue(ev, n.value) + # Do not call redraw() here! That is already done + # by ``karax.addEventHandler``. + +proc wrapEvent(d: Node; n: VNode; k: EventKind; action: EventHandler) = + proc stdWrapper(): (proc (ev: Event)) = + let action = action + let n = n + result = proc (ev: Event) = + action(ev, n) + + proc enterWrapper(): (proc (ev: Event)) = + let action = action + let n = n + result = proc (ev: Event) = + if ev.keyCode == 13: keyeventBody() + + proc laterWrapper(): (proc (ev: Event)) = + let action = action + let n = n + var timer: Timeout + result = proc (ev: Event) = + proc wrapper() = keyeventBody() + if timer != nil: clearTimeout(timer) + timer = setTimeout(wrapper, 400) + + case k + of EventKind.onkeyuplater: + d.addEventListener("keyup", laterWrapper()) + of EventKind.onkeyupenter: + d.addEventListener("keyup", enterWrapper()) + else: + d.addEventListener(toEventName[k], stdWrapper()) + +# --------------------- DOM diff ----------------------------------------- + +template detach(n: VNode) = n.dom = nil +template attach(n: Vnode) = n.dom = result + +proc vnodeToDom(n: VNode): Node = + if n.kind == VNodeKind.text: + result = document.createTextNode(n.text) + attach n + elif n.kind == VNodeKind.vthunk: + let x = callThunk(vcomponents[n.text], n) + result = vnodeToDom(x) + n.key = result.key + attach n + return result + elif n.kind == VNodeKind.dthunk: + result = callThunk(dcomponents[n.text], n) + n.key = result.key + attach n + return result + else: + result = document.createElement(toTag[n.kind]) + attach n + for k in n: + appendChild(result, vnodeToDom(k)) + # text is mapped to 'value': + if n.text != nil: + result.value = n.text + if n.id != nil: + result.id = n.id + if n.class != nil: + result.class = n.class + if n.key >= 0: + result.key = n.key + for k, v in attrs(n): + if v != nil: + result.setAttr(k, v) + for e, h in items(n.events): + wrapEvent(result, n, e, h) + if n == toFocusV and toFocus.isNil: + toFocus = result + +proc same(n: VNode, e: Node): bool = + if toTag[n.kind] == e.nodename: + result = true + if n.kind != VNodeKind.text: + if e.len != n.len: return false + for i in 0 ..< n.len: + if not same(n[i], e[i]): return false + +var + dorender: proc (): VNode {.closure.} + currentTree: VNode + +proc replaceById(id: cstring; newTree: Node) = + let x = document.getElementById(id) + x.parentNode.replaceChild(newTree, x) + #newTree.id = id + +proc equalsShallow(a, b: VNode): bool = + if a.kind != b.kind: return false + if a.id != b.id: return false + if a.key != b.key: return false + if a.kind == VNodeKind.text: + if a.text != b.text: return false + elif a.kind == VNodeKind.vthunk or a.kind == VNodeKind.dthunk: + if a.text != b.text: return false + if a.len != b.len: return false + for i in 0..= 0 and isDirty(newNode.key): + unmarkDirty(newNode.key) + let n = vnodeToDom(newNode) + if parent == nil: + replaceById("ROOT", n) + else: + parent.replaceChild(n, current) + elif newNode.kind != VNodeKind.text and newNode.kind != VNodeKind.vthunk and + newNode.kind != VNodeKind.dthunk: + for i in 0..newNode.len-1: + updateDirtyElements(current, current[i], newNode[i]) + # leave early if we know there cannot be anything left to do: + #if dirtyCount <= 0: return + +proc updateElement(parent, current: Node, newNode, oldNode: VNode) = + if not equalsShallow(newNode, oldNode): + detach(oldNode) + let n = vnodeToDom(newNode) + if parent == nil: + replaceById("ROOT", n) + else: + parent.replaceChild(n, current) + elif newNode.kind != VNodeKind.text: + let newLength = newNode.len + var oldLength = oldNode.len + let minLength = min(newLength, oldLength) + assert oldNode.kind == newNode.kind + when defined(simpleDiff): + for i in 0..min(newLength, oldLength)-1: + updateElement(current, current[i], newNode[i], oldNode[i]) + if newLength > oldLength: + for i in oldLength..newLength-1: + current.appendChild(vnodeToDom(newNode[i])) + elif oldLength > newLength: + for i in countdown(oldLength-1, newLength): + detach(oldNode[i]) + current.removeChild(current.lastChild) + else: + var commonPrefix = 0 + while commonPrefix < minLength and + equalsTree(newNode[commonPrefix], oldNode[commonPrefix]): + inc commonPrefix + + var oldPos = oldLength - 1 + var newPos = newLength - 1 + while oldPos >= commonPrefix and newPos >= commonPrefix and + equalsTree(newNode[newPos], oldNode[oldPos]): + dec oldPos + dec newPos + + var pos = min(oldPos, newPos) + 1 + for i in commonPrefix..pos-1: + updateElement(current, current.childNodes[i], newNode[i], oldNode[i]) + + var nextChildPos = oldPos + 1 + while pos <= newPos: + if nextChildPos == oldLength: + current.appendChild(vnodeToDom(newNode[pos])) + else: + current.insertBefore(vnodeToDom(newNode[pos]), current.childNodes[nextChildPos]) + # added new Node, so old state of VDOM have one more Node + inc oldLength + inc pos + inc nextChildPos + + for i in pos..oldPos: + detach(oldNode[i]) + current.removeChild(current.childNodes[pos]) + +when false: + var drawTimeout: Timeout + +proc dodraw() = + let newtree = dorender() + newtree.id = "ROOT" + toFocus = nil + if currentTree == nil: + currentTree = newtree + let asdom = vnodeToDom currentTree + replaceById("ROOT", asdom) + else: + let olddom = document.getElementById("ROOT") + updateElement(nil, olddom, newtree, currentTree) + #assert same(newtree, document.getElementById("ROOT")) + if someDirty: + updateDirtyElements(nil, olddom, newtree) + someDirty = false + currentTree = newtree + # now that it's part of the DOM, give it the focus: + if toFocus != nil: + toFocus.focus() + +proc reqFrame(callback: proc()) {.importc: "window.requestAnimationFrame".} + +proc redraw*() = + # we buffer redraw requests: + when false: + if drawTimeout != nil: + clearTimeout(drawTimeout) + drawTimeout = setTimeout(dodraw, 30) + elif true: + reqFrame(dodraw) + else: + dodraw() + +proc init(ev: Event) = + reqFrame(dodraw) + +proc setRenderer*(renderer: proc (): VNode) = + dorender = renderer + window.onload = init + +proc addEventHandler*(n: VNode; k: EventKind; action: EventHandler) = + ## Implements the foundation of Karax's event management. + ## Karax DSL transforms ``tag(onEvent = handler)`` to + ## ``tempNode.addEventHandler(tagNode, EventKind.onEvent, wrapper)`` + ## where ``wrapper`` calls the passed ``action`` and then triggers + ## a ``redraw``. + proc wrapper(ev: Event; n: VNode) = + action(ev, n) + redraw() + addEventListener(n, k, wrapper) + +proc setOnHashChange*(action: proc (hashPart: cstring)) = + var onhashChange {.importc: "window.onhashchange".}: proc() + var hashPart {.importc: "window.location.hash".}: cstring + proc wrapper() = + action(hashPart) + redraw() + onhashchange = wrapper + +proc ajax(meth, url: cstring; headers: openarray[(cstring, cstring)]; + data: cstring; + cont: proc (httpStatus: int; response: cstring)) = + proc setRequestHeader(a, b: cstring) {.importc: "ajax.setRequestHeader".} + {.emit: """ + var ajax = new XMLHttpRequest(); + ajax.open(`meth`,`url`,true);""".} + for a, b in items(headers): + setRequestHeader(a, b) + {.emit: """ + ajax.onreadystatechange = function(){ + if(this.readyState == 4){ + if(this.status == 200){ + `cont`(this.status, this.responseText); + } else { + `cont`(this.status, this.statusText); + } + } + } + ajax.send(`data`); + """.} + +proc ajaxPut*(url: string; headers: openarray[(cstring, cstring)]; + data: cstring; + cont: proc (httpStatus: int, response: cstring)) = + ajax("PUT", url, headers, data, cont) + +proc ajaxGet*(url: string; headers: openarray[(cstring, cstring)]; + cont: proc (httpStatus: int, response: cstring)) = + ajax("GET", url, headers, nil, cont) + +{.push stackTrace:off.} + +proc setupErrorHandler*(useAlert=false) = + ## Installs an error handler that transforms native JS unhandled + ## exceptions into Nim based stack traces. If `useAlert` is false, + ## the error message is put into the console, otherwise `alert` + ## is called. + proc stackTraceAsCstring(): cstring = cstring(getStackTrace()) + {.emit: """ + window.onerror = function(msg, url, line, col, error) { + var x = "Error: " + msg + "\n" + `stackTraceAsCstring`() + if (`useAlert`) + alert(x); + else + console.log(x); + var suppressErrorAlert = true; + return suppressErrorAlert; + };""".} + +{.pop.} + +proc prepend(parent, kid: Element) = + parent.insertBefore(kid, parent.firstChild) + +proc loadScript*(jsfilename: cstring) = + let body = getElementById("body") + let s = document.createElement("script") + s.setAttr "type", "text/javascript" + s.setAttr "src", jsfilename + body.prepend(s) + redraw() diff --git a/bench/implementations/nim-karax-comp/src/karaxdsl.nim b/bench/implementations/nim-karax-comp/src/karaxdsl.nim new file mode 100644 index 0000000..ade1c24 --- /dev/null +++ b/bench/implementations/nim-karax-comp/src/karaxdsl.nim @@ -0,0 +1,119 @@ + +import macros, karax, vdom, components +from strutils import startsWith, toLowerAscii + +const + StmtContext = ["kout", "inc", "echo", "dec", "!"] + SpecialAttrs = ["id", "class", "value", "key"] + +proc getName(n: NimNode): string = + case n.kind + of nnkIdent: + result = $n.ident + of nnkAccQuoted: + result = "" + for i in 0.. 0: + result[L-1] = tcall2(result[L-1], tmpContext) + of nnkStmtList, nnkStmtListExpr, nnkWhenStmt, nnkIfStmt, nnkCaseStmt, + nnkTryStmt, nnkFinally: + # recurse for every child: + result = copyNimNode(n) + for x in n: + result.add tcall2(x, tmpContext) + of nnkVarSection, nnkLetSection, nnkConstSection: + result = n + of nnkCallKinds: + let op = getName(n[0]) + let ck = isComponent(op) + if ck != ComponentKind.None: + let tmp = genSym(nskLet, "tmp") + let call = if ck == ComponentKind.Tag: + newCall(bindSym"tree", newDotExpr(bindSym"VNodeKind", n[0])) + elif ck == ComponentKind.VNode: + newCall(bindSym"vthunk", newLit(op)) + else: + newCall(bindSym"dthunk", newLit(op)) + result = newTree( + if tmpContext == nil: nnkStmtListExpr else: nnkStmtList, + newLetStmt(tmp, call)) + for i in 1 ..< n.len: + # named parameters are transformed into attributes or events: + let x = n[i] + if x.kind == nnkExprEqExpr: + let key = getName x[0] + if key.startsWith("on"): + result.add newCall(bindSym"addEventHandler", + tmp, newDotExpr(bindSym"EventKind", x[0]), x[1]) + elif key in SpecialAttrs: + result.add newDotAsgn(tmp, key, x[1]) + else: + result.add newCall(bindSym"setAttr", tmp, newLit(key), x[1]) + elif ck != ComponentKind.Tag: + call.add x + elif eqIdent(x, "setFocus"): + result.add newCall(x, tmp) + else: + result.add tcall2(x, tmp) + if tmpContext == nil: + result.add tmp + else: + result.add newCall(bindSym"add", tmpContext, tmp) + elif tmpContext != nil and op notin StmtContext: + result = newCall(bindSym"add", tmpContext, n) + elif op == "!" and n.len == 2: + result = n[1] + else: + result = n + else: + result = n + +macro buildHtml*(tag, children: untyped): VNode = + expectKind children, nnkDo + var call: NimNode + if tag.kind in nnkCallKinds: + call = tag + else: + call = newCall(tag) + call.add body(children) + result = tcall2(call, nil) + when defined(debugKaraxDsl): + echo repr result + +macro buildHtml*(children: untyped): VNode = + expectKind children, nnkDo + result = tcall2(body(children), nil) + when defined(debugKaraxDsl): + echo repr result diff --git a/bench/implementations/nim-karax-comp/src/karaxprelude.nim b/bench/implementations/nim-karax-comp/src/karaxprelude.nim new file mode 100644 index 0000000..285730a --- /dev/null +++ b/bench/implementations/nim-karax-comp/src/karaxprelude.nim @@ -0,0 +1,3 @@ +## Include file that contains the common imports for the Karax framework. + +import karax, karaxdsl, vdom, components diff --git a/bench/implementations/nim-karax-comp/src/shash.nim b/bench/implementations/nim-karax-comp/src/shash.nim new file mode 100644 index 0000000..c387e22 --- /dev/null +++ b/bench/implementations/nim-karax-comp/src/shash.nim @@ -0,0 +1,17 @@ +# Simple hashing for the JS target. + +type + Hash* = int + +{.push checks: off.} +proc sdbmHash(hash: Hash, c: int): Hash {.inline.} = + return Hash(c) + (hash shl 6) + (hash shl 16) - hash +{.pop.} + +proc charCodeAt(s: cstring; i: int): int {.importcpp: "#.charCodeAt(#)".} + +template `&=`*(x: var Hash, c: int) = x = sdbmHash(x, c) +template `&=`*(x: var Hash, s: cstring) = + for i in 0..\L" + if n.kind == VNodeKind.text: + result.add n.text + else: + if n.text != nil: + result.add " value = " + result.add n.text + for child in items(n): + toString(child, result, indent+2) + for i in 1..indent: result.add ' ' + result.add "\L" + +proc calcHash*(n: VNode) = + if n.validHash: return + n.validHash = true + var h: Hash = ord n.kind + if n.id != nil: + h &= "id" + h &= n.id + if n.class != nil: + h &= "class" + h &= n.class + if n.key >= 0: + h &= "k" + h &= n.key + for k, v in attrs(n): + h &= " " + h &= k + h &= "=" + h &= v + if n.kind == VNodeKind.text or n.text != nil: + h &= "t" + h &= n.text + else: + for child in items(n): + calcHash(child) + h &= child.hash + n.hash = h + +proc `$`*(n: VNode): cstring = + var res = "" + toString(n, res, 0) + result = cstring(res) diff --git a/bench/implementations/nim-karax-comp/tests/diffDomTests.html b/bench/implementations/nim-karax-comp/tests/diffDomTests.html new file mode 100644 index 0000000..5ecf130 --- /dev/null +++ b/bench/implementations/nim-karax-comp/tests/diffDomTests.html @@ -0,0 +1,19 @@ + + + + + Diff dom tests + + + + + +
    + + + + + + diff --git a/bench/implementations/nim-karax-comp/tests/diffDomTests.nim b/bench/implementations/nim-karax-comp/tests/diffDomTests.nim new file mode 100644 index 0000000..7fdcf85 --- /dev/null +++ b/bench/implementations/nim-karax-comp/tests/diffDomTests.nim @@ -0,0 +1,183 @@ + +import dom, vdom, times, karax, karaxdsl, jdict, jstrutils, parseutils, sequtils + +var + entries: seq[cstring] + results: seq[cstring] + timeout: Timeout + +proc reset() = + results.add cstring"reset started" + entries = @[cstring("0"), cstring("1"), cstring("2"), cstring("3"), cstring("4"), cstring("5") ] + redraw() + results.add cstring"reset finished" + +proc checkOrder(order : seq[int]): bool = + var ul = getElementById("ul") + if ul == nil or len(ul.children) != len(order): + return false + var pos = 0 + for child in ul.children: + if child.id != $order[pos]: + return false + inc pos + return true + +proc check1() = + let result = checkOrder(@[0, 1, 2, 3, 4, 7, 5]) + if result: + results.add cstring"test1 - OK" + else: + results.add cstring"test1 - FAIL" + +# result: 0 1 2 3 4 7 5 +proc test1() = + results.add cstring"test1 started" + entries = @[cstring("0"), cstring("1"), cstring("2"), cstring("3"), cstring("4"), cstring("5") ] + entries.insert(cstring("7"), 5) + redraw() + timeout = setTimeout(check1, 20) + +proc check2() = + let result = checkOrder(@[8, 0, 1, 2, 3, 4, 7, 5]) + if result: + results.add cstring"test1 - OK" + else: + results.add cstring"test2 - FAIL" + +# result: 8 0 1 2 3 4 7 5 +proc test2() = + results.add cstring"test2 started" + entries = @[cstring("0"), cstring("1"), cstring("2"), cstring("3"), cstring("4"), cstring("5") ] + entries.insert(cstring("7"), 5) + entries.insert(cstring("8"), 0) + redraw() + timeout = setTimeout(check2, 20) + +proc check3() = + let result = checkOrder(@[2, 3, 4, 1]) + if result: + results.add cstring"test3 - OK" + else: + results.add cstring"test3 - FAIL" + +# result: 2 3 4 1 +proc test3() = + results.add cstring"test3 started" + entries = @[cstring("2"), cstring("3"), cstring("4"), cstring("1") ] + redraw() + timeout = setTimeout(check3, 20) + +proc check4() = + let result = checkOrder(@[5, 6, 7, 8]) + if result: + results.add cstring"test4 - OK" + else: + results.add cstring"test4 - FAIL" + +# result: 5 6 7 8 +proc test4() = + results.add cstring"test4 started" + entries = @[cstring("5"), cstring("6"), cstring("7"), cstring("8") ] + redraw() + timeout = setTimeout(check4, 20) + +proc check5() = + let result = checkOrder(@[0, 1, 3, 5, 4, 5]) + if result: + results.add cstring"test5 - OK" + else: + results.add cstring"test5 - FAIL" + +# result: 0 1 3 5 4 5 +proc test5() = + results.add cstring"test5 started" + entries = @[cstring("0"), cstring("1"), cstring("3"), cstring("5"), cstring("4"), cstring("5") ] + redraw() + timeout = setTimeout(check5, 20) + +proc check6() = + let result = checkOrder(@[]) + if result: + results.add cstring"test6 - OK" + else: + results.add cstring"test6 - FAIL" + +# result: empty +proc test6() = + results.add cstring"test6 started" + entries = @[] + redraw() + timeout = setTimeout(check6, 20) + +proc check7() = + let result = checkOrder(@[2]) + if result: + results.add cstring"test7 - OK" + else: + results.add cstring"test7 - FAIL" + redraw() + +# result: 2 +proc test7() = + results.add cstring"test7 started" + entries = @[cstring("2")] + redraw() + timeout = setTimeout(check7, 20) + +proc createEntry(id: int): VNode = + result = buildHtml(): + button(id="" & $id): + text $id + +proc createDom(): VNode = + result = buildHtml(tdiv()): + ul(id="ul"): + for e in entries: + createEntry(parseInt(e)) + for r in results: + tdiv: + text r + +proc onload() = + for i in 0..5: # 0_000: + entries.add(cstring($i)) + + var dtReset = 100 + var dtTest = 500 + + var t = dtReset + timeout = setTimeout(test1, t) + t += dtTest + timeout = setTimeout(reset, t) + t += dtReset + + timeout = setTimeout(test2, t) + t += dtTest + timeout = setTimeout(reset, t) + t += dtReset + + timeout = setTimeout(test3, t) + t += dtTest + timeout = setTimeout(reset, t) + t += dtReset + + timeout = setTimeout(test4, t) + t += dtTest + timeout = setTimeout(reset, t) + t += dtReset + + timeout = setTimeout(test5, t) + t += dtTest + timeout = setTimeout(reset, t) + t += dtReset + + timeout = setTimeout(test6, t) + t += dtTest + timeout = setTimeout(reset, t) + t += dtReset + + timeout = setTimeout(test7, t) + +onload() +setRenderer createDom diff --git a/bench/implementations/nim-karax-comp/tests/diffDomTests.nims b/bench/implementations/nim-karax-comp/tests/diffDomTests.nims new file mode 100644 index 0000000..532b206 --- /dev/null +++ b/bench/implementations/nim-karax-comp/tests/diffDomTests.nims @@ -0,0 +1 @@ +--path: "../src" diff --git a/bench/implementations/nim-karax/docs/docs.rst b/bench/implementations/nim-karax/docs/docs.rst new file mode 100644 index 0000000..8298ba9 --- /dev/null +++ b/bench/implementations/nim-karax/docs/docs.rst @@ -0,0 +1,58 @@ + +Virtual DOM +=========== + +The virtual dom is in the ``vdom`` module. + +The ``VNodeKind`` enum describes every tag that the HTML 5 spec includes +and some extensions that allow for an efficient component system. + +These extensions are: + +``VNodeKind.int`` + The node havs a single integer field. + +``VNodeKind.bool`` + The node has a single boolean field. + +``VNodeKint.vthunk`` + The node is a `virtual thunk`:idx:. This means there is a + function attached to it that produces the ``VNode`` structure + on demand. + +``VNodeKint.dthunk`` + The node is a `DOM thunk`:idx:. This means there is a + function attached to it that produces the ``Node`` DOM structure + on demand. + +For convenience of the resulting Nim DSL these tags have enum names +that differ from their HTML equivalent: + +================= ======================================================= +Enum value HTML +================= ======================================================= +``tdiv`` ``div`` (changed because ``div`` is a keyword in Nim) +``italic`` ``i`` +``bold`` ``b`` +``strikethrough`` ``s`` +``underlined`` ``u`` +================= ======================================================= + + +A virtual dom node also has a special field set called ``key``, an integer +that can be used as a data model specific key/id. It can be accessed in event +handlers to change the data model. See the todoapp for an example of how to +use it. + +**Note**: This is not a hint for the DOM diff algorithm, multipe nodes can +all have the same key value. + + +Event system +============ + +Karax does not abstract over the event system the DOM offers much: The same +``Event`` structure is used. Every callback has the +signature ``proc (ev: Event; n: VNode)``. + + diff --git a/bench/implementations/nim-karax/examples/mediaplayer/mediaplayer.nim b/bench/implementations/nim-karax/examples/mediaplayer/mediaplayer.nim new file mode 100644 index 0000000..18179c1 --- /dev/null +++ b/bench/implementations/nim-karax/examples/mediaplayer/mediaplayer.nim @@ -0,0 +1,42 @@ + +import karax, karaxdsl, vdom, dom, components + +const + Play = 0 + Big = 1 + Small = 2 + Normal = 3 + +proc paused(n: Node): bool {.importcpp: "#.paused".} +proc play(n: Node) {.importcpp.} +proc pause(n: Node) {.importcpp.} +proc `width=`(n: Node, w: int) {.importcpp: "#.width = #".} + +proc mplayer*(id, resource: cstring): VNode {.component.} = + proc handler(ev: Event; n: VNode) = + let myVideo = document.getElementById(id) + case n.key + of Play: + if myVideo.paused: + myVideo.play() + else: + myVideo.pause() + of Big: myVideo.width = 560 + of Small: myVideo.width = 320 + of Normal: myVideo.width = 420 + else: discard + + result = buildHtml(tdiv): + button(onclick=handler, key=Play): + text "Play/Pause" + button(onclick=handler, key=Big): + text "Big" + button(onclick=handler, key=Small): + text "Small" + button(onclick=handler, key=Normal): + text "Normal" + br() + br() + video(id=id, width="420"): + source(src=resource, `type`="video/mp4"): + text "Your browser does not support HTML5 video." diff --git a/bench/implementations/nim-karax/examples/mediaplayer/playerapp.html b/bench/implementations/nim-karax/examples/mediaplayer/playerapp.html new file mode 100644 index 0000000..9e076e6 --- /dev/null +++ b/bench/implementations/nim-karax/examples/mediaplayer/playerapp.html @@ -0,0 +1,15 @@ + + + + + Player app + + + + +
    + + + + + diff --git a/bench/implementations/nim-karax/examples/mediaplayer/playerapp.nim b/bench/implementations/nim-karax/examples/mediaplayer/playerapp.nim new file mode 100644 index 0000000..e611eec --- /dev/null +++ b/bench/implementations/nim-karax/examples/mediaplayer/playerapp.nim @@ -0,0 +1,21 @@ +## Example app that shows how to write and embed a custom component. + +include karaxprelude +import mediaplayer + +const url = "https://www.w3schools.com/html/mov_bbb.mp4" + +proc createDom(): VNode = + result = buildHtml(table): + tr: + td: + mplayer("vid1", url) + td: + mplayer("vid2", url) + tr: + td: + mplayer("vid3", url) + td: + mplayer("vid4", url) + +setRenderer createDom diff --git a/bench/implementations/nim-karax/examples/mediaplayer/playerapp.nims b/bench/implementations/nim-karax/examples/mediaplayer/playerapp.nims new file mode 100644 index 0000000..9028ff1 --- /dev/null +++ b/bench/implementations/nim-karax/examples/mediaplayer/playerapp.nims @@ -0,0 +1 @@ +--path: "../../src" diff --git a/bench/implementations/nim-karax/examples/scrollapp/scrollapp.html b/bench/implementations/nim-karax/examples/scrollapp/scrollapp.html new file mode 100644 index 0000000..1ff8b1b --- /dev/null +++ b/bench/implementations/nim-karax/examples/scrollapp/scrollapp.html @@ -0,0 +1,15 @@ + + + + + Todo app + + + + +
    + + + + + diff --git a/bench/implementations/nim-karax/examples/scrollapp/scrollapp.nim b/bench/implementations/nim-karax/examples/scrollapp/scrollapp.nim new file mode 100644 index 0000000..e5ef9c1 --- /dev/null +++ b/bench/implementations/nim-karax/examples/scrollapp/scrollapp.nim @@ -0,0 +1,24 @@ +## Example that shows how to accomplish an "infinitely scrolling" app. + +include karaxprelude +import jstrutils, dom + +var entries: seq[cstring] = @[] +for i in 1..500: + entries.add(cstring("Entry ") & &i) + +proc scrollEvent(ev: Event; n: VNode) = + let d = n.dom + if d != nil and inViewport(d.lastChild): + # "load" more data: + for i in 1..50: + entries.add(cstring("Loaded Entry ") & &i) + +proc createDom(): VNode = + result = buildHtml(): + tdiv(onscroll=scrollEvent, style="height: 400px; overflow: scroll"): + for x in entries: + tdiv: + text x + +setRenderer createDom diff --git a/bench/implementations/nim-karax/examples/scrollapp/scrollapp.nims b/bench/implementations/nim-karax/examples/scrollapp/scrollapp.nims new file mode 100644 index 0000000..9028ff1 --- /dev/null +++ b/bench/implementations/nim-karax/examples/scrollapp/scrollapp.nims @@ -0,0 +1 @@ +--path: "../../src" diff --git a/bench/implementations/nim-karax/examples/todoapp/index.html b/bench/implementations/nim-karax/examples/todoapp/index.html new file mode 100644 index 0000000..488a3bf --- /dev/null +++ b/bench/implementations/nim-karax/examples/todoapp/index.html @@ -0,0 +1,16 @@ + + + + + Todo app + + + + + +
    + + + + + diff --git a/bench/implementations/nim-karax/examples/todoapp/style.css b/bench/implementations/nim-karax/examples/todoapp/style.css new file mode 100644 index 0000000..ceaf090 --- /dev/null +++ b/bench/implementations/nim-karax/examples/todoapp/style.css @@ -0,0 +1,378 @@ +html, +body { + margin: 0; + padding: 0; +} + +.todomvc-wrapper { + visibility: visible !important; +} + +button { + margin: 0; + padding: 0; + border: 0; + background: none; + font-size: 100%; + vertical-align: baseline; + font-family: inherit; + font-weight: inherit; + color: inherit; + -webkit-appearance: none; + appearance: none; + -webkit-font-smoothing: antialiased; + -moz-font-smoothing: antialiased; + font-smoothing: antialiased; +} + +body { + font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif; + line-height: 1.4em; + background: #f5f5f5; + color: #4d4d4d; + min-width: 230px; + max-width: 550px; + margin: 0 auto; + -webkit-font-smoothing: antialiased; + -moz-font-smoothing: antialiased; + font-smoothing: antialiased; + font-weight: 300; +} + +button, +input[type="checkbox"] { + outline: none; +} + +.hidden { + display: none; +} + +.todoapp { + background: #fff; + margin: 130px 0 40px 0; + position: relative; + box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), + 0 25px 50px 0 rgba(0, 0, 0, 0.1); +} + +.todoapp input::-webkit-input-placeholder { + font-style: italic; + font-weight: 300; + color: #e6e6e6; +} + +.todoapp input::-moz-placeholder { + font-style: italic; + font-weight: 300; + color: #e6e6e6; +} + +.todoapp input::input-placeholder { + font-style: italic; + font-weight: 300; + color: #e6e6e6; +} + +.todoapp h1 { + position: absolute; + top: -155px; + width: 100%; + font-size: 100px; + font-weight: 100; + text-align: center; + color: rgba(175, 47, 47, 0.15); + -webkit-text-rendering: optimizeLegibility; + -moz-text-rendering: optimizeLegibility; + text-rendering: optimizeLegibility; +} + +.new-todo, +.edit { + position: relative; + margin: 0; + width: 100%; + font-size: 24px; + font-family: inherit; + font-weight: 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); + box-sizing: border-box; + -webkit-font-smoothing: antialiased; + -moz-font-smoothing: antialiased; + font-smoothing: antialiased; +} + +.new-todo { + padding: 16px 16px 16px 60px; + border: none; + background: rgba(0, 0, 0, 0.003); + box-shadow: inset 0 -2px 1px rgba(0,0,0,0.03); +} + +.main { + position: relative; + z-index: 2; + border-top: 1px solid #e6e6e6; +} + +label[for='toggle-all'] { + display: none; +} + +.toggle-all { + position: absolute; + top: -55px; + left: -12px; + width: 60px; + height: 34px; + text-align: center; + border: none; /* Mobile Safari */ +} + +.toggle-all:before { + content: '>'; + font-size: 22px; + color: #e6e6e6; + padding: 10px 27px 10px 27px; +} + +.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 solid #ededed; +} + +.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; + appearance: none; +} + +.todo-list li .toggle:after { + content: url('data:image/svg+xml,'); +} + +.todo-list li .toggle:checked:after { + content: url('data:image/svg+xml,'); +} + +.todo-list li label { + white-space: pre-line; + word-break: break-all; + padding: 15px 60px 15px 15px; + margin-left: 45px; + display: block; + line-height: 1.2; + transition: color 0.4s; +} + +.todo-list li.completed label { + color: #d9d9d9; + 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: 30px; + color: #cc9a9a; + margin-bottom: 11px; + transition: color 0.2s ease-out; +} + +.todo-list li .destroy:hover { + color: #af5b5e; +} + +.todo-list li .destroy:after { + content: 'x'; +} + +.todo-list li:hover .destroy { + display: block; +} + +.todo-list li.editing:last-child { + margin-bottom: -1px; +} + +.footer { + color: #777; + padding: 10px 15px; + height: 20px; + text-align: center; + border-top: 1px solid #e6e6e6; +} + +.footer:before { + content: ''; + position: absolute; + right: 0; + bottom: 0; + left: 0; + height: 50px; + overflow: hidden; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), + 0 8px 0 -3px #f6f6f6, + 0 9px 1px -3px rgba(0, 0, 0, 0.2), + 0 16px 0 -6px #f6f6f6, + 0 17px 2px -6px rgba(0, 0, 0, 0.2); +} + +.todo-count { + float: left; + text-align: left; +} + +.todo-count strong { + font-weight: 300; +} + +.filters { + margin: 0; + padding: 0; + list-style: none; + position: absolute; + right: 0; + left: 0; +} + +.filters li { + display: inline; +} + +.filters li a { + color: inherit; + margin: 3px; + padding: 3px 7px; + text-decoration: none; + border: 1px solid transparent; + border-radius: 3px; +} + +.filters li a.selected, +.filters li a:hover { + border-color: rgba(175, 47, 47, 0.1); +} + +.filters li a.selected { + border-color: rgba(175, 47, 47, 0.2); +} + +.clear-completed, +html .clear-completed:active { + float: right; + position: relative; + line-height: 20px; + text-decoration: none; + cursor: pointer; + position: relative; +} + +.clear-completed:hover { + text-decoration: underline; +} + +.info { + margin: 65px auto 0; + color: #bfbfbf; + /* font-size: 10px; */ + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + text-align: center; +} + +.info p { + line-height: 1; +} + +.info a { + color: inherit; + text-decoration: none; + font-weight: 400; +} + +.info a:hover { + text-decoration: underline; +} + +/* + Hack to remove background from Mobile Safari. + Can't use it globally since it destroys checkboxes in Firefox +*/ +@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 { + -webkit-transform: rotate(90deg); + transform: rotate(90deg); + -webkit-appearance: none; + appearance: none; + } +} + +@media (max-width: 430px) { + .footer { + height: 50px; + } + + .filters { + bottom: 10px; + } +} \ No newline at end of file diff --git a/bench/implementations/nim-karax/examples/todoapp/todoapp.nim b/bench/implementations/nim-karax/examples/todoapp/todoapp.nim new file mode 100644 index 0000000..7fd6104 --- /dev/null +++ b/bench/implementations/nim-karax/examples/todoapp/todoapp.nim @@ -0,0 +1,119 @@ + +import vdom, karax, karaxdsl, jstrutils, components + +type + Filter = enum + all, active, completed + +var + entries: seq[(cstring, bool)] + selectedEntry = -1 + filter: Filter + +proc onTodoEnter(ev: Event; n: VNode) = + entries.add((n.value, false)) + n.value = "" + +proc removeHandler(ev: Event; n: VNode) = + entries[n.key] = (cstring(nil), false) + +proc editHandler(ev: Event; n: VNode) = + selectedEntry = n.key + +proc focusLost(ev: Event; n: VNode) = selectedEntry = -1 + +proc editEntry(ev: Event; n: VNode) = + entries[n.key][0] = n.value + selectedEntry = -1 + +proc toggleEntry(ev: Event; n: VNode) = + let id = n.key + entries[id][1] = not entries[id][1] + +proc onAllDone(ev: Event; n: VNode) = + entries = @[] + selectedEntry = -1 + +proc clearCompleted(ev: Event, n: VNode) = + for i in 0.. + + + + Todo app + + + + +
    + + + + + diff --git a/bench/implementations/nim-karax/experiments/example.nim b/bench/implementations/nim-karax/experiments/example.nim new file mode 100644 index 0000000..3fe4000 --- /dev/null +++ b/bench/implementations/nim-karax/experiments/example.nim @@ -0,0 +1,32 @@ + +import vdom, components, karax, karaxdsl, jdict, jstrutils + +var + images: seq[cstring] = @[cstring"a", "b", "c", "d"] + +proc carousel*(key: VKey): VNode {.component.} = + state: + var counter: int = 0 + + proc next(ev: Event; n: VNode) = + counter = (counter + 1) mod images.len + + result = buildHtml(tdiv(key=key)): + text images[counter] + button(onclick = next): + text "Next" + +proc createDom(): VNode = + result = buildHtml(table): + tr: + td: + carousel(0) + td: + carousel(1) + tr: + td: + carousel(2) + td: + carousel(3) + +setRenderer createDom diff --git a/bench/implementations/nim-karax/experiments/example.nims b/bench/implementations/nim-karax/experiments/example.nims new file mode 100644 index 0000000..532b206 --- /dev/null +++ b/bench/implementations/nim-karax/experiments/example.nims @@ -0,0 +1 @@ +--path: "../src" diff --git a/bench/implementations/nim-karax/experiments/oldwidgets.nim b/bench/implementations/nim-karax/experiments/oldwidgets.nim new file mode 100644 index 0000000..c947d7f --- /dev/null +++ b/bench/implementations/nim-karax/experiments/oldwidgets.nim @@ -0,0 +1,251 @@ +var + linkCounter: int + +proc link*(id: int): VNode = + result = newVNode(VNodeKind.anchor) + result.setAttr("href", "#") + inc linkCounter + result.setAttr("id", $linkCounter & ":" & $id) + +proc link*(action: EventHandler): VNode = + result = newVNode(VNodeKind.anchor) + result.setAttr("href", "#") + result.setOnclick action + +when false: + proc button*(caption: cstring; action: EventHandler; disabled=false): VNode = + result = newVNode(VNodeKind.button) + result.add text(caption) + if action != nil: + result.setOnClick action + if disabled: + result.setAttr("disabled", "true") + +proc select*(choices: openarray[cstring]): VNode = + result = newVNode(VNodeKind.select) + var i = 0 + for c in choices: + result.add tree(VNodeKind.option, [(cstring"value", toCstr(i))], text(c)) + inc i + +proc select*(choices: openarray[(int, cstring)]): VNode = + result = newVNode(VNodeKind.select) + for c in choices: + result.add tree(VNodeKind.option, [(cstring"value", toCstr(c[0]))], text(c[1])) + +var radioCounter: int + +proc radio*(choices: openarray[(int, cstring)]): VNode = + result = newVNode(VNodeKind.fieldset) + var i = 0 + inc radioCounter + for c in choices: + let id = cstring"radio_" & c[1] & toCstr(i) + var kid = tree(VNodeKind.input, [(cstring"type", cstring"radio"), + (cstring"id", id), (cstring"name", cstring"radio" & toCStr(radioCounter)), + (cstring"value", toCStr(c[0]))]) + if i == 0: + kid.setAttr(cstring"checked", cstring"checked") + var lab = tree(VNodeKind.label, [(cstring"for", id)], text(c[1])) + kid.add lab + result.add kid + inc i + +proc tag*(kind: VNodeKind; id=cstring(nil), class=cstring(nil)): VNode = + result = newVNode(kind) + result.id = id + result.class = class + +proc tdiv*(id=cstring(nil), class=cstring(nil)): VNode = tag(VNodeKind.tdiv, id, class) +proc span*(id=cstring(nil), class=cstring(nil)): VNode = tag(VNodeKind.span, id, class) + +proc valueAsInt*(e: Node): int = parseInt(e.value) + +proc th*(s: cstring): VNode = + result = newVNode(VNodeKind.th) + result.add text(s) + +proc td*(s: string): VNode = + result = newVNode(VNodeKind.td) + result.add text(s) + +proc td*(s: VNode): VNode = + result = newVNode(VNodeKind.td) + result.add s + +proc td*(class: cstring; s: VNode): VNode = + result = newVNode(VNodeKind.td) + result.add s + result.class = class + +proc table*(class=cstring(nil), kids: varargs[VNode]): VNode = + result = tag(VNodeKind.table, nil, class) + for k in kids: result.add k + +proc tr*(kids: varargs[VNode]): VNode = + result = newVNode(VNodeKind.tr) + for k in kids: + if k.kind in {VNodeKind.td, VNodeKind.th}: + result.add k + else: + result.add td(k) + +proc suffix*(s, prefix: cstring): cstring = + if s.startsWith(prefix): + result = s.substr(prefix.len) + else: + kout(cstring"bug! " & s & cstring" does not start with " & prefix) + +proc suffixAsInt*(s, prefix: cstring): int = parseInt(suffix(s, prefix)) + +#proc ceil(f: float): int {.importc: "Math.ceil", nodecl.} + +proc realtimeInput*(val: cstring; action: EventHandler): VNode = + var timer: Timeout + proc onkeyup(ev: Event; n: VNode) = + proc wrapper() = keyeventBody() + + if timer != nil: clearTimeout(timer) + timer = setTimeout(wrapper, 400) + result = tree(VNodeKind.input, [(cstring"type", cstring"text")]) + result.value = val + result.addEventListener(EventKind.onkeyup, onkeyup) + +proc enterInput*(id, val: cstring; action: EventHandler): VNode = + proc onkeyup(ev: Event; n: VNode) = + if ev.keyCode == 13: keyeventBody() + + result = tree(VNodeKind.input, [(cstring"type", cstring"text")]) + result.id = id + result.value = val + result.addEventListener(EventKind.onkeyup, onkeyup) + +proc setOnEnter*(n: VNode; action: EventHandler) = + proc onkeyup(ev: Event; n: VNode) = + if ev.keyCode == 13: keyeventBody() + n.addEventListener(EventKind.onkeyup, onkeyup) + +proc setOnscroll*(action: proc(min, max: VKey; diff: int)) = + var oldY = window.pageYOffset + + proc wrapper(ev: Event) = + let dir = window.pageYOffset - oldY + if dir == 0: return + + var a = VKey high(int) + var b = VKey 0 + var h, count: int + document.visibleKeys(a, b, h, count) + let avgh = h / count + let diff = toInt(dir.float / avgh) + if diff != 0: + oldY = window.pageYOffset + action(a, b, diff) + redraw() + + document.addEventListener("scroll", wrapper) + +when false: + var plugins {.exportc.}: seq[(string, proc())] = @[] + + proc onInput(val: cstring) = + kout val + if val == "dyn": + kout(plugins.len) + if plugins.len > 0: + plugins[0][1]() + +var + images: seq[cstring] = @[cstring"a", "b", "c", "d"] + +proc carousel*(): VNode = + var currentIndex = 0 + + proc next(ev: Event; n: VNode) = + currentIndex = (currentIndex + 1) mod images.len + + proc prev(ev: Event; n: VNode) = + currentIndex = (currentIndex - 1) mod images.len + + result = buildHtml(tdiv): + text images[currentIndex] + button(onclick = next): + text "Next" + button(onclick = prev): + text "Previous" + +#proc targetElem*(e: Event): Element = cast[Element](e.target) + +#proc getElementsByClassName*(cls: cstring): seq[Element] {.importc: +# "document.getElementsByClassName", nodecl.} +#proc textContent(e: Node): cstring {. +# importcpp: "#.textContent", nodecl.} + +proc isElementInViewport(el: Node; h: var int): bool = + let rect = el.getBoundingClientRect() + h = rect.bottom - rect.top + result = rect.top >= 0 and rect.left >= 0 and + rect.bottom <= clientHeight() and + rect.right <= clientWidth() + +proc visibleKeys(e: Node; a, b: var VKey; h, count: var int) = + # we only care about nodes that have a key: + var hh = 0 + # do not recurse if there is a 'key' field already: + if e.key >= 0: + if isElementInViewport(e, hh): + inc count + inc h, hh + a = min(a, e.key) + b = max(b, e.key) + else: + for i in 0.. + + + + Todo app + + + + + +
    + + + + + + diff --git a/bench/implementations/nim-karax/experiments/scrollapp.nim b/bench/implementations/nim-karax/experiments/scrollapp.nim new file mode 100644 index 0000000..f9c8ccb --- /dev/null +++ b/bench/implementations/nim-karax/experiments/scrollapp.nim @@ -0,0 +1,142 @@ + +import vdom, karax, karaxdsl, jdict, jstrutils, components + +type + Filter = enum + all, active, completed + +var + entries: seq[(cstring, bool)] + visibleA = 0 + visibleB = 10 + selectedEntry = -1 + filter: Filter + +proc onTodoEnter(ev: Event; n: VNode) = + entries.add((n.value, false)) + n.value = "" + +proc removeHandler(ev: Event; n: VNode) = + entries[n.key] = (cstring(nil), false) + +proc editHandler(ev: Event; n: VNode) = + selectedEntry = n.key + +proc focusLost(ev: Event; n: VNode) = selectedEntry = -1 + +proc editEntry(ev: Event; n: VNode) = + entries[n.key][0] = n.value + selectedEntry = -1 + +proc toggleEntry(ev: Event; n: VNode) = + let id = n.key + entries[id][1] = not entries[id][1] + +proc onAllDone(ev: Event; n: VNode) = + entries = @[] + selectedEntry = -1 + +proc clearCompleted(ev: Event, n: VNode) = + for i in 0.. 0: + # scroll downwards: + visibleA = max(a-overshoot2, 0) + visibleB = min(b+diff+overshoot1, entries.len-1) + elif diff < 0: + # scroll upwards: + visibleA = max(a+diff-overshoot1, 0) + visibleB = min(b+overshoot2, entries.len-1) + ) + +setOnHashChange(proc(hash: cstring) = + if hash == cstring"#/": filter = all + elif hash == cstring"#/completed": filter = completed + elif hash == cstring"#/active": filter = active +) +setRenderer createDom + +proc onload(session: cstring) {.exportc.} = + for i in 0..visibleB: + entries.add((cstring"Entry " & &i, false)) + init() diff --git a/bench/implementations/nim-karax/experiments/scrollapp.nims b/bench/implementations/nim-karax/experiments/scrollapp.nims new file mode 100644 index 0000000..532b206 --- /dev/null +++ b/bench/implementations/nim-karax/experiments/scrollapp.nims @@ -0,0 +1 @@ +--path: "../src" diff --git a/bench/implementations/nim-karax/experiments/style.css b/bench/implementations/nim-karax/experiments/style.css new file mode 100644 index 0000000..ceaf090 --- /dev/null +++ b/bench/implementations/nim-karax/experiments/style.css @@ -0,0 +1,378 @@ +html, +body { + margin: 0; + padding: 0; +} + +.todomvc-wrapper { + visibility: visible !important; +} + +button { + margin: 0; + padding: 0; + border: 0; + background: none; + font-size: 100%; + vertical-align: baseline; + font-family: inherit; + font-weight: inherit; + color: inherit; + -webkit-appearance: none; + appearance: none; + -webkit-font-smoothing: antialiased; + -moz-font-smoothing: antialiased; + font-smoothing: antialiased; +} + +body { + font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif; + line-height: 1.4em; + background: #f5f5f5; + color: #4d4d4d; + min-width: 230px; + max-width: 550px; + margin: 0 auto; + -webkit-font-smoothing: antialiased; + -moz-font-smoothing: antialiased; + font-smoothing: antialiased; + font-weight: 300; +} + +button, +input[type="checkbox"] { + outline: none; +} + +.hidden { + display: none; +} + +.todoapp { + background: #fff; + margin: 130px 0 40px 0; + position: relative; + box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), + 0 25px 50px 0 rgba(0, 0, 0, 0.1); +} + +.todoapp input::-webkit-input-placeholder { + font-style: italic; + font-weight: 300; + color: #e6e6e6; +} + +.todoapp input::-moz-placeholder { + font-style: italic; + font-weight: 300; + color: #e6e6e6; +} + +.todoapp input::input-placeholder { + font-style: italic; + font-weight: 300; + color: #e6e6e6; +} + +.todoapp h1 { + position: absolute; + top: -155px; + width: 100%; + font-size: 100px; + font-weight: 100; + text-align: center; + color: rgba(175, 47, 47, 0.15); + -webkit-text-rendering: optimizeLegibility; + -moz-text-rendering: optimizeLegibility; + text-rendering: optimizeLegibility; +} + +.new-todo, +.edit { + position: relative; + margin: 0; + width: 100%; + font-size: 24px; + font-family: inherit; + font-weight: 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); + box-sizing: border-box; + -webkit-font-smoothing: antialiased; + -moz-font-smoothing: antialiased; + font-smoothing: antialiased; +} + +.new-todo { + padding: 16px 16px 16px 60px; + border: none; + background: rgba(0, 0, 0, 0.003); + box-shadow: inset 0 -2px 1px rgba(0,0,0,0.03); +} + +.main { + position: relative; + z-index: 2; + border-top: 1px solid #e6e6e6; +} + +label[for='toggle-all'] { + display: none; +} + +.toggle-all { + position: absolute; + top: -55px; + left: -12px; + width: 60px; + height: 34px; + text-align: center; + border: none; /* Mobile Safari */ +} + +.toggle-all:before { + content: '>'; + font-size: 22px; + color: #e6e6e6; + padding: 10px 27px 10px 27px; +} + +.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 solid #ededed; +} + +.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; + appearance: none; +} + +.todo-list li .toggle:after { + content: url('data:image/svg+xml,'); +} + +.todo-list li .toggle:checked:after { + content: url('data:image/svg+xml,'); +} + +.todo-list li label { + white-space: pre-line; + word-break: break-all; + padding: 15px 60px 15px 15px; + margin-left: 45px; + display: block; + line-height: 1.2; + transition: color 0.4s; +} + +.todo-list li.completed label { + color: #d9d9d9; + 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: 30px; + color: #cc9a9a; + margin-bottom: 11px; + transition: color 0.2s ease-out; +} + +.todo-list li .destroy:hover { + color: #af5b5e; +} + +.todo-list li .destroy:after { + content: 'x'; +} + +.todo-list li:hover .destroy { + display: block; +} + +.todo-list li.editing:last-child { + margin-bottom: -1px; +} + +.footer { + color: #777; + padding: 10px 15px; + height: 20px; + text-align: center; + border-top: 1px solid #e6e6e6; +} + +.footer:before { + content: ''; + position: absolute; + right: 0; + bottom: 0; + left: 0; + height: 50px; + overflow: hidden; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), + 0 8px 0 -3px #f6f6f6, + 0 9px 1px -3px rgba(0, 0, 0, 0.2), + 0 16px 0 -6px #f6f6f6, + 0 17px 2px -6px rgba(0, 0, 0, 0.2); +} + +.todo-count { + float: left; + text-align: left; +} + +.todo-count strong { + font-weight: 300; +} + +.filters { + margin: 0; + padding: 0; + list-style: none; + position: absolute; + right: 0; + left: 0; +} + +.filters li { + display: inline; +} + +.filters li a { + color: inherit; + margin: 3px; + padding: 3px 7px; + text-decoration: none; + border: 1px solid transparent; + border-radius: 3px; +} + +.filters li a.selected, +.filters li a:hover { + border-color: rgba(175, 47, 47, 0.1); +} + +.filters li a.selected { + border-color: rgba(175, 47, 47, 0.2); +} + +.clear-completed, +html .clear-completed:active { + float: right; + position: relative; + line-height: 20px; + text-decoration: none; + cursor: pointer; + position: relative; +} + +.clear-completed:hover { + text-decoration: underline; +} + +.info { + margin: 65px auto 0; + color: #bfbfbf; + /* font-size: 10px; */ + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + text-align: center; +} + +.info p { + line-height: 1; +} + +.info a { + color: inherit; + text-decoration: none; + font-weight: 400; +} + +.info a:hover { + text-decoration: underline; +} + +/* + Hack to remove background from Mobile Safari. + Can't use it globally since it destroys checkboxes in Firefox +*/ +@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 { + -webkit-transform: rotate(90deg); + transform: rotate(90deg); + -webkit-appearance: none; + appearance: none; + } +} + +@media (max-width: 430px) { + .footer { + height: 50px; + } + + .filters { + bottom: 10px; + } +} \ No newline at end of file diff --git a/bench/implementations/nim-karax/karax.nimble b/bench/implementations/nim-karax/karax.nimble new file mode 100644 index 0000000..be4879f --- /dev/null +++ b/bench/implementations/nim-karax/karax.nimble @@ -0,0 +1,12 @@ +# Package + +version = "0.1.0" +author = "Araq" +description = "Karax is a framework for developing single page applications in Nim." +license = "MIT" + +# Dependencies + +requires "nim >= 0.16.1" + +skipDirs = @["examples/todoapp"] \ No newline at end of file diff --git a/bench/implementations/nim-karax/readme.rst b/bench/implementations/nim-karax/readme.rst new file mode 100644 index 0000000..907f016 --- /dev/null +++ b/bench/implementations/nim-karax/readme.rst @@ -0,0 +1,38 @@ +Karax -- Single page applications in Nim +======================================== + +Karax is a framework for developing single page applications in Nim. +It's still in heavy development, so keep in mind that the API is subject +to change. + +To try it out, run:: + + nimble install # For first time + + cd examples/todoapp + nim js todoapp.nim + open todoapp.html + cd ../.. + + cd examples/mediaplayer + nim js playerapp.nim + open playerapp.html + +It uses a virtual DOM like React, but is much smaller than the existing +frameworks plus of course it's written in Nim for Nim. No external +dependencies! And thanks to Nim's whole program optimization only what +is used ends up in the generated JavaScript code. + + +Goals +===== + +- Leverage Nim's macro system to produce a framework that allows + for the development of applications that are boilerplate free. +- Keep it small, keep it fast, keep it flexible. + + +Todo +==== + +- Expose a nice API to do Ajax requests. diff --git a/bench/implementations/nim-karax/src/components.nim b/bench/implementations/nim-karax/src/components.nim new file mode 100644 index 0000000..b93742d --- /dev/null +++ b/bench/implementations/nim-karax/src/components.nim @@ -0,0 +1,225 @@ +## Components in Karax are built by the ``.component`` macro annotation. + +import macros, jdict, dom, vdom, tables, strutils + +type + StateDict*[V] = ref object + defaultValue*: V + +proc get[V](d: StateDict[V], k: VKey): V {.importcpp: "#[#]".} +proc put[V](d: StateDict[V], k: VKey, v: V) {.importcpp: "#[#] = #".} + +proc contains*[V](d: StateDict[V], k: VKey): bool {.importcpp: "#.hasOwnProperty(#)".} +proc del*[V](d: StateDict[V], k: VKey) {.importcpp: "delete #[#]".} + +proc newStateDict*[V](): StateDict[V] {.importcpp: "{@}".} + +var + dirty = newStateDict[bool]() + someDirty*: bool + +proc markDirty*(key: VKey) = + dirty.put(key, true) + someDirty = true + +proc unmarkDirty*(key: VKey) = dirty.del key +proc isDirty*(key: VKey): bool = dirty.contains(key) + +proc `[]`*[V](d: StateDict[V], k: VKey): V = + if d.contains(k): result = d.get(k) + else: result = d.defaultValue + +proc `[]=`*[V](d: StateDict[V], k: VKey, v: V) = + d.put(k, v) + markDirty(k) + +var + vcomponents* = newJDict[cstring, proc(args: seq[VNode]): VNode]() + dcomponents* = newJDict[cstring, proc(args: seq[VNode]): Node]() + +type + ComponentKind* {.pure.} = enum + None, + Tag, + VNode, + Node + +var + allcomponents {.compileTime.} = initTable[string, ComponentKind]() + +proc isComponent*(x: string): ComponentKind {.compileTime.} = + allcomponents.getOrDefault(x) + +proc addTags() {.compileTime.} = + let x = (bindSym"VNodeKind").getTypeImpl + expectKind(x, nnkEnumTy) + for i in ord(VNodeKind.html)..ord(VNodeKind.high): + # +1 because of empty node at the start of the enum AST: + let tag = $x[i+1] + allcomponents[tag] = ComponentKind.Tag + +static: + addTags() + + +template toState(x): untyped = newIdentNode("state" & x) +proc accessState(sv: NimNode): NimNode {.compileTime.} = + newTree(nnkBracketExpr, sv, newIdentNode("key")) + +proc stateDecl(n: NimNode; names: TableRef[string, bool]; decl: NimNode) = + case n.kind + of nnkVarSection, nnkLetSection: + for c in n: + expectKind c, nnkIdentDefs + let typ = c[^2] + let val = c[^1] + let usedType = if typ.kind != nnkEmpty: typ else: newCall("type", val) + if usedType.kind == nnkEmpty: + error("cannot determine the variable's type", c) + for i in 0 .. c.len-3: + let v = $c[i] + let sv = toState v + decl.add quote do: + var `sv` = newStateDict[`usedType`]() + if val.kind != nnkEmpty: + decl.add newTree(nnkAsgn, newDotExpr(sv, newIdentNode"defaultValue"), + val) + else: + error("component state must have a primitive initializer") + names[v] = true + of nnkStmtList, nnkStmtListExpr: + for x in n: stateDecl(x, names, decl) + of nnkDo: + stateDecl(n.body, names, decl) + of nnkCommentStmt: discard + else: + error("invalid 'state' declaration", n) + +proc doState(n: NimNode; names: TableRef[string, bool]; + decl: NimNode): NimNode = + case n.kind + of nnkCallKinds: + # handle 'state' declaration and remove it from the AST: + if n.len == 2 and repr(n[0]) == "state": + stateDecl(n[1], names, decl) + return nil #newTree(nnkEmpty) + of nnkSym, nnkIdent: + let v = $n + if v in names: + let sv = toState v + return accessState(sv) + else: discard + result = copyNimNode(n) + for i in 0..`_. + +when not defined(js) and not defined(Nimdoc): + {.error: "This module only works on the JavaScript platform".} + +type + EventTarget* = ref EventTargetObj + EventTargetObj {.importc.} = object of RootObj + onabort*: proc (event: Event) {.nimcall.} + onblur*: proc (event: Event) {.nimcall.} + onchange*: proc (event: Event) {.nimcall.} + onclick*: proc (event: Event) {.nimcall.} + ondblclick*: proc (event: Event) {.nimcall.} + onerror*: proc (event: Event) {.nimcall.} + onfocus*: proc (event: Event) {.nimcall.} + onkeydown*: proc (event: Event) {.nimcall.} + onkeypress*: proc (event: Event) {.nimcall.} + onkeyup*: proc (event: Event) {.nimcall.} + onload*: proc (event: Event) {.nimcall.} + onmousedown*: proc (event: Event) {.nimcall.} + onmousemove*: proc (event: Event) {.nimcall.} + onmouseout*: proc (event: Event) {.nimcall.} + onmouseover*: proc (event: Event) {.nimcall.} + onmouseup*: proc (event: Event) {.nimcall.} + onreset*: proc (event: Event) {.nimcall.} + onselect*: proc (event: Event) {.nimcall.} + onsubmit*: proc (event: Event) {.nimcall.} + onunload*: proc (event: Event) {.nimcall.} + + Window* = ref WindowObj + WindowObj {.importc.} = object of EventTargetObj + document*: Document + event*: Event + history*: History + location*: Location + closed*: bool + defaultStatus*: cstring + innerHeight*, innerWidth*: int + locationbar*: ref LocationBar + menubar*: ref MenuBar + name*: cstring + outerHeight*, outerWidth*: int + pageXOffset*, pageYOffset*: int + personalbar*: ref PersonalBar + scrollbars*: ref ScrollBars + statusbar*: ref StatusBar + status*: cstring + toolbar*: ref ToolBar + frames*: seq[Frame] + + Frame* = ref FrameObj + FrameObj {.importc.} = object of WindowObj + + ClassList* = ref ClassListObj + ClassListObj {.importc.} = object of RootObj + + NodeType* = enum + ElementNode = 1, + AttributeNode, + TextNode, + CDATANode, + EntityRefNode, + EntityNode, + ProcessingInstructionNode, + CommentNode, + DocumentNode, + DocumentTypeNode, + DocumentFragmentNode, + NotationNode + + Node* = ref NodeObj + NodeObj {.importc.} = object of EventTargetObj + attributes*: seq[Node] + childNodes*: seq[Node] + children*: seq[Node] + data*: cstring + firstChild*: Node + lastChild*: Node + nextSibling*: Node + nodeName*: cstring + nodeType*: NodeType + nodeValue*: cstring + parentNode*: Node + previousSibling*: Node + innerHTML*: cstring + style*: Style + + Document* = ref DocumentObj + DocumentObj {.importc.} = object of NodeObj + alinkColor*: cstring + bgColor*: cstring + body*: Element + charset*: cstring + cookie*: cstring + defaultCharset*: cstring + fgColor*: cstring + head*: Element + lastModified*: cstring + linkColor*: cstring + referrer*: cstring + title*: cstring + URL*: cstring + vlinkColor*: cstring + anchors*: seq[AnchorElement] + forms*: seq[FormElement] + images*: seq[ImageElement] + applets*: seq[Element] + embeds*: seq[EmbedElement] + links*: seq[LinkElement] + + Element* = ref ElementObj + ElementObj {.importc.} = object of NodeObj + classList*: Classlist + checked*: bool + defaultChecked*: bool + defaultValue*: cstring + disabled*: bool + form*: FormElement + name*: cstring + readOnly*: bool + options*: seq[OptionElement] + + # https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement + HtmlElement* = ref object of Element + contentEditable*: string + isContentEditable*: bool + dir*: string + offsetHeight*: int + offsetWidth*: int + offsetLeft*: int + offsetTop*: int + + LinkElement* = ref LinkObj + LinkObj {.importc.} = object of ElementObj + target*: cstring + text*: cstring + x*: int + y*: int + + EmbedElement* = ref EmbedObj + EmbedObj {.importc.} = object of ElementObj + height*: int + hspace*: int + src*: cstring + width*: int + `type`*: cstring + vspace*: int + + AnchorElement* = ref AnchorObj + AnchorObj {.importc.} = object of ElementObj + text*: cstring + x*, y*: int + + OptionElement* = ref OptionObj + OptionObj {.importc.} = object of ElementObj + defaultSelected*: bool + selected*: bool + selectedIndex*: int + text*: cstring + value*: cstring + + FormElement* = ref FormObj + FormObj {.importc.} = object of ElementObj + action*: cstring + encoding*: cstring + `method`*: cstring + target*: cstring + elements*: seq[Element] + + ImageElement* = ref ImageObj + ImageObj {.importc.} = object of ElementObj + border*: int + complete*: bool + height*: int + hspace*: int + lowsrc*: cstring + src*: cstring + vspace*: int + width*: int + + Style = ref StyleObj + StyleObj {.importc.} = object of RootObj + background*: cstring + backgroundAttachment*: cstring + backgroundColor*: cstring + backgroundImage*: cstring + backgroundPosition*: cstring + backgroundRepeat*: cstring + border*: cstring + borderBottom*: cstring + borderBottomColor*: cstring + borderBottomStyle*: cstring + borderBottomWidth*: cstring + borderColor*: cstring + borderLeft*: cstring + borderLeftColor*: cstring + borderLeftStyle*: cstring + borderLeftWidth*: cstring + borderRight*: cstring + borderRightColor*: cstring + borderRightStyle*: cstring + borderRightWidth*: cstring + borderStyle*: cstring + borderTop*: cstring + borderTopColor*: cstring + borderTopStyle*: cstring + borderTopWidth*: cstring + borderWidth*: cstring + bottom*: cstring + captionSide*: cstring + clear*: cstring + clip*: cstring + color*: cstring + cursor*: cstring + direction*: cstring + display*: cstring + emptyCells*: cstring + cssFloat*: cstring + font*: cstring + fontFamily*: cstring + fontSize*: cstring + fontStretch*: cstring + fontStyle*: cstring + fontVariant*: cstring + fontWeight*: cstring + height*: cstring + left*: cstring + letterSpacing*: cstring + lineHeight*: cstring + listStyle*: cstring + listStyleImage*: cstring + listStylePosition*: cstring + listStyleType*: cstring + margin*: cstring + marginBottom*: cstring + marginLeft*: cstring + marginRight*: cstring + marginTop*: cstring + maxHeight*: cstring + maxWidth*: cstring + minHeight*: cstring + minWidth*: cstring + overflow*: cstring + padding*: cstring + paddingBottom*: cstring + paddingLeft*: cstring + paddingRight*: cstring + paddingTop*: cstring + pageBreakAfter*: cstring + pageBreakBefore*: cstring + position*: cstring + right*: cstring + scrollbar3dLightColor*: cstring + scrollbarArrowColor*: cstring + scrollbarBaseColor*: cstring + scrollbarDarkshadowColor*: cstring + scrollbarFaceColor*: cstring + scrollbarHighlightColor*: cstring + scrollbarShadowColor*: cstring + scrollbarTrackColor*: cstring + tableLayout*: cstring + textAlign*: cstring + textDecoration*: cstring + textIndent*: cstring + textTransform*: cstring + top*: cstring + verticalAlign*: cstring + visibility*: cstring + width*: cstring + wordSpacing*: cstring + zIndex*: int + + # TODO: A lot of the fields in Event belong to a more specific type of event. + # TODO: Should we clean this up? + Event* = ref EventObj + EventObj {.importc.} = object of RootObj + target*: Node + altKey*, ctrlKey*, shiftKey*: bool + button*: int + clientX*, clientY*: int + keyCode*: int + layerX*, layerY*: int + modifiers*: int + ALT_MASK*, CONTROL_MASK*, SHIFT_MASK*, META_MASK*: int + offsetX*, offsetY*: int + pageX*, pageY*: int + screenX*, screenY*: int + which*: int + `type`*: cstring + x*, y*: int + ABORT*: int + BLUR*: int + CHANGE*: int + CLICK*: int + DBLCLICK*: int + DRAGDROP*: int + ERROR*: int + FOCUS*: int + KEYDOWN*: int + KEYPRESS*: int + KEYUP*: int + LOAD*: int + MOUSEDOWN*: int + MOUSEMOVE*: int + MOUSEOUT*: int + MOUSEOVER*: int + MOUSEUP*: int + MOVE*: int + RESET*: int + RESIZE*: int + SELECT*: int + SUBMIT*: int + UNLOAD*: int + + TouchList* {.importc.} = ref object of RootObj + length*: int + + TouchEvent* {.importc.} = ref object of Event + changedTouches*, targetTouches*, touches*: TouchList + + Touch* {.importc.} = ref object of RootObj + identifier*: int + screenX*, screenY*, clientX*, clientY*, pageX*, pageY*: int + target*: Element + radiusX*, radiusY*: int + rotationAngle*: int + force*: float + + Location* = ref LocationObj + LocationObj {.importc.} = object of RootObj + hash*: cstring + host*: cstring + hostname*: cstring + href*: cstring + pathname*: cstring + port*: cstring + protocol*: cstring + search*: cstring + + History* = ref HistoryObj + HistoryObj {.importc.} = object of RootObj + length*: int + + Navigator* = ref NavigatorObj + NavigatorObj {.importc.} = object of RootObj + appCodeName*: cstring + appName*: cstring + appVersion*: cstring + cookieEnabled*: bool + language*: cstring + platform*: cstring + userAgent*: cstring + mimeTypes*: seq[ref MimeType] + + Plugin* {.importc.} = object of RootObj + description*: cstring + filename*: cstring + name*: cstring + + MimeType* {.importc.} = object of RootObj + description*: cstring + enabledPlugin*: ref Plugin + suffixes*: seq[cstring] + `type`*: cstring + + LocationBar* {.importc.} = object of RootObj + visible*: bool + MenuBar* = LocationBar + PersonalBar* = LocationBar + ScrollBars* = LocationBar + ToolBar* = LocationBar + StatusBar* = LocationBar + + Screen = ref ScreenObj + ScreenObj {.importc.} = object of RootObj + availHeight*: int + availWidth*: int + colorDepth*: int + height*: int + pixelDepth*: int + width*: int + + TimeOut* {.importc.} = ref object of RootObj + Interval* {.importc.} = object of RootObj + +proc len*(x: Node): int {.importcpp: "#.childNodes.length".} +proc `[]`*(x: Node; idx: int): Element {.importcpp: "#.childNodes[#]".} + +proc setTimeout*(action: proc(); ms: int): Timeout {.importc, nodecl.} +proc clearTimeout*(t: Timeout) {.importc, nodecl.} +proc getElementById*(id: cstring): Element {.importc: "document.getElementById", nodecl.} + +{.push importcpp.} + +# EventTarget "methods" +proc addEventListener*(et: EventTarget, ev: cstring, cb: proc(ev: Event), useCapture: bool = false) + +# Window "methods" +proc alert*(w: Window, msg: cstring) +proc back*(w: Window) +proc blur*(w: Window) +proc captureEvents*(w: Window, eventMask: int) {.deprecated.} +proc clearInterval*(w: Window, interval: ref Interval) +proc clearTimeout*(w: Window, timeout: TimeOut) +proc close*(w: Window) +proc confirm*(w: Window, msg: cstring): bool +proc disableExternalCapture*(w: Window) +proc enableExternalCapture*(w: Window) +proc find*(w: Window, text: cstring, caseSensitive = false, + backwards = false) +proc focus*(w: Window) +proc forward*(w: Window) +proc handleEvent*(w: Window, e: Event) +proc home*(w: Window) +proc moveBy*(w: Window, x, y: int) +proc moveTo*(w: Window, x, y: int) +proc open*(w: Window, uri, windowname: cstring, + properties: cstring = nil): Window +proc print*(w: Window) +proc prompt*(w: Window, text, default: cstring): cstring +proc releaseEvents*(w: Window, eventMask: int) {.deprecated.} +proc resizeBy*(w: Window, x, y: int) +proc resizeTo*(w: Window, x, y: int) +proc routeEvent*(w: Window, event: Event) +proc scrollBy*(w: Window, x, y: int) +proc scrollTo*(w: Window, x, y: int) +proc setInterval*(w: Window, code: cstring, pause: int): ref Interval +proc setInterval*(w: Window, function: proc (), pause: int): ref Interval +proc setTimeout*(w: Window, code: cstring, pause: int): TimeOut +proc setTimeout*(w: Window, function: proc (), pause: int): ref Interval +proc stop*(w: Window) +proc requestAnimationFrame*(w: Window, function: proc (time: float)): int +proc cancelAnimationFrame*(w: Window, id: int) + +# Node "methods" +proc appendChild*(n, child: Node) +proc appendData*(n: Node, data: cstring) +proc cloneNode*(n: Node, copyContent: bool): Node +proc deleteData*(n: Node, start, len: int) +proc getAttribute*(n: Node, attr: cstring): cstring +proc getAttributeNode*(n: Node, attr: cstring): Node +proc hasChildNodes*(n: Node): bool +proc insertBefore*(n, newNode, before: Node) +proc insertData*(n: Node, position: int, data: cstring) +proc removeAttribute*(n: Node, attr: cstring) +proc removeAttributeNode*(n, attr: Node) +proc removeChild*(n, child: Node) +proc replaceChild*(n, newNode, oldNode: Node) +proc replaceData*(n: Node, start, len: int, text: cstring) +proc scrollIntoView*(n: Node) +proc setAttribute*(n: Node, name, value: cstring) +proc setAttributeNode*(n: Node, attr: Node) + +# Document "methods" +proc captureEvents*(d: Document, eventMask: int) {.deprecated.} +proc createAttribute*(d: Document, identifier: cstring): Node +proc createElement*(d: Document, identifier: cstring): Element +proc createTextNode*(d: Document, identifier: cstring): Node +proc getElementById*(d: Document, id: cstring): Element +proc getElementsByName*(d: Document, name: cstring): seq[Element] +proc getElementsByTagName*(d: Document, name: cstring): seq[Element] +proc getElementsByClassName*(d: Document, name: cstring): seq[Element] +proc getSelection*(d: Document): cstring +proc handleEvent*(d: Document, event: Event) +proc open*(d: Document) +proc releaseEvents*(d: Document, eventMask: int) {.deprecated.} +proc routeEvent*(d: Document, event: Event) +proc write*(d: Document, text: cstring) +proc writeln*(d: Document, text: cstring) + +# Element "methods" +proc blur*(e: Element) +proc click*(e: Element) +proc focus*(e: Node) +proc handleEvent*(e: Element, event: Event) +proc select*(e: Element) +proc getElementsByTagName*(e: Element, name: cstring): seq[Element] +proc getElementsByClassName*(e: Element, name: cstring): seq[Element] + +# FormElement "methods" +proc reset*(f: FormElement) +proc submit*(f: FormElement) + +# EmbedElement "methods" +proc play*(e: EmbedElement) +proc stop*(e: EmbedElement) + +# Location "methods" +proc reload*(loc: Location) +proc replace*(loc: Location, s: cstring) + +# History "methods" +proc back*(h: History) +proc forward*(h: History) +proc go*(h: History, pagesToJump: int) + +# Navigator "methods" +proc javaEnabled*(h: Navigator): bool + +# ClassList "methods" +proc add*(c: ClassList, class: cstring) +proc remove*(c: ClassList, class: cstring) +proc contains*(c: ClassList, class: cstring):bool +proc toggle*(c: ClassList, class: cstring) + +# Style "methods" +proc getAttribute*(s: Style, attr: cstring, caseSensitive=false): cstring +proc removeAttribute*(s: Style, attr: cstring, caseSensitive=false) +proc setAttribute*(s: Style, attr, value: cstring, caseSensitive=false) + +# Event "methods" +proc preventDefault*(ev: Event) + +# TouchEvent "methods" +proc identifiedTouch*(list: TouchList): Touch +proc item*(list: TouchList, i: int): Touch + +{.pop.} + +proc setAttr*(n: Node; key, val: cstring) {.importcpp: "#.setAttribute(@)".} + +var + window* {.importc, nodecl.}: Window + document* {.importc, nodecl.}: Document + navigator* {.importc, nodecl.}: Navigator + screen* {.importc, nodecl.}: Screen + +proc decodeURI*(uri: cstring): cstring {.importc, nodecl.} +proc encodeURI*(uri: cstring): cstring {.importc, nodecl.} + +proc escape*(uri: cstring): cstring {.importc, nodecl.} +proc unescape*(uri: cstring): cstring {.importc, nodecl.} + +proc decodeURIComponent*(uri: cstring): cstring {.importc, nodecl.} +proc encodeURIComponent*(uri: cstring): cstring {.importc, nodecl.} +proc isFinite*(x: BiggestFloat): bool {.importc, nodecl.} +proc isNaN*(x: BiggestFloat): bool {.importc, nodecl.} +proc parseFloat*(s: cstring): BiggestFloat {.importc, nodecl.} +proc parseInt*(s: cstring): int {.importc, nodecl.} +proc parseInt*(s: cstring, radix: int):int {.importc, nodecl.} + + +proc id*(n: Node): cstring {.importcpp: "#.id", nodecl.} +proc `id=`*(n: Node; x: cstring) {.importcpp: "#.id = #", nodecl.} +proc class*(n: Node): cstring {.importcpp: "#.className", nodecl.} +proc `class=`*(n: Node; v: cstring) {.importcpp: "#.className = #", nodecl.} + +proc value*(n: Node): cstring {.importcpp: "#.value", nodecl.} +proc `value=`*(n: Node; v: cstring) {.importcpp: "#.value = #", nodecl.} + +proc `disabled=`*(n: Node; v: bool) {.importcpp: "#.disabled = #", nodecl.} + +proc getElementsByClass*(n: Node; name: cstring): seq[Node] {. + importcpp: "#.getElementsByClassName(#)", nodecl.} + + +type + BoundingRect* {.importc.} = object + top*, bottom*, left*, right*: int + +proc getBoundingClientRect*(e: Node): BoundingRect {. + importcpp: "getBoundingClientRect", nodecl.} +proc clientHeight*(): int {. + importcpp: "(window.innerHeight || document.documentElement.clientHeight)@", nodecl} +proc clientWidth*(): int {. + importcpp: "(window.innerWidth || document.documentElement.clientWidth)@", nodecl} + +proc inViewport*(el: Node): bool = + let rect = el.getBoundingClientRect() + result = rect.top >= 0 and rect.left >= 0 and + rect.bottom <= clientHeight() and + rect.right <= clientWidth() + +proc scrollTop*(e: Node): int {.importcpp: "#.scrollTop", nodecl.} +proc offsetHeight*(e: Node): int {.importcpp: "#.offsetHeight", nodecl.} +proc offsetTop*(e: Node): int {.importcpp: "#.offsetTop", nodecl.} diff --git a/bench/implementations/nim-karax/src/jdict.nim b/bench/implementations/nim-karax/src/jdict.nim new file mode 100644 index 0000000..0eecb58 --- /dev/null +++ b/bench/implementations/nim-karax/src/jdict.nim @@ -0,0 +1,13 @@ + +type + JDict*[K, V] = ref object + +proc `[]`*[K, V](d: JDict[K, V], k: K): V {.importcpp: "#[#]".} +proc `[]=`*[K, V](d: JDict[K, V], k: K, v: V) {.importcpp: "#[#] = #".} + +proc newJDict*[K, V](): JDict[K, V] {.importcpp: "{@}".} + +proc contains*[K, V](d: JDict[K, V], k: K): bool {.importcpp: "#.hasOwnProperty(#)".} + +proc del*[K, V](d: JDict[K, V], k: K) {.importcpp: "delete #[#]".} + diff --git a/bench/implementations/nim-karax/src/jstrutils.nim b/bench/implementations/nim-karax/src/jstrutils.nim new file mode 100644 index 0000000..c69e2fa --- /dev/null +++ b/bench/implementations/nim-karax/src/jstrutils.nim @@ -0,0 +1,23 @@ +# cstring handling utilities for performance + +proc split*(s, sep: cstring): seq[cstring] {.importcpp, nodecl.} + +proc split*(s, sep: cstring; max: int): seq[cstring] {.importcpp, nodecl.} + +proc startsWith*(a, b: cstring): bool {.importcpp: "startsWith", nodecl.} +proc contains*(a, b: cstring): bool {.importcpp: "(#.indexOf(#)>=0)", nodecl.} +proc substr*(s: cstring; start: int): cstring {.importcpp: "substr", nodecl.} +proc substr*(s: cstring; start, length: int): cstring {.importcpp: "substr", nodecl.} + +#proc len*(s: cstring): int {.importcpp: "#.length", nodecl.} +proc `&`*(a, b: cstring): cstring {.importcpp: "(# + #)", nodecl.} +proc toCstr*(s: int): cstring {.importcpp: "((#)+'')", nodecl.} +proc `&`*(s: int): cstring {.importcpp: "((#)+'')", nodecl.} +proc `&`*(s: bool): cstring {.importcpp: "((#)+'')", nodecl.} + +proc `&`*(s: cstring): cstring {.importcpp: "(#)", nodecl.} + +proc isInt*(s: cstring): bool {.asmNoStackFrame.} = + asm """ + return s.match(/^[0-9]+$/); + """ diff --git a/bench/implementations/nim-karax/src/karax.nim b/bench/implementations/nim-karax/src/karax.nim new file mode 100644 index 0000000..1908d6f --- /dev/null +++ b/bench/implementations/nim-karax/src/karax.nim @@ -0,0 +1,345 @@ +## Karax -- Single page applications for Nim. + +import dom, vdom, jstrutils, components, jdict + +export dom.Event #, dom.cloneNode, dom + +proc kout*[T](x: T) {.importc: "console.log", varargs.} + ## the preferred way of debugging karax applications. + +proc hasProp(e: Node; prop: cstring): bool {.importcpp: "(#.hasOwnProperty(#))".} +proc rawkey(e: Node): VKey {.importcpp: "#.karaxKey", nodecl.} +proc key*(e: Node): VKey = + if e.hasProp"karaxKey": result = e.rawkey + else: result = -1 +proc `key=`*(e: Node; x: VKey) {.importcpp: "#.karaxKey = #", nodecl.} + +var + toFocus: Node + toFocusV: VNode + +proc setFocus*(n: VNode) = + toFocusV = n + +# ----------------- event wrapping --------------------------------------- + +template nativeValue(ev): cstring = cast[Element](ev.target).value +template setNativeValue(ev, val) = cast[Element](ev.target).value = val + +template keyeventBody() = + n.value = nativeValue(ev) + action(ev, n) + setNativeValue(ev, n.value) + # Do not call redraw() here! That is already done + # by ``karax.addEventHandler``. + +proc wrapEvent(d: Node; n: VNode; k: EventKind; action: EventHandler) = + proc stdWrapper(): (proc (ev: Event)) = + let action = action + let n = n + result = proc (ev: Event) = + action(ev, n) + + proc enterWrapper(): (proc (ev: Event)) = + let action = action + let n = n + result = proc (ev: Event) = + if ev.keyCode == 13: keyeventBody() + + proc laterWrapper(): (proc (ev: Event)) = + let action = action + let n = n + var timer: Timeout + result = proc (ev: Event) = + proc wrapper() = keyeventBody() + if timer != nil: clearTimeout(timer) + timer = setTimeout(wrapper, 400) + + case k + of EventKind.onkeyuplater: + d.addEventListener("keyup", laterWrapper()) + of EventKind.onkeyupenter: + d.addEventListener("keyup", enterWrapper()) + else: + d.addEventListener(toEventName[k], stdWrapper()) + +# --------------------- DOM diff ----------------------------------------- + +template detach(n: VNode) = n.dom = nil +template attach(n: Vnode) = n.dom = result + +proc vnodeToDom(n: VNode): Node = + if n.kind == VNodeKind.text: + result = document.createTextNode(n.text) + attach n + elif n.kind == VNodeKind.vthunk: + let x = callThunk(vcomponents[n.text], n) + result = vnodeToDom(x) + n.key = result.key + attach n + return result + elif n.kind == VNodeKind.dthunk: + result = callThunk(dcomponents[n.text], n) + n.key = result.key + attach n + return result + else: + result = document.createElement(toTag[n.kind]) + attach n + for k in n: + appendChild(result, vnodeToDom(k)) + # text is mapped to 'value': + if n.text != nil: + result.value = n.text + if n.id != nil: + result.id = n.id + if n.class != nil: + result.class = n.class + if n.key >= 0: + result.key = n.key + for k, v in attrs(n): + if v != nil: + result.setAttr(k, v) + for e, h in items(n.events): + wrapEvent(result, n, e, h) + if n == toFocusV and toFocus.isNil: + toFocus = result + +proc same(n: VNode, e: Node): bool = + if toTag[n.kind] == e.nodename: + result = true + if n.kind != VNodeKind.text: + if e.len != n.len: return false + for i in 0 ..< n.len: + if not same(n[i], e[i]): return false + +var + dorender: proc (): VNode {.closure.} + currentTree: VNode + +proc replaceById(id: cstring; newTree: Node) = + let x = document.getElementById(id) + x.parentNode.replaceChild(newTree, x) + #newTree.id = id + +proc equalsShallow(a, b: VNode): bool = + if a.kind != b.kind: return false + if a.id != b.id: return false + if a.key != b.key: return false + if a.kind == VNodeKind.text: + if a.text != b.text: return false + elif a.kind == VNodeKind.vthunk or a.kind == VNodeKind.dthunk: + if a.text != b.text: return false + if a.len != b.len: return false + for i in 0..= 0 and isDirty(newNode.key): + unmarkDirty(newNode.key) + let n = vnodeToDom(newNode) + if parent == nil: + replaceById("ROOT", n) + else: + parent.replaceChild(n, current) + elif newNode.kind != VNodeKind.text and newNode.kind != VNodeKind.vthunk and + newNode.kind != VNodeKind.dthunk: + for i in 0..newNode.len-1: + updateDirtyElements(current, current[i], newNode[i]) + # leave early if we know there cannot be anything left to do: + #if dirtyCount <= 0: return + +proc updateElement(parent, current: Node, newNode, oldNode: VNode) = + if not equalsShallow(newNode, oldNode): + detach(oldNode) + let n = vnodeToDom(newNode) + if parent == nil: + replaceById("ROOT", n) + else: + parent.replaceChild(n, current) + elif newNode.kind != VNodeKind.text: + let newLength = newNode.len + var oldLength = oldNode.len + let minLength = min(newLength, oldLength) + assert oldNode.kind == newNode.kind + when defined(simpleDiff): + for i in 0..min(newLength, oldLength)-1: + updateElement(current, current[i], newNode[i], oldNode[i]) + if newLength > oldLength: + for i in oldLength..newLength-1: + current.appendChild(vnodeToDom(newNode[i])) + elif oldLength > newLength: + for i in countdown(oldLength-1, newLength): + detach(oldNode[i]) + current.removeChild(current.lastChild) + else: + var commonPrefix = 0 + while commonPrefix < minLength and + equalsTree(newNode[commonPrefix], oldNode[commonPrefix]): + inc commonPrefix + + var oldPos = oldLength - 1 + var newPos = newLength - 1 + while oldPos >= commonPrefix and newPos >= commonPrefix and + equalsTree(newNode[newPos], oldNode[oldPos]): + dec oldPos + dec newPos + + var pos = min(oldPos, newPos) + 1 + for i in commonPrefix..pos-1: + updateElement(current, current.childNodes[i], newNode[i], oldNode[i]) + + var nextChildPos = oldPos + 1 + while pos <= newPos: + if nextChildPos == oldLength: + current.appendChild(vnodeToDom(newNode[pos])) + else: + current.insertBefore(vnodeToDom(newNode[pos]), current.childNodes[nextChildPos]) + # added new Node, so old state of VDOM have one more Node + inc oldLength + inc pos + inc nextChildPos + + for i in pos..oldPos: + detach(oldNode[i]) + current.removeChild(current.childNodes[pos]) + +when false: + var drawTimeout: Timeout + +proc dodraw() = + let newtree = dorender() + newtree.id = "ROOT" + toFocus = nil + if currentTree == nil: + currentTree = newtree + let asdom = vnodeToDom currentTree + replaceById("ROOT", asdom) + else: + let olddom = document.getElementById("ROOT") + updateElement(nil, olddom, newtree, currentTree) + #assert same(newtree, document.getElementById("ROOT")) + if someDirty: + updateDirtyElements(nil, olddom, newtree) + someDirty = false + currentTree = newtree + # now that it's part of the DOM, give it the focus: + if toFocus != nil: + toFocus.focus() + +proc reqFrame(callback: proc()) {.importc: "window.requestAnimationFrame".} + +proc redraw*() = + # we buffer redraw requests: + when false: + if drawTimeout != nil: + clearTimeout(drawTimeout) + drawTimeout = setTimeout(dodraw, 30) + elif true: + reqFrame(dodraw) + else: + dodraw() + +proc init(ev: Event) = + reqFrame(dodraw) + +proc setRenderer*(renderer: proc (): VNode) = + dorender = renderer + window.onload = init + +proc addEventHandler*(n: VNode; k: EventKind; action: EventHandler) = + ## Implements the foundation of Karax's event management. + ## Karax DSL transforms ``tag(onEvent = handler)`` to + ## ``tempNode.addEventHandler(tagNode, EventKind.onEvent, wrapper)`` + ## where ``wrapper`` calls the passed ``action`` and then triggers + ## a ``redraw``. + proc wrapper(ev: Event; n: VNode) = + action(ev, n) + redraw() + addEventListener(n, k, wrapper) + +proc setOnHashChange*(action: proc (hashPart: cstring)) = + var onhashChange {.importc: "window.onhashchange".}: proc() + var hashPart {.importc: "window.location.hash".}: cstring + proc wrapper() = + action(hashPart) + redraw() + onhashchange = wrapper + +proc ajax(meth, url: cstring; headers: openarray[(cstring, cstring)]; + data: cstring; + cont: proc (httpStatus: int; response: cstring)) = + proc setRequestHeader(a, b: cstring) {.importc: "ajax.setRequestHeader".} + {.emit: """ + var ajax = new XMLHttpRequest(); + ajax.open(`meth`,`url`,true);""".} + for a, b in items(headers): + setRequestHeader(a, b) + {.emit: """ + ajax.onreadystatechange = function(){ + if(this.readyState == 4){ + if(this.status == 200){ + `cont`(this.status, this.responseText); + } else { + `cont`(this.status, this.statusText); + } + } + } + ajax.send(`data`); + """.} + +proc ajaxPut*(url: string; headers: openarray[(cstring, cstring)]; + data: cstring; + cont: proc (httpStatus: int, response: cstring)) = + ajax("PUT", url, headers, data, cont) + +proc ajaxGet*(url: string; headers: openarray[(cstring, cstring)]; + cont: proc (httpStatus: int, response: cstring)) = + ajax("GET", url, headers, nil, cont) + +{.push stackTrace:off.} + +proc setupErrorHandler*(useAlert=false) = + ## Installs an error handler that transforms native JS unhandled + ## exceptions into Nim based stack traces. If `useAlert` is false, + ## the error message is put into the console, otherwise `alert` + ## is called. + proc stackTraceAsCstring(): cstring = cstring(getStackTrace()) + {.emit: """ + window.onerror = function(msg, url, line, col, error) { + var x = "Error: " + msg + "\n" + `stackTraceAsCstring`() + if (`useAlert`) + alert(x); + else + console.log(x); + var suppressErrorAlert = true; + return suppressErrorAlert; + };""".} + +{.pop.} + +proc prepend(parent, kid: Element) = + parent.insertBefore(kid, parent.firstChild) + +proc loadScript*(jsfilename: cstring) = + let body = getElementById("body") + let s = document.createElement("script") + s.setAttr "type", "text/javascript" + s.setAttr "src", jsfilename + body.prepend(s) + redraw() diff --git a/bench/implementations/nim-karax/src/karaxdsl.nim b/bench/implementations/nim-karax/src/karaxdsl.nim new file mode 100644 index 0000000..ade1c24 --- /dev/null +++ b/bench/implementations/nim-karax/src/karaxdsl.nim @@ -0,0 +1,119 @@ + +import macros, karax, vdom, components +from strutils import startsWith, toLowerAscii + +const + StmtContext = ["kout", "inc", "echo", "dec", "!"] + SpecialAttrs = ["id", "class", "value", "key"] + +proc getName(n: NimNode): string = + case n.kind + of nnkIdent: + result = $n.ident + of nnkAccQuoted: + result = "" + for i in 0.. 0: + result[L-1] = tcall2(result[L-1], tmpContext) + of nnkStmtList, nnkStmtListExpr, nnkWhenStmt, nnkIfStmt, nnkCaseStmt, + nnkTryStmt, nnkFinally: + # recurse for every child: + result = copyNimNode(n) + for x in n: + result.add tcall2(x, tmpContext) + of nnkVarSection, nnkLetSection, nnkConstSection: + result = n + of nnkCallKinds: + let op = getName(n[0]) + let ck = isComponent(op) + if ck != ComponentKind.None: + let tmp = genSym(nskLet, "tmp") + let call = if ck == ComponentKind.Tag: + newCall(bindSym"tree", newDotExpr(bindSym"VNodeKind", n[0])) + elif ck == ComponentKind.VNode: + newCall(bindSym"vthunk", newLit(op)) + else: + newCall(bindSym"dthunk", newLit(op)) + result = newTree( + if tmpContext == nil: nnkStmtListExpr else: nnkStmtList, + newLetStmt(tmp, call)) + for i in 1 ..< n.len: + # named parameters are transformed into attributes or events: + let x = n[i] + if x.kind == nnkExprEqExpr: + let key = getName x[0] + if key.startsWith("on"): + result.add newCall(bindSym"addEventHandler", + tmp, newDotExpr(bindSym"EventKind", x[0]), x[1]) + elif key in SpecialAttrs: + result.add newDotAsgn(tmp, key, x[1]) + else: + result.add newCall(bindSym"setAttr", tmp, newLit(key), x[1]) + elif ck != ComponentKind.Tag: + call.add x + elif eqIdent(x, "setFocus"): + result.add newCall(x, tmp) + else: + result.add tcall2(x, tmp) + if tmpContext == nil: + result.add tmp + else: + result.add newCall(bindSym"add", tmpContext, tmp) + elif tmpContext != nil and op notin StmtContext: + result = newCall(bindSym"add", tmpContext, n) + elif op == "!" and n.len == 2: + result = n[1] + else: + result = n + else: + result = n + +macro buildHtml*(tag, children: untyped): VNode = + expectKind children, nnkDo + var call: NimNode + if tag.kind in nnkCallKinds: + call = tag + else: + call = newCall(tag) + call.add body(children) + result = tcall2(call, nil) + when defined(debugKaraxDsl): + echo repr result + +macro buildHtml*(children: untyped): VNode = + expectKind children, nnkDo + result = tcall2(body(children), nil) + when defined(debugKaraxDsl): + echo repr result diff --git a/bench/implementations/nim-karax/src/karaxprelude.nim b/bench/implementations/nim-karax/src/karaxprelude.nim new file mode 100644 index 0000000..285730a --- /dev/null +++ b/bench/implementations/nim-karax/src/karaxprelude.nim @@ -0,0 +1,3 @@ +## Include file that contains the common imports for the Karax framework. + +import karax, karaxdsl, vdom, components diff --git a/bench/implementations/nim-karax/src/shash.nim b/bench/implementations/nim-karax/src/shash.nim new file mode 100644 index 0000000..c387e22 --- /dev/null +++ b/bench/implementations/nim-karax/src/shash.nim @@ -0,0 +1,17 @@ +# Simple hashing for the JS target. + +type + Hash* = int + +{.push checks: off.} +proc sdbmHash(hash: Hash, c: int): Hash {.inline.} = + return Hash(c) + (hash shl 6) + (hash shl 16) - hash +{.pop.} + +proc charCodeAt(s: cstring; i: int): int {.importcpp: "#.charCodeAt(#)".} + +template `&=`*(x: var Hash, c: int) = x = sdbmHash(x, c) +template `&=`*(x: var Hash, s: cstring) = + for i in 0..\L" + if n.kind == VNodeKind.text: + result.add n.text + else: + if n.text != nil: + result.add " value = " + result.add n.text + for child in items(n): + toString(child, result, indent+2) + for i in 1..indent: result.add ' ' + result.add "\L" + +proc calcHash*(n: VNode) = + if n.validHash: return + n.validHash = true + var h: Hash = ord n.kind + if n.id != nil: + h &= "id" + h &= n.id + if n.class != nil: + h &= "class" + h &= n.class + if n.key >= 0: + h &= "k" + h &= n.key + for k, v in attrs(n): + h &= " " + h &= k + h &= "=" + h &= v + if n.kind == VNodeKind.text or n.text != nil: + h &= "t" + h &= n.text + else: + for child in items(n): + calcHash(child) + h &= child.hash + n.hash = h + +proc `$`*(n: VNode): cstring = + var res = "" + toString(n, res, 0) + result = cstring(res) diff --git a/bench/implementations/nim-karax/tests/diffDomTests.html b/bench/implementations/nim-karax/tests/diffDomTests.html new file mode 100644 index 0000000..5ecf130 --- /dev/null +++ b/bench/implementations/nim-karax/tests/diffDomTests.html @@ -0,0 +1,19 @@ + + + + + Diff dom tests + + + + + +
    + + + + + + diff --git a/bench/implementations/nim-karax/tests/diffDomTests.nim b/bench/implementations/nim-karax/tests/diffDomTests.nim new file mode 100644 index 0000000..7fdcf85 --- /dev/null +++ b/bench/implementations/nim-karax/tests/diffDomTests.nim @@ -0,0 +1,183 @@ + +import dom, vdom, times, karax, karaxdsl, jdict, jstrutils, parseutils, sequtils + +var + entries: seq[cstring] + results: seq[cstring] + timeout: Timeout + +proc reset() = + results.add cstring"reset started" + entries = @[cstring("0"), cstring("1"), cstring("2"), cstring("3"), cstring("4"), cstring("5") ] + redraw() + results.add cstring"reset finished" + +proc checkOrder(order : seq[int]): bool = + var ul = getElementById("ul") + if ul == nil or len(ul.children) != len(order): + return false + var pos = 0 + for child in ul.children: + if child.id != $order[pos]: + return false + inc pos + return true + +proc check1() = + let result = checkOrder(@[0, 1, 2, 3, 4, 7, 5]) + if result: + results.add cstring"test1 - OK" + else: + results.add cstring"test1 - FAIL" + +# result: 0 1 2 3 4 7 5 +proc test1() = + results.add cstring"test1 started" + entries = @[cstring("0"), cstring("1"), cstring("2"), cstring("3"), cstring("4"), cstring("5") ] + entries.insert(cstring("7"), 5) + redraw() + timeout = setTimeout(check1, 20) + +proc check2() = + let result = checkOrder(@[8, 0, 1, 2, 3, 4, 7, 5]) + if result: + results.add cstring"test1 - OK" + else: + results.add cstring"test2 - FAIL" + +# result: 8 0 1 2 3 4 7 5 +proc test2() = + results.add cstring"test2 started" + entries = @[cstring("0"), cstring("1"), cstring("2"), cstring("3"), cstring("4"), cstring("5") ] + entries.insert(cstring("7"), 5) + entries.insert(cstring("8"), 0) + redraw() + timeout = setTimeout(check2, 20) + +proc check3() = + let result = checkOrder(@[2, 3, 4, 1]) + if result: + results.add cstring"test3 - OK" + else: + results.add cstring"test3 - FAIL" + +# result: 2 3 4 1 +proc test3() = + results.add cstring"test3 started" + entries = @[cstring("2"), cstring("3"), cstring("4"), cstring("1") ] + redraw() + timeout = setTimeout(check3, 20) + +proc check4() = + let result = checkOrder(@[5, 6, 7, 8]) + if result: + results.add cstring"test4 - OK" + else: + results.add cstring"test4 - FAIL" + +# result: 5 6 7 8 +proc test4() = + results.add cstring"test4 started" + entries = @[cstring("5"), cstring("6"), cstring("7"), cstring("8") ] + redraw() + timeout = setTimeout(check4, 20) + +proc check5() = + let result = checkOrder(@[0, 1, 3, 5, 4, 5]) + if result: + results.add cstring"test5 - OK" + else: + results.add cstring"test5 - FAIL" + +# result: 0 1 3 5 4 5 +proc test5() = + results.add cstring"test5 started" + entries = @[cstring("0"), cstring("1"), cstring("3"), cstring("5"), cstring("4"), cstring("5") ] + redraw() + timeout = setTimeout(check5, 20) + +proc check6() = + let result = checkOrder(@[]) + if result: + results.add cstring"test6 - OK" + else: + results.add cstring"test6 - FAIL" + +# result: empty +proc test6() = + results.add cstring"test6 started" + entries = @[] + redraw() + timeout = setTimeout(check6, 20) + +proc check7() = + let result = checkOrder(@[2]) + if result: + results.add cstring"test7 - OK" + else: + results.add cstring"test7 - FAIL" + redraw() + +# result: 2 +proc test7() = + results.add cstring"test7 started" + entries = @[cstring("2")] + redraw() + timeout = setTimeout(check7, 20) + +proc createEntry(id: int): VNode = + result = buildHtml(): + button(id="" & $id): + text $id + +proc createDom(): VNode = + result = buildHtml(tdiv()): + ul(id="ul"): + for e in entries: + createEntry(parseInt(e)) + for r in results: + tdiv: + text r + +proc onload() = + for i in 0..5: # 0_000: + entries.add(cstring($i)) + + var dtReset = 100 + var dtTest = 500 + + var t = dtReset + timeout = setTimeout(test1, t) + t += dtTest + timeout = setTimeout(reset, t) + t += dtReset + + timeout = setTimeout(test2, t) + t += dtTest + timeout = setTimeout(reset, t) + t += dtReset + + timeout = setTimeout(test3, t) + t += dtTest + timeout = setTimeout(reset, t) + t += dtReset + + timeout = setTimeout(test4, t) + t += dtTest + timeout = setTimeout(reset, t) + t += dtReset + + timeout = setTimeout(test5, t) + t += dtTest + timeout = setTimeout(reset, t) + t += dtReset + + timeout = setTimeout(test6, t) + t += dtTest + timeout = setTimeout(reset, t) + t += dtReset + + timeout = setTimeout(test7, t) + +onload() +setRenderer createDom diff --git a/bench/implementations/nim-karax/tests/diffDomTests.nims b/bench/implementations/nim-karax/tests/diffDomTests.nims new file mode 100644 index 0000000..532b206 --- /dev/null +++ b/bench/implementations/nim-karax/tests/diffDomTests.nims @@ -0,0 +1 @@ +--path: "../src" diff --git a/bench/implementations/react-15.3.1-optimized/build.min.js b/bench/implementations/react-15.3.1-optimized/build.min.js new file mode 100755 index 0000000..1c5eaf2 --- /dev/null +++ b/bench/implementations/react-15.3.1-optimized/build.min.js @@ -0,0 +1 @@ +var app=app||{};(function(){"use strict";app.ALL_TODOS="all";app.ACTIVE_TODOS="active";app.COMPLETED_TODOS="completed";app.Utils={uuid:function(){var i,random;var uuid="";for(i=0;i<32;i++){random=Math.random()*16|0;if(i===8||i===12||i===16||i===20){uuid+="-"}uuid+=(i===12?4:i===16?random&3|8:random).toString(16)}return uuid},pluralize:function(count,word){return count===1?word:word+"s"},extend:function(){var newObj={};for(var i=0;i0){clearButton=React.createElement("button",{className:"clear-completed",onClick:this.props.onClearCompleted},"Clear completed")}var nowShowing=this.props.nowShowing;return React.createElement("footer",{className:"footer"},React.createElement("span",{className:"todo-count"},React.createElement("strong",null,this.props.count)," ",activeTodoWord," left"),React.createElement("ul",{className:"filters"},React.createElement("li",null,React.createElement("a",{href:"#/",className:classNames({selected:nowShowing===app.ALL_TODOS})},"All"))," ",React.createElement("li",null,React.createElement("a",{href:"#/active",className:classNames({selected:nowShowing===app.ACTIVE_TODOS})},"Active"))," ",React.createElement("li",null,React.createElement("a",{href:"#/completed",className:classNames({selected:nowShowing===app.COMPLETED_TODOS})},"Completed"))),clearButton)}});var ESCAPE_KEY=27;var ENTER_KEY=13;var TodoItem=React.createClass({handleSubmit:function(event){var val=this.state.editText.trim();if(val){this.props.onSave(val);this.setState({editText:val})}else{this.props.onDestroy()}},handleEdit:function(){this.props.onEdit();this.setState({editText:this.props.todo.title})},handleKeyDown:function(event){if(event.which===ESCAPE_KEY){this.setState({editText:this.props.todo.title});this.props.onCancel(event)}else if(event.which===ENTER_KEY){this.handleSubmit(event)}},handleChange:function(event){if(this.props.editing){this.setState({editText:event.target.value})}},getInitialState:function(){return{editText:this.props.todo.title}},shouldComponentUpdate:function(nextProps,nextState){return nextProps.todo!==this.props.todo||nextProps.editing!==this.props.editing||nextState.editText!==this.state.editText},componentDidUpdate:function(prevProps){if(!prevProps.editing&&this.props.editing){var node=React.findDOMNode(this.refs.editField);node.focus();node.setSelectionRange(node.value.length,node.value.length)}},render:function(){return React.createElement("li",{className:classNames({completed:this.props.todo.completed,editing:this.props.editing})},React.createElement("div",{className:"view"},React.createElement("input",{className:"toggle",type:"checkbox",checked:this.props.todo.completed,onChange:this.props.onToggle}),React.createElement("label",{onDoubleClick:this.handleEdit},this.props.todo.title),React.createElement("button",{className:"destroy",onClick:this.props.onDestroy})),React.createElement("input",{ref:"editField",className:"edit",value:this.state.editText,onBlur:this.handleSubmit,onChange:this.handleChange,onKeyDown:this.handleKeyDown}))}});var ENTER_KEY=13;var TodoApp=React.createClass({getInitialState:function(){return{nowShowing:app.ALL_TODOS,editing:null,newTodo:""}},componentDidMount:function(){var setState=this.setState;var router=Router({"/":setState.bind(this,{nowShowing:app.ALL_TODOS}),"/active":setState.bind(this,{nowShowing:app.ACTIVE_TODOS}),"/completed":setState.bind(this,{nowShowing:app.COMPLETED_TODOS})});router.init("/")},handleChange:function(event){this.setState({newTodo:event.target.value})},handleNewTodoKeyDown:function(event){if(event.keyCode!==ENTER_KEY){return}event.preventDefault();var val=this.state.newTodo.trim();if(val){this.props.model.addTodo(val);this.setState({newTodo:""})}},toggleAll:function(event){var checked=event.target.checked;this.props.model.toggleAll(checked)},toggle:function(todoToToggle){this.props.model.toggle(todoToToggle)},destroy:function(todo){this.props.model.destroy(todo)},edit:function(todo){this.setState({editing:todo.id})},save:function(todoToSave,text){this.props.model.save(todoToSave,text);this.setState({editing:null})},cancel:function(){this.setState({editing:null})},clearCompleted:function(){this.props.model.clearCompleted()},render:function(){var footer;var main;var todos=this.props.model.todos;var shownTodos=todos.filter(function(todo){switch(this.state.nowShowing){case app.ACTIVE_TODOS:return!todo.completed;case app.COMPLETED_TODOS:return todo.completed;default:return true}},this);var todoItems=shownTodos.map(function(todo){return React.createElement(TodoItem,{key:todo.id,todo:todo,onToggle:this.toggle.bind(this,todo),onDestroy:this.destroy.bind(this,todo),onEdit:this.edit.bind(this,todo),editing:this.state.editing===todo.id,onSave:this.save.bind(this,todo),onCancel:this.cancel})},this);var activeTodoCount=todos.reduce(function(accum,todo){return todo.completed?accum:accum+1},0);var completedCount=todos.length-activeTodoCount;if(activeTodoCount||completedCount){footer=React.createElement(TodoFooter,{count:activeTodoCount,completedCount:completedCount,nowShowing:this.state.nowShowing,onClearCompleted:this.clearCompleted})}if(todos.length){main=React.createElement("section",{className:"main"},React.createElement("input",{className:"toggle-all",type:"checkbox",onChange:this.toggleAll,checked:activeTodoCount===0}),React.createElement("ul",{className:"todo-list"},todoItems))}return React.createElement("div",null,React.createElement("header",{className:"header"},React.createElement("h1",null,"todos"),React.createElement("input",{className:"new-todo",placeholder:"What needs to be done?",value:this.state.newTodo,onKeyDown:this.handleNewTodoKeyDown,onChange:this.handleChange,autoFocus:true})),main,footer)}});var model=new app.TodoModel("react-todos");function render(){ReactDOM.render(React.createElement(TodoApp,{model:model}),document.getElementsByClassName("todoapp")[0])}model.subscribe(render);render()})(); \ No newline at end of file diff --git a/bench/implementations/react-15.3.1-optimized/index.html b/bench/implementations/react-15.3.1-optimized/index.html new file mode 100755 index 0000000..304bd87 --- /dev/null +++ b/bench/implementations/react-15.3.1-optimized/index.html @@ -0,0 +1,23 @@ + + + + + React • TodoMVC + + + + +
    + + + + + + + + + diff --git a/bench/implementations/react-15.3.1-optimized/js/app.jsx b/bench/implementations/react-15.3.1-optimized/js/app.jsx new file mode 100755 index 0000000..fd895e5 --- /dev/null +++ b/bench/implementations/react-15.3.1-optimized/js/app.jsx @@ -0,0 +1,442 @@ +/*jshint quotmark:false */ +/*jshint white:false */ +/*jshint trailing:false */ +/*jshint newcap:false */ +/*global React, Router*/ +var app = app || {}; + +(function () { + 'use strict'; + + app.ALL_TODOS = 'all'; + app.ACTIVE_TODOS = 'active'; + app.COMPLETED_TODOS = 'completed'; + + app.Utils = { + uuid: function () { + /*jshint bitwise:false */ + var i, random; + var uuid = ''; + + for (i = 0; i < 32; i++) { + random = Math.random() * 16 | 0; + if (i === 8 || i === 12 || i === 16 || i === 20) { + uuid += '-'; + } + uuid += (i === 12 ? 4 : (i === 16 ? (random & 3 | 8) : random)) + .toString(16); + } + + return uuid; + }, + + pluralize: function (count, word) { + return count === 1 ? word : word + 's'; + }, + + extend: function () { + var newObj = {}; + for (var i = 0; i < arguments.length; i++) { + var obj = arguments[i]; + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + newObj[key] = obj[key]; + } + } + } + return newObj; + } + }; + + var Utils = app.Utils; + // Generic "model" object. You can use whatever + // framework you want. For this application it + // may not even be worth separating this logic + // out, but we do this to demonstrate one way to + // separate out parts of your application. + app.TodoModel = function (key) { + this.key = key; + this.todos = []; + this.onChanges = []; + }; + + app.TodoModel.prototype.subscribe = function (onChange) { + this.onChanges.push(onChange); + }; + + app.TodoModel.prototype.inform = function () { + this.onChanges.forEach(function (cb) { cb(); }); + }; + + app.TodoModel.prototype.addTodo = function (title) { + this.todos = this.todos.concat({ + id: Utils.uuid(), + title: title, + completed: false + }); + + this.inform(); + }; + + app.TodoModel.prototype.toggleAll = function (checked) { + // Note: it's usually better to use immutable data structures since they're + // easier to reason about and React works very well with them. That's why + // we use map() and filter() everywhere instead of mutating the array or + // todo items themselves. + this.todos = this.todos.map(function (todo) { + return Utils.extend({}, todo, {completed: checked}); + }); + + this.inform(); + }; + + app.TodoModel.prototype.toggle = function (todoToToggle) { + this.todos = this.todos.map(function (todo) { + return todo !== todoToToggle ? + todo : + Utils.extend({}, todo, {completed: !todo.completed}); + }); + + this.inform(); + }; + + app.TodoModel.prototype.destroy = function (todo) { + this.todos = this.todos.filter(function (candidate) { + return candidate !== todo; + }); + + this.inform(); + }; + + app.TodoModel.prototype.save = function (todoToSave, text) { + this.todos = this.todos.map(function (todo) { + return todo !== todoToSave ? todo : Utils.extend({}, todo, {title: text}); + }); + + this.inform(); + }; + + app.TodoModel.prototype.clearCompleted = function () { + this.todos = this.todos.filter(function (todo) { + return !todo.completed; + }); + + this.inform(); + }; + + + var TodoFooter = React.createClass({ + render: function () { + var activeTodoWord = app.Utils.pluralize(this.props.count, 'item'); + var clearButton = null; + + if (this.props.completedCount > 0) { + clearButton = ( + + ); + } + + var nowShowing = this.props.nowShowing; + return ( + + ); + } + }); + + var ESCAPE_KEY = 27; + var ENTER_KEY = 13; + + var TodoItem = React.createClass({ + handleSubmit: function (event) { + var val = this.state.editText.trim(); + if (val) { + this.props.onSave(val); + this.setState({editText: val}); + } else { + this.props.onDestroy(); + } + }, + + handleEdit: function () { + this.props.onEdit(); + this.setState({editText: this.props.todo.title}); + }, + + handleKeyDown: function (event) { + if (event.which === ESCAPE_KEY) { + this.setState({editText: this.props.todo.title}); + this.props.onCancel(event); + } else if (event.which === ENTER_KEY) { + this.handleSubmit(event); + } + }, + + handleChange: function (event) { + if (this.props.editing) { + this.setState({editText: event.target.value}); + } + }, + + getInitialState: function () { + return {editText: this.props.todo.title}; + }, + + /** + * This is a completely optional performance enhancement that you can + * implement on any React component. If you were to delete this method + * the app would still work correctly (and still be very performant!), we + * just use it as an example of how little code it takes to get an order + * of magnitude performance improvement. + */ + shouldComponentUpdate: function (nextProps, nextState) { + return ( + nextProps.todo !== this.props.todo || + nextProps.editing !== this.props.editing || + nextState.editText !== this.state.editText + ); + }, + + /** + * Safely manipulate the DOM after updating the state when invoking + * `this.props.onEdit()` in the `handleEdit` method above. + * For more info refer to notes at https://facebook.github.io/react/docs/component-api.html#setstate + * and https://facebook.github.io/react/docs/component-specs.html#updating-componentdidupdate + */ + componentDidUpdate: function (prevProps) { + if (!prevProps.editing && this.props.editing) { + var node = React.findDOMNode(this.refs.editField); + node.focus(); + node.setSelectionRange(node.value.length, node.value.length); + } + }, + + render: function () { + return ( +
  • +
    + + +
    + +
  • + ); + } + }); + + var ENTER_KEY = 13; + + var TodoApp = React.createClass({ + getInitialState: function () { + return { + nowShowing: app.ALL_TODOS, + editing: null, + newTodo: '' + }; + }, + + componentDidMount: function () { + var setState = this.setState; + var router = Router({ + '/': setState.bind(this, {nowShowing: app.ALL_TODOS}), + '/active': setState.bind(this, {nowShowing: app.ACTIVE_TODOS}), + '/completed': setState.bind(this, {nowShowing: app.COMPLETED_TODOS}) + }); + router.init('/'); + }, + + handleChange: function (event) { + this.setState({newTodo: event.target.value}); + }, + + handleNewTodoKeyDown: function (event) { + if (event.keyCode !== ENTER_KEY) { + return; + } + + event.preventDefault(); + + var val = this.state.newTodo.trim(); + + if (val) { + this.props.model.addTodo(val); + this.setState({newTodo: ''}); + } + }, + + toggleAll: function (event) { + var checked = event.target.checked; + this.props.model.toggleAll(checked); + }, + + toggle: function (todoToToggle) { + this.props.model.toggle(todoToToggle); + }, + + destroy: function (todo) { + this.props.model.destroy(todo); + }, + + edit: function (todo) { + this.setState({editing: todo.id}); + }, + + save: function (todoToSave, text) { + this.props.model.save(todoToSave, text); + this.setState({editing: null}); + }, + + cancel: function () { + this.setState({editing: null}); + }, + + clearCompleted: function () { + this.props.model.clearCompleted(); + }, + + render: function () { + var footer; + var main; + var todos = this.props.model.todos; + + var shownTodos = todos.filter(function (todo) { + switch (this.state.nowShowing) { + case app.ACTIVE_TODOS: + return !todo.completed; + case app.COMPLETED_TODOS: + return todo.completed; + default: + return true; + } + }, this); + + var todoItems = shownTodos.map(function (todo) { + return ( + + ); + }, this); + + var activeTodoCount = todos.reduce(function (accum, todo) { + return todo.completed ? accum : accum + 1; + }, 0); + + var completedCount = todos.length - activeTodoCount; + + if (activeTodoCount || completedCount) { + footer = + ; + } + + if (todos.length) { + main = ( +
    + +
      + {todoItems} +
    +
    + ); + } + + return ( +
    +
    +

    todos

    + +
    + {main} + {footer} +
    + ); + } + }); + + var model = new app.TodoModel('react-todos'); + + function render() { + ReactDOM.render( + , + document.getElementsByClassName('todoapp')[0] + ); + } + + model.subscribe(render); + render(); +})(); diff --git a/bench/implementations/react-15.3.1-optimized/license.md b/bench/implementations/react-15.3.1-optimized/license.md new file mode 100644 index 0000000..fbfa2e3 --- /dev/null +++ b/bench/implementations/react-15.3.1-optimized/license.md @@ -0,0 +1,20 @@ +Everything in this repo is MIT License unless otherwise specified. + +Copyright (c) Addy Osmani, Sindre Sorhus, Pascal Hartig, Stephen Sawchuk. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/bench/implementations/react-15.3.1-optimized/package.json b/bench/implementations/react-15.3.1-optimized/package.json new file mode 100755 index 0000000..95189e7 --- /dev/null +++ b/bench/implementations/react-15.3.1-optimized/package.json @@ -0,0 +1,20 @@ +{ + "private": true, + "scripts": { + "make": "babel --plugins transform-react-jsx js/app.jsx | uglifyjs -o build.min.js" + }, + "dependencies": { + "classnames": "^2.2.5", + "director": "^1.2.8", + "react": "^15.3.1", + "react-dom": "^15.3.1", + "todomvc-app-css": "^2.0.0", + "todomvc-common": "^1.0.2" + }, + "devDependencies": { + "babel-cli": "^6.10.1", + "babel-plugin-transform-react-jsx": "^6.8.0", + "babel-plugin-uglify": "^1.0.2", + "uglify-js": "^2.6.4" + } +} diff --git a/bench/implementations/react-15.3.1-optimized/readme.md b/bench/implementations/react-15.3.1-optimized/readme.md new file mode 100755 index 0000000..c3d0894 --- /dev/null +++ b/bench/implementations/react-15.3.1-optimized/readme.md @@ -0,0 +1,31 @@ +# React TodoMVC for Benchmarking + +This is an update of the React TodoMVC example to use React 15.1 and +precompiled/minified JSX instead of the slow JSXTransformer. The idea is that +this is a reasonable approximation of the performance characteristics of modern +production React code. + +This is not a perfect reflection of React best practices, because there is no +such thing. If you ask five professional React users what current React best +practices are, you'll get five different answers—each of which will benchmark +differently. React Router, Immutable.js, Redux (with or without sagas), Ramda, +ES2015 (with various Babel plugins), Webpack...the list never ends. + +Rather than wading into that combinatorial explosion, this example is leaving +the original React TodoMVC implementation's supporting stack alone, and only +performing the following upgrades: + +* Upgrade to React 15.1 +* Move everything into one JSX file and precompile it with Babel +* Minify with uglify + +If you're curious how it benchmarks with your particular stack, please fork +this repo and find out! + +# Building + +1. `npm install` +2. `npm run make` +3. Open a local server (e.g. with `npm install -g http-server`) and open index.html + + diff --git a/bench/implementations/react-15.3.1/build.min.js b/bench/implementations/react-15.3.1/build.min.js new file mode 100755 index 0000000..5c0600e --- /dev/null +++ b/bench/implementations/react-15.3.1/build.min.js @@ -0,0 +1 @@ +var app=app||{};(function(){"use strict";app.ALL_TODOS="all";app.ACTIVE_TODOS="active";app.COMPLETED_TODOS="completed";app.Utils={uuid:function(){var i,random;var uuid="";for(i=0;i<32;i++){random=Math.random()*16|0;if(i===8||i===12||i===16||i===20){uuid+="-"}uuid+=(i===12?4:i===16?random&3|8:random).toString(16)}return uuid},pluralize:function(count,word){return count===1?word:word+"s"},extend:function(){var newObj={};for(var i=0;i0){clearButton=React.createElement("button",{className:"clear-completed",onClick:this.props.onClearCompleted},"Clear completed")}var nowShowing=this.props.nowShowing;return React.createElement("footer",{className:"footer"},React.createElement("span",{className:"todo-count"},React.createElement("strong",null,this.props.count)," ",activeTodoWord," left"),React.createElement("ul",{className:"filters"},React.createElement("li",null,React.createElement("a",{href:"#/",className:classNames({selected:nowShowing===app.ALL_TODOS})},"All"))," ",React.createElement("li",null,React.createElement("a",{href:"#/active",className:classNames({selected:nowShowing===app.ACTIVE_TODOS})},"Active"))," ",React.createElement("li",null,React.createElement("a",{href:"#/completed",className:classNames({selected:nowShowing===app.COMPLETED_TODOS})},"Completed"))),clearButton)}});var ESCAPE_KEY=27;var ENTER_KEY=13;var TodoItem=React.createClass({handleSubmit:function(event){var val=this.state.editText.trim();if(val){this.props.onSave(val);this.setState({editText:val})}else{this.props.onDestroy()}},handleEdit:function(){this.props.onEdit();this.setState({editText:this.props.todo.title})},handleKeyDown:function(event){if(event.which===ESCAPE_KEY){this.setState({editText:this.props.todo.title});this.props.onCancel(event)}else if(event.which===ENTER_KEY){this.handleSubmit(event)}},handleChange:function(event){if(this.props.editing){this.setState({editText:event.target.value})}},getInitialState:function(){return{editText:this.props.todo.title}},componentDidUpdate:function(prevProps){if(!prevProps.editing&&this.props.editing){var node=React.findDOMNode(this.refs.editField);node.focus();node.setSelectionRange(node.value.length,node.value.length)}},render:function(){return React.createElement("li",{className:classNames({completed:this.props.todo.completed,editing:this.props.editing})},React.createElement("div",{className:"view"},React.createElement("input",{className:"toggle",type:"checkbox",checked:this.props.todo.completed,onChange:this.props.onToggle}),React.createElement("label",{onDoubleClick:this.handleEdit},this.props.todo.title),React.createElement("button",{className:"destroy",onClick:this.props.onDestroy})),React.createElement("input",{ref:"editField",className:"edit",value:this.state.editText,onBlur:this.handleSubmit,onChange:this.handleChange,onKeyDown:this.handleKeyDown}))}});var ENTER_KEY=13;var TodoApp=React.createClass({getInitialState:function(){return{nowShowing:app.ALL_TODOS,editing:null,newTodo:""}},componentDidMount:function(){var setState=this.setState;var router=Router({"/":setState.bind(this,{nowShowing:app.ALL_TODOS}),"/active":setState.bind(this,{nowShowing:app.ACTIVE_TODOS}),"/completed":setState.bind(this,{nowShowing:app.COMPLETED_TODOS})});router.init("/")},handleChange:function(event){this.setState({newTodo:event.target.value})},handleNewTodoKeyDown:function(event){if(event.keyCode!==ENTER_KEY){return}event.preventDefault();var val=this.state.newTodo.trim();if(val){this.props.model.addTodo(val);this.setState({newTodo:""})}},toggleAll:function(event){var checked=event.target.checked;this.props.model.toggleAll(checked)},toggle:function(todoToToggle){this.props.model.toggle(todoToToggle)},destroy:function(todo){this.props.model.destroy(todo)},edit:function(todo){this.setState({editing:todo.id})},save:function(todoToSave,text){this.props.model.save(todoToSave,text);this.setState({editing:null})},cancel:function(){this.setState({editing:null})},clearCompleted:function(){this.props.model.clearCompleted()},render:function(){var footer;var main;var todos=this.props.model.todos;var shownTodos=todos.filter(function(todo){switch(this.state.nowShowing){case app.ACTIVE_TODOS:return!todo.completed;case app.COMPLETED_TODOS:return todo.completed;default:return true}},this);var todoItems=shownTodos.map(function(todo){return React.createElement(TodoItem,{todo:todo,onToggle:this.toggle.bind(this,todo),onDestroy:this.destroy.bind(this,todo),onEdit:this.edit.bind(this,todo),editing:this.state.editing===todo.id,onSave:this.save.bind(this,todo),onCancel:this.cancel})},this);var activeTodoCount=todos.reduce(function(accum,todo){return todo.completed?accum:accum+1},0);var completedCount=todos.length-activeTodoCount;if(activeTodoCount||completedCount){footer=React.createElement(TodoFooter,{count:activeTodoCount,completedCount:completedCount,nowShowing:this.state.nowShowing,onClearCompleted:this.clearCompleted})}if(todos.length){main=React.createElement("section",{className:"main"},React.createElement("input",{className:"toggle-all",type:"checkbox",onChange:this.toggleAll,checked:activeTodoCount===0}),React.createElement("ul",{className:"todo-list"},todoItems))}return React.createElement("div",null,React.createElement("header",{className:"header"},React.createElement("h1",null,"todos"),React.createElement("input",{className:"new-todo",placeholder:"What needs to be done?",value:this.state.newTodo,onKeyDown:this.handleNewTodoKeyDown,onChange:this.handleChange,autoFocus:true})),main,footer)}});var model=new app.TodoModel("react-todos");function render(){ReactDOM.render(React.createElement(TodoApp,{model:model}),document.getElementsByClassName("todoapp")[0])}model.subscribe(render);render()})(); \ No newline at end of file diff --git a/bench/implementations/react-15.3.1/index.html b/bench/implementations/react-15.3.1/index.html new file mode 100755 index 0000000..304bd87 --- /dev/null +++ b/bench/implementations/react-15.3.1/index.html @@ -0,0 +1,23 @@ + + + + + React • TodoMVC + + + + +
    + + + + + + + + + diff --git a/bench/implementations/react-15.3.1/js/app.jsx b/bench/implementations/react-15.3.1/js/app.jsx new file mode 100755 index 0000000..6c845a3 --- /dev/null +++ b/bench/implementations/react-15.3.1/js/app.jsx @@ -0,0 +1,426 @@ +/*jshint quotmark:false */ +/*jshint white:false */ +/*jshint trailing:false */ +/*jshint newcap:false */ +/*global React, Router*/ +var app = app || {}; + +(function () { + 'use strict'; + + app.ALL_TODOS = 'all'; + app.ACTIVE_TODOS = 'active'; + app.COMPLETED_TODOS = 'completed'; + + app.Utils = { + uuid: function () { + /*jshint bitwise:false */ + var i, random; + var uuid = ''; + + for (i = 0; i < 32; i++) { + random = Math.random() * 16 | 0; + if (i === 8 || i === 12 || i === 16 || i === 20) { + uuid += '-'; + } + uuid += (i === 12 ? 4 : (i === 16 ? (random & 3 | 8) : random)) + .toString(16); + } + + return uuid; + }, + + pluralize: function (count, word) { + return count === 1 ? word : word + 's'; + }, + + extend: function () { + var newObj = {}; + for (var i = 0; i < arguments.length; i++) { + var obj = arguments[i]; + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + newObj[key] = obj[key]; + } + } + } + return newObj; + } + }; + + var Utils = app.Utils; + // Generic "model" object. You can use whatever + // framework you want. For this application it + // may not even be worth separating this logic + // out, but we do this to demonstrate one way to + // separate out parts of your application. + app.TodoModel = function (key) { + this.key = key; + this.todos = []; + this.onChanges = []; + }; + + app.TodoModel.prototype.subscribe = function (onChange) { + this.onChanges.push(onChange); + }; + + app.TodoModel.prototype.inform = function () { + this.onChanges.forEach(function (cb) { cb(); }); + }; + + app.TodoModel.prototype.addTodo = function (title) { + this.todos = this.todos.concat({ + id: Utils.uuid(), + title: title, + completed: false + }); + + this.inform(); + }; + + app.TodoModel.prototype.toggleAll = function (checked) { + // Note: it's usually better to use immutable data structures since they're + // easier to reason about and React works very well with them. That's why + // we use map() and filter() everywhere instead of mutating the array or + // todo items themselves. + this.todos = this.todos.map(function (todo) { + return Utils.extend({}, todo, {completed: checked}); + }); + + this.inform(); + }; + + app.TodoModel.prototype.toggle = function (todoToToggle) { + this.todos = this.todos.map(function (todo) { + return todo !== todoToToggle ? + todo : + Utils.extend({}, todo, {completed: !todo.completed}); + }); + + this.inform(); + }; + + app.TodoModel.prototype.destroy = function (todo) { + this.todos = this.todos.filter(function (candidate) { + return candidate !== todo; + }); + + this.inform(); + }; + + app.TodoModel.prototype.save = function (todoToSave, text) { + this.todos = this.todos.map(function (todo) { + return todo !== todoToSave ? todo : Utils.extend({}, todo, {title: text}); + }); + + this.inform(); + }; + + app.TodoModel.prototype.clearCompleted = function () { + this.todos = this.todos.filter(function (todo) { + return !todo.completed; + }); + + this.inform(); + }; + + + var TodoFooter = React.createClass({ + render: function () { + var activeTodoWord = app.Utils.pluralize(this.props.count, 'item'); + var clearButton = null; + + if (this.props.completedCount > 0) { + clearButton = ( + + ); + } + + var nowShowing = this.props.nowShowing; + return ( + + ); + } + }); + + var ESCAPE_KEY = 27; + var ENTER_KEY = 13; + + var TodoItem = React.createClass({ + handleSubmit: function (event) { + var val = this.state.editText.trim(); + if (val) { + this.props.onSave(val); + this.setState({editText: val}); + } else { + this.props.onDestroy(); + } + }, + + handleEdit: function () { + this.props.onEdit(); + this.setState({editText: this.props.todo.title}); + }, + + handleKeyDown: function (event) { + if (event.which === ESCAPE_KEY) { + this.setState({editText: this.props.todo.title}); + this.props.onCancel(event); + } else if (event.which === ENTER_KEY) { + this.handleSubmit(event); + } + }, + + handleChange: function (event) { + if (this.props.editing) { + this.setState({editText: event.target.value}); + } + }, + + getInitialState: function () { + return {editText: this.props.todo.title}; + }, + + /** + * Safely manipulate the DOM after updating the state when invoking + * `this.props.onEdit()` in the `handleEdit` method above. + * For more info refer to notes at https://facebook.github.io/react/docs/component-api.html#setstate + * and https://facebook.github.io/react/docs/component-specs.html#updating-componentdidupdate + */ + componentDidUpdate: function (prevProps) { + if (!prevProps.editing && this.props.editing) { + var node = React.findDOMNode(this.refs.editField); + node.focus(); + node.setSelectionRange(node.value.length, node.value.length); + } + }, + + render: function () { + return ( +
  • +
    + + +
    + +
  • + ); + } + }); + + var ENTER_KEY = 13; + + var TodoApp = React.createClass({ + getInitialState: function () { + return { + nowShowing: app.ALL_TODOS, + editing: null, + newTodo: '' + }; + }, + + componentDidMount: function () { + var setState = this.setState; + var router = Router({ + '/': setState.bind(this, {nowShowing: app.ALL_TODOS}), + '/active': setState.bind(this, {nowShowing: app.ACTIVE_TODOS}), + '/completed': setState.bind(this, {nowShowing: app.COMPLETED_TODOS}) + }); + router.init('/'); + }, + + handleChange: function (event) { + this.setState({newTodo: event.target.value}); + }, + + handleNewTodoKeyDown: function (event) { + if (event.keyCode !== ENTER_KEY) { + return; + } + + event.preventDefault(); + + var val = this.state.newTodo.trim(); + + if (val) { + this.props.model.addTodo(val); + this.setState({newTodo: ''}); + } + }, + + toggleAll: function (event) { + var checked = event.target.checked; + this.props.model.toggleAll(checked); + }, + + toggle: function (todoToToggle) { + this.props.model.toggle(todoToToggle); + }, + + destroy: function (todo) { + this.props.model.destroy(todo); + }, + + edit: function (todo) { + this.setState({editing: todo.id}); + }, + + save: function (todoToSave, text) { + this.props.model.save(todoToSave, text); + this.setState({editing: null}); + }, + + cancel: function () { + this.setState({editing: null}); + }, + + clearCompleted: function () { + this.props.model.clearCompleted(); + }, + + render: function () { + var footer; + var main; + var todos = this.props.model.todos; + + var shownTodos = todos.filter(function (todo) { + switch (this.state.nowShowing) { + case app.ACTIVE_TODOS: + return !todo.completed; + case app.COMPLETED_TODOS: + return todo.completed; + default: + return true; + } + }, this); + + var todoItems = shownTodos.map(function (todo) { + return ( + + ); + }, this); + + var activeTodoCount = todos.reduce(function (accum, todo) { + return todo.completed ? accum : accum + 1; + }, 0); + + var completedCount = todos.length - activeTodoCount; + + if (activeTodoCount || completedCount) { + footer = + ; + } + + if (todos.length) { + main = ( +
    + +
      + {todoItems} +
    +
    + ); + } + + return ( +
    +
    +

    todos

    + +
    + {main} + {footer} +
    + ); + } + }); + + var model = new app.TodoModel('react-todos'); + + function render() { + ReactDOM.render( + , + document.getElementsByClassName('todoapp')[0] + ); + } + + model.subscribe(render); + render(); +})(); diff --git a/bench/implementations/react-15.3.1/license.md b/bench/implementations/react-15.3.1/license.md new file mode 100644 index 0000000..fbfa2e3 --- /dev/null +++ b/bench/implementations/react-15.3.1/license.md @@ -0,0 +1,20 @@ +Everything in this repo is MIT License unless otherwise specified. + +Copyright (c) Addy Osmani, Sindre Sorhus, Pascal Hartig, Stephen Sawchuk. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/bench/implementations/react-15.3.1/package.json b/bench/implementations/react-15.3.1/package.json new file mode 100755 index 0000000..95189e7 --- /dev/null +++ b/bench/implementations/react-15.3.1/package.json @@ -0,0 +1,20 @@ +{ + "private": true, + "scripts": { + "make": "babel --plugins transform-react-jsx js/app.jsx | uglifyjs -o build.min.js" + }, + "dependencies": { + "classnames": "^2.2.5", + "director": "^1.2.8", + "react": "^15.3.1", + "react-dom": "^15.3.1", + "todomvc-app-css": "^2.0.0", + "todomvc-common": "^1.0.2" + }, + "devDependencies": { + "babel-cli": "^6.10.1", + "babel-plugin-transform-react-jsx": "^6.8.0", + "babel-plugin-uglify": "^1.0.2", + "uglify-js": "^2.6.4" + } +} diff --git a/bench/implementations/react-15.3.1/readme.md b/bench/implementations/react-15.3.1/readme.md new file mode 100755 index 0000000..c3d0894 --- /dev/null +++ b/bench/implementations/react-15.3.1/readme.md @@ -0,0 +1,31 @@ +# React TodoMVC for Benchmarking + +This is an update of the React TodoMVC example to use React 15.1 and +precompiled/minified JSX instead of the slow JSXTransformer. The idea is that +this is a reasonable approximation of the performance characteristics of modern +production React code. + +This is not a perfect reflection of React best practices, because there is no +such thing. If you ask five professional React users what current React best +practices are, you'll get five different answers—each of which will benchmark +differently. React Router, Immutable.js, Redux (with or without sagas), Ramda, +ES2015 (with various Babel plugins), Webpack...the list never ends. + +Rather than wading into that combinatorial explosion, this example is leaving +the original React TodoMVC implementation's supporting stack alone, and only +performing the following upgrades: + +* Upgrade to React 15.1 +* Move everything into one JSX file and precompile it with Babel +* Minify with uglify + +If you're curious how it benchmarks with your particular stack, please fork +this repo and find out! + +# Building + +1. `npm install` +2. `npm run make` +3. Open a local server (e.g. with `npm install -g http-server`) and open index.html + + diff --git a/bench/index.html b/bench/index.html new file mode 100644 index 0000000..8424d86 --- /dev/null +++ b/bench/index.html @@ -0,0 +1,66 @@ + + + + + + Performance Comparison + + + + + + + + + + +
    +

    Performance Comparison of Elm, React, Angular, and Ember

    +

    This is the benchmark behind Blazing Fast HTML, Round Two, so you can try it out for yourself. +

    +

    Controls are on the right. Pick which implementations you want to race and press “Run”. +

    +

    Between the full writeup and the repo for this runner, there is a bunch more information on the methodology and results of these benchmarks. Check them out! +

    +
    + + + + + + diff --git a/bench/readme.md b/bench/readme.md new file mode 100644 index 0000000..1b77d92 --- /dev/null +++ b/bench/readme.md @@ -0,0 +1,3 @@ +Change number of entries: +1. open src/add-complete-delete.js +2. change addCompleteDeleteSteps(500) diff --git a/bench/scratch/0bool b/bench/scratch/0bool new file mode 100644 index 0000000..02e4a84 --- /dev/null +++ b/bench/scratch/0bool @@ -0,0 +1 @@ +false \ No newline at end of file diff --git a/bench/scratch/0cstring b/bench/scratch/0cstring new file mode 100644 index 0000000..575ae13 --- /dev/null +++ b/bench/scratch/0cstring @@ -0,0 +1 @@ +dssdf \ No newline at end of file diff --git a/bench/src/.add-complete-delete.js.swp b/bench/src/.add-complete-delete.js.swp new file mode 100644 index 0000000..221c2c8 Binary files /dev/null and b/bench/src/.add-complete-delete.js.swp differ diff --git a/bench/src/Picker.elm b/bench/src/Picker.elm new file mode 100644 index 0000000..15db129 --- /dev/null +++ b/bench/src/Picker.elm @@ -0,0 +1,147 @@ +port module Picker exposing (main) + +import Html exposing (..) +import Html.App as App +import Html.Attributes exposing (..) +import Html.Events exposing (..) + + + +main = + App.programWithFlags + { init = init + , view = view + , update = update + , subscriptions = subscriptions + } + + + +-- MODEL + + +type alias Model = + { running : Bool + , entries : List Entry + } + + +type alias Entry = + { selected : Bool + , id : Int + , impl : Impl + } + + +type alias Impl = + { name : String + , version : String + , url : String + , optimized : Bool + } + + +init : List Impl -> ( Model, Cmd msg ) +init impls = + { running = False + , entries = List.indexedMap (Entry False) impls + } + ! [] + + + +-- UPDATE + + +type Msg + = Toggle Int + | Start + | End + + +update : Msg -> Model -> ( Model, Cmd msg ) +update msg model = + case msg of + Toggle id -> + { model | entries = toggle id model.entries } + ! [] + + Start -> + { model | running = True } + ! [ startSelected model.entries ] + + End -> + { model | running = False } + ! [] + + +toggle : Int -> List Entry -> List Entry +toggle id entries = + case entries of + [] -> + [] + + entry :: rest -> + if entry.id == id then + { entry | selected = not entry.selected } :: rest + + else + entry :: toggle id rest + + +port start : List Impl -> Cmd msg + + +startSelected : List Entry -> Cmd msg +startSelected entries = + start (List.map .impl (List.filter .selected entries)) + + + +-- SUBSCRIPTIONS + + +port end : (() -> msg) -> Sub msg + + +subscriptions : Model -> Sub Msg +subscriptions model = + end (always End) + + + +-- VIEW + + +view : Model -> Html Msg +view { running, entries } = + div [] + [ ul + (if running then [ style [("color", "#aaa")] ] else []) + (List.map (viewEntry running) entries) + , button + [ style [("width","100%")] + , disabled running + , onClick Start + ] + [ text "Run" ] + ] + + +viewEntry : Bool -> Entry -> Html Msg +viewEntry running { id, selected, impl } = + li + (if running then [ pointer ] else [ pointer, onClick (Toggle id) ]) + [ input [ type' "checkbox", checked selected, disabled running ] [] + , text (" " ++ impl.name ++ " " ++ impl.version) + , span + [ style [("color","#aaa")] + ] + [ text (if impl.optimized then " (optimized)" else "") + ] + ] + + +pointer : Attribute msg +pointer = + style [ ("cursor", "pointer") ] \ No newline at end of file diff --git a/bench/src/add-complete-delete-batched.js b/bench/src/add-complete-delete-batched.js new file mode 100644 index 0000000..ce69df7 --- /dev/null +++ b/bench/src/add-complete-delete-batched.js @@ -0,0 +1,76 @@ + +var suite = function() { + + +// FACTS + +function getFacts(doc) +{ + var input = doc.getElementsByClassName('new-todo')[0]; + return input ? { doc: doc, input: input } : undefined; +} + + +// STEPS + +function addCompleteDeleteSteps(numItems) +{ + return [ + { + name: 'Adding ' + numItems + ' Items', + work: add(numItems) + }, + { + name: 'Completing All Items', + work: clickAll('.toggle') + }, + { + name: 'Deleting All Items', + work: clickAll('.destroy') + } + ]; +} + +function add(numItems) +{ + return function(facts) + { + var node = facts.input; + + for (var i = 0; i < numItems; i++) + { + var inputEvent = document.createEvent('Event'); + inputEvent.initEvent('input', true, true); + node.value = 'Do task ' + i; + node.dispatchEvent(inputEvent); + + var keydownEvent = document.createEvent('Event'); + keydownEvent.initEvent('keydown', true, true); + keydownEvent.keyCode = 13; + node.dispatchEvent(keydownEvent); + } + }; +} + +function clickAll(selector) +{ + return function(facts) + { + var checkboxes = facts.doc.querySelectorAll(selector); + for (var i = 0; i < checkboxes.length; i++) + { + checkboxes[i].click(); + } + }; +} + + +// SUITE + +return { + getFacts: getFacts, + steps: addCompleteDeleteSteps(100) +}; + + +}(); \ No newline at end of file diff --git a/bench/src/add-complete-delete.js b/bench/src/add-complete-delete.js new file mode 100644 index 0000000..2b2d9f7 --- /dev/null +++ b/bench/src/add-complete-delete.js @@ -0,0 +1,88 @@ + +var suite = function() { + + +// FACTS + +function getFacts(doc) +{ + var input = doc.getElementsByClassName('new-todo')[0]; + return input ? { doc: doc, input: input } : undefined; +} + + +// STEPS + +function addCompleteDeleteSteps(numItems) +{ + var steps = []; + + for (var i = 0; i < numItems; i++) + { + steps.push({ name: 'Inputing ' + i, work: inputTodo(i) }); + steps.push({ name: 'Entering ' + i, work: pressEnter }); + } + + for (var i = 0; i < numItems; i++) + { + steps.push({ name: 'Checking ' + i, work: click('toggle', i) }); + } + + for (var i = 0; i < numItems; i++) + { + steps.push({ name: 'Removing ' + i, work: click('destroy', 0) }); + } + + return steps; +} + +function inputTodo(number) +{ + return function(facts) + { + var node = facts.input; + + var inputEvent = document.createEvent('Event'); + inputEvent.initEvent('input', true, true); + node.value = 'Do task ' + number; + node.dispatchEvent(inputEvent); + }; +} + +function pressEnter(facts) +{ + var event = document.createEvent('Event'); + event.initEvent('keydown', true, true); + event.key = 'Enter'; + event.keyCode = 13; + event.which = 13; + facts.input.dispatchEvent(event); + facts.input.click(); + + var ev = document.createEvent('Event'); + ev.initEvent('keyup', true, true); + ev.key = 'Enter'; + ev.keyCode = 13; + ev.which = 13; + facts.input.dispatchEvent(ev); + facts.input.click(); +} + +function click(className, index) +{ + return function(facts) + { + facts.doc.getElementsByClassName(className)[index].click(); + }; +} + + +// SUITE + +return { + getFacts: getFacts, + steps: addCompleteDeleteSteps(150) +}; + + +}(); diff --git a/bench/src/elm-package.json b/bench/src/elm-package.json new file mode 100644 index 0000000..110e106 --- /dev/null +++ b/bench/src/elm-package.json @@ -0,0 +1,15 @@ +{ + "version": "1.0.0", + "summary": "helpful summary of your project, less than 80 characters", + "repository": "https://github.com/user/project.git", + "license": "BSD3", + "source-directories": [ + "." + ], + "exposed-modules": [], + "dependencies": { + "elm-lang/core": "4.0.3 <= v < 5.0.0", + "elm-lang/html": "1.1.0 <= v < 2.0.0" + }, + "elm-version": "0.17.1 <= v < 0.18.0" +} diff --git a/bench/src/picker.js b/bench/src/picker.js new file mode 100644 index 0000000..1d6008a --- /dev/null +++ b/bench/src/picker.js @@ -0,0 +1,8174 @@ + +(function() { +'use strict'; + +function F2(fun) +{ + function wrapper(a) { return function(b) { return fun(a,b); }; } + wrapper.arity = 2; + wrapper.func = fun; + return wrapper; +} + +function F3(fun) +{ + function wrapper(a) { + return function(b) { return function(c) { return fun(a, b, c); }; }; + } + wrapper.arity = 3; + wrapper.func = fun; + return wrapper; +} + +function F4(fun) +{ + function wrapper(a) { return function(b) { return function(c) { + return function(d) { return fun(a, b, c, d); }; }; }; + } + wrapper.arity = 4; + wrapper.func = fun; + return wrapper; +} + +function F5(fun) +{ + function wrapper(a) { return function(b) { return function(c) { + return function(d) { return function(e) { return fun(a, b, c, d, e); }; }; }; }; + } + wrapper.arity = 5; + wrapper.func = fun; + return wrapper; +} + +function F6(fun) +{ + function wrapper(a) { return function(b) { return function(c) { + return function(d) { return function(e) { return function(f) { + return fun(a, b, c, d, e, f); }; }; }; }; }; + } + wrapper.arity = 6; + wrapper.func = fun; + return wrapper; +} + +function F7(fun) +{ + function wrapper(a) { return function(b) { return function(c) { + return function(d) { return function(e) { return function(f) { + return function(g) { return fun(a, b, c, d, e, f, g); }; }; }; }; }; }; + } + wrapper.arity = 7; + wrapper.func = fun; + return wrapper; +} + +function F8(fun) +{ + function wrapper(a) { return function(b) { return function(c) { + return function(d) { return function(e) { return function(f) { + return function(g) { return function(h) { + return fun(a, b, c, d, e, f, g, h); }; }; }; }; }; }; }; + } + wrapper.arity = 8; + wrapper.func = fun; + return wrapper; +} + +function F9(fun) +{ + function wrapper(a) { return function(b) { return function(c) { + return function(d) { return function(e) { return function(f) { + return function(g) { return function(h) { return function(i) { + return fun(a, b, c, d, e, f, g, h, i); }; }; }; }; }; }; }; }; + } + wrapper.arity = 9; + wrapper.func = fun; + return wrapper; +} + +function A2(fun, a, b) +{ + return fun.arity === 2 + ? fun.func(a, b) + : fun(a)(b); +} +function A3(fun, a, b, c) +{ + return fun.arity === 3 + ? fun.func(a, b, c) + : fun(a)(b)(c); +} +function A4(fun, a, b, c, d) +{ + return fun.arity === 4 + ? fun.func(a, b, c, d) + : fun(a)(b)(c)(d); +} +function A5(fun, a, b, c, d, e) +{ + return fun.arity === 5 + ? fun.func(a, b, c, d, e) + : fun(a)(b)(c)(d)(e); +} +function A6(fun, a, b, c, d, e, f) +{ + return fun.arity === 6 + ? fun.func(a, b, c, d, e, f) + : fun(a)(b)(c)(d)(e)(f); +} +function A7(fun, a, b, c, d, e, f, g) +{ + return fun.arity === 7 + ? fun.func(a, b, c, d, e, f, g) + : fun(a)(b)(c)(d)(e)(f)(g); +} +function A8(fun, a, b, c, d, e, f, g, h) +{ + return fun.arity === 8 + ? fun.func(a, b, c, d, e, f, g, h) + : fun(a)(b)(c)(d)(e)(f)(g)(h); +} +function A9(fun, a, b, c, d, e, f, g, h, i) +{ + return fun.arity === 9 + ? fun.func(a, b, c, d, e, f, g, h, i) + : fun(a)(b)(c)(d)(e)(f)(g)(h)(i); +} + +//import Native.List // + +var _elm_lang$core$Native_Array = function() { + +// A RRB-Tree has two distinct data types. +// Leaf -> "height" is always 0 +// "table" is an array of elements +// Node -> "height" is always greater than 0 +// "table" is an array of child nodes +// "lengths" is an array of accumulated lengths of the child nodes + +// M is the maximal table size. 32 seems fast. E is the allowed increase +// of search steps when concatting to find an index. Lower values will +// decrease balancing, but will increase search steps. +var M = 32; +var E = 2; + +// An empty array. +var empty = { + ctor: '_Array', + height: 0, + table: [] +}; + + +function get(i, array) +{ + if (i < 0 || i >= length(array)) + { + throw new Error( + 'Index ' + i + ' is out of range. Check the length of ' + + 'your array first or use getMaybe or getWithDefault.'); + } + return unsafeGet(i, array); +} + + +function unsafeGet(i, array) +{ + for (var x = array.height; x > 0; x--) + { + var slot = i >> (x * 5); + while (array.lengths[slot] <= i) + { + slot++; + } + if (slot > 0) + { + i -= array.lengths[slot - 1]; + } + array = array.table[slot]; + } + return array.table[i]; +} + + +// Sets the value at the index i. Only the nodes leading to i will get +// copied and updated. +function set(i, item, array) +{ + if (i < 0 || length(array) <= i) + { + return array; + } + return unsafeSet(i, item, array); +} + + +function unsafeSet(i, item, array) +{ + array = nodeCopy(array); + + if (array.height === 0) + { + array.table[i] = item; + } + else + { + var slot = getSlot(i, array); + if (slot > 0) + { + i -= array.lengths[slot - 1]; + } + array.table[slot] = unsafeSet(i, item, array.table[slot]); + } + return array; +} + + +function initialize(len, f) +{ + if (len <= 0) + { + return empty; + } + var h = Math.floor( Math.log(len) / Math.log(M) ); + return initialize_(f, h, 0, len); +} + +function initialize_(f, h, from, to) +{ + if (h === 0) + { + var table = new Array((to - from) % (M + 1)); + for (var i = 0; i < table.length; i++) + { + table[i] = f(from + i); + } + return { + ctor: '_Array', + height: 0, + table: table + }; + } + + var step = Math.pow(M, h); + var table = new Array(Math.ceil((to - from) / step)); + var lengths = new Array(table.length); + for (var i = 0; i < table.length; i++) + { + table[i] = initialize_(f, h - 1, from + (i * step), Math.min(from + ((i + 1) * step), to)); + lengths[i] = length(table[i]) + (i > 0 ? lengths[i-1] : 0); + } + return { + ctor: '_Array', + height: h, + table: table, + lengths: lengths + }; +} + +function fromList(list) +{ + if (list.ctor === '[]') + { + return empty; + } + + // Allocate M sized blocks (table) and write list elements to it. + var table = new Array(M); + var nodes = []; + var i = 0; + + while (list.ctor !== '[]') + { + table[i] = list._0; + list = list._1; + i++; + + // table is full, so we can push a leaf containing it into the + // next node. + if (i === M) + { + var leaf = { + ctor: '_Array', + height: 0, + table: table + }; + fromListPush(leaf, nodes); + table = new Array(M); + i = 0; + } + } + + // Maybe there is something left on the table. + if (i > 0) + { + var leaf = { + ctor: '_Array', + height: 0, + table: table.splice(0, i) + }; + fromListPush(leaf, nodes); + } + + // Go through all of the nodes and eventually push them into higher nodes. + for (var h = 0; h < nodes.length - 1; h++) + { + if (nodes[h].table.length > 0) + { + fromListPush(nodes[h], nodes); + } + } + + var head = nodes[nodes.length - 1]; + if (head.height > 0 && head.table.length === 1) + { + return head.table[0]; + } + else + { + return head; + } +} + +// Push a node into a higher node as a child. +function fromListPush(toPush, nodes) +{ + var h = toPush.height; + + // Maybe the node on this height does not exist. + if (nodes.length === h) + { + var node = { + ctor: '_Array', + height: h + 1, + table: [], + lengths: [] + }; + nodes.push(node); + } + + nodes[h].table.push(toPush); + var len = length(toPush); + if (nodes[h].lengths.length > 0) + { + len += nodes[h].lengths[nodes[h].lengths.length - 1]; + } + nodes[h].lengths.push(len); + + if (nodes[h].table.length === M) + { + fromListPush(nodes[h], nodes); + nodes[h] = { + ctor: '_Array', + height: h + 1, + table: [], + lengths: [] + }; + } +} + +// Pushes an item via push_ to the bottom right of a tree. +function push(item, a) +{ + var pushed = push_(item, a); + if (pushed !== null) + { + return pushed; + } + + var newTree = create(item, a.height); + return siblise(a, newTree); +} + +// Recursively tries to push an item to the bottom-right most +// tree possible. If there is no space left for the item, +// null will be returned. +function push_(item, a) +{ + // Handle resursion stop at leaf level. + if (a.height === 0) + { + if (a.table.length < M) + { + var newA = { + ctor: '_Array', + height: 0, + table: a.table.slice() + }; + newA.table.push(item); + return newA; + } + else + { + return null; + } + } + + // Recursively push + var pushed = push_(item, botRight(a)); + + // There was space in the bottom right tree, so the slot will + // be updated. + if (pushed !== null) + { + var newA = nodeCopy(a); + newA.table[newA.table.length - 1] = pushed; + newA.lengths[newA.lengths.length - 1]++; + return newA; + } + + // When there was no space left, check if there is space left + // for a new slot with a tree which contains only the item + // at the bottom. + if (a.table.length < M) + { + var newSlot = create(item, a.height - 1); + var newA = nodeCopy(a); + newA.table.push(newSlot); + newA.lengths.push(newA.lengths[newA.lengths.length - 1] + length(newSlot)); + return newA; + } + else + { + return null; + } +} + +// Converts an array into a list of elements. +function toList(a) +{ + return toList_(_elm_lang$core$Native_List.Nil, a); +} + +function toList_(list, a) +{ + for (var i = a.table.length - 1; i >= 0; i--) + { + list = + a.height === 0 + ? _elm_lang$core$Native_List.Cons(a.table[i], list) + : toList_(list, a.table[i]); + } + return list; +} + +// Maps a function over the elements of an array. +function map(f, a) +{ + var newA = { + ctor: '_Array', + height: a.height, + table: new Array(a.table.length) + }; + if (a.height > 0) + { + newA.lengths = a.lengths; + } + for (var i = 0; i < a.table.length; i++) + { + newA.table[i] = + a.height === 0 + ? f(a.table[i]) + : map(f, a.table[i]); + } + return newA; +} + +// Maps a function over the elements with their index as first argument. +function indexedMap(f, a) +{ + return indexedMap_(f, a, 0); +} + +function indexedMap_(f, a, from) +{ + var newA = { + ctor: '_Array', + height: a.height, + table: new Array(a.table.length) + }; + if (a.height > 0) + { + newA.lengths = a.lengths; + } + for (var i = 0; i < a.table.length; i++) + { + newA.table[i] = + a.height === 0 + ? A2(f, from + i, a.table[i]) + : indexedMap_(f, a.table[i], i == 0 ? from : from + a.lengths[i - 1]); + } + return newA; +} + +function foldl(f, b, a) +{ + if (a.height === 0) + { + for (var i = 0; i < a.table.length; i++) + { + b = A2(f, a.table[i], b); + } + } + else + { + for (var i = 0; i < a.table.length; i++) + { + b = foldl(f, b, a.table[i]); + } + } + return b; +} + +function foldr(f, b, a) +{ + if (a.height === 0) + { + for (var i = a.table.length; i--; ) + { + b = A2(f, a.table[i], b); + } + } + else + { + for (var i = a.table.length; i--; ) + { + b = foldr(f, b, a.table[i]); + } + } + return b; +} + +// TODO: currently, it slices the right, then the left. This can be +// optimized. +function slice(from, to, a) +{ + if (from < 0) + { + from += length(a); + } + if (to < 0) + { + to += length(a); + } + return sliceLeft(from, sliceRight(to, a)); +} + +function sliceRight(to, a) +{ + if (to === length(a)) + { + return a; + } + + // Handle leaf level. + if (a.height === 0) + { + var newA = { ctor:'_Array', height:0 }; + newA.table = a.table.slice(0, to); + return newA; + } + + // Slice the right recursively. + var right = getSlot(to, a); + var sliced = sliceRight(to - (right > 0 ? a.lengths[right - 1] : 0), a.table[right]); + + // Maybe the a node is not even needed, as sliced contains the whole slice. + if (right === 0) + { + return sliced; + } + + // Create new node. + var newA = { + ctor: '_Array', + height: a.height, + table: a.table.slice(0, right), + lengths: a.lengths.slice(0, right) + }; + if (sliced.table.length > 0) + { + newA.table[right] = sliced; + newA.lengths[right] = length(sliced) + (right > 0 ? newA.lengths[right - 1] : 0); + } + return newA; +} + +function sliceLeft(from, a) +{ + if (from === 0) + { + return a; + } + + // Handle leaf level. + if (a.height === 0) + { + var newA = { ctor:'_Array', height:0 }; + newA.table = a.table.slice(from, a.table.length + 1); + return newA; + } + + // Slice the left recursively. + var left = getSlot(from, a); + var sliced = sliceLeft(from - (left > 0 ? a.lengths[left - 1] : 0), a.table[left]); + + // Maybe the a node is not even needed, as sliced contains the whole slice. + if (left === a.table.length - 1) + { + return sliced; + } + + // Create new node. + var newA = { + ctor: '_Array', + height: a.height, + table: a.table.slice(left, a.table.length + 1), + lengths: new Array(a.table.length - left) + }; + newA.table[0] = sliced; + var len = 0; + for (var i = 0; i < newA.table.length; i++) + { + len += length(newA.table[i]); + newA.lengths[i] = len; + } + + return newA; +} + +// Appends two trees. +function append(a,b) +{ + if (a.table.length === 0) + { + return b; + } + if (b.table.length === 0) + { + return a; + } + + var c = append_(a, b); + + // Check if both nodes can be crunshed together. + if (c[0].table.length + c[1].table.length <= M) + { + if (c[0].table.length === 0) + { + return c[1]; + } + if (c[1].table.length === 0) + { + return c[0]; + } + + // Adjust .table and .lengths + c[0].table = c[0].table.concat(c[1].table); + if (c[0].height > 0) + { + var len = length(c[0]); + for (var i = 0; i < c[1].lengths.length; i++) + { + c[1].lengths[i] += len; + } + c[0].lengths = c[0].lengths.concat(c[1].lengths); + } + + return c[0]; + } + + if (c[0].height > 0) + { + var toRemove = calcToRemove(a, b); + if (toRemove > E) + { + c = shuffle(c[0], c[1], toRemove); + } + } + + return siblise(c[0], c[1]); +} + +// Returns an array of two nodes; right and left. One node _may_ be empty. +function append_(a, b) +{ + if (a.height === 0 && b.height === 0) + { + return [a, b]; + } + + if (a.height !== 1 || b.height !== 1) + { + if (a.height === b.height) + { + a = nodeCopy(a); + b = nodeCopy(b); + var appended = append_(botRight(a), botLeft(b)); + + insertRight(a, appended[1]); + insertLeft(b, appended[0]); + } + else if (a.height > b.height) + { + a = nodeCopy(a); + var appended = append_(botRight(a), b); + + insertRight(a, appended[0]); + b = parentise(appended[1], appended[1].height + 1); + } + else + { + b = nodeCopy(b); + var appended = append_(a, botLeft(b)); + + var left = appended[0].table.length === 0 ? 0 : 1; + var right = left === 0 ? 1 : 0; + insertLeft(b, appended[left]); + a = parentise(appended[right], appended[right].height + 1); + } + } + + // Check if balancing is needed and return based on that. + if (a.table.length === 0 || b.table.length === 0) + { + return [a, b]; + } + + var toRemove = calcToRemove(a, b); + if (toRemove <= E) + { + return [a, b]; + } + return shuffle(a, b, toRemove); +} + +// Helperfunctions for append_. Replaces a child node at the side of the parent. +function insertRight(parent, node) +{ + var index = parent.table.length - 1; + parent.table[index] = node; + parent.lengths[index] = length(node); + parent.lengths[index] += index > 0 ? parent.lengths[index - 1] : 0; +} + +function insertLeft(parent, node) +{ + if (node.table.length > 0) + { + parent.table[0] = node; + parent.lengths[0] = length(node); + + var len = length(parent.table[0]); + for (var i = 1; i < parent.lengths.length; i++) + { + len += length(parent.table[i]); + parent.lengths[i] = len; + } + } + else + { + parent.table.shift(); + for (var i = 1; i < parent.lengths.length; i++) + { + parent.lengths[i] = parent.lengths[i] - parent.lengths[0]; + } + parent.lengths.shift(); + } +} + +// Returns the extra search steps for E. Refer to the paper. +function calcToRemove(a, b) +{ + var subLengths = 0; + for (var i = 0; i < a.table.length; i++) + { + subLengths += a.table[i].table.length; + } + for (var i = 0; i < b.table.length; i++) + { + subLengths += b.table[i].table.length; + } + + var toRemove = a.table.length + b.table.length; + return toRemove - (Math.floor((subLengths - 1) / M) + 1); +} + +// get2, set2 and saveSlot are helpers for accessing elements over two arrays. +function get2(a, b, index) +{ + return index < a.length + ? a[index] + : b[index - a.length]; +} + +function set2(a, b, index, value) +{ + if (index < a.length) + { + a[index] = value; + } + else + { + b[index - a.length] = value; + } +} + +function saveSlot(a, b, index, slot) +{ + set2(a.table, b.table, index, slot); + + var l = (index === 0 || index === a.lengths.length) + ? 0 + : get2(a.lengths, a.lengths, index - 1); + + set2(a.lengths, b.lengths, index, l + length(slot)); +} + +// Creates a node or leaf with a given length at their arrays for perfomance. +// Is only used by shuffle. +function createNode(h, length) +{ + if (length < 0) + { + length = 0; + } + var a = { + ctor: '_Array', + height: h, + table: new Array(length) + }; + if (h > 0) + { + a.lengths = new Array(length); + } + return a; +} + +// Returns an array of two balanced nodes. +function shuffle(a, b, toRemove) +{ + var newA = createNode(a.height, Math.min(M, a.table.length + b.table.length - toRemove)); + var newB = createNode(a.height, newA.table.length - (a.table.length + b.table.length - toRemove)); + + // Skip the slots with size M. More precise: copy the slot references + // to the new node + var read = 0; + while (get2(a.table, b.table, read).table.length % M === 0) + { + set2(newA.table, newB.table, read, get2(a.table, b.table, read)); + set2(newA.lengths, newB.lengths, read, get2(a.lengths, b.lengths, read)); + read++; + } + + // Pulling items from left to right, caching in a slot before writing + // it into the new nodes. + var write = read; + var slot = new createNode(a.height - 1, 0); + var from = 0; + + // If the current slot is still containing data, then there will be at + // least one more write, so we do not break this loop yet. + while (read - write - (slot.table.length > 0 ? 1 : 0) < toRemove) + { + // Find out the max possible items for copying. + var source = get2(a.table, b.table, read); + var to = Math.min(M - slot.table.length, source.table.length); + + // Copy and adjust size table. + slot.table = slot.table.concat(source.table.slice(from, to)); + if (slot.height > 0) + { + var len = slot.lengths.length; + for (var i = len; i < len + to - from; i++) + { + slot.lengths[i] = length(slot.table[i]); + slot.lengths[i] += (i > 0 ? slot.lengths[i - 1] : 0); + } + } + + from += to; + + // Only proceed to next slots[i] if the current one was + // fully copied. + if (source.table.length <= to) + { + read++; from = 0; + } + + // Only create a new slot if the current one is filled up. + if (slot.table.length === M) + { + saveSlot(newA, newB, write, slot); + slot = createNode(a.height - 1, 0); + write++; + } + } + + // Cleanup after the loop. Copy the last slot into the new nodes. + if (slot.table.length > 0) + { + saveSlot(newA, newB, write, slot); + write++; + } + + // Shift the untouched slots to the left + while (read < a.table.length + b.table.length ) + { + saveSlot(newA, newB, write, get2(a.table, b.table, read)); + read++; + write++; + } + + return [newA, newB]; +} + +// Navigation functions +function botRight(a) +{ + return a.table[a.table.length - 1]; +} +function botLeft(a) +{ + return a.table[0]; +} + +// Copies a node for updating. Note that you should not use this if +// only updating only one of "table" or "lengths" for performance reasons. +function nodeCopy(a) +{ + var newA = { + ctor: '_Array', + height: a.height, + table: a.table.slice() + }; + if (a.height > 0) + { + newA.lengths = a.lengths.slice(); + } + return newA; +} + +// Returns how many items are in the tree. +function length(array) +{ + if (array.height === 0) + { + return array.table.length; + } + else + { + return array.lengths[array.lengths.length - 1]; + } +} + +// Calculates in which slot of "table" the item probably is, then +// find the exact slot via forward searching in "lengths". Returns the index. +function getSlot(i, a) +{ + var slot = i >> (5 * a.height); + while (a.lengths[slot] <= i) + { + slot++; + } + return slot; +} + +// Recursively creates a tree with a given height containing +// only the given item. +function create(item, h) +{ + if (h === 0) + { + return { + ctor: '_Array', + height: 0, + table: [item] + }; + } + return { + ctor: '_Array', + height: h, + table: [create(item, h - 1)], + lengths: [1] + }; +} + +// Recursively creates a tree that contains the given tree. +function parentise(tree, h) +{ + if (h === tree.height) + { + return tree; + } + + return { + ctor: '_Array', + height: h, + table: [parentise(tree, h - 1)], + lengths: [length(tree)] + }; +} + +// Emphasizes blood brotherhood beneath two trees. +function siblise(a, b) +{ + return { + ctor: '_Array', + height: a.height + 1, + table: [a, b], + lengths: [length(a), length(a) + length(b)] + }; +} + +function toJSArray(a) +{ + var jsArray = new Array(length(a)); + toJSArray_(jsArray, 0, a); + return jsArray; +} + +function toJSArray_(jsArray, i, a) +{ + for (var t = 0; t < a.table.length; t++) + { + if (a.height === 0) + { + jsArray[i + t] = a.table[t]; + } + else + { + var inc = t === 0 ? 0 : a.lengths[t - 1]; + toJSArray_(jsArray, i + inc, a.table[t]); + } + } +} + +function fromJSArray(jsArray) +{ + if (jsArray.length === 0) + { + return empty; + } + var h = Math.floor(Math.log(jsArray.length) / Math.log(M)); + return fromJSArray_(jsArray, h, 0, jsArray.length); +} + +function fromJSArray_(jsArray, h, from, to) +{ + if (h === 0) + { + return { + ctor: '_Array', + height: 0, + table: jsArray.slice(from, to) + }; + } + + var step = Math.pow(M, h); + var table = new Array(Math.ceil((to - from) / step)); + var lengths = new Array(table.length); + for (var i = 0; i < table.length; i++) + { + table[i] = fromJSArray_(jsArray, h - 1, from + (i * step), Math.min(from + ((i + 1) * step), to)); + lengths[i] = length(table[i]) + (i > 0 ? lengths[i - 1] : 0); + } + return { + ctor: '_Array', + height: h, + table: table, + lengths: lengths + }; +} + +return { + empty: empty, + fromList: fromList, + toList: toList, + initialize: F2(initialize), + append: F2(append), + push: F2(push), + slice: F3(slice), + get: F2(get), + set: F3(set), + map: F2(map), + indexedMap: F2(indexedMap), + foldl: F3(foldl), + foldr: F3(foldr), + length: length, + + toJSArray: toJSArray, + fromJSArray: fromJSArray +}; + +}(); +//import Native.Utils // + +var _elm_lang$core$Native_Basics = function() { + +function div(a, b) +{ + return (a / b) | 0; +} +function rem(a, b) +{ + return a % b; +} +function mod(a, b) +{ + if (b === 0) + { + throw new Error('Cannot perform mod 0. Division by zero error.'); + } + var r = a % b; + var m = a === 0 ? 0 : (b > 0 ? (a >= 0 ? r : r + b) : -mod(-a, -b)); + + return m === b ? 0 : m; +} +function logBase(base, n) +{ + return Math.log(n) / Math.log(base); +} +function negate(n) +{ + return -n; +} +function abs(n) +{ + return n < 0 ? -n : n; +} + +function min(a, b) +{ + return _elm_lang$core$Native_Utils.cmp(a, b) < 0 ? a : b; +} +function max(a, b) +{ + return _elm_lang$core$Native_Utils.cmp(a, b) > 0 ? a : b; +} +function clamp(lo, hi, n) +{ + return _elm_lang$core$Native_Utils.cmp(n, lo) < 0 + ? lo + : _elm_lang$core$Native_Utils.cmp(n, hi) > 0 + ? hi + : n; +} + +var ord = ['LT', 'EQ', 'GT']; + +function compare(x, y) +{ + return { ctor: ord[_elm_lang$core$Native_Utils.cmp(x, y) + 1] }; +} + +function xor(a, b) +{ + return a !== b; +} +function not(b) +{ + return !b; +} +function isInfinite(n) +{ + return n === Infinity || n === -Infinity; +} + +function truncate(n) +{ + return n | 0; +} + +function degrees(d) +{ + return d * Math.PI / 180; +} +function turns(t) +{ + return 2 * Math.PI * t; +} +function fromPolar(point) +{ + var r = point._0; + var t = point._1; + return _elm_lang$core$Native_Utils.Tuple2(r * Math.cos(t), r * Math.sin(t)); +} +function toPolar(point) +{ + var x = point._0; + var y = point._1; + return _elm_lang$core$Native_Utils.Tuple2(Math.sqrt(x * x + y * y), Math.atan2(y, x)); +} + +return { + div: F2(div), + rem: F2(rem), + mod: F2(mod), + + pi: Math.PI, + e: Math.E, + cos: Math.cos, + sin: Math.sin, + tan: Math.tan, + acos: Math.acos, + asin: Math.asin, + atan: Math.atan, + atan2: F2(Math.atan2), + + degrees: degrees, + turns: turns, + fromPolar: fromPolar, + toPolar: toPolar, + + sqrt: Math.sqrt, + logBase: F2(logBase), + negate: negate, + abs: abs, + min: F2(min), + max: F2(max), + clamp: F3(clamp), + compare: F2(compare), + + xor: F2(xor), + not: not, + + truncate: truncate, + ceiling: Math.ceil, + floor: Math.floor, + round: Math.round, + toFloat: function(x) { return x; }, + isNaN: isNaN, + isInfinite: isInfinite +}; + +}(); +//import // + +var _elm_lang$core$Native_Utils = function() { + +// COMPARISONS + +function eq(x, y) +{ + var stack = []; + var isEqual = eqHelp(x, y, 0, stack); + var pair; + while (isEqual && (pair = stack.pop())) + { + isEqual = eqHelp(pair.x, pair.y, 0, stack); + } + return isEqual; +} + + +function eqHelp(x, y, depth, stack) +{ + if (depth > 100) + { + stack.push({ x: x, y: y }); + return true; + } + + if (x === y) + { + return true; + } + + if (typeof x !== 'object') + { + if (typeof x === 'function') + { + throw new Error( + 'Trying to use `(==)` on functions. There is no way to know if functions are "the same" in the Elm sense.' + + ' Read more about this at http://package.elm-lang.org/packages/elm-lang/core/latest/Basics#==' + + ' which describes why it is this way and what the better version will look like.' + ); + } + return false; + } + + if (x === null || y === null) + { + return false + } + + if (x instanceof Date) + { + return x.getTime() === y.getTime(); + } + + if (!('ctor' in x)) + { + for (var key in x) + { + if (!eqHelp(x[key], y[key], depth + 1, stack)) + { + return false; + } + } + return true; + } + + // convert Dicts and Sets to lists + if (x.ctor === 'RBNode_elm_builtin' || x.ctor === 'RBEmpty_elm_builtin') + { + x = _elm_lang$core$Dict$toList(x); + y = _elm_lang$core$Dict$toList(y); + } + if (x.ctor === 'Set_elm_builtin') + { + x = _elm_lang$core$Set$toList(x); + y = _elm_lang$core$Set$toList(y); + } + + // check if lists are equal without recursion + if (x.ctor === '::') + { + var a = x; + var b = y; + while (a.ctor === '::' && b.ctor === '::') + { + if (!eqHelp(a._0, b._0, depth + 1, stack)) + { + return false; + } + a = a._1; + b = b._1; + } + return a.ctor === b.ctor; + } + + // check if Arrays are equal + if (x.ctor === '_Array') + { + var xs = _elm_lang$core$Native_Array.toJSArray(x); + var ys = _elm_lang$core$Native_Array.toJSArray(y); + if (xs.length !== ys.length) + { + return false; + } + for (var i = 0; i < xs.length; i++) + { + if (!eqHelp(xs[i], ys[i], depth + 1, stack)) + { + return false; + } + } + return true; + } + + if (!eqHelp(x.ctor, y.ctor, depth + 1, stack)) + { + return false; + } + + for (var key in x) + { + if (!eqHelp(x[key], y[key], depth + 1, stack)) + { + return false; + } + } + return true; +} + +// Code in Generate/JavaScript.hs, Basics.js, and List.js depends on +// the particular integer values assigned to LT, EQ, and GT. + +var LT = -1, EQ = 0, GT = 1; + +function cmp(x, y) +{ + if (typeof x !== 'object') + { + return x === y ? EQ : x < y ? LT : GT; + } + + if (x instanceof String) + { + var a = x.valueOf(); + var b = y.valueOf(); + return a === b ? EQ : a < b ? LT : GT; + } + + if (x.ctor === '::' || x.ctor === '[]') + { + while (x.ctor === '::' && y.ctor === '::') + { + var ord = cmp(x._0, y._0); + if (ord !== EQ) + { + return ord; + } + x = x._1; + y = y._1; + } + return x.ctor === y.ctor ? EQ : x.ctor === '[]' ? LT : GT; + } + + if (x.ctor.slice(0, 6) === '_Tuple') + { + var ord; + var n = x.ctor.slice(6) - 0; + var err = 'cannot compare tuples with more than 6 elements.'; + if (n === 0) return EQ; + if (n >= 1) { ord = cmp(x._0, y._0); if (ord !== EQ) return ord; + if (n >= 2) { ord = cmp(x._1, y._1); if (ord !== EQ) return ord; + if (n >= 3) { ord = cmp(x._2, y._2); if (ord !== EQ) return ord; + if (n >= 4) { ord = cmp(x._3, y._3); if (ord !== EQ) return ord; + if (n >= 5) { ord = cmp(x._4, y._4); if (ord !== EQ) return ord; + if (n >= 6) { ord = cmp(x._5, y._5); if (ord !== EQ) return ord; + if (n >= 7) throw new Error('Comparison error: ' + err); } } } } } } + return EQ; + } + + throw new Error( + 'Comparison error: comparison is only defined on ints, ' + + 'floats, times, chars, strings, lists of comparable values, ' + + 'and tuples of comparable values.' + ); +} + + +// COMMON VALUES + +var Tuple0 = { + ctor: '_Tuple0' +}; + +function Tuple2(x, y) +{ + return { + ctor: '_Tuple2', + _0: x, + _1: y + }; +} + +function chr(c) +{ + return new String(c); +} + + +// GUID + +var count = 0; +function guid(_) +{ + return count++; +} + + +// RECORDS + +function update(oldRecord, updatedFields) +{ + var newRecord = {}; + for (var key in oldRecord) + { + var value = (key in updatedFields) ? updatedFields[key] : oldRecord[key]; + newRecord[key] = value; + } + return newRecord; +} + + +//// LIST STUFF //// + +var Nil = { ctor: '[]' }; + +function Cons(hd, tl) +{ + return { + ctor: '::', + _0: hd, + _1: tl + }; +} + +function append(xs, ys) +{ + // append Strings + if (typeof xs === 'string') + { + return xs + ys; + } + + // append Lists + if (xs.ctor === '[]') + { + return ys; + } + var root = Cons(xs._0, Nil); + var curr = root; + xs = xs._1; + while (xs.ctor !== '[]') + { + curr._1 = Cons(xs._0, Nil); + xs = xs._1; + curr = curr._1; + } + curr._1 = ys; + return root; +} + + +// CRASHES + +function crash(moduleName, region) +{ + return function(message) { + throw new Error( + 'Ran into a `Debug.crash` in module `' + moduleName + '` ' + regionToString(region) + '\n' + + 'The message provided by the code author is:\n\n ' + + message + ); + }; +} + +function crashCase(moduleName, region, value) +{ + return function(message) { + throw new Error( + 'Ran into a `Debug.crash` in module `' + moduleName + '`\n\n' + + 'This was caused by the `case` expression ' + regionToString(region) + '.\n' + + 'One of the branches ended with a crash and the following value got through:\n\n ' + toString(value) + '\n\n' + + 'The message provided by the code author is:\n\n ' + + message + ); + }; +} + +function regionToString(region) +{ + if (region.start.line == region.end.line) + { + return 'on line ' + region.start.line; + } + return 'between lines ' + region.start.line + ' and ' + region.end.line; +} + + +// TO STRING + +function toString(v) +{ + var type = typeof v; + if (type === 'function') + { + var name = v.func ? v.func.name : v.name; + return ''; + } + + if (type === 'boolean') + { + return v ? 'True' : 'False'; + } + + if (type === 'number') + { + return v + ''; + } + + if (v instanceof String) + { + return '\'' + addSlashes(v, true) + '\''; + } + + if (type === 'string') + { + return '"' + addSlashes(v, false) + '"'; + } + + if (v === null) + { + return 'null'; + } + + if (type === 'object' && 'ctor' in v) + { + var ctorStarter = v.ctor.substring(0, 5); + + if (ctorStarter === '_Tupl') + { + var output = []; + for (var k in v) + { + if (k === 'ctor') continue; + output.push(toString(v[k])); + } + return '(' + output.join(',') + ')'; + } + + if (ctorStarter === '_Task') + { + return '' + } + + if (v.ctor === '_Array') + { + var list = _elm_lang$core$Array$toList(v); + return 'Array.fromList ' + toString(list); + } + + if (v.ctor === '') + { + return ''; + } + + if (v.ctor === '_Process') + { + return ''; + } + + if (v.ctor === '::') + { + var output = '[' + toString(v._0); + v = v._1; + while (v.ctor === '::') + { + output += ',' + toString(v._0); + v = v._1; + } + return output + ']'; + } + + if (v.ctor === '[]') + { + return '[]'; + } + + if (v.ctor === 'Set_elm_builtin') + { + return 'Set.fromList ' + toString(_elm_lang$core$Set$toList(v)); + } + + if (v.ctor === 'RBNode_elm_builtin' || v.ctor === 'RBEmpty_elm_builtin') + { + return 'Dict.fromList ' + toString(_elm_lang$core$Dict$toList(v)); + } + + var output = ''; + for (var i in v) + { + if (i === 'ctor') continue; + var str = toString(v[i]); + var c0 = str[0]; + var parenless = c0 === '{' || c0 === '(' || c0 === '<' || c0 === '"' || str.indexOf(' ') < 0; + output += ' ' + (parenless ? str : '(' + str + ')'); + } + return v.ctor + output; + } + + if (type === 'object') + { + if (v instanceof Date) + { + return '<' + v.toString() + '>'; + } + + if (v.elm_web_socket) + { + return ''; + } + + var output = []; + for (var k in v) + { + output.push(k + ' = ' + toString(v[k])); + } + if (output.length === 0) + { + return '{}'; + } + return '{ ' + output.join(', ') + ' }'; + } + + return ''; +} + +function addSlashes(str, isChar) +{ + var s = str.replace(/\\/g, '\\\\') + .replace(/\n/g, '\\n') + .replace(/\t/g, '\\t') + .replace(/\r/g, '\\r') + .replace(/\v/g, '\\v') + .replace(/\0/g, '\\0'); + if (isChar) + { + return s.replace(/\'/g, '\\\''); + } + else + { + return s.replace(/\"/g, '\\"'); + } +} + + +return { + eq: eq, + cmp: cmp, + Tuple0: Tuple0, + Tuple2: Tuple2, + chr: chr, + update: update, + guid: guid, + + append: F2(append), + + crash: crash, + crashCase: crashCase, + + toString: toString +}; + +}(); +var _elm_lang$core$Basics$uncurry = F2( + function (f, _p0) { + var _p1 = _p0; + return A2(f, _p1._0, _p1._1); + }); +var _elm_lang$core$Basics$curry = F3( + function (f, a, b) { + return f( + {ctor: '_Tuple2', _0: a, _1: b}); + }); +var _elm_lang$core$Basics$flip = F3( + function (f, b, a) { + return A2(f, a, b); + }); +var _elm_lang$core$Basics$snd = function (_p2) { + var _p3 = _p2; + return _p3._1; +}; +var _elm_lang$core$Basics$fst = function (_p4) { + var _p5 = _p4; + return _p5._0; +}; +var _elm_lang$core$Basics$always = F2( + function (a, _p6) { + return a; + }); +var _elm_lang$core$Basics$identity = function (x) { + return x; +}; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['<|'] = F2( + function (f, x) { + return f(x); + }); +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['|>'] = F2( + function (x, f) { + return f(x); + }); +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['>>'] = F3( + function (f, g, x) { + return g( + f(x)); + }); +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['<<'] = F3( + function (g, f, x) { + return g( + f(x)); + }); +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['++'] = _elm_lang$core$Native_Utils.append; +var _elm_lang$core$Basics$toString = _elm_lang$core$Native_Utils.toString; +var _elm_lang$core$Basics$isInfinite = _elm_lang$core$Native_Basics.isInfinite; +var _elm_lang$core$Basics$isNaN = _elm_lang$core$Native_Basics.isNaN; +var _elm_lang$core$Basics$toFloat = _elm_lang$core$Native_Basics.toFloat; +var _elm_lang$core$Basics$ceiling = _elm_lang$core$Native_Basics.ceiling; +var _elm_lang$core$Basics$floor = _elm_lang$core$Native_Basics.floor; +var _elm_lang$core$Basics$truncate = _elm_lang$core$Native_Basics.truncate; +var _elm_lang$core$Basics$round = _elm_lang$core$Native_Basics.round; +var _elm_lang$core$Basics$not = _elm_lang$core$Native_Basics.not; +var _elm_lang$core$Basics$xor = _elm_lang$core$Native_Basics.xor; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['||'] = _elm_lang$core$Native_Basics.or; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['&&'] = _elm_lang$core$Native_Basics.and; +var _elm_lang$core$Basics$max = _elm_lang$core$Native_Basics.max; +var _elm_lang$core$Basics$min = _elm_lang$core$Native_Basics.min; +var _elm_lang$core$Basics$compare = _elm_lang$core$Native_Basics.compare; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['>='] = _elm_lang$core$Native_Basics.ge; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['<='] = _elm_lang$core$Native_Basics.le; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['>'] = _elm_lang$core$Native_Basics.gt; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['<'] = _elm_lang$core$Native_Basics.lt; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['/='] = _elm_lang$core$Native_Basics.neq; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['=='] = _elm_lang$core$Native_Basics.eq; +var _elm_lang$core$Basics$e = _elm_lang$core$Native_Basics.e; +var _elm_lang$core$Basics$pi = _elm_lang$core$Native_Basics.pi; +var _elm_lang$core$Basics$clamp = _elm_lang$core$Native_Basics.clamp; +var _elm_lang$core$Basics$logBase = _elm_lang$core$Native_Basics.logBase; +var _elm_lang$core$Basics$abs = _elm_lang$core$Native_Basics.abs; +var _elm_lang$core$Basics$negate = _elm_lang$core$Native_Basics.negate; +var _elm_lang$core$Basics$sqrt = _elm_lang$core$Native_Basics.sqrt; +var _elm_lang$core$Basics$atan2 = _elm_lang$core$Native_Basics.atan2; +var _elm_lang$core$Basics$atan = _elm_lang$core$Native_Basics.atan; +var _elm_lang$core$Basics$asin = _elm_lang$core$Native_Basics.asin; +var _elm_lang$core$Basics$acos = _elm_lang$core$Native_Basics.acos; +var _elm_lang$core$Basics$tan = _elm_lang$core$Native_Basics.tan; +var _elm_lang$core$Basics$sin = _elm_lang$core$Native_Basics.sin; +var _elm_lang$core$Basics$cos = _elm_lang$core$Native_Basics.cos; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['^'] = _elm_lang$core$Native_Basics.exp; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['%'] = _elm_lang$core$Native_Basics.mod; +var _elm_lang$core$Basics$rem = _elm_lang$core$Native_Basics.rem; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['//'] = _elm_lang$core$Native_Basics.div; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['/'] = _elm_lang$core$Native_Basics.floatDiv; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['*'] = _elm_lang$core$Native_Basics.mul; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['-'] = _elm_lang$core$Native_Basics.sub; +var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {}; +_elm_lang$core$Basics_ops['+'] = _elm_lang$core$Native_Basics.add; +var _elm_lang$core$Basics$toPolar = _elm_lang$core$Native_Basics.toPolar; +var _elm_lang$core$Basics$fromPolar = _elm_lang$core$Native_Basics.fromPolar; +var _elm_lang$core$Basics$turns = _elm_lang$core$Native_Basics.turns; +var _elm_lang$core$Basics$degrees = _elm_lang$core$Native_Basics.degrees; +var _elm_lang$core$Basics$radians = function (t) { + return t; +}; +var _elm_lang$core$Basics$GT = {ctor: 'GT'}; +var _elm_lang$core$Basics$EQ = {ctor: 'EQ'}; +var _elm_lang$core$Basics$LT = {ctor: 'LT'}; +var _elm_lang$core$Basics$Never = function (a) { + return {ctor: 'Never', _0: a}; +}; + +var _elm_lang$core$Maybe$withDefault = F2( + function ($default, maybe) { + var _p0 = maybe; + if (_p0.ctor === 'Just') { + return _p0._0; + } else { + return $default; + } + }); +var _elm_lang$core$Maybe$Nothing = {ctor: 'Nothing'}; +var _elm_lang$core$Maybe$oneOf = function (maybes) { + oneOf: + while (true) { + var _p1 = maybes; + if (_p1.ctor === '[]') { + return _elm_lang$core$Maybe$Nothing; + } else { + var _p3 = _p1._0; + var _p2 = _p3; + if (_p2.ctor === 'Nothing') { + var _v3 = _p1._1; + maybes = _v3; + continue oneOf; + } else { + return _p3; + } + } + } +}; +var _elm_lang$core$Maybe$andThen = F2( + function (maybeValue, callback) { + var _p4 = maybeValue; + if (_p4.ctor === 'Just') { + return callback(_p4._0); + } else { + return _elm_lang$core$Maybe$Nothing; + } + }); +var _elm_lang$core$Maybe$Just = function (a) { + return {ctor: 'Just', _0: a}; +}; +var _elm_lang$core$Maybe$map = F2( + function (f, maybe) { + var _p5 = maybe; + if (_p5.ctor === 'Just') { + return _elm_lang$core$Maybe$Just( + f(_p5._0)); + } else { + return _elm_lang$core$Maybe$Nothing; + } + }); +var _elm_lang$core$Maybe$map2 = F3( + function (func, ma, mb) { + var _p6 = {ctor: '_Tuple2', _0: ma, _1: mb}; + if (((_p6.ctor === '_Tuple2') && (_p6._0.ctor === 'Just')) && (_p6._1.ctor === 'Just')) { + return _elm_lang$core$Maybe$Just( + A2(func, _p6._0._0, _p6._1._0)); + } else { + return _elm_lang$core$Maybe$Nothing; + } + }); +var _elm_lang$core$Maybe$map3 = F4( + function (func, ma, mb, mc) { + var _p7 = {ctor: '_Tuple3', _0: ma, _1: mb, _2: mc}; + if ((((_p7.ctor === '_Tuple3') && (_p7._0.ctor === 'Just')) && (_p7._1.ctor === 'Just')) && (_p7._2.ctor === 'Just')) { + return _elm_lang$core$Maybe$Just( + A3(func, _p7._0._0, _p7._1._0, _p7._2._0)); + } else { + return _elm_lang$core$Maybe$Nothing; + } + }); +var _elm_lang$core$Maybe$map4 = F5( + function (func, ma, mb, mc, md) { + var _p8 = {ctor: '_Tuple4', _0: ma, _1: mb, _2: mc, _3: md}; + if (((((_p8.ctor === '_Tuple4') && (_p8._0.ctor === 'Just')) && (_p8._1.ctor === 'Just')) && (_p8._2.ctor === 'Just')) && (_p8._3.ctor === 'Just')) { + return _elm_lang$core$Maybe$Just( + A4(func, _p8._0._0, _p8._1._0, _p8._2._0, _p8._3._0)); + } else { + return _elm_lang$core$Maybe$Nothing; + } + }); +var _elm_lang$core$Maybe$map5 = F6( + function (func, ma, mb, mc, md, me) { + var _p9 = {ctor: '_Tuple5', _0: ma, _1: mb, _2: mc, _3: md, _4: me}; + if ((((((_p9.ctor === '_Tuple5') && (_p9._0.ctor === 'Just')) && (_p9._1.ctor === 'Just')) && (_p9._2.ctor === 'Just')) && (_p9._3.ctor === 'Just')) && (_p9._4.ctor === 'Just')) { + return _elm_lang$core$Maybe$Just( + A5(func, _p9._0._0, _p9._1._0, _p9._2._0, _p9._3._0, _p9._4._0)); + } else { + return _elm_lang$core$Maybe$Nothing; + } + }); + +//import Native.Utils // + +var _elm_lang$core$Native_List = function() { + +var Nil = { ctor: '[]' }; + +function Cons(hd, tl) +{ + return { ctor: '::', _0: hd, _1: tl }; +} + +function fromArray(arr) +{ + var out = Nil; + for (var i = arr.length; i--; ) + { + out = Cons(arr[i], out); + } + return out; +} + +function toArray(xs) +{ + var out = []; + while (xs.ctor !== '[]') + { + out.push(xs._0); + xs = xs._1; + } + return out; +} + + +function range(lo, hi) +{ + var list = Nil; + if (lo <= hi) + { + do + { + list = Cons(hi, list); + } + while (hi-- > lo); + } + return list; +} + +function foldr(f, b, xs) +{ + var arr = toArray(xs); + var acc = b; + for (var i = arr.length; i--; ) + { + acc = A2(f, arr[i], acc); + } + return acc; +} + +function map2(f, xs, ys) +{ + var arr = []; + while (xs.ctor !== '[]' && ys.ctor !== '[]') + { + arr.push(A2(f, xs._0, ys._0)); + xs = xs._1; + ys = ys._1; + } + return fromArray(arr); +} + +function map3(f, xs, ys, zs) +{ + var arr = []; + while (xs.ctor !== '[]' && ys.ctor !== '[]' && zs.ctor !== '[]') + { + arr.push(A3(f, xs._0, ys._0, zs._0)); + xs = xs._1; + ys = ys._1; + zs = zs._1; + } + return fromArray(arr); +} + +function map4(f, ws, xs, ys, zs) +{ + var arr = []; + while ( ws.ctor !== '[]' + && xs.ctor !== '[]' + && ys.ctor !== '[]' + && zs.ctor !== '[]') + { + arr.push(A4(f, ws._0, xs._0, ys._0, zs._0)); + ws = ws._1; + xs = xs._1; + ys = ys._1; + zs = zs._1; + } + return fromArray(arr); +} + +function map5(f, vs, ws, xs, ys, zs) +{ + var arr = []; + while ( vs.ctor !== '[]' + && ws.ctor !== '[]' + && xs.ctor !== '[]' + && ys.ctor !== '[]' + && zs.ctor !== '[]') + { + arr.push(A5(f, vs._0, ws._0, xs._0, ys._0, zs._0)); + vs = vs._1; + ws = ws._1; + xs = xs._1; + ys = ys._1; + zs = zs._1; + } + return fromArray(arr); +} + +function sortBy(f, xs) +{ + return fromArray(toArray(xs).sort(function(a, b) { + return _elm_lang$core$Native_Utils.cmp(f(a), f(b)); + })); +} + +function sortWith(f, xs) +{ + return fromArray(toArray(xs).sort(function(a, b) { + var ord = f(a)(b).ctor; + return ord === 'EQ' ? 0 : ord === 'LT' ? -1 : 1; + })); +} + +return { + Nil: Nil, + Cons: Cons, + cons: F2(Cons), + toArray: toArray, + fromArray: fromArray, + range: range, + + foldr: F3(foldr), + + map2: F3(map2), + map3: F4(map3), + map4: F5(map4), + map5: F6(map5), + sortBy: F2(sortBy), + sortWith: F2(sortWith) +}; + +}(); +var _elm_lang$core$List$sortWith = _elm_lang$core$Native_List.sortWith; +var _elm_lang$core$List$sortBy = _elm_lang$core$Native_List.sortBy; +var _elm_lang$core$List$sort = function (xs) { + return A2(_elm_lang$core$List$sortBy, _elm_lang$core$Basics$identity, xs); +}; +var _elm_lang$core$List$drop = F2( + function (n, list) { + drop: + while (true) { + if (_elm_lang$core$Native_Utils.cmp(n, 0) < 1) { + return list; + } else { + var _p0 = list; + if (_p0.ctor === '[]') { + return list; + } else { + var _v1 = n - 1, + _v2 = _p0._1; + n = _v1; + list = _v2; + continue drop; + } + } + } + }); +var _elm_lang$core$List$map5 = _elm_lang$core$Native_List.map5; +var _elm_lang$core$List$map4 = _elm_lang$core$Native_List.map4; +var _elm_lang$core$List$map3 = _elm_lang$core$Native_List.map3; +var _elm_lang$core$List$map2 = _elm_lang$core$Native_List.map2; +var _elm_lang$core$List$any = F2( + function (isOkay, list) { + any: + while (true) { + var _p1 = list; + if (_p1.ctor === '[]') { + return false; + } else { + if (isOkay(_p1._0)) { + return true; + } else { + var _v4 = isOkay, + _v5 = _p1._1; + isOkay = _v4; + list = _v5; + continue any; + } + } + } + }); +var _elm_lang$core$List$all = F2( + function (isOkay, list) { + return _elm_lang$core$Basics$not( + A2( + _elm_lang$core$List$any, + function (_p2) { + return _elm_lang$core$Basics$not( + isOkay(_p2)); + }, + list)); + }); +var _elm_lang$core$List$foldr = _elm_lang$core$Native_List.foldr; +var _elm_lang$core$List$foldl = F3( + function (func, acc, list) { + foldl: + while (true) { + var _p3 = list; + if (_p3.ctor === '[]') { + return acc; + } else { + var _v7 = func, + _v8 = A2(func, _p3._0, acc), + _v9 = _p3._1; + func = _v7; + acc = _v8; + list = _v9; + continue foldl; + } + } + }); +var _elm_lang$core$List$length = function (xs) { + return A3( + _elm_lang$core$List$foldl, + F2( + function (_p4, i) { + return i + 1; + }), + 0, + xs); +}; +var _elm_lang$core$List$sum = function (numbers) { + return A3( + _elm_lang$core$List$foldl, + F2( + function (x, y) { + return x + y; + }), + 0, + numbers); +}; +var _elm_lang$core$List$product = function (numbers) { + return A3( + _elm_lang$core$List$foldl, + F2( + function (x, y) { + return x * y; + }), + 1, + numbers); +}; +var _elm_lang$core$List$maximum = function (list) { + var _p5 = list; + if (_p5.ctor === '::') { + return _elm_lang$core$Maybe$Just( + A3(_elm_lang$core$List$foldl, _elm_lang$core$Basics$max, _p5._0, _p5._1)); + } else { + return _elm_lang$core$Maybe$Nothing; + } +}; +var _elm_lang$core$List$minimum = function (list) { + var _p6 = list; + if (_p6.ctor === '::') { + return _elm_lang$core$Maybe$Just( + A3(_elm_lang$core$List$foldl, _elm_lang$core$Basics$min, _p6._0, _p6._1)); + } else { + return _elm_lang$core$Maybe$Nothing; + } +}; +var _elm_lang$core$List$indexedMap = F2( + function (f, xs) { + return A3( + _elm_lang$core$List$map2, + f, + _elm_lang$core$Native_List.range( + 0, + _elm_lang$core$List$length(xs) - 1), + xs); + }); +var _elm_lang$core$List$member = F2( + function (x, xs) { + return A2( + _elm_lang$core$List$any, + function (a) { + return _elm_lang$core$Native_Utils.eq(a, x); + }, + xs); + }); +var _elm_lang$core$List$isEmpty = function (xs) { + var _p7 = xs; + if (_p7.ctor === '[]') { + return true; + } else { + return false; + } +}; +var _elm_lang$core$List$tail = function (list) { + var _p8 = list; + if (_p8.ctor === '::') { + return _elm_lang$core$Maybe$Just(_p8._1); + } else { + return _elm_lang$core$Maybe$Nothing; + } +}; +var _elm_lang$core$List$head = function (list) { + var _p9 = list; + if (_p9.ctor === '::') { + return _elm_lang$core$Maybe$Just(_p9._0); + } else { + return _elm_lang$core$Maybe$Nothing; + } +}; +var _elm_lang$core$List_ops = _elm_lang$core$List_ops || {}; +_elm_lang$core$List_ops['::'] = _elm_lang$core$Native_List.cons; +var _elm_lang$core$List$map = F2( + function (f, xs) { + return A3( + _elm_lang$core$List$foldr, + F2( + function (x, acc) { + return A2( + _elm_lang$core$List_ops['::'], + f(x), + acc); + }), + _elm_lang$core$Native_List.fromArray( + []), + xs); + }); +var _elm_lang$core$List$filter = F2( + function (pred, xs) { + var conditionalCons = F2( + function (x, xs$) { + return pred(x) ? A2(_elm_lang$core$List_ops['::'], x, xs$) : xs$; + }); + return A3( + _elm_lang$core$List$foldr, + conditionalCons, + _elm_lang$core$Native_List.fromArray( + []), + xs); + }); +var _elm_lang$core$List$maybeCons = F3( + function (f, mx, xs) { + var _p10 = f(mx); + if (_p10.ctor === 'Just') { + return A2(_elm_lang$core$List_ops['::'], _p10._0, xs); + } else { + return xs; + } + }); +var _elm_lang$core$List$filterMap = F2( + function (f, xs) { + return A3( + _elm_lang$core$List$foldr, + _elm_lang$core$List$maybeCons(f), + _elm_lang$core$Native_List.fromArray( + []), + xs); + }); +var _elm_lang$core$List$reverse = function (list) { + return A3( + _elm_lang$core$List$foldl, + F2( + function (x, y) { + return A2(_elm_lang$core$List_ops['::'], x, y); + }), + _elm_lang$core$Native_List.fromArray( + []), + list); +}; +var _elm_lang$core$List$scanl = F3( + function (f, b, xs) { + var scan1 = F2( + function (x, accAcc) { + var _p11 = accAcc; + if (_p11.ctor === '::') { + return A2( + _elm_lang$core$List_ops['::'], + A2(f, x, _p11._0), + accAcc); + } else { + return _elm_lang$core$Native_List.fromArray( + []); + } + }); + return _elm_lang$core$List$reverse( + A3( + _elm_lang$core$List$foldl, + scan1, + _elm_lang$core$Native_List.fromArray( + [b]), + xs)); + }); +var _elm_lang$core$List$append = F2( + function (xs, ys) { + var _p12 = ys; + if (_p12.ctor === '[]') { + return xs; + } else { + return A3( + _elm_lang$core$List$foldr, + F2( + function (x, y) { + return A2(_elm_lang$core$List_ops['::'], x, y); + }), + ys, + xs); + } + }); +var _elm_lang$core$List$concat = function (lists) { + return A3( + _elm_lang$core$List$foldr, + _elm_lang$core$List$append, + _elm_lang$core$Native_List.fromArray( + []), + lists); +}; +var _elm_lang$core$List$concatMap = F2( + function (f, list) { + return _elm_lang$core$List$concat( + A2(_elm_lang$core$List$map, f, list)); + }); +var _elm_lang$core$List$partition = F2( + function (pred, list) { + var step = F2( + function (x, _p13) { + var _p14 = _p13; + var _p16 = _p14._0; + var _p15 = _p14._1; + return pred(x) ? { + ctor: '_Tuple2', + _0: A2(_elm_lang$core$List_ops['::'], x, _p16), + _1: _p15 + } : { + ctor: '_Tuple2', + _0: _p16, + _1: A2(_elm_lang$core$List_ops['::'], x, _p15) + }; + }); + return A3( + _elm_lang$core$List$foldr, + step, + { + ctor: '_Tuple2', + _0: _elm_lang$core$Native_List.fromArray( + []), + _1: _elm_lang$core$Native_List.fromArray( + []) + }, + list); + }); +var _elm_lang$core$List$unzip = function (pairs) { + var step = F2( + function (_p18, _p17) { + var _p19 = _p18; + var _p20 = _p17; + return { + ctor: '_Tuple2', + _0: A2(_elm_lang$core$List_ops['::'], _p19._0, _p20._0), + _1: A2(_elm_lang$core$List_ops['::'], _p19._1, _p20._1) + }; + }); + return A3( + _elm_lang$core$List$foldr, + step, + { + ctor: '_Tuple2', + _0: _elm_lang$core$Native_List.fromArray( + []), + _1: _elm_lang$core$Native_List.fromArray( + []) + }, + pairs); +}; +var _elm_lang$core$List$intersperse = F2( + function (sep, xs) { + var _p21 = xs; + if (_p21.ctor === '[]') { + return _elm_lang$core$Native_List.fromArray( + []); + } else { + var step = F2( + function (x, rest) { + return A2( + _elm_lang$core$List_ops['::'], + sep, + A2(_elm_lang$core$List_ops['::'], x, rest)); + }); + var spersed = A3( + _elm_lang$core$List$foldr, + step, + _elm_lang$core$Native_List.fromArray( + []), + _p21._1); + return A2(_elm_lang$core$List_ops['::'], _p21._0, spersed); + } + }); +var _elm_lang$core$List$takeReverse = F3( + function (n, list, taken) { + takeReverse: + while (true) { + if (_elm_lang$core$Native_Utils.cmp(n, 0) < 1) { + return taken; + } else { + var _p22 = list; + if (_p22.ctor === '[]') { + return taken; + } else { + var _v23 = n - 1, + _v24 = _p22._1, + _v25 = A2(_elm_lang$core$List_ops['::'], _p22._0, taken); + n = _v23; + list = _v24; + taken = _v25; + continue takeReverse; + } + } + } + }); +var _elm_lang$core$List$takeTailRec = F2( + function (n, list) { + return _elm_lang$core$List$reverse( + A3( + _elm_lang$core$List$takeReverse, + n, + list, + _elm_lang$core$Native_List.fromArray( + []))); + }); +var _elm_lang$core$List$takeFast = F3( + function (ctr, n, list) { + if (_elm_lang$core$Native_Utils.cmp(n, 0) < 1) { + return _elm_lang$core$Native_List.fromArray( + []); + } else { + var _p23 = {ctor: '_Tuple2', _0: n, _1: list}; + _v26_5: + do { + _v26_1: + do { + if (_p23.ctor === '_Tuple2') { + if (_p23._1.ctor === '[]') { + return list; + } else { + if (_p23._1._1.ctor === '::') { + switch (_p23._0) { + case 1: + break _v26_1; + case 2: + return _elm_lang$core$Native_List.fromArray( + [_p23._1._0, _p23._1._1._0]); + case 3: + if (_p23._1._1._1.ctor === '::') { + return _elm_lang$core$Native_List.fromArray( + [_p23._1._0, _p23._1._1._0, _p23._1._1._1._0]); + } else { + break _v26_5; + } + default: + if ((_p23._1._1._1.ctor === '::') && (_p23._1._1._1._1.ctor === '::')) { + var _p28 = _p23._1._1._1._0; + var _p27 = _p23._1._1._0; + var _p26 = _p23._1._0; + var _p25 = _p23._1._1._1._1._0; + var _p24 = _p23._1._1._1._1._1; + return (_elm_lang$core$Native_Utils.cmp(ctr, 1000) > 0) ? A2( + _elm_lang$core$List_ops['::'], + _p26, + A2( + _elm_lang$core$List_ops['::'], + _p27, + A2( + _elm_lang$core$List_ops['::'], + _p28, + A2( + _elm_lang$core$List_ops['::'], + _p25, + A2(_elm_lang$core$List$takeTailRec, n - 4, _p24))))) : A2( + _elm_lang$core$List_ops['::'], + _p26, + A2( + _elm_lang$core$List_ops['::'], + _p27, + A2( + _elm_lang$core$List_ops['::'], + _p28, + A2( + _elm_lang$core$List_ops['::'], + _p25, + A3(_elm_lang$core$List$takeFast, ctr + 1, n - 4, _p24))))); + } else { + break _v26_5; + } + } + } else { + if (_p23._0 === 1) { + break _v26_1; + } else { + break _v26_5; + } + } + } + } else { + break _v26_5; + } + } while(false); + return _elm_lang$core$Native_List.fromArray( + [_p23._1._0]); + } while(false); + return list; + } + }); +var _elm_lang$core$List$take = F2( + function (n, list) { + return A3(_elm_lang$core$List$takeFast, 0, n, list); + }); +var _elm_lang$core$List$repeatHelp = F3( + function (result, n, value) { + repeatHelp: + while (true) { + if (_elm_lang$core$Native_Utils.cmp(n, 0) < 1) { + return result; + } else { + var _v27 = A2(_elm_lang$core$List_ops['::'], value, result), + _v28 = n - 1, + _v29 = value; + result = _v27; + n = _v28; + value = _v29; + continue repeatHelp; + } + } + }); +var _elm_lang$core$List$repeat = F2( + function (n, value) { + return A3( + _elm_lang$core$List$repeatHelp, + _elm_lang$core$Native_List.fromArray( + []), + n, + value); + }); + +var _elm_lang$core$Array$append = _elm_lang$core$Native_Array.append; +var _elm_lang$core$Array$length = _elm_lang$core$Native_Array.length; +var _elm_lang$core$Array$isEmpty = function (array) { + return _elm_lang$core$Native_Utils.eq( + _elm_lang$core$Array$length(array), + 0); +}; +var _elm_lang$core$Array$slice = _elm_lang$core$Native_Array.slice; +var _elm_lang$core$Array$set = _elm_lang$core$Native_Array.set; +var _elm_lang$core$Array$get = F2( + function (i, array) { + return ((_elm_lang$core$Native_Utils.cmp(0, i) < 1) && (_elm_lang$core$Native_Utils.cmp( + i, + _elm_lang$core$Native_Array.length(array)) < 0)) ? _elm_lang$core$Maybe$Just( + A2(_elm_lang$core$Native_Array.get, i, array)) : _elm_lang$core$Maybe$Nothing; + }); +var _elm_lang$core$Array$push = _elm_lang$core$Native_Array.push; +var _elm_lang$core$Array$empty = _elm_lang$core$Native_Array.empty; +var _elm_lang$core$Array$filter = F2( + function (isOkay, arr) { + var update = F2( + function (x, xs) { + return isOkay(x) ? A2(_elm_lang$core$Native_Array.push, x, xs) : xs; + }); + return A3(_elm_lang$core$Native_Array.foldl, update, _elm_lang$core$Native_Array.empty, arr); + }); +var _elm_lang$core$Array$foldr = _elm_lang$core$Native_Array.foldr; +var _elm_lang$core$Array$foldl = _elm_lang$core$Native_Array.foldl; +var _elm_lang$core$Array$indexedMap = _elm_lang$core$Native_Array.indexedMap; +var _elm_lang$core$Array$map = _elm_lang$core$Native_Array.map; +var _elm_lang$core$Array$toIndexedList = function (array) { + return A3( + _elm_lang$core$List$map2, + F2( + function (v0, v1) { + return {ctor: '_Tuple2', _0: v0, _1: v1}; + }), + _elm_lang$core$Native_List.range( + 0, + _elm_lang$core$Native_Array.length(array) - 1), + _elm_lang$core$Native_Array.toList(array)); +}; +var _elm_lang$core$Array$toList = _elm_lang$core$Native_Array.toList; +var _elm_lang$core$Array$fromList = _elm_lang$core$Native_Array.fromList; +var _elm_lang$core$Array$initialize = _elm_lang$core$Native_Array.initialize; +var _elm_lang$core$Array$repeat = F2( + function (n, e) { + return A2( + _elm_lang$core$Array$initialize, + n, + _elm_lang$core$Basics$always(e)); + }); +var _elm_lang$core$Array$Array = {ctor: 'Array'}; + +//import Native.Utils // + +var _elm_lang$core$Native_Char = function() { + +return { + fromCode: function(c) { return _elm_lang$core$Native_Utils.chr(String.fromCharCode(c)); }, + toCode: function(c) { return c.charCodeAt(0); }, + toUpper: function(c) { return _elm_lang$core$Native_Utils.chr(c.toUpperCase()); }, + toLower: function(c) { return _elm_lang$core$Native_Utils.chr(c.toLowerCase()); }, + toLocaleUpper: function(c) { return _elm_lang$core$Native_Utils.chr(c.toLocaleUpperCase()); }, + toLocaleLower: function(c) { return _elm_lang$core$Native_Utils.chr(c.toLocaleLowerCase()); } +}; + +}(); +var _elm_lang$core$Char$fromCode = _elm_lang$core$Native_Char.fromCode; +var _elm_lang$core$Char$toCode = _elm_lang$core$Native_Char.toCode; +var _elm_lang$core$Char$toLocaleLower = _elm_lang$core$Native_Char.toLocaleLower; +var _elm_lang$core$Char$toLocaleUpper = _elm_lang$core$Native_Char.toLocaleUpper; +var _elm_lang$core$Char$toLower = _elm_lang$core$Native_Char.toLower; +var _elm_lang$core$Char$toUpper = _elm_lang$core$Native_Char.toUpper; +var _elm_lang$core$Char$isBetween = F3( + function (low, high, $char) { + var code = _elm_lang$core$Char$toCode($char); + return (_elm_lang$core$Native_Utils.cmp( + code, + _elm_lang$core$Char$toCode(low)) > -1) && (_elm_lang$core$Native_Utils.cmp( + code, + _elm_lang$core$Char$toCode(high)) < 1); + }); +var _elm_lang$core$Char$isUpper = A2( + _elm_lang$core$Char$isBetween, + _elm_lang$core$Native_Utils.chr('A'), + _elm_lang$core$Native_Utils.chr('Z')); +var _elm_lang$core$Char$isLower = A2( + _elm_lang$core$Char$isBetween, + _elm_lang$core$Native_Utils.chr('a'), + _elm_lang$core$Native_Utils.chr('z')); +var _elm_lang$core$Char$isDigit = A2( + _elm_lang$core$Char$isBetween, + _elm_lang$core$Native_Utils.chr('0'), + _elm_lang$core$Native_Utils.chr('9')); +var _elm_lang$core$Char$isOctDigit = A2( + _elm_lang$core$Char$isBetween, + _elm_lang$core$Native_Utils.chr('0'), + _elm_lang$core$Native_Utils.chr('7')); +var _elm_lang$core$Char$isHexDigit = function ($char) { + return _elm_lang$core$Char$isDigit($char) || (A3( + _elm_lang$core$Char$isBetween, + _elm_lang$core$Native_Utils.chr('a'), + _elm_lang$core$Native_Utils.chr('f'), + $char) || A3( + _elm_lang$core$Char$isBetween, + _elm_lang$core$Native_Utils.chr('A'), + _elm_lang$core$Native_Utils.chr('F'), + $char)); +}; + +//import Native.Utils // + +var _elm_lang$core$Native_Scheduler = function() { + +var MAX_STEPS = 10000; + + +// TASKS + +function succeed(value) +{ + return { + ctor: '_Task_succeed', + value: value + }; +} + +function fail(error) +{ + return { + ctor: '_Task_fail', + value: error + }; +} + +function nativeBinding(callback) +{ + return { + ctor: '_Task_nativeBinding', + callback: callback, + cancel: null + }; +} + +function andThen(task, callback) +{ + return { + ctor: '_Task_andThen', + task: task, + callback: callback + }; +} + +function onError(task, callback) +{ + return { + ctor: '_Task_onError', + task: task, + callback: callback + }; +} + +function receive(callback) +{ + return { + ctor: '_Task_receive', + callback: callback + }; +} + + +// PROCESSES + +function rawSpawn(task) +{ + var process = { + ctor: '_Process', + id: _elm_lang$core$Native_Utils.guid(), + root: task, + stack: null, + mailbox: [] + }; + + enqueue(process); + + return process; +} + +function spawn(task) +{ + return nativeBinding(function(callback) { + var process = rawSpawn(task); + callback(succeed(process)); + }); +} + +function rawSend(process, msg) +{ + process.mailbox.push(msg); + enqueue(process); +} + +function send(process, msg) +{ + return nativeBinding(function(callback) { + rawSend(process, msg); + callback(succeed(_elm_lang$core$Native_Utils.Tuple0)); + }); +} + +function kill(process) +{ + return nativeBinding(function(callback) { + var root = process.root; + if (root.ctor === '_Task_nativeBinding' && root.cancel) + { + root.cancel(); + } + + process.root = null; + + callback(succeed(_elm_lang$core$Native_Utils.Tuple0)); + }); +} + +function sleep(time) +{ + return nativeBinding(function(callback) { + var id = setTimeout(function() { + callback(succeed(_elm_lang$core$Native_Utils.Tuple0)); + }, time); + + return function() { clearTimeout(id); }; + }); +} + + +// STEP PROCESSES + +function step(numSteps, process) +{ + while (numSteps < MAX_STEPS) + { + var ctor = process.root.ctor; + + if (ctor === '_Task_succeed') + { + while (process.stack && process.stack.ctor === '_Task_onError') + { + process.stack = process.stack.rest; + } + if (process.stack === null) + { + break; + } + process.root = process.stack.callback(process.root.value); + process.stack = process.stack.rest; + ++numSteps; + continue; + } + + if (ctor === '_Task_fail') + { + while (process.stack && process.stack.ctor === '_Task_andThen') + { + process.stack = process.stack.rest; + } + if (process.stack === null) + { + break; + } + process.root = process.stack.callback(process.root.value); + process.stack = process.stack.rest; + ++numSteps; + continue; + } + + if (ctor === '_Task_andThen') + { + process.stack = { + ctor: '_Task_andThen', + callback: process.root.callback, + rest: process.stack + }; + process.root = process.root.task; + ++numSteps; + continue; + } + + if (ctor === '_Task_onError') + { + process.stack = { + ctor: '_Task_onError', + callback: process.root.callback, + rest: process.stack + }; + process.root = process.root.task; + ++numSteps; + continue; + } + + if (ctor === '_Task_nativeBinding') + { + process.root.cancel = process.root.callback(function(newRoot) { + process.root = newRoot; + enqueue(process); + }); + + break; + } + + if (ctor === '_Task_receive') + { + var mailbox = process.mailbox; + if (mailbox.length === 0) + { + break; + } + + process.root = process.root.callback(mailbox.shift()); + ++numSteps; + continue; + } + + throw new Error(ctor); + } + + if (numSteps < MAX_STEPS) + { + return numSteps + 1; + } + enqueue(process); + + return numSteps; +} + + +// WORK QUEUE + +var working = false; +var workQueue = []; + +function enqueue(process) +{ + workQueue.push(process); + + if (!working) + { + setTimeout(work, 0); + working = true; + } +} + +function work() +{ + var numSteps = 0; + var process; + while (numSteps < MAX_STEPS && (process = workQueue.shift())) + { + if (process.root) + { + numSteps = step(numSteps, process); + } + } + if (!process) + { + working = false; + return; + } + setTimeout(work, 0); +} + + +return { + succeed: succeed, + fail: fail, + nativeBinding: nativeBinding, + andThen: F2(andThen), + onError: F2(onError), + receive: receive, + + spawn: spawn, + kill: kill, + sleep: sleep, + send: F2(send), + + rawSpawn: rawSpawn, + rawSend: rawSend +}; + +}(); +//import // + +var _elm_lang$core$Native_Platform = function() { + + +// PROGRAMS + +function addPublicModule(object, name, main) +{ + var init = main ? makeEmbed(name, main) : mainIsUndefined(name); + + object['worker'] = function worker(flags) + { + return init(undefined, flags, false); + } + + object['embed'] = function embed(domNode, flags) + { + return init(domNode, flags, true); + } + + object['fullscreen'] = function fullscreen(flags) + { + return init(document.body, flags, true); + }; +} + + +// PROGRAM FAIL + +function mainIsUndefined(name) +{ + return function(domNode) + { + var message = 'Cannot initialize module `' + name + + '` because it has no `main` value!\nWhat should I show on screen?'; + domNode.innerHTML = errorHtml(message); + throw new Error(message); + }; +} + +function errorHtml(message) +{ + return '
    ' + + '

    Oops! Something went wrong when starting your Elm program.

    ' + + '
    ' + message + '
    ' + + '
    '; +} + + +// PROGRAM SUCCESS + +function makeEmbed(moduleName, main) +{ + return function embed(rootDomNode, flags, withRenderer) + { + try + { + var program = mainToProgram(moduleName, main); + if (!withRenderer) + { + program.renderer = dummyRenderer; + } + return makeEmbedHelp(moduleName, program, rootDomNode, flags); + } + catch (e) + { + rootDomNode.innerHTML = errorHtml(e.message); + throw e; + } + }; +} + +function dummyRenderer() +{ + return { update: function() {} }; +} + + +// MAIN TO PROGRAM + +function mainToProgram(moduleName, wrappedMain) +{ + var main = wrappedMain.main; + + if (typeof main.init === 'undefined') + { + var emptyBag = batch(_elm_lang$core$Native_List.Nil); + var noChange = _elm_lang$core$Native_Utils.Tuple2( + _elm_lang$core$Native_Utils.Tuple0, + emptyBag + ); + + return _elm_lang$virtual_dom$VirtualDom$programWithFlags({ + init: function() { return noChange; }, + view: function() { return main; }, + update: F2(function() { return noChange; }), + subscriptions: function () { return emptyBag; } + }); + } + + var flags = wrappedMain.flags; + var init = flags + ? initWithFlags(moduleName, main.init, flags) + : initWithoutFlags(moduleName, main.init); + + return _elm_lang$virtual_dom$VirtualDom$programWithFlags({ + init: init, + view: main.view, + update: main.update, + subscriptions: main.subscriptions, + }); +} + +function initWithoutFlags(moduleName, realInit) +{ + return function init(flags) + { + if (typeof flags !== 'undefined') + { + throw new Error( + 'You are giving module `' + moduleName + '` an argument in JavaScript.\n' + + 'This module does not take arguments though! You probably need to change the\n' + + 'initialization code to something like `Elm.' + moduleName + '.fullscreen()`' + ); + } + return realInit(); + }; +} + +function initWithFlags(moduleName, realInit, flagDecoder) +{ + return function init(flags) + { + var result = A2(_elm_lang$core$Native_Json.run, flagDecoder, flags); + if (result.ctor === 'Err') + { + throw new Error( + 'You are trying to initialize module `' + moduleName + '` with an unexpected argument.\n' + + 'When trying to convert it to a usable Elm value, I run into this problem:\n\n' + + result._0 + ); + } + return realInit(result._0); + }; +} + + +// SETUP RUNTIME SYSTEM + +function makeEmbedHelp(moduleName, program, rootDomNode, flags) +{ + var init = program.init; + var update = program.update; + var subscriptions = program.subscriptions; + var view = program.view; + var makeRenderer = program.renderer; + + // ambient state + var managers = {}; + var renderer; + + // init and update state in main process + var initApp = _elm_lang$core$Native_Scheduler.nativeBinding(function(callback) { + var results = init(flags); + var model = results._0; + renderer = makeRenderer(rootDomNode, enqueue, view(model)); + var cmds = results._1; + var subs = subscriptions(model); + dispatchEffects(managers, cmds, subs); + callback(_elm_lang$core$Native_Scheduler.succeed(model)); + }); + + function onMessage(msg, model) + { + return _elm_lang$core$Native_Scheduler.nativeBinding(function(callback) { + var results = A2(update, msg, model); + model = results._0; + renderer.update(view(model)); + var cmds = results._1; + var subs = subscriptions(model); + dispatchEffects(managers, cmds, subs); + callback(_elm_lang$core$Native_Scheduler.succeed(model)); + }); + } + + var mainProcess = spawnLoop(initApp, onMessage); + + function enqueue(msg) + { + _elm_lang$core$Native_Scheduler.rawSend(mainProcess, msg); + } + + var ports = setupEffects(managers, enqueue); + + return ports ? { ports: ports } : {}; +} + + +// EFFECT MANAGERS + +var effectManagers = {}; + +function setupEffects(managers, callback) +{ + var ports; + + // setup all necessary effect managers + for (var key in effectManagers) + { + var manager = effectManagers[key]; + + if (manager.isForeign) + { + ports = ports || {}; + ports[key] = manager.tag === 'cmd' + ? setupOutgoingPort(key) + : setupIncomingPort(key, callback); + } + + managers[key] = makeManager(manager, callback); + } + + return ports; +} + +function makeManager(info, callback) +{ + var router = { + main: callback, + self: undefined + }; + + var tag = info.tag; + var onEffects = info.onEffects; + var onSelfMsg = info.onSelfMsg; + + function onMessage(msg, state) + { + if (msg.ctor === 'self') + { + return A3(onSelfMsg, router, msg._0, state); + } + + var fx = msg._0; + switch (tag) + { + case 'cmd': + return A3(onEffects, router, fx.cmds, state); + + case 'sub': + return A3(onEffects, router, fx.subs, state); + + case 'fx': + return A4(onEffects, router, fx.cmds, fx.subs, state); + } + } + + var process = spawnLoop(info.init, onMessage); + router.self = process; + return process; +} + +function sendToApp(router, msg) +{ + return _elm_lang$core$Native_Scheduler.nativeBinding(function(callback) + { + router.main(msg); + callback(_elm_lang$core$Native_Scheduler.succeed(_elm_lang$core$Native_Utils.Tuple0)); + }); +} + +function sendToSelf(router, msg) +{ + return A2(_elm_lang$core$Native_Scheduler.send, router.self, { + ctor: 'self', + _0: msg + }); +} + + +// HELPER for STATEFUL LOOPS + +function spawnLoop(init, onMessage) +{ + var andThen = _elm_lang$core$Native_Scheduler.andThen; + + function loop(state) + { + var handleMsg = _elm_lang$core$Native_Scheduler.receive(function(msg) { + return onMessage(msg, state); + }); + return A2(andThen, handleMsg, loop); + } + + var task = A2(andThen, init, loop); + + return _elm_lang$core$Native_Scheduler.rawSpawn(task); +} + + +// BAGS + +function leaf(home) +{ + return function(value) + { + return { + type: 'leaf', + home: home, + value: value + }; + }; +} + +function batch(list) +{ + return { + type: 'node', + branches: list + }; +} + +function map(tagger, bag) +{ + return { + type: 'map', + tagger: tagger, + tree: bag + } +} + + +// PIPE BAGS INTO EFFECT MANAGERS + +function dispatchEffects(managers, cmdBag, subBag) +{ + var effectsDict = {}; + gatherEffects(true, cmdBag, effectsDict, null); + gatherEffects(false, subBag, effectsDict, null); + + for (var home in managers) + { + var fx = home in effectsDict + ? effectsDict[home] + : { + cmds: _elm_lang$core$Native_List.Nil, + subs: _elm_lang$core$Native_List.Nil + }; + + _elm_lang$core$Native_Scheduler.rawSend(managers[home], { ctor: 'fx', _0: fx }); + } +} + +function gatherEffects(isCmd, bag, effectsDict, taggers) +{ + switch (bag.type) + { + case 'leaf': + var home = bag.home; + var effect = toEffect(isCmd, home, taggers, bag.value); + effectsDict[home] = insert(isCmd, effect, effectsDict[home]); + return; + + case 'node': + var list = bag.branches; + while (list.ctor !== '[]') + { + gatherEffects(isCmd, list._0, effectsDict, taggers); + list = list._1; + } + return; + + case 'map': + gatherEffects(isCmd, bag.tree, effectsDict, { + tagger: bag.tagger, + rest: taggers + }); + return; + } +} + +function toEffect(isCmd, home, taggers, value) +{ + function applyTaggers(x) + { + var temp = taggers; + while (temp) + { + x = temp.tagger(x); + temp = temp.rest; + } + return x; + } + + var map = isCmd + ? effectManagers[home].cmdMap + : effectManagers[home].subMap; + + return A2(map, applyTaggers, value) +} + +function insert(isCmd, newEffect, effects) +{ + effects = effects || { + cmds: _elm_lang$core$Native_List.Nil, + subs: _elm_lang$core$Native_List.Nil + }; + if (isCmd) + { + effects.cmds = _elm_lang$core$Native_List.Cons(newEffect, effects.cmds); + return effects; + } + effects.subs = _elm_lang$core$Native_List.Cons(newEffect, effects.subs); + return effects; +} + + +// PORTS + +function checkPortName(name) +{ + if (name in effectManagers) + { + throw new Error('There can only be one port named `' + name + '`, but your program has multiple.'); + } +} + + +// OUTGOING PORTS + +function outgoingPort(name, converter) +{ + checkPortName(name); + effectManagers[name] = { + tag: 'cmd', + cmdMap: outgoingPortMap, + converter: converter, + isForeign: true + }; + return leaf(name); +} + +var outgoingPortMap = F2(function cmdMap(tagger, value) { + return value; +}); + +function setupOutgoingPort(name) +{ + var subs = []; + var converter = effectManagers[name].converter; + + // CREATE MANAGER + + var init = _elm_lang$core$Native_Scheduler.succeed(null); + + function onEffects(router, cmdList, state) + { + while (cmdList.ctor !== '[]') + { + var value = converter(cmdList._0); + for (var i = 0; i < subs.length; i++) + { + subs[i](value); + } + cmdList = cmdList._1; + } + return init; + } + + effectManagers[name].init = init; + effectManagers[name].onEffects = F3(onEffects); + + // PUBLIC API + + function subscribe(callback) + { + subs.push(callback); + } + + function unsubscribe(callback) + { + var index = subs.indexOf(callback); + if (index >= 0) + { + subs.splice(index, 1); + } + } + + return { + subscribe: subscribe, + unsubscribe: unsubscribe + }; +} + + +// INCOMING PORTS + +function incomingPort(name, converter) +{ + checkPortName(name); + effectManagers[name] = { + tag: 'sub', + subMap: incomingPortMap, + converter: converter, + isForeign: true + }; + return leaf(name); +} + +var incomingPortMap = F2(function subMap(tagger, finalTagger) +{ + return function(value) + { + return tagger(finalTagger(value)); + }; +}); + +function setupIncomingPort(name, callback) +{ + var sentBeforeInit = []; + var subs = _elm_lang$core$Native_List.Nil; + var converter = effectManagers[name].converter; + var currentOnEffects = preInitOnEffects; + var currentSend = preInitSend; + + // CREATE MANAGER + + var init = _elm_lang$core$Native_Scheduler.succeed(null); + + function preInitOnEffects(router, subList, state) + { + var postInitResult = postInitOnEffects(router, subList, state); + + for(var i = 0; i < sentBeforeInit.length; i++) + { + postInitSend(sentBeforeInit[i]); + } + + sentBeforeInit = null; // to release objects held in queue + currentSend = postInitSend; + currentOnEffects = postInitOnEffects; + return postInitResult; + } + + function postInitOnEffects(router, subList, state) + { + subs = subList; + return init; + } + + function onEffects(router, subList, state) + { + return currentOnEffects(router, subList, state); + } + + effectManagers[name].init = init; + effectManagers[name].onEffects = F3(onEffects); + + // PUBLIC API + + function preInitSend(value) + { + sentBeforeInit.push(value); + } + + function postInitSend(incomingValue) + { + var result = A2(_elm_lang$core$Json_Decode$decodeValue, converter, incomingValue); + if (result.ctor === 'Err') + { + throw new Error('Trying to send an unexpected type of value through port `' + name + '`:\n' + result._0); + } + + var value = result._0; + var temp = subs; + while (temp.ctor !== '[]') + { + callback(temp._0(value)); + temp = temp._1; + } + } + + function send(incomingValue) + { + currentSend(incomingValue); + } + + return { send: send }; +} + +return { + // routers + sendToApp: F2(sendToApp), + sendToSelf: F2(sendToSelf), + + // global setup + mainToProgram: mainToProgram, + effectManagers: effectManagers, + outgoingPort: outgoingPort, + incomingPort: incomingPort, + addPublicModule: addPublicModule, + + // effect bags + leaf: leaf, + batch: batch, + map: F2(map) +}; + +}(); + +var _elm_lang$core$Platform$hack = _elm_lang$core$Native_Scheduler.succeed; +var _elm_lang$core$Platform$sendToSelf = _elm_lang$core$Native_Platform.sendToSelf; +var _elm_lang$core$Platform$sendToApp = _elm_lang$core$Native_Platform.sendToApp; +var _elm_lang$core$Platform$Program = {ctor: 'Program'}; +var _elm_lang$core$Platform$Task = {ctor: 'Task'}; +var _elm_lang$core$Platform$ProcessId = {ctor: 'ProcessId'}; +var _elm_lang$core$Platform$Router = {ctor: 'Router'}; + +var _elm_lang$core$Platform_Cmd$batch = _elm_lang$core$Native_Platform.batch; +var _elm_lang$core$Platform_Cmd$none = _elm_lang$core$Platform_Cmd$batch( + _elm_lang$core$Native_List.fromArray( + [])); +var _elm_lang$core$Platform_Cmd_ops = _elm_lang$core$Platform_Cmd_ops || {}; +_elm_lang$core$Platform_Cmd_ops['!'] = F2( + function (model, commands) { + return { + ctor: '_Tuple2', + _0: model, + _1: _elm_lang$core$Platform_Cmd$batch(commands) + }; + }); +var _elm_lang$core$Platform_Cmd$map = _elm_lang$core$Native_Platform.map; +var _elm_lang$core$Platform_Cmd$Cmd = {ctor: 'Cmd'}; + +var _elm_lang$core$Result$toMaybe = function (result) { + var _p0 = result; + if (_p0.ctor === 'Ok') { + return _elm_lang$core$Maybe$Just(_p0._0); + } else { + return _elm_lang$core$Maybe$Nothing; + } +}; +var _elm_lang$core$Result$withDefault = F2( + function (def, result) { + var _p1 = result; + if (_p1.ctor === 'Ok') { + return _p1._0; + } else { + return def; + } + }); +var _elm_lang$core$Result$Err = function (a) { + return {ctor: 'Err', _0: a}; +}; +var _elm_lang$core$Result$andThen = F2( + function (result, callback) { + var _p2 = result; + if (_p2.ctor === 'Ok') { + return callback(_p2._0); + } else { + return _elm_lang$core$Result$Err(_p2._0); + } + }); +var _elm_lang$core$Result$Ok = function (a) { + return {ctor: 'Ok', _0: a}; +}; +var _elm_lang$core$Result$map = F2( + function (func, ra) { + var _p3 = ra; + if (_p3.ctor === 'Ok') { + return _elm_lang$core$Result$Ok( + func(_p3._0)); + } else { + return _elm_lang$core$Result$Err(_p3._0); + } + }); +var _elm_lang$core$Result$map2 = F3( + function (func, ra, rb) { + var _p4 = {ctor: '_Tuple2', _0: ra, _1: rb}; + if (_p4._0.ctor === 'Ok') { + if (_p4._1.ctor === 'Ok') { + return _elm_lang$core$Result$Ok( + A2(func, _p4._0._0, _p4._1._0)); + } else { + return _elm_lang$core$Result$Err(_p4._1._0); + } + } else { + return _elm_lang$core$Result$Err(_p4._0._0); + } + }); +var _elm_lang$core$Result$map3 = F4( + function (func, ra, rb, rc) { + var _p5 = {ctor: '_Tuple3', _0: ra, _1: rb, _2: rc}; + if (_p5._0.ctor === 'Ok') { + if (_p5._1.ctor === 'Ok') { + if (_p5._2.ctor === 'Ok') { + return _elm_lang$core$Result$Ok( + A3(func, _p5._0._0, _p5._1._0, _p5._2._0)); + } else { + return _elm_lang$core$Result$Err(_p5._2._0); + } + } else { + return _elm_lang$core$Result$Err(_p5._1._0); + } + } else { + return _elm_lang$core$Result$Err(_p5._0._0); + } + }); +var _elm_lang$core$Result$map4 = F5( + function (func, ra, rb, rc, rd) { + var _p6 = {ctor: '_Tuple4', _0: ra, _1: rb, _2: rc, _3: rd}; + if (_p6._0.ctor === 'Ok') { + if (_p6._1.ctor === 'Ok') { + if (_p6._2.ctor === 'Ok') { + if (_p6._3.ctor === 'Ok') { + return _elm_lang$core$Result$Ok( + A4(func, _p6._0._0, _p6._1._0, _p6._2._0, _p6._3._0)); + } else { + return _elm_lang$core$Result$Err(_p6._3._0); + } + } else { + return _elm_lang$core$Result$Err(_p6._2._0); + } + } else { + return _elm_lang$core$Result$Err(_p6._1._0); + } + } else { + return _elm_lang$core$Result$Err(_p6._0._0); + } + }); +var _elm_lang$core$Result$map5 = F6( + function (func, ra, rb, rc, rd, re) { + var _p7 = {ctor: '_Tuple5', _0: ra, _1: rb, _2: rc, _3: rd, _4: re}; + if (_p7._0.ctor === 'Ok') { + if (_p7._1.ctor === 'Ok') { + if (_p7._2.ctor === 'Ok') { + if (_p7._3.ctor === 'Ok') { + if (_p7._4.ctor === 'Ok') { + return _elm_lang$core$Result$Ok( + A5(func, _p7._0._0, _p7._1._0, _p7._2._0, _p7._3._0, _p7._4._0)); + } else { + return _elm_lang$core$Result$Err(_p7._4._0); + } + } else { + return _elm_lang$core$Result$Err(_p7._3._0); + } + } else { + return _elm_lang$core$Result$Err(_p7._2._0); + } + } else { + return _elm_lang$core$Result$Err(_p7._1._0); + } + } else { + return _elm_lang$core$Result$Err(_p7._0._0); + } + }); +var _elm_lang$core$Result$formatError = F2( + function (f, result) { + var _p8 = result; + if (_p8.ctor === 'Ok') { + return _elm_lang$core$Result$Ok(_p8._0); + } else { + return _elm_lang$core$Result$Err( + f(_p8._0)); + } + }); +var _elm_lang$core$Result$fromMaybe = F2( + function (err, maybe) { + var _p9 = maybe; + if (_p9.ctor === 'Just') { + return _elm_lang$core$Result$Ok(_p9._0); + } else { + return _elm_lang$core$Result$Err(err); + } + }); + +//import Native.Utils // + +var _elm_lang$core$Native_Debug = function() { + +function log(tag, value) +{ + var msg = tag + ': ' + _elm_lang$core$Native_Utils.toString(value); + var process = process || {}; + if (process.stdout) + { + process.stdout.write(msg); + } + else + { + console.log(msg); + } + return value; +} + +function crash(message) +{ + throw new Error(message); +} + +return { + crash: crash, + log: F2(log) +}; + +}(); +//import Maybe, Native.List, Native.Utils, Result // + +var _elm_lang$core$Native_String = function() { + +function isEmpty(str) +{ + return str.length === 0; +} +function cons(chr, str) +{ + return chr + str; +} +function uncons(str) +{ + var hd = str[0]; + if (hd) + { + return _elm_lang$core$Maybe$Just(_elm_lang$core$Native_Utils.Tuple2(_elm_lang$core$Native_Utils.chr(hd), str.slice(1))); + } + return _elm_lang$core$Maybe$Nothing; +} +function append(a, b) +{ + return a + b; +} +function concat(strs) +{ + return _elm_lang$core$Native_List.toArray(strs).join(''); +} +function length(str) +{ + return str.length; +} +function map(f, str) +{ + var out = str.split(''); + for (var i = out.length; i--; ) + { + out[i] = f(_elm_lang$core$Native_Utils.chr(out[i])); + } + return out.join(''); +} +function filter(pred, str) +{ + return str.split('').map(_elm_lang$core$Native_Utils.chr).filter(pred).join(''); +} +function reverse(str) +{ + return str.split('').reverse().join(''); +} +function foldl(f, b, str) +{ + var len = str.length; + for (var i = 0; i < len; ++i) + { + b = A2(f, _elm_lang$core$Native_Utils.chr(str[i]), b); + } + return b; +} +function foldr(f, b, str) +{ + for (var i = str.length; i--; ) + { + b = A2(f, _elm_lang$core$Native_Utils.chr(str[i]), b); + } + return b; +} +function split(sep, str) +{ + return _elm_lang$core$Native_List.fromArray(str.split(sep)); +} +function join(sep, strs) +{ + return _elm_lang$core$Native_List.toArray(strs).join(sep); +} +function repeat(n, str) +{ + var result = ''; + while (n > 0) + { + if (n & 1) + { + result += str; + } + n >>= 1, str += str; + } + return result; +} +function slice(start, end, str) +{ + return str.slice(start, end); +} +function left(n, str) +{ + return n < 1 ? '' : str.slice(0, n); +} +function right(n, str) +{ + return n < 1 ? '' : str.slice(-n); +} +function dropLeft(n, str) +{ + return n < 1 ? str : str.slice(n); +} +function dropRight(n, str) +{ + return n < 1 ? str : str.slice(0, -n); +} +function pad(n, chr, str) +{ + var half = (n - str.length) / 2; + return repeat(Math.ceil(half), chr) + str + repeat(half | 0, chr); +} +function padRight(n, chr, str) +{ + return str + repeat(n - str.length, chr); +} +function padLeft(n, chr, str) +{ + return repeat(n - str.length, chr) + str; +} + +function trim(str) +{ + return str.trim(); +} +function trimLeft(str) +{ + return str.replace(/^\s+/, ''); +} +function trimRight(str) +{ + return str.replace(/\s+$/, ''); +} + +function words(str) +{ + return _elm_lang$core$Native_List.fromArray(str.trim().split(/\s+/g)); +} +function lines(str) +{ + return _elm_lang$core$Native_List.fromArray(str.split(/\r\n|\r|\n/g)); +} + +function toUpper(str) +{ + return str.toUpperCase(); +} +function toLower(str) +{ + return str.toLowerCase(); +} + +function any(pred, str) +{ + for (var i = str.length; i--; ) + { + if (pred(_elm_lang$core$Native_Utils.chr(str[i]))) + { + return true; + } + } + return false; +} +function all(pred, str) +{ + for (var i = str.length; i--; ) + { + if (!pred(_elm_lang$core$Native_Utils.chr(str[i]))) + { + return false; + } + } + return true; +} + +function contains(sub, str) +{ + return str.indexOf(sub) > -1; +} +function startsWith(sub, str) +{ + return str.indexOf(sub) === 0; +} +function endsWith(sub, str) +{ + return str.length >= sub.length && + str.lastIndexOf(sub) === str.length - sub.length; +} +function indexes(sub, str) +{ + var subLen = sub.length; + + if (subLen < 1) + { + return _elm_lang$core$Native_List.Nil; + } + + var i = 0; + var is = []; + + while ((i = str.indexOf(sub, i)) > -1) + { + is.push(i); + i = i + subLen; + } + + return _elm_lang$core$Native_List.fromArray(is); +} + +function toInt(s) +{ + var len = s.length; + if (len === 0) + { + return _elm_lang$core$Result$Err("could not convert string '" + s + "' to an Int" ); + } + var start = 0; + if (s[0] === '-') + { + if (len === 1) + { + return _elm_lang$core$Result$Err("could not convert string '" + s + "' to an Int" ); + } + start = 1; + } + for (var i = start; i < len; ++i) + { + var c = s[i]; + if (c < '0' || '9' < c) + { + return _elm_lang$core$Result$Err("could not convert string '" + s + "' to an Int" ); + } + } + return _elm_lang$core$Result$Ok(parseInt(s, 10)); +} + +function toFloat(s) +{ + var len = s.length; + if (len === 0) + { + return _elm_lang$core$Result$Err("could not convert string '" + s + "' to a Float" ); + } + var start = 0; + if (s[0] === '-') + { + if (len === 1) + { + return _elm_lang$core$Result$Err("could not convert string '" + s + "' to a Float" ); + } + start = 1; + } + var dotCount = 0; + for (var i = start; i < len; ++i) + { + var c = s[i]; + if ('0' <= c && c <= '9') + { + continue; + } + if (c === '.') + { + dotCount += 1; + if (dotCount <= 1) + { + continue; + } + } + return _elm_lang$core$Result$Err("could not convert string '" + s + "' to a Float" ); + } + return _elm_lang$core$Result$Ok(parseFloat(s)); +} + +function toList(str) +{ + return _elm_lang$core$Native_List.fromArray(str.split('').map(_elm_lang$core$Native_Utils.chr)); +} +function fromList(chars) +{ + return _elm_lang$core$Native_List.toArray(chars).join(''); +} + +return { + isEmpty: isEmpty, + cons: F2(cons), + uncons: uncons, + append: F2(append), + concat: concat, + length: length, + map: F2(map), + filter: F2(filter), + reverse: reverse, + foldl: F3(foldl), + foldr: F3(foldr), + + split: F2(split), + join: F2(join), + repeat: F2(repeat), + + slice: F3(slice), + left: F2(left), + right: F2(right), + dropLeft: F2(dropLeft), + dropRight: F2(dropRight), + + pad: F3(pad), + padLeft: F3(padLeft), + padRight: F3(padRight), + + trim: trim, + trimLeft: trimLeft, + trimRight: trimRight, + + words: words, + lines: lines, + + toUpper: toUpper, + toLower: toLower, + + any: F2(any), + all: F2(all), + + contains: F2(contains), + startsWith: F2(startsWith), + endsWith: F2(endsWith), + indexes: F2(indexes), + + toInt: toInt, + toFloat: toFloat, + toList: toList, + fromList: fromList +}; + +}(); + +var _elm_lang$core$String$fromList = _elm_lang$core$Native_String.fromList; +var _elm_lang$core$String$toList = _elm_lang$core$Native_String.toList; +var _elm_lang$core$String$toFloat = _elm_lang$core$Native_String.toFloat; +var _elm_lang$core$String$toInt = _elm_lang$core$Native_String.toInt; +var _elm_lang$core$String$indices = _elm_lang$core$Native_String.indexes; +var _elm_lang$core$String$indexes = _elm_lang$core$Native_String.indexes; +var _elm_lang$core$String$endsWith = _elm_lang$core$Native_String.endsWith; +var _elm_lang$core$String$startsWith = _elm_lang$core$Native_String.startsWith; +var _elm_lang$core$String$contains = _elm_lang$core$Native_String.contains; +var _elm_lang$core$String$all = _elm_lang$core$Native_String.all; +var _elm_lang$core$String$any = _elm_lang$core$Native_String.any; +var _elm_lang$core$String$toLower = _elm_lang$core$Native_String.toLower; +var _elm_lang$core$String$toUpper = _elm_lang$core$Native_String.toUpper; +var _elm_lang$core$String$lines = _elm_lang$core$Native_String.lines; +var _elm_lang$core$String$words = _elm_lang$core$Native_String.words; +var _elm_lang$core$String$trimRight = _elm_lang$core$Native_String.trimRight; +var _elm_lang$core$String$trimLeft = _elm_lang$core$Native_String.trimLeft; +var _elm_lang$core$String$trim = _elm_lang$core$Native_String.trim; +var _elm_lang$core$String$padRight = _elm_lang$core$Native_String.padRight; +var _elm_lang$core$String$padLeft = _elm_lang$core$Native_String.padLeft; +var _elm_lang$core$String$pad = _elm_lang$core$Native_String.pad; +var _elm_lang$core$String$dropRight = _elm_lang$core$Native_String.dropRight; +var _elm_lang$core$String$dropLeft = _elm_lang$core$Native_String.dropLeft; +var _elm_lang$core$String$right = _elm_lang$core$Native_String.right; +var _elm_lang$core$String$left = _elm_lang$core$Native_String.left; +var _elm_lang$core$String$slice = _elm_lang$core$Native_String.slice; +var _elm_lang$core$String$repeat = _elm_lang$core$Native_String.repeat; +var _elm_lang$core$String$join = _elm_lang$core$Native_String.join; +var _elm_lang$core$String$split = _elm_lang$core$Native_String.split; +var _elm_lang$core$String$foldr = _elm_lang$core$Native_String.foldr; +var _elm_lang$core$String$foldl = _elm_lang$core$Native_String.foldl; +var _elm_lang$core$String$reverse = _elm_lang$core$Native_String.reverse; +var _elm_lang$core$String$filter = _elm_lang$core$Native_String.filter; +var _elm_lang$core$String$map = _elm_lang$core$Native_String.map; +var _elm_lang$core$String$length = _elm_lang$core$Native_String.length; +var _elm_lang$core$String$concat = _elm_lang$core$Native_String.concat; +var _elm_lang$core$String$append = _elm_lang$core$Native_String.append; +var _elm_lang$core$String$uncons = _elm_lang$core$Native_String.uncons; +var _elm_lang$core$String$cons = _elm_lang$core$Native_String.cons; +var _elm_lang$core$String$fromChar = function ($char) { + return A2(_elm_lang$core$String$cons, $char, ''); +}; +var _elm_lang$core$String$isEmpty = _elm_lang$core$Native_String.isEmpty; + +var _elm_lang$core$Dict$foldr = F3( + function (f, acc, t) { + foldr: + while (true) { + var _p0 = t; + if (_p0.ctor === 'RBEmpty_elm_builtin') { + return acc; + } else { + var _v1 = f, + _v2 = A3( + f, + _p0._1, + _p0._2, + A3(_elm_lang$core$Dict$foldr, f, acc, _p0._4)), + _v3 = _p0._3; + f = _v1; + acc = _v2; + t = _v3; + continue foldr; + } + } + }); +var _elm_lang$core$Dict$keys = function (dict) { + return A3( + _elm_lang$core$Dict$foldr, + F3( + function (key, value, keyList) { + return A2(_elm_lang$core$List_ops['::'], key, keyList); + }), + _elm_lang$core$Native_List.fromArray( + []), + dict); +}; +var _elm_lang$core$Dict$values = function (dict) { + return A3( + _elm_lang$core$Dict$foldr, + F3( + function (key, value, valueList) { + return A2(_elm_lang$core$List_ops['::'], value, valueList); + }), + _elm_lang$core$Native_List.fromArray( + []), + dict); +}; +var _elm_lang$core$Dict$toList = function (dict) { + return A3( + _elm_lang$core$Dict$foldr, + F3( + function (key, value, list) { + return A2( + _elm_lang$core$List_ops['::'], + {ctor: '_Tuple2', _0: key, _1: value}, + list); + }), + _elm_lang$core$Native_List.fromArray( + []), + dict); +}; +var _elm_lang$core$Dict$foldl = F3( + function (f, acc, dict) { + foldl: + while (true) { + var _p1 = dict; + if (_p1.ctor === 'RBEmpty_elm_builtin') { + return acc; + } else { + var _v5 = f, + _v6 = A3( + f, + _p1._1, + _p1._2, + A3(_elm_lang$core$Dict$foldl, f, acc, _p1._3)), + _v7 = _p1._4; + f = _v5; + acc = _v6; + dict = _v7; + continue foldl; + } + } + }); +var _elm_lang$core$Dict$merge = F6( + function (leftStep, bothStep, rightStep, leftDict, rightDict, initialResult) { + var stepState = F3( + function (rKey, rValue, _p2) { + stepState: + while (true) { + var _p3 = _p2; + var _p9 = _p3._1; + var _p8 = _p3._0; + var _p4 = _p8; + if (_p4.ctor === '[]') { + return { + ctor: '_Tuple2', + _0: _p8, + _1: A3(rightStep, rKey, rValue, _p9) + }; + } else { + var _p7 = _p4._1; + var _p6 = _p4._0._1; + var _p5 = _p4._0._0; + if (_elm_lang$core$Native_Utils.cmp(_p5, rKey) < 0) { + var _v10 = rKey, + _v11 = rValue, + _v12 = { + ctor: '_Tuple2', + _0: _p7, + _1: A3(leftStep, _p5, _p6, _p9) + }; + rKey = _v10; + rValue = _v11; + _p2 = _v12; + continue stepState; + } else { + if (_elm_lang$core$Native_Utils.cmp(_p5, rKey) > 0) { + return { + ctor: '_Tuple2', + _0: _p8, + _1: A3(rightStep, rKey, rValue, _p9) + }; + } else { + return { + ctor: '_Tuple2', + _0: _p7, + _1: A4(bothStep, _p5, _p6, rValue, _p9) + }; + } + } + } + } + }); + var _p10 = A3( + _elm_lang$core$Dict$foldl, + stepState, + { + ctor: '_Tuple2', + _0: _elm_lang$core$Dict$toList(leftDict), + _1: initialResult + }, + rightDict); + var leftovers = _p10._0; + var intermediateResult = _p10._1; + return A3( + _elm_lang$core$List$foldl, + F2( + function (_p11, result) { + var _p12 = _p11; + return A3(leftStep, _p12._0, _p12._1, result); + }), + intermediateResult, + leftovers); + }); +var _elm_lang$core$Dict$reportRemBug = F4( + function (msg, c, lgot, rgot) { + return _elm_lang$core$Native_Debug.crash( + _elm_lang$core$String$concat( + _elm_lang$core$Native_List.fromArray( + [ + 'Internal red-black tree invariant violated, expected ', + msg, + ' and got ', + _elm_lang$core$Basics$toString(c), + '/', + lgot, + '/', + rgot, + '\nPlease report this bug to ' + ]))); + }); +var _elm_lang$core$Dict$isBBlack = function (dict) { + var _p13 = dict; + _v14_2: + do { + if (_p13.ctor === 'RBNode_elm_builtin') { + if (_p13._0.ctor === 'BBlack') { + return true; + } else { + break _v14_2; + } + } else { + if (_p13._0.ctor === 'LBBlack') { + return true; + } else { + break _v14_2; + } + } + } while(false); + return false; +}; +var _elm_lang$core$Dict$sizeHelp = F2( + function (n, dict) { + sizeHelp: + while (true) { + var _p14 = dict; + if (_p14.ctor === 'RBEmpty_elm_builtin') { + return n; + } else { + var _v16 = A2(_elm_lang$core$Dict$sizeHelp, n + 1, _p14._4), + _v17 = _p14._3; + n = _v16; + dict = _v17; + continue sizeHelp; + } + } + }); +var _elm_lang$core$Dict$size = function (dict) { + return A2(_elm_lang$core$Dict$sizeHelp, 0, dict); +}; +var _elm_lang$core$Dict$get = F2( + function (targetKey, dict) { + get: + while (true) { + var _p15 = dict; + if (_p15.ctor === 'RBEmpty_elm_builtin') { + return _elm_lang$core$Maybe$Nothing; + } else { + var _p16 = A2(_elm_lang$core$Basics$compare, targetKey, _p15._1); + switch (_p16.ctor) { + case 'LT': + var _v20 = targetKey, + _v21 = _p15._3; + targetKey = _v20; + dict = _v21; + continue get; + case 'EQ': + return _elm_lang$core$Maybe$Just(_p15._2); + default: + var _v22 = targetKey, + _v23 = _p15._4; + targetKey = _v22; + dict = _v23; + continue get; + } + } + } + }); +var _elm_lang$core$Dict$member = F2( + function (key, dict) { + var _p17 = A2(_elm_lang$core$Dict$get, key, dict); + if (_p17.ctor === 'Just') { + return true; + } else { + return false; + } + }); +var _elm_lang$core$Dict$maxWithDefault = F3( + function (k, v, r) { + maxWithDefault: + while (true) { + var _p18 = r; + if (_p18.ctor === 'RBEmpty_elm_builtin') { + return {ctor: '_Tuple2', _0: k, _1: v}; + } else { + var _v26 = _p18._1, + _v27 = _p18._2, + _v28 = _p18._4; + k = _v26; + v = _v27; + r = _v28; + continue maxWithDefault; + } + } + }); +var _elm_lang$core$Dict$NBlack = {ctor: 'NBlack'}; +var _elm_lang$core$Dict$BBlack = {ctor: 'BBlack'}; +var _elm_lang$core$Dict$Black = {ctor: 'Black'}; +var _elm_lang$core$Dict$blackish = function (t) { + var _p19 = t; + if (_p19.ctor === 'RBNode_elm_builtin') { + var _p20 = _p19._0; + return _elm_lang$core$Native_Utils.eq(_p20, _elm_lang$core$Dict$Black) || _elm_lang$core$Native_Utils.eq(_p20, _elm_lang$core$Dict$BBlack); + } else { + return true; + } +}; +var _elm_lang$core$Dict$Red = {ctor: 'Red'}; +var _elm_lang$core$Dict$moreBlack = function (color) { + var _p21 = color; + switch (_p21.ctor) { + case 'Black': + return _elm_lang$core$Dict$BBlack; + case 'Red': + return _elm_lang$core$Dict$Black; + case 'NBlack': + return _elm_lang$core$Dict$Red; + default: + return _elm_lang$core$Native_Debug.crash('Can\'t make a double black node more black!'); + } +}; +var _elm_lang$core$Dict$lessBlack = function (color) { + var _p22 = color; + switch (_p22.ctor) { + case 'BBlack': + return _elm_lang$core$Dict$Black; + case 'Black': + return _elm_lang$core$Dict$Red; + case 'Red': + return _elm_lang$core$Dict$NBlack; + default: + return _elm_lang$core$Native_Debug.crash('Can\'t make a negative black node less black!'); + } +}; +var _elm_lang$core$Dict$LBBlack = {ctor: 'LBBlack'}; +var _elm_lang$core$Dict$LBlack = {ctor: 'LBlack'}; +var _elm_lang$core$Dict$RBEmpty_elm_builtin = function (a) { + return {ctor: 'RBEmpty_elm_builtin', _0: a}; +}; +var _elm_lang$core$Dict$empty = _elm_lang$core$Dict$RBEmpty_elm_builtin(_elm_lang$core$Dict$LBlack); +var _elm_lang$core$Dict$isEmpty = function (dict) { + return _elm_lang$core$Native_Utils.eq(dict, _elm_lang$core$Dict$empty); +}; +var _elm_lang$core$Dict$RBNode_elm_builtin = F5( + function (a, b, c, d, e) { + return {ctor: 'RBNode_elm_builtin', _0: a, _1: b, _2: c, _3: d, _4: e}; + }); +var _elm_lang$core$Dict$ensureBlackRoot = function (dict) { + var _p23 = dict; + if ((_p23.ctor === 'RBNode_elm_builtin') && (_p23._0.ctor === 'Red')) { + return A5(_elm_lang$core$Dict$RBNode_elm_builtin, _elm_lang$core$Dict$Black, _p23._1, _p23._2, _p23._3, _p23._4); + } else { + return dict; + } +}; +var _elm_lang$core$Dict$lessBlackTree = function (dict) { + var _p24 = dict; + if (_p24.ctor === 'RBNode_elm_builtin') { + return A5( + _elm_lang$core$Dict$RBNode_elm_builtin, + _elm_lang$core$Dict$lessBlack(_p24._0), + _p24._1, + _p24._2, + _p24._3, + _p24._4); + } else { + return _elm_lang$core$Dict$RBEmpty_elm_builtin(_elm_lang$core$Dict$LBlack); + } +}; +var _elm_lang$core$Dict$balancedTree = function (col) { + return function (xk) { + return function (xv) { + return function (yk) { + return function (yv) { + return function (zk) { + return function (zv) { + return function (a) { + return function (b) { + return function (c) { + return function (d) { + return A5( + _elm_lang$core$Dict$RBNode_elm_builtin, + _elm_lang$core$Dict$lessBlack(col), + yk, + yv, + A5(_elm_lang$core$Dict$RBNode_elm_builtin, _elm_lang$core$Dict$Black, xk, xv, a, b), + A5(_elm_lang$core$Dict$RBNode_elm_builtin, _elm_lang$core$Dict$Black, zk, zv, c, d)); + }; + }; + }; + }; + }; + }; + }; + }; + }; + }; +}; +var _elm_lang$core$Dict$blacken = function (t) { + var _p25 = t; + if (_p25.ctor === 'RBEmpty_elm_builtin') { + return _elm_lang$core$Dict$RBEmpty_elm_builtin(_elm_lang$core$Dict$LBlack); + } else { + return A5(_elm_lang$core$Dict$RBNode_elm_builtin, _elm_lang$core$Dict$Black, _p25._1, _p25._2, _p25._3, _p25._4); + } +}; +var _elm_lang$core$Dict$redden = function (t) { + var _p26 = t; + if (_p26.ctor === 'RBEmpty_elm_builtin') { + return _elm_lang$core$Native_Debug.crash('can\'t make a Leaf red'); + } else { + return A5(_elm_lang$core$Dict$RBNode_elm_builtin, _elm_lang$core$Dict$Red, _p26._1, _p26._2, _p26._3, _p26._4); + } +}; +var _elm_lang$core$Dict$balanceHelp = function (tree) { + var _p27 = tree; + _v36_6: + do { + _v36_5: + do { + _v36_4: + do { + _v36_3: + do { + _v36_2: + do { + _v36_1: + do { + _v36_0: + do { + if (_p27.ctor === 'RBNode_elm_builtin') { + if (_p27._3.ctor === 'RBNode_elm_builtin') { + if (_p27._4.ctor === 'RBNode_elm_builtin') { + switch (_p27._3._0.ctor) { + case 'Red': + switch (_p27._4._0.ctor) { + case 'Red': + if ((_p27._3._3.ctor === 'RBNode_elm_builtin') && (_p27._3._3._0.ctor === 'Red')) { + break _v36_0; + } else { + if ((_p27._3._4.ctor === 'RBNode_elm_builtin') && (_p27._3._4._0.ctor === 'Red')) { + break _v36_1; + } else { + if ((_p27._4._3.ctor === 'RBNode_elm_builtin') && (_p27._4._3._0.ctor === 'Red')) { + break _v36_2; + } else { + if ((_p27._4._4.ctor === 'RBNode_elm_builtin') && (_p27._4._4._0.ctor === 'Red')) { + break _v36_3; + } else { + break _v36_6; + } + } + } + } + case 'NBlack': + if ((_p27._3._3.ctor === 'RBNode_elm_builtin') && (_p27._3._3._0.ctor === 'Red')) { + break _v36_0; + } else { + if ((_p27._3._4.ctor === 'RBNode_elm_builtin') && (_p27._3._4._0.ctor === 'Red')) { + break _v36_1; + } else { + if (((((_p27._0.ctor === 'BBlack') && (_p27._4._3.ctor === 'RBNode_elm_builtin')) && (_p27._4._3._0.ctor === 'Black')) && (_p27._4._4.ctor === 'RBNode_elm_builtin')) && (_p27._4._4._0.ctor === 'Black')) { + break _v36_4; + } else { + break _v36_6; + } + } + } + default: + if ((_p27._3._3.ctor === 'RBNode_elm_builtin') && (_p27._3._3._0.ctor === 'Red')) { + break _v36_0; + } else { + if ((_p27._3._4.ctor === 'RBNode_elm_builtin') && (_p27._3._4._0.ctor === 'Red')) { + break _v36_1; + } else { + break _v36_6; + } + } + } + case 'NBlack': + switch (_p27._4._0.ctor) { + case 'Red': + if ((_p27._4._3.ctor === 'RBNode_elm_builtin') && (_p27._4._3._0.ctor === 'Red')) { + break _v36_2; + } else { + if ((_p27._4._4.ctor === 'RBNode_elm_builtin') && (_p27._4._4._0.ctor === 'Red')) { + break _v36_3; + } else { + if (((((_p27._0.ctor === 'BBlack') && (_p27._3._3.ctor === 'RBNode_elm_builtin')) && (_p27._3._3._0.ctor === 'Black')) && (_p27._3._4.ctor === 'RBNode_elm_builtin')) && (_p27._3._4._0.ctor === 'Black')) { + break _v36_5; + } else { + break _v36_6; + } + } + } + case 'NBlack': + if (_p27._0.ctor === 'BBlack') { + if ((((_p27._4._3.ctor === 'RBNode_elm_builtin') && (_p27._4._3._0.ctor === 'Black')) && (_p27._4._4.ctor === 'RBNode_elm_builtin')) && (_p27._4._4._0.ctor === 'Black')) { + break _v36_4; + } else { + if ((((_p27._3._3.ctor === 'RBNode_elm_builtin') && (_p27._3._3._0.ctor === 'Black')) && (_p27._3._4.ctor === 'RBNode_elm_builtin')) && (_p27._3._4._0.ctor === 'Black')) { + break _v36_5; + } else { + break _v36_6; + } + } + } else { + break _v36_6; + } + default: + if (((((_p27._0.ctor === 'BBlack') && (_p27._3._3.ctor === 'RBNode_elm_builtin')) && (_p27._3._3._0.ctor === 'Black')) && (_p27._3._4.ctor === 'RBNode_elm_builtin')) && (_p27._3._4._0.ctor === 'Black')) { + break _v36_5; + } else { + break _v36_6; + } + } + default: + switch (_p27._4._0.ctor) { + case 'Red': + if ((_p27._4._3.ctor === 'RBNode_elm_builtin') && (_p27._4._3._0.ctor === 'Red')) { + break _v36_2; + } else { + if ((_p27._4._4.ctor === 'RBNode_elm_builtin') && (_p27._4._4._0.ctor === 'Red')) { + break _v36_3; + } else { + break _v36_6; + } + } + case 'NBlack': + if (((((_p27._0.ctor === 'BBlack') && (_p27._4._3.ctor === 'RBNode_elm_builtin')) && (_p27._4._3._0.ctor === 'Black')) && (_p27._4._4.ctor === 'RBNode_elm_builtin')) && (_p27._4._4._0.ctor === 'Black')) { + break _v36_4; + } else { + break _v36_6; + } + default: + break _v36_6; + } + } + } else { + switch (_p27._3._0.ctor) { + case 'Red': + if ((_p27._3._3.ctor === 'RBNode_elm_builtin') && (_p27._3._3._0.ctor === 'Red')) { + break _v36_0; + } else { + if ((_p27._3._4.ctor === 'RBNode_elm_builtin') && (_p27._3._4._0.ctor === 'Red')) { + break _v36_1; + } else { + break _v36_6; + } + } + case 'NBlack': + if (((((_p27._0.ctor === 'BBlack') && (_p27._3._3.ctor === 'RBNode_elm_builtin')) && (_p27._3._3._0.ctor === 'Black')) && (_p27._3._4.ctor === 'RBNode_elm_builtin')) && (_p27._3._4._0.ctor === 'Black')) { + break _v36_5; + } else { + break _v36_6; + } + default: + break _v36_6; + } + } + } else { + if (_p27._4.ctor === 'RBNode_elm_builtin') { + switch (_p27._4._0.ctor) { + case 'Red': + if ((_p27._4._3.ctor === 'RBNode_elm_builtin') && (_p27._4._3._0.ctor === 'Red')) { + break _v36_2; + } else { + if ((_p27._4._4.ctor === 'RBNode_elm_builtin') && (_p27._4._4._0.ctor === 'Red')) { + break _v36_3; + } else { + break _v36_6; + } + } + case 'NBlack': + if (((((_p27._0.ctor === 'BBlack') && (_p27._4._3.ctor === 'RBNode_elm_builtin')) && (_p27._4._3._0.ctor === 'Black')) && (_p27._4._4.ctor === 'RBNode_elm_builtin')) && (_p27._4._4._0.ctor === 'Black')) { + break _v36_4; + } else { + break _v36_6; + } + default: + break _v36_6; + } + } else { + break _v36_6; + } + } + } else { + break _v36_6; + } + } while(false); + return _elm_lang$core$Dict$balancedTree(_p27._0)(_p27._3._3._1)(_p27._3._3._2)(_p27._3._1)(_p27._3._2)(_p27._1)(_p27._2)(_p27._3._3._3)(_p27._3._3._4)(_p27._3._4)(_p27._4); + } while(false); + return _elm_lang$core$Dict$balancedTree(_p27._0)(_p27._3._1)(_p27._3._2)(_p27._3._4._1)(_p27._3._4._2)(_p27._1)(_p27._2)(_p27._3._3)(_p27._3._4._3)(_p27._3._4._4)(_p27._4); + } while(false); + return _elm_lang$core$Dict$balancedTree(_p27._0)(_p27._1)(_p27._2)(_p27._4._3._1)(_p27._4._3._2)(_p27._4._1)(_p27._4._2)(_p27._3)(_p27._4._3._3)(_p27._4._3._4)(_p27._4._4); + } while(false); + return _elm_lang$core$Dict$balancedTree(_p27._0)(_p27._1)(_p27._2)(_p27._4._1)(_p27._4._2)(_p27._4._4._1)(_p27._4._4._2)(_p27._3)(_p27._4._3)(_p27._4._4._3)(_p27._4._4._4); + } while(false); + return A5( + _elm_lang$core$Dict$RBNode_elm_builtin, + _elm_lang$core$Dict$Black, + _p27._4._3._1, + _p27._4._3._2, + A5(_elm_lang$core$Dict$RBNode_elm_builtin, _elm_lang$core$Dict$Black, _p27._1, _p27._2, _p27._3, _p27._4._3._3), + A5( + _elm_lang$core$Dict$balance, + _elm_lang$core$Dict$Black, + _p27._4._1, + _p27._4._2, + _p27._4._3._4, + _elm_lang$core$Dict$redden(_p27._4._4))); + } while(false); + return A5( + _elm_lang$core$Dict$RBNode_elm_builtin, + _elm_lang$core$Dict$Black, + _p27._3._4._1, + _p27._3._4._2, + A5( + _elm_lang$core$Dict$balance, + _elm_lang$core$Dict$Black, + _p27._3._1, + _p27._3._2, + _elm_lang$core$Dict$redden(_p27._3._3), + _p27._3._4._3), + A5(_elm_lang$core$Dict$RBNode_elm_builtin, _elm_lang$core$Dict$Black, _p27._1, _p27._2, _p27._3._4._4, _p27._4)); + } while(false); + return tree; +}; +var _elm_lang$core$Dict$balance = F5( + function (c, k, v, l, r) { + var tree = A5(_elm_lang$core$Dict$RBNode_elm_builtin, c, k, v, l, r); + return _elm_lang$core$Dict$blackish(tree) ? _elm_lang$core$Dict$balanceHelp(tree) : tree; + }); +var _elm_lang$core$Dict$bubble = F5( + function (c, k, v, l, r) { + return (_elm_lang$core$Dict$isBBlack(l) || _elm_lang$core$Dict$isBBlack(r)) ? A5( + _elm_lang$core$Dict$balance, + _elm_lang$core$Dict$moreBlack(c), + k, + v, + _elm_lang$core$Dict$lessBlackTree(l), + _elm_lang$core$Dict$lessBlackTree(r)) : A5(_elm_lang$core$Dict$RBNode_elm_builtin, c, k, v, l, r); + }); +var _elm_lang$core$Dict$removeMax = F5( + function (c, k, v, l, r) { + var _p28 = r; + if (_p28.ctor === 'RBEmpty_elm_builtin') { + return A3(_elm_lang$core$Dict$rem, c, l, r); + } else { + return A5( + _elm_lang$core$Dict$bubble, + c, + k, + v, + l, + A5(_elm_lang$core$Dict$removeMax, _p28._0, _p28._1, _p28._2, _p28._3, _p28._4)); + } + }); +var _elm_lang$core$Dict$rem = F3( + function (c, l, r) { + var _p29 = {ctor: '_Tuple2', _0: l, _1: r}; + if (_p29._0.ctor === 'RBEmpty_elm_builtin') { + if (_p29._1.ctor === 'RBEmpty_elm_builtin') { + var _p30 = c; + switch (_p30.ctor) { + case 'Red': + return _elm_lang$core$Dict$RBEmpty_elm_builtin(_elm_lang$core$Dict$LBlack); + case 'Black': + return _elm_lang$core$Dict$RBEmpty_elm_builtin(_elm_lang$core$Dict$LBBlack); + default: + return _elm_lang$core$Native_Debug.crash('cannot have bblack or nblack nodes at this point'); + } + } else { + var _p33 = _p29._1._0; + var _p32 = _p29._0._0; + var _p31 = {ctor: '_Tuple3', _0: c, _1: _p32, _2: _p33}; + if ((((_p31.ctor === '_Tuple3') && (_p31._0.ctor === 'Black')) && (_p31._1.ctor === 'LBlack')) && (_p31._2.ctor === 'Red')) { + return A5(_elm_lang$core$Dict$RBNode_elm_builtin, _elm_lang$core$Dict$Black, _p29._1._1, _p29._1._2, _p29._1._3, _p29._1._4); + } else { + return A4( + _elm_lang$core$Dict$reportRemBug, + 'Black/LBlack/Red', + c, + _elm_lang$core$Basics$toString(_p32), + _elm_lang$core$Basics$toString(_p33)); + } + } + } else { + if (_p29._1.ctor === 'RBEmpty_elm_builtin') { + var _p36 = _p29._1._0; + var _p35 = _p29._0._0; + var _p34 = {ctor: '_Tuple3', _0: c, _1: _p35, _2: _p36}; + if ((((_p34.ctor === '_Tuple3') && (_p34._0.ctor === 'Black')) && (_p34._1.ctor === 'Red')) && (_p34._2.ctor === 'LBlack')) { + return A5(_elm_lang$core$Dict$RBNode_elm_builtin, _elm_lang$core$Dict$Black, _p29._0._1, _p29._0._2, _p29._0._3, _p29._0._4); + } else { + return A4( + _elm_lang$core$Dict$reportRemBug, + 'Black/Red/LBlack', + c, + _elm_lang$core$Basics$toString(_p35), + _elm_lang$core$Basics$toString(_p36)); + } + } else { + var _p40 = _p29._0._2; + var _p39 = _p29._0._4; + var _p38 = _p29._0._1; + var l$ = A5(_elm_lang$core$Dict$removeMax, _p29._0._0, _p38, _p40, _p29._0._3, _p39); + var _p37 = A3(_elm_lang$core$Dict$maxWithDefault, _p38, _p40, _p39); + var k = _p37._0; + var v = _p37._1; + return A5(_elm_lang$core$Dict$bubble, c, k, v, l$, r); + } + } + }); +var _elm_lang$core$Dict$map = F2( + function (f, dict) { + var _p41 = dict; + if (_p41.ctor === 'RBEmpty_elm_builtin') { + return _elm_lang$core$Dict$RBEmpty_elm_builtin(_elm_lang$core$Dict$LBlack); + } else { + var _p42 = _p41._1; + return A5( + _elm_lang$core$Dict$RBNode_elm_builtin, + _p41._0, + _p42, + A2(f, _p42, _p41._2), + A2(_elm_lang$core$Dict$map, f, _p41._3), + A2(_elm_lang$core$Dict$map, f, _p41._4)); + } + }); +var _elm_lang$core$Dict$Same = {ctor: 'Same'}; +var _elm_lang$core$Dict$Remove = {ctor: 'Remove'}; +var _elm_lang$core$Dict$Insert = {ctor: 'Insert'}; +var _elm_lang$core$Dict$update = F3( + function (k, alter, dict) { + var up = function (dict) { + var _p43 = dict; + if (_p43.ctor === 'RBEmpty_elm_builtin') { + var _p44 = alter(_elm_lang$core$Maybe$Nothing); + if (_p44.ctor === 'Nothing') { + return {ctor: '_Tuple2', _0: _elm_lang$core$Dict$Same, _1: _elm_lang$core$Dict$empty}; + } else { + return { + ctor: '_Tuple2', + _0: _elm_lang$core$Dict$Insert, + _1: A5(_elm_lang$core$Dict$RBNode_elm_builtin, _elm_lang$core$Dict$Red, k, _p44._0, _elm_lang$core$Dict$empty, _elm_lang$core$Dict$empty) + }; + } + } else { + var _p55 = _p43._2; + var _p54 = _p43._4; + var _p53 = _p43._3; + var _p52 = _p43._1; + var _p51 = _p43._0; + var _p45 = A2(_elm_lang$core$Basics$compare, k, _p52); + switch (_p45.ctor) { + case 'EQ': + var _p46 = alter( + _elm_lang$core$Maybe$Just(_p55)); + if (_p46.ctor === 'Nothing') { + return { + ctor: '_Tuple2', + _0: _elm_lang$core$Dict$Remove, + _1: A3(_elm_lang$core$Dict$rem, _p51, _p53, _p54) + }; + } else { + return { + ctor: '_Tuple2', + _0: _elm_lang$core$Dict$Same, + _1: A5(_elm_lang$core$Dict$RBNode_elm_builtin, _p51, _p52, _p46._0, _p53, _p54) + }; + } + case 'LT': + var _p47 = up(_p53); + var flag = _p47._0; + var newLeft = _p47._1; + var _p48 = flag; + switch (_p48.ctor) { + case 'Same': + return { + ctor: '_Tuple2', + _0: _elm_lang$core$Dict$Same, + _1: A5(_elm_lang$core$Dict$RBNode_elm_builtin, _p51, _p52, _p55, newLeft, _p54) + }; + case 'Insert': + return { + ctor: '_Tuple2', + _0: _elm_lang$core$Dict$Insert, + _1: A5(_elm_lang$core$Dict$balance, _p51, _p52, _p55, newLeft, _p54) + }; + default: + return { + ctor: '_Tuple2', + _0: _elm_lang$core$Dict$Remove, + _1: A5(_elm_lang$core$Dict$bubble, _p51, _p52, _p55, newLeft, _p54) + }; + } + default: + var _p49 = up(_p54); + var flag = _p49._0; + var newRight = _p49._1; + var _p50 = flag; + switch (_p50.ctor) { + case 'Same': + return { + ctor: '_Tuple2', + _0: _elm_lang$core$Dict$Same, + _1: A5(_elm_lang$core$Dict$RBNode_elm_builtin, _p51, _p52, _p55, _p53, newRight) + }; + case 'Insert': + return { + ctor: '_Tuple2', + _0: _elm_lang$core$Dict$Insert, + _1: A5(_elm_lang$core$Dict$balance, _p51, _p52, _p55, _p53, newRight) + }; + default: + return { + ctor: '_Tuple2', + _0: _elm_lang$core$Dict$Remove, + _1: A5(_elm_lang$core$Dict$bubble, _p51, _p52, _p55, _p53, newRight) + }; + } + } + } + }; + var _p56 = up(dict); + var flag = _p56._0; + var updatedDict = _p56._1; + var _p57 = flag; + switch (_p57.ctor) { + case 'Same': + return updatedDict; + case 'Insert': + return _elm_lang$core$Dict$ensureBlackRoot(updatedDict); + default: + return _elm_lang$core$Dict$blacken(updatedDict); + } + }); +var _elm_lang$core$Dict$insert = F3( + function (key, value, dict) { + return A3( + _elm_lang$core$Dict$update, + key, + _elm_lang$core$Basics$always( + _elm_lang$core$Maybe$Just(value)), + dict); + }); +var _elm_lang$core$Dict$singleton = F2( + function (key, value) { + return A3(_elm_lang$core$Dict$insert, key, value, _elm_lang$core$Dict$empty); + }); +var _elm_lang$core$Dict$union = F2( + function (t1, t2) { + return A3(_elm_lang$core$Dict$foldl, _elm_lang$core$Dict$insert, t2, t1); + }); +var _elm_lang$core$Dict$filter = F2( + function (predicate, dictionary) { + var add = F3( + function (key, value, dict) { + return A2(predicate, key, value) ? A3(_elm_lang$core$Dict$insert, key, value, dict) : dict; + }); + return A3(_elm_lang$core$Dict$foldl, add, _elm_lang$core$Dict$empty, dictionary); + }); +var _elm_lang$core$Dict$intersect = F2( + function (t1, t2) { + return A2( + _elm_lang$core$Dict$filter, + F2( + function (k, _p58) { + return A2(_elm_lang$core$Dict$member, k, t2); + }), + t1); + }); +var _elm_lang$core$Dict$partition = F2( + function (predicate, dict) { + var add = F3( + function (key, value, _p59) { + var _p60 = _p59; + var _p62 = _p60._1; + var _p61 = _p60._0; + return A2(predicate, key, value) ? { + ctor: '_Tuple2', + _0: A3(_elm_lang$core$Dict$insert, key, value, _p61), + _1: _p62 + } : { + ctor: '_Tuple2', + _0: _p61, + _1: A3(_elm_lang$core$Dict$insert, key, value, _p62) + }; + }); + return A3( + _elm_lang$core$Dict$foldl, + add, + {ctor: '_Tuple2', _0: _elm_lang$core$Dict$empty, _1: _elm_lang$core$Dict$empty}, + dict); + }); +var _elm_lang$core$Dict$fromList = function (assocs) { + return A3( + _elm_lang$core$List$foldl, + F2( + function (_p63, dict) { + var _p64 = _p63; + return A3(_elm_lang$core$Dict$insert, _p64._0, _p64._1, dict); + }), + _elm_lang$core$Dict$empty, + assocs); +}; +var _elm_lang$core$Dict$remove = F2( + function (key, dict) { + return A3( + _elm_lang$core$Dict$update, + key, + _elm_lang$core$Basics$always(_elm_lang$core$Maybe$Nothing), + dict); + }); +var _elm_lang$core$Dict$diff = F2( + function (t1, t2) { + return A3( + _elm_lang$core$Dict$foldl, + F3( + function (k, v, t) { + return A2(_elm_lang$core$Dict$remove, k, t); + }), + t1, + t2); + }); + +var _elm_lang$core$Platform_Sub$batch = _elm_lang$core$Native_Platform.batch; +var _elm_lang$core$Platform_Sub$none = _elm_lang$core$Platform_Sub$batch( + _elm_lang$core$Native_List.fromArray( + [])); +var _elm_lang$core$Platform_Sub$map = _elm_lang$core$Native_Platform.map; +var _elm_lang$core$Platform_Sub$Sub = {ctor: 'Sub'}; + +var _elm_lang$core$Debug$crash = _elm_lang$core$Native_Debug.crash; +var _elm_lang$core$Debug$log = _elm_lang$core$Native_Debug.log; + +//import Maybe, Native.Array, Native.List, Native.Utils, Result // + +var _elm_lang$core$Native_Json = function() { + + +// CORE DECODERS + +function succeed(msg) +{ + return { + ctor: '', + tag: 'succeed', + msg: msg + }; +} + +function fail(msg) +{ + return { + ctor: '', + tag: 'fail', + msg: msg + }; +} + +function decodePrimitive(tag) +{ + return { + ctor: '', + tag: tag + }; +} + +function decodeContainer(tag, decoder) +{ + return { + ctor: '', + tag: tag, + decoder: decoder + }; +} + +function decodeNull(value) +{ + return { + ctor: '', + tag: 'null', + value: value + }; +} + +function decodeField(field, decoder) +{ + return { + ctor: '', + tag: 'field', + field: field, + decoder: decoder + }; +} + +function decodeKeyValuePairs(decoder) +{ + return { + ctor: '', + tag: 'key-value', + decoder: decoder + }; +} + +function decodeObject(f, decoders) +{ + return { + ctor: '', + tag: 'map-many', + func: f, + decoders: decoders + }; +} + +function decodeTuple(f, decoders) +{ + return { + ctor: '', + tag: 'tuple', + func: f, + decoders: decoders + }; +} + +function andThen(decoder, callback) +{ + return { + ctor: '', + tag: 'andThen', + decoder: decoder, + callback: callback + }; +} + +function customAndThen(decoder, callback) +{ + return { + ctor: '', + tag: 'customAndThen', + decoder: decoder, + callback: callback + }; +} + +function oneOf(decoders) +{ + return { + ctor: '', + tag: 'oneOf', + decoders: decoders + }; +} + + +// DECODING OBJECTS + +function decodeObject1(f, d1) +{ + return decodeObject(f, [d1]); +} + +function decodeObject2(f, d1, d2) +{ + return decodeObject(f, [d1, d2]); +} + +function decodeObject3(f, d1, d2, d3) +{ + return decodeObject(f, [d1, d2, d3]); +} + +function decodeObject4(f, d1, d2, d3, d4) +{ + return decodeObject(f, [d1, d2, d3, d4]); +} + +function decodeObject5(f, d1, d2, d3, d4, d5) +{ + return decodeObject(f, [d1, d2, d3, d4, d5]); +} + +function decodeObject6(f, d1, d2, d3, d4, d5, d6) +{ + return decodeObject(f, [d1, d2, d3, d4, d5, d6]); +} + +function decodeObject7(f, d1, d2, d3, d4, d5, d6, d7) +{ + return decodeObject(f, [d1, d2, d3, d4, d5, d6, d7]); +} + +function decodeObject8(f, d1, d2, d3, d4, d5, d6, d7, d8) +{ + return decodeObject(f, [d1, d2, d3, d4, d5, d6, d7, d8]); +} + + +// DECODING TUPLES + +function decodeTuple1(f, d1) +{ + return decodeTuple(f, [d1]); +} + +function decodeTuple2(f, d1, d2) +{ + return decodeTuple(f, [d1, d2]); +} + +function decodeTuple3(f, d1, d2, d3) +{ + return decodeTuple(f, [d1, d2, d3]); +} + +function decodeTuple4(f, d1, d2, d3, d4) +{ + return decodeTuple(f, [d1, d2, d3, d4]); +} + +function decodeTuple5(f, d1, d2, d3, d4, d5) +{ + return decodeTuple(f, [d1, d2, d3, d4, d5]); +} + +function decodeTuple6(f, d1, d2, d3, d4, d5, d6) +{ + return decodeTuple(f, [d1, d2, d3, d4, d5, d6]); +} + +function decodeTuple7(f, d1, d2, d3, d4, d5, d6, d7) +{ + return decodeTuple(f, [d1, d2, d3, d4, d5, d6, d7]); +} + +function decodeTuple8(f, d1, d2, d3, d4, d5, d6, d7, d8) +{ + return decodeTuple(f, [d1, d2, d3, d4, d5, d6, d7, d8]); +} + + +// DECODE HELPERS + +function ok(value) +{ + return { tag: 'ok', value: value }; +} + +function badPrimitive(type, value) +{ + return { tag: 'primitive', type: type, value: value }; +} + +function badIndex(index, nestedProblems) +{ + return { tag: 'index', index: index, rest: nestedProblems }; +} + +function badField(field, nestedProblems) +{ + return { tag: 'field', field: field, rest: nestedProblems }; +} + +function badOneOf(problems) +{ + return { tag: 'oneOf', problems: problems }; +} + +function badCustom(msg) +{ + return { tag: 'custom', msg: msg }; +} + +function bad(msg) +{ + return { tag: 'fail', msg: msg }; +} + +function badToString(problem) +{ + var context = '_'; + while (problem) + { + switch (problem.tag) + { + case 'primitive': + return 'Expecting ' + problem.type + + (context === '_' ? '' : ' at ' + context) + + ' but instead got: ' + jsToString(problem.value); + + case 'index': + context += '[' + problem.index + ']'; + problem = problem.rest; + break; + + case 'field': + context += '.' + problem.field; + problem = problem.rest; + break; + + case 'oneOf': + var problems = problem.problems; + for (var i = 0; i < problems.length; i++) + { + problems[i] = badToString(problems[i]); + } + return 'I ran into the following problems' + + (context === '_' ? '' : ' at ' + context) + + ':\n\n' + problems.join('\n'); + + case 'custom': + return 'A `customDecoder` failed' + + (context === '_' ? '' : ' at ' + context) + + ' with the message: ' + problem.msg; + + case 'fail': + return 'I ran into a `fail` decoder' + + (context === '_' ? '' : ' at ' + context) + + ': ' + problem.msg; + } + } +} + +function jsToString(value) +{ + return value === undefined + ? 'undefined' + : JSON.stringify(value); +} + + +// DECODE + +function runOnString(decoder, string) +{ + var json; + try + { + json = JSON.parse(string); + } + catch (e) + { + return _elm_lang$core$Result$Err('Given an invalid JSON: ' + e.message); + } + return run(decoder, json); +} + +function run(decoder, value) +{ + var result = runHelp(decoder, value); + return (result.tag === 'ok') + ? _elm_lang$core$Result$Ok(result.value) + : _elm_lang$core$Result$Err(badToString(result)); +} + +function runHelp(decoder, value) +{ + switch (decoder.tag) + { + case 'bool': + return (typeof value === 'boolean') + ? ok(value) + : badPrimitive('a Bool', value); + + case 'int': + if (typeof value !== 'number') { + return badPrimitive('an Int', value); + } + + if (-2147483647 < value && value < 2147483647 && (value | 0) === value) { + return ok(value); + } + + if (isFinite(value) && !(value % 1)) { + return ok(value); + } + + return badPrimitive('an Int', value); + + case 'float': + return (typeof value === 'number') + ? ok(value) + : badPrimitive('a Float', value); + + case 'string': + return (typeof value === 'string') + ? ok(value) + : (value instanceof String) + ? ok(value + '') + : badPrimitive('a String', value); + + case 'null': + return (value === null) + ? ok(decoder.value) + : badPrimitive('null', value); + + case 'value': + return ok(value); + + case 'list': + if (!(value instanceof Array)) + { + return badPrimitive('a List', value); + } + + var list = _elm_lang$core$Native_List.Nil; + for (var i = value.length; i--; ) + { + var result = runHelp(decoder.decoder, value[i]); + if (result.tag !== 'ok') + { + return badIndex(i, result) + } + list = _elm_lang$core$Native_List.Cons(result.value, list); + } + return ok(list); + + case 'array': + if (!(value instanceof Array)) + { + return badPrimitive('an Array', value); + } + + var len = value.length; + var array = new Array(len); + for (var i = len; i--; ) + { + var result = runHelp(decoder.decoder, value[i]); + if (result.tag !== 'ok') + { + return badIndex(i, result); + } + array[i] = result.value; + } + return ok(_elm_lang$core$Native_Array.fromJSArray(array)); + + case 'maybe': + var result = runHelp(decoder.decoder, value); + return (result.tag === 'ok') + ? ok(_elm_lang$core$Maybe$Just(result.value)) + : ok(_elm_lang$core$Maybe$Nothing); + + case 'field': + var field = decoder.field; + if (typeof value !== 'object' || value === null || !(field in value)) + { + return badPrimitive('an object with a field named `' + field + '`', value); + } + + var result = runHelp(decoder.decoder, value[field]); + return (result.tag === 'ok') + ? result + : badField(field, result); + + case 'key-value': + if (typeof value !== 'object' || value === null || value instanceof Array) + { + return badPrimitive('an object', value); + } + + var keyValuePairs = _elm_lang$core$Native_List.Nil; + for (var key in value) + { + var result = runHelp(decoder.decoder, value[key]); + if (result.tag !== 'ok') + { + return badField(key, result); + } + var pair = _elm_lang$core$Native_Utils.Tuple2(key, result.value); + keyValuePairs = _elm_lang$core$Native_List.Cons(pair, keyValuePairs); + } + return ok(keyValuePairs); + + case 'map-many': + var answer = decoder.func; + var decoders = decoder.decoders; + for (var i = 0; i < decoders.length; i++) + { + var result = runHelp(decoders[i], value); + if (result.tag !== 'ok') + { + return result; + } + answer = answer(result.value); + } + return ok(answer); + + case 'tuple': + var decoders = decoder.decoders; + var len = decoders.length; + + if ( !(value instanceof Array) || value.length !== len ) + { + return badPrimitive('a Tuple with ' + len + ' entries', value); + } + + var answer = decoder.func; + for (var i = 0; i < len; i++) + { + var result = runHelp(decoders[i], value[i]); + if (result.tag !== 'ok') + { + return badIndex(i, result); + } + answer = answer(result.value); + } + return ok(answer); + + case 'customAndThen': + var result = runHelp(decoder.decoder, value); + if (result.tag !== 'ok') + { + return result; + } + var realResult = decoder.callback(result.value); + if (realResult.ctor === 'Err') + { + return badCustom(realResult._0); + } + return ok(realResult._0); + + case 'andThen': + var result = runHelp(decoder.decoder, value); + return (result.tag !== 'ok') + ? result + : runHelp(decoder.callback(result.value), value); + + case 'oneOf': + var errors = []; + var temp = decoder.decoders; + while (temp.ctor !== '[]') + { + var result = runHelp(temp._0, value); + + if (result.tag === 'ok') + { + return result; + } + + errors.push(result); + + temp = temp._1; + } + return badOneOf(errors); + + case 'fail': + return bad(decoder.msg); + + case 'succeed': + return ok(decoder.msg); + } +} + + +// EQUALITY + +function equality(a, b) +{ + if (a === b) + { + return true; + } + + if (a.tag !== b.tag) + { + return false; + } + + switch (a.tag) + { + case 'succeed': + case 'fail': + return a.msg === b.msg; + + case 'bool': + case 'int': + case 'float': + case 'string': + case 'value': + return true; + + case 'null': + return a.value === b.value; + + case 'list': + case 'array': + case 'maybe': + case 'key-value': + return equality(a.decoder, b.decoder); + + case 'field': + return a.field === b.field && equality(a.decoder, b.decoder); + + case 'map-many': + case 'tuple': + if (a.func !== b.func) + { + return false; + } + return listEquality(a.decoders, b.decoders); + + case 'andThen': + case 'customAndThen': + return a.callback === b.callback && equality(a.decoder, b.decoder); + + case 'oneOf': + return listEquality(a.decoders, b.decoders); + } +} + +function listEquality(aDecoders, bDecoders) +{ + var len = aDecoders.length; + if (len !== bDecoders.length) + { + return false; + } + for (var i = 0; i < len; i++) + { + if (!equality(aDecoders[i], bDecoders[i])) + { + return false; + } + } + return true; +} + + +// ENCODE + +function encode(indentLevel, value) +{ + return JSON.stringify(value, null, indentLevel); +} + +function identity(value) +{ + return value; +} + +function encodeObject(keyValuePairs) +{ + var obj = {}; + while (keyValuePairs.ctor !== '[]') + { + var pair = keyValuePairs._0; + obj[pair._0] = pair._1; + keyValuePairs = keyValuePairs._1; + } + return obj; +} + +return { + encode: F2(encode), + runOnString: F2(runOnString), + run: F2(run), + + decodeNull: decodeNull, + decodePrimitive: decodePrimitive, + decodeContainer: F2(decodeContainer), + + decodeField: F2(decodeField), + + decodeObject1: F2(decodeObject1), + decodeObject2: F3(decodeObject2), + decodeObject3: F4(decodeObject3), + decodeObject4: F5(decodeObject4), + decodeObject5: F6(decodeObject5), + decodeObject6: F7(decodeObject6), + decodeObject7: F8(decodeObject7), + decodeObject8: F9(decodeObject8), + decodeKeyValuePairs: decodeKeyValuePairs, + + decodeTuple1: F2(decodeTuple1), + decodeTuple2: F3(decodeTuple2), + decodeTuple3: F4(decodeTuple3), + decodeTuple4: F5(decodeTuple4), + decodeTuple5: F6(decodeTuple5), + decodeTuple6: F7(decodeTuple6), + decodeTuple7: F8(decodeTuple7), + decodeTuple8: F9(decodeTuple8), + + andThen: F2(andThen), + customAndThen: F2(customAndThen), + fail: fail, + succeed: succeed, + oneOf: oneOf, + + identity: identity, + encodeNull: null, + encodeArray: _elm_lang$core$Native_Array.toJSArray, + encodeList: _elm_lang$core$Native_List.toArray, + encodeObject: encodeObject, + + equality: equality +}; + +}(); + +var _elm_lang$core$Json_Encode$list = _elm_lang$core$Native_Json.encodeList; +var _elm_lang$core$Json_Encode$array = _elm_lang$core$Native_Json.encodeArray; +var _elm_lang$core$Json_Encode$object = _elm_lang$core$Native_Json.encodeObject; +var _elm_lang$core$Json_Encode$null = _elm_lang$core$Native_Json.encodeNull; +var _elm_lang$core$Json_Encode$bool = _elm_lang$core$Native_Json.identity; +var _elm_lang$core$Json_Encode$float = _elm_lang$core$Native_Json.identity; +var _elm_lang$core$Json_Encode$int = _elm_lang$core$Native_Json.identity; +var _elm_lang$core$Json_Encode$string = _elm_lang$core$Native_Json.identity; +var _elm_lang$core$Json_Encode$encode = _elm_lang$core$Native_Json.encode; +var _elm_lang$core$Json_Encode$Value = {ctor: 'Value'}; + +var _elm_lang$core$Json_Decode$tuple8 = _elm_lang$core$Native_Json.decodeTuple8; +var _elm_lang$core$Json_Decode$tuple7 = _elm_lang$core$Native_Json.decodeTuple7; +var _elm_lang$core$Json_Decode$tuple6 = _elm_lang$core$Native_Json.decodeTuple6; +var _elm_lang$core$Json_Decode$tuple5 = _elm_lang$core$Native_Json.decodeTuple5; +var _elm_lang$core$Json_Decode$tuple4 = _elm_lang$core$Native_Json.decodeTuple4; +var _elm_lang$core$Json_Decode$tuple3 = _elm_lang$core$Native_Json.decodeTuple3; +var _elm_lang$core$Json_Decode$tuple2 = _elm_lang$core$Native_Json.decodeTuple2; +var _elm_lang$core$Json_Decode$tuple1 = _elm_lang$core$Native_Json.decodeTuple1; +var _elm_lang$core$Json_Decode$succeed = _elm_lang$core$Native_Json.succeed; +var _elm_lang$core$Json_Decode$fail = _elm_lang$core$Native_Json.fail; +var _elm_lang$core$Json_Decode$andThen = _elm_lang$core$Native_Json.andThen; +var _elm_lang$core$Json_Decode$customDecoder = _elm_lang$core$Native_Json.customAndThen; +var _elm_lang$core$Json_Decode$decodeValue = _elm_lang$core$Native_Json.run; +var _elm_lang$core$Json_Decode$value = _elm_lang$core$Native_Json.decodePrimitive('value'); +var _elm_lang$core$Json_Decode$maybe = function (decoder) { + return A2(_elm_lang$core$Native_Json.decodeContainer, 'maybe', decoder); +}; +var _elm_lang$core$Json_Decode$null = _elm_lang$core$Native_Json.decodeNull; +var _elm_lang$core$Json_Decode$array = function (decoder) { + return A2(_elm_lang$core$Native_Json.decodeContainer, 'array', decoder); +}; +var _elm_lang$core$Json_Decode$list = function (decoder) { + return A2(_elm_lang$core$Native_Json.decodeContainer, 'list', decoder); +}; +var _elm_lang$core$Json_Decode$bool = _elm_lang$core$Native_Json.decodePrimitive('bool'); +var _elm_lang$core$Json_Decode$int = _elm_lang$core$Native_Json.decodePrimitive('int'); +var _elm_lang$core$Json_Decode$float = _elm_lang$core$Native_Json.decodePrimitive('float'); +var _elm_lang$core$Json_Decode$string = _elm_lang$core$Native_Json.decodePrimitive('string'); +var _elm_lang$core$Json_Decode$oneOf = _elm_lang$core$Native_Json.oneOf; +var _elm_lang$core$Json_Decode$keyValuePairs = _elm_lang$core$Native_Json.decodeKeyValuePairs; +var _elm_lang$core$Json_Decode$object8 = _elm_lang$core$Native_Json.decodeObject8; +var _elm_lang$core$Json_Decode$object7 = _elm_lang$core$Native_Json.decodeObject7; +var _elm_lang$core$Json_Decode$object6 = _elm_lang$core$Native_Json.decodeObject6; +var _elm_lang$core$Json_Decode$object5 = _elm_lang$core$Native_Json.decodeObject5; +var _elm_lang$core$Json_Decode$object4 = _elm_lang$core$Native_Json.decodeObject4; +var _elm_lang$core$Json_Decode$object3 = _elm_lang$core$Native_Json.decodeObject3; +var _elm_lang$core$Json_Decode$object2 = _elm_lang$core$Native_Json.decodeObject2; +var _elm_lang$core$Json_Decode$object1 = _elm_lang$core$Native_Json.decodeObject1; +var _elm_lang$core$Json_Decode_ops = _elm_lang$core$Json_Decode_ops || {}; +_elm_lang$core$Json_Decode_ops[':='] = _elm_lang$core$Native_Json.decodeField; +var _elm_lang$core$Json_Decode$at = F2( + function (fields, decoder) { + return A3( + _elm_lang$core$List$foldr, + F2( + function (x, y) { + return A2(_elm_lang$core$Json_Decode_ops[':='], x, y); + }), + decoder, + fields); + }); +var _elm_lang$core$Json_Decode$decodeString = _elm_lang$core$Native_Json.runOnString; +var _elm_lang$core$Json_Decode$map = _elm_lang$core$Native_Json.decodeObject1; +var _elm_lang$core$Json_Decode$dict = function (decoder) { + return A2( + _elm_lang$core$Json_Decode$map, + _elm_lang$core$Dict$fromList, + _elm_lang$core$Json_Decode$keyValuePairs(decoder)); +}; +var _elm_lang$core$Json_Decode$Decoder = {ctor: 'Decoder'}; + +//import Native.Json // + +var _elm_lang$virtual_dom$Native_VirtualDom = function() { + +var STYLE_KEY = 'STYLE'; +var EVENT_KEY = 'EVENT'; +var ATTR_KEY = 'ATTR'; +var ATTR_NS_KEY = 'ATTR_NS'; + + + +//////////// VIRTUAL DOM NODES //////////// + + +function text(string) +{ + return { + type: 'text', + text: string + }; +} + + +function node(tag) +{ + return F2(function(factList, kidList) { + return nodeHelp(tag, factList, kidList); + }); +} + + +function nodeHelp(tag, factList, kidList) +{ + var organized = organizeFacts(factList); + var namespace = organized.namespace; + var facts = organized.facts; + + var children = []; + var descendantsCount = 0; + while (kidList.ctor !== '[]') + { + var kid = kidList._0; + descendantsCount += (kid.descendantsCount || 0); + children.push(kid); + kidList = kidList._1; + } + descendantsCount += children.length; + + return { + type: 'node', + tag: tag, + facts: facts, + children: children, + namespace: namespace, + descendantsCount: descendantsCount + }; +} + + +function keyedNode(tag, factList, kidList) +{ + var organized = organizeFacts(factList); + var namespace = organized.namespace; + var facts = organized.facts; + + var children = []; + var descendantsCount = 0; + while (kidList.ctor !== '[]') + { + var kid = kidList._0; + descendantsCount += (kid._1.descendantsCount || 0); + children.push(kid); + kidList = kidList._1; + } + descendantsCount += children.length; + + return { + type: 'keyed-node', + tag: tag, + facts: facts, + children: children, + namespace: namespace, + descendantsCount: descendantsCount + }; +} + + +function custom(factList, model, impl) +{ + var facts = organizeFacts(factList).facts; + + return { + type: 'custom', + facts: facts, + model: model, + impl: impl + }; +} + + +function map(tagger, node) +{ + return { + type: 'tagger', + tagger: tagger, + node: node, + descendantsCount: 1 + (node.descendantsCount || 0) + }; +} + + +function thunk(func, args, thunk) +{ + return { + type: 'thunk', + func: func, + args: args, + thunk: thunk, + node: undefined + }; +} + +function lazy(fn, a) +{ + return thunk(fn, [a], function() { + return fn(a); + }); +} + +function lazy2(fn, a, b) +{ + return thunk(fn, [a,b], function() { + return A2(fn, a, b); + }); +} + +function lazy3(fn, a, b, c) +{ + return thunk(fn, [a,b,c], function() { + return A3(fn, a, b, c); + }); +} + + + +// FACTS + + +function organizeFacts(factList) +{ + var namespace, facts = {}; + + while (factList.ctor !== '[]') + { + var entry = factList._0; + var key = entry.key; + + if (key === ATTR_KEY || key === ATTR_NS_KEY || key === EVENT_KEY) + { + var subFacts = facts[key] || {}; + subFacts[entry.realKey] = entry.value; + facts[key] = subFacts; + } + else if (key === STYLE_KEY) + { + var styles = facts[key] || {}; + var styleList = entry.value; + while (styleList.ctor !== '[]') + { + var style = styleList._0; + styles[style._0] = style._1; + styleList = styleList._1; + } + facts[key] = styles; + } + else if (key === 'namespace') + { + namespace = entry.value; + } + else + { + facts[key] = entry.value; + } + factList = factList._1; + } + + return { + facts: facts, + namespace: namespace + }; +} + + + +//////////// PROPERTIES AND ATTRIBUTES //////////// + + +function style(value) +{ + return { + key: STYLE_KEY, + value: value + }; +} + + +function property(key, value) +{ + return { + key: key, + value: value + }; +} + + +function attribute(key, value) +{ + return { + key: ATTR_KEY, + realKey: key, + value: value + }; +} + + +function attributeNS(namespace, key, value) +{ + return { + key: ATTR_NS_KEY, + realKey: key, + value: { + value: value, + namespace: namespace + } + }; +} + + +function on(name, options, decoder) +{ + return { + key: EVENT_KEY, + realKey: name, + value: { + options: options, + decoder: decoder + } + }; +} + + +function equalEvents(a, b) +{ + if (!a.options === b.options) + { + if (a.stopPropagation !== b.stopPropagation || a.preventDefault !== b.preventDefault) + { + return false; + } + } + return _elm_lang$core$Native_Json.equality(a.decoder, b.decoder); +} + + + +//////////// RENDERER //////////// + + +function renderer(parent, tagger, initialVirtualNode) +{ + var eventNode = { tagger: tagger, parent: undefined }; + + var domNode = render(initialVirtualNode, eventNode); + parent.appendChild(domNode); + + var state = 'NO_REQUEST'; + var currentVirtualNode = initialVirtualNode; + var nextVirtualNode = initialVirtualNode; + + function registerVirtualNode(vNode) + { + if (state === 'NO_REQUEST') + { + rAF(updateIfNeeded); + } + state = 'PENDING_REQUEST'; + nextVirtualNode = vNode; + } + + function updateIfNeeded() + { + switch (state) + { + case 'NO_REQUEST': + throw new Error( + 'Unexpected draw callback.\n' + + 'Please report this to .' + ); + + case 'PENDING_REQUEST': + rAF(updateIfNeeded); + state = 'EXTRA_REQUEST'; + + var patches = diff(currentVirtualNode, nextVirtualNode); + domNode = applyPatches(domNode, currentVirtualNode, patches, eventNode); + currentVirtualNode = nextVirtualNode; + + return; + + case 'EXTRA_REQUEST': + state = 'NO_REQUEST'; + return; + } + } + + return { update: registerVirtualNode }; +} + + +var rAF = + typeof requestAnimationFrame !== 'undefined' + ? requestAnimationFrame + : function(cb) { setTimeout(cb, 1000 / 60); }; + + + +//////////// RENDER //////////// + + +function render(vNode, eventNode) +{ + switch (vNode.type) + { + case 'thunk': + if (!vNode.node) + { + vNode.node = vNode.thunk(); + } + return render(vNode.node, eventNode); + + case 'tagger': + var subNode = vNode.node; + var tagger = vNode.tagger; + + while (subNode.type === 'tagger') + { + typeof tagger !== 'object' + ? tagger = [tagger, subNode.tagger] + : tagger.push(subNode.tagger); + + subNode = subNode.node; + } + + var subEventRoot = { + tagger: tagger, + parent: eventNode + }; + + var domNode = render(subNode, subEventRoot); + domNode.elm_event_node_ref = subEventRoot; + return domNode; + + case 'text': + return document.createTextNode(vNode.text); + + case 'node': + var domNode = vNode.namespace + ? document.createElementNS(vNode.namespace, vNode.tag) + : document.createElement(vNode.tag); + + applyFacts(domNode, eventNode, vNode.facts); + + var children = vNode.children; + + for (var i = 0; i < children.length; i++) + { + domNode.appendChild(render(children[i], eventNode)); + } + + return domNode; + + case 'keyed-node': + var domNode = vNode.namespace + ? document.createElementNS(vNode.namespace, vNode.tag) + : document.createElement(vNode.tag); + + applyFacts(domNode, eventNode, vNode.facts); + + var children = vNode.children; + + for (var i = 0; i < children.length; i++) + { + domNode.appendChild(render(children[i]._1, eventNode)); + } + + return domNode; + + case 'custom': + var domNode = vNode.impl.render(vNode.model); + applyFacts(domNode, eventNode, vNode.facts); + return domNode; + } +} + + + +//////////// APPLY FACTS //////////// + + +function applyFacts(domNode, eventNode, facts) +{ + for (var key in facts) + { + var value = facts[key]; + + switch (key) + { + case STYLE_KEY: + applyStyles(domNode, value); + break; + + case EVENT_KEY: + applyEvents(domNode, eventNode, value); + break; + + case ATTR_KEY: + applyAttrs(domNode, value); + break; + + case ATTR_NS_KEY: + applyAttrsNS(domNode, value); + break; + + case 'value': + if (domNode[key] !== value) + { + domNode[key] = value; + } + break; + + default: + domNode[key] = value; + break; + } + } +} + +function applyStyles(domNode, styles) +{ + var domNodeStyle = domNode.style; + + for (var key in styles) + { + domNodeStyle[key] = styles[key]; + } +} + +function applyEvents(domNode, eventNode, events) +{ + var allHandlers = domNode.elm_handlers || {}; + + for (var key in events) + { + var handler = allHandlers[key]; + var value = events[key]; + + if (typeof value === 'undefined') + { + domNode.removeEventListener(key, handler); + allHandlers[key] = undefined; + } + else if (typeof handler === 'undefined') + { + var handler = makeEventHandler(eventNode, value); + domNode.addEventListener(key, handler); + allHandlers[key] = handler; + } + else + { + handler.info = value; + } + } + + domNode.elm_handlers = allHandlers; +} + +function makeEventHandler(eventNode, info) +{ + function eventHandler(event) + { + var info = eventHandler.info; + + var value = A2(_elm_lang$core$Native_Json.run, info.decoder, event); + + if (value.ctor === 'Ok') + { + var options = info.options; + if (options.stopPropagation) + { + event.stopPropagation(); + } + if (options.preventDefault) + { + event.preventDefault(); + } + + var message = value._0; + + var currentEventNode = eventNode; + while (currentEventNode) + { + var tagger = currentEventNode.tagger; + if (typeof tagger === 'function') + { + message = tagger(message); + } + else + { + for (var i = tagger.length; i--; ) + { + message = tagger[i](message); + } + } + currentEventNode = currentEventNode.parent; + } + } + }; + + eventHandler.info = info; + + return eventHandler; +} + +function applyAttrs(domNode, attrs) +{ + for (var key in attrs) + { + var value = attrs[key]; + if (typeof value === 'undefined') + { + domNode.removeAttribute(key); + } + else + { + domNode.setAttribute(key, value); + } + } +} + +function applyAttrsNS(domNode, nsAttrs) +{ + for (var key in nsAttrs) + { + var pair = nsAttrs[key]; + var namespace = pair.namespace; + var value = pair.value; + + if (typeof value === 'undefined') + { + domNode.removeAttributeNS(namespace, key); + } + else + { + domNode.setAttributeNS(namespace, key, value); + } + } +} + + + +//////////// DIFF //////////// + + +function diff(a, b) +{ + var patches = []; + diffHelp(a, b, patches, 0); + return patches; +} + + +function makePatch(type, index, data) +{ + return { + index: index, + type: type, + data: data, + domNode: undefined, + eventNode: undefined + }; +} + + +function diffHelp(a, b, patches, index) +{ + if (a === b) + { + return; + } + + var aType = a.type; + var bType = b.type; + + // Bail if you run into different types of nodes. Implies that the + // structure has changed significantly and it's not worth a diff. + if (aType !== bType) + { + patches.push(makePatch('p-redraw', index, b)); + return; + } + + // Now we know that both nodes are the same type. + switch (bType) + { + case 'thunk': + var aArgs = a.args; + var bArgs = b.args; + var i = aArgs.length; + var same = a.func === b.func && i === bArgs.length; + while (same && i--) + { + same = aArgs[i] === bArgs[i]; + } + if (same) + { + b.node = a.node; + return; + } + b.node = b.thunk(); + var subPatches = []; + diffHelp(a.node, b.node, subPatches, 0); + if (subPatches.length > 0) + { + patches.push(makePatch('p-thunk', index, subPatches)); + } + return; + + case 'tagger': + // gather nested taggers + var aTaggers = a.tagger; + var bTaggers = b.tagger; + var nesting = false; + + var aSubNode = a.node; + while (aSubNode.type === 'tagger') + { + nesting = true; + + typeof aTaggers !== 'object' + ? aTaggers = [aTaggers, aSubNode.tagger] + : aTaggers.push(aSubNode.tagger); + + aSubNode = aSubNode.node; + } + + var bSubNode = b.node; + while (bSubNode.type === 'tagger') + { + nesting = true; + + typeof bTaggers !== 'object' + ? bTaggers = [bTaggers, bSubNode.tagger] + : bTaggers.push(bSubNode.tagger); + + bSubNode = bSubNode.node; + } + + // Just bail if different numbers of taggers. This implies the + // structure of the virtual DOM has changed. + if (nesting && aTaggers.length !== bTaggers.length) + { + patches.push(makePatch('p-redraw', index, b)); + return; + } + + // check if taggers are "the same" + if (nesting ? !pairwiseRefEqual(aTaggers, bTaggers) : aTaggers !== bTaggers) + { + patches.push(makePatch('p-tagger', index, bTaggers)); + } + + // diff everything below the taggers + diffHelp(aSubNode, bSubNode, patches, index + 1); + return; + + case 'text': + if (a.text !== b.text) + { + patches.push(makePatch('p-text', index, b.text)); + return; + } + + return; + + case 'node': + // Bail if obvious indicators have changed. Implies more serious + // structural changes such that it's not worth it to diff. + if (a.tag !== b.tag || a.namespace !== b.namespace) + { + patches.push(makePatch('p-redraw', index, b)); + return; + } + + var factsDiff = diffFacts(a.facts, b.facts); + + if (typeof factsDiff !== 'undefined') + { + patches.push(makePatch('p-facts', index, factsDiff)); + } + + diffChildren(a, b, patches, index); + return; + + case 'keyed-node': + // Bail if obvious indicators have changed. Implies more serious + // structural changes such that it's not worth it to diff. + if (a.tag !== b.tag || a.namespace !== b.namespace) + { + patches.push(makePatch('p-redraw', index, b)); + return; + } + + var factsDiff = diffFacts(a.facts, b.facts); + + if (typeof factsDiff !== 'undefined') + { + patches.push(makePatch('p-facts', index, factsDiff)); + } + + diffKeyedChildren(a, b, patches, index); + return; + + case 'custom': + if (a.impl !== b.impl) + { + patches.push(makePatch('p-redraw', index, b)); + return; + } + + var factsDiff = diffFacts(a.facts, b.facts); + if (typeof factsDiff !== 'undefined') + { + patches.push(makePatch('p-facts', index, factsDiff)); + } + + var patch = b.impl.diff(a,b); + if (patch) + { + patches.push(makePatch('p-custom', index, patch)); + return; + } + + return; + } +} + + +// assumes the incoming arrays are the same length +function pairwiseRefEqual(as, bs) +{ + for (var i = 0; i < as.length; i++) + { + if (as[i] !== bs[i]) + { + return false; + } + } + + return true; +} + + +// TODO Instead of creating a new diff object, it's possible to just test if +// there *is* a diff. During the actual patch, do the diff again and make the +// modifications directly. This way, there's no new allocations. Worth it? +function diffFacts(a, b, category) +{ + var diff; + + // look for changes and removals + for (var aKey in a) + { + if (aKey === STYLE_KEY || aKey === EVENT_KEY || aKey === ATTR_KEY || aKey === ATTR_NS_KEY) + { + var subDiff = diffFacts(a[aKey], b[aKey] || {}, aKey); + if (subDiff) + { + diff = diff || {}; + diff[aKey] = subDiff; + } + continue; + } + + // remove if not in the new facts + if (!(aKey in b)) + { + diff = diff || {}; + diff[aKey] = + (typeof category === 'undefined') + ? (typeof a[aKey] === 'string' ? '' : null) + : + (category === STYLE_KEY) + ? '' + : + (category === EVENT_KEY || category === ATTR_KEY) + ? undefined + : + { namespace: a[aKey].namespace, value: undefined }; + + continue; + } + + var aValue = a[aKey]; + var bValue = b[aKey]; + + // reference equal, so don't worry about it + if (aValue === bValue && aKey !== 'value' + || category === EVENT_KEY && equalEvents(aValue, bValue)) + { + continue; + } + + diff = diff || {}; + diff[aKey] = bValue; + } + + // add new stuff + for (var bKey in b) + { + if (!(bKey in a)) + { + diff = diff || {}; + diff[bKey] = b[bKey]; + } + } + + return diff; +} + + +function diffChildren(aParent, bParent, patches, rootIndex) +{ + var aChildren = aParent.children; + var bChildren = bParent.children; + + var aLen = aChildren.length; + var bLen = bChildren.length; + + // FIGURE OUT IF THERE ARE INSERTS OR REMOVALS + + if (aLen > bLen) + { + patches.push(makePatch('p-remove-last', rootIndex, aLen - bLen)); + } + else if (aLen < bLen) + { + patches.push(makePatch('p-append', rootIndex, bChildren.slice(aLen))); + } + + // PAIRWISE DIFF EVERYTHING ELSE + + var index = rootIndex; + var minLen = aLen < bLen ? aLen : bLen; + for (var i = 0; i < minLen; i++) + { + index++; + var aChild = aChildren[i]; + diffHelp(aChild, bChildren[i], patches, index); + index += aChild.descendantsCount || 0; + } +} + + + +//////////// KEYED DIFF //////////// + + +function diffKeyedChildren(aParent, bParent, patches, rootIndex) +{ + var localPatches = []; + + var changes = {}; // Dict String Entry + var inserts = []; // Array { index : Int, entry : Entry } + // type Entry = { tag : String, vnode : VNode, index : Int, data : _ } + + var aChildren = aParent.children; + var bChildren = bParent.children; + var aLen = aChildren.length; + var bLen = bChildren.length; + var aIndex = 0; + var bIndex = 0; + + var index = rootIndex; + + while (aIndex < aLen && bIndex < bLen) + { + var a = aChildren[aIndex]; + var b = bChildren[bIndex]; + + var aKey = a._0; + var bKey = b._0; + var aNode = a._1; + var bNode = b._1; + + // check if keys match + + if (aKey === bKey) + { + index++; + diffHelp(aNode, bNode, localPatches, index); + index += aNode.descendantsCount || 0; + + aIndex++; + bIndex++; + continue; + } + + // look ahead 1 to detect insertions and removals. + + var aLookAhead = aIndex + 1 < aLen; + var bLookAhead = bIndex + 1 < bLen; + + if (aLookAhead) + { + var aNext = aChildren[aIndex + 1]; + var aNextKey = aNext._0; + var aNextNode = aNext._1; + var oldMatch = bKey === aNextKey; + } + + if (bLookAhead) + { + var bNext = bChildren[bIndex + 1]; + var bNextKey = bNext._0; + var bNextNode = bNext._1; + var newMatch = aKey === bNextKey; + } + + + // swap a and b + if (aLookAhead && bLookAhead && newMatch && oldMatch) + { + index++; + diffHelp(aNode, bNextNode, localPatches, index); + insertNode(changes, localPatches, aKey, bNode, bIndex, inserts); + index += aNode.descendantsCount || 0; + + index++; + removeNode(changes, localPatches, aKey, aNextNode, index); + index += aNextNode.descendantsCount || 0; + + aIndex += 2; + bIndex += 2; + continue; + } + + // insert b + if (bLookAhead && newMatch) + { + index++; + insertNode(changes, localPatches, bKey, bNode, bIndex, inserts); + diffHelp(aNode, bNextNode, localPatches, index); + index += aNode.descendantsCount || 0; + + aIndex += 1; + bIndex += 2; + continue; + } + + // remove a + if (aLookAhead && oldMatch) + { + index++; + removeNode(changes, localPatches, aKey, aNode, index); + index += aNode.descendantsCount || 0; + + index++; + diffHelp(aNextNode, bNode, localPatches, index); + index += aNextNode.descendantsCount || 0; + + aIndex += 2; + bIndex += 1; + continue; + } + + // remove a, insert b + if (aLookAhead && bLookAhead && aNextKey === bNextKey) + { + index++; + removeNode(changes, localPatches, aKey, aNode, index); + insertNode(changes, localPatches, bKey, bNode, bIndex, inserts); + index += aNode.descendantsCount || 0; + + index++; + diffHelp(aNextNode, bNextNode, localPatches, index); + index += aNextNode.descendantsCount || 0; + + aIndex += 2; + bIndex += 2; + continue; + } + + break; + } + + // eat up any remaining nodes with removeNode and insertNode + + while (aIndex < aLen) + { + index++; + var a = aChildren[aIndex]; + var aNode = a._1; + removeNode(changes, localPatches, a._0, aNode, index); + index += aNode.descendantsCount || 0; + aIndex++; + } + + var endInserts; + while (bIndex < bLen) + { + endInserts = endInserts || []; + var b = bChildren[bIndex]; + insertNode(changes, localPatches, b._0, b._1, undefined, endInserts); + bIndex++; + } + + if (localPatches.length > 0 || inserts.length > 0 || typeof endInserts !== 'undefined') + { + patches.push(makePatch('p-reorder', rootIndex, { + patches: localPatches, + inserts: inserts, + endInserts: endInserts + })); + } +} + + + +//////////// CHANGES FROM KEYED DIFF //////////// + + +var POSTFIX = '_elmW6BL'; + + +function insertNode(changes, localPatches, key, vnode, bIndex, inserts) +{ + var entry = changes[key]; + + // never seen this key before + if (typeof entry === 'undefined') + { + entry = { + tag: 'insert', + vnode: vnode, + index: bIndex, + data: undefined + }; + + inserts.push({ index: bIndex, entry: entry }); + changes[key] = entry; + + return; + } + + // this key was removed earlier, a match! + if (entry.tag === 'remove') + { + inserts.push({ index: bIndex, entry: entry }); + + entry.tag = 'move'; + var subPatches = []; + diffHelp(entry.vnode, vnode, subPatches, entry.index); + entry.index = bIndex; + entry.data.data = { + patches: subPatches, + entry: entry + }; + + return; + } + + // this key has already been inserted or moved, a duplicate! + insertNode(changes, localPatches, key + POSTFIX, vnode, bIndex, inserts); +} + + +function removeNode(changes, localPatches, key, vnode, index) +{ + var entry = changes[key]; + + // never seen this key before + if (typeof entry === 'undefined') + { + var patch = makePatch('p-remove', index, undefined); + localPatches.push(patch); + + changes[key] = { + tag: 'remove', + vnode: vnode, + index: index, + data: patch + }; + + return; + } + + // this key was inserted earlier, a match! + if (entry.tag === 'insert') + { + entry.tag = 'move'; + var subPatches = []; + diffHelp(vnode, entry.vnode, subPatches, index); + + var patch = makePatch('p-remove', index, { + patches: subPatches, + entry: entry + }); + localPatches.push(patch); + + return; + } + + // this key has already been removed or moved, a duplicate! + removeNode(changes, localPatches, key + POSTFIX, vnode, index); +} + + + +//////////// ADD DOM NODES //////////// +// +// Each DOM node has an "index" assigned in order of traversal. It is important +// to minimize our crawl over the actual DOM, so these indexes (along with the +// descendantsCount of virtual nodes) let us skip touching entire subtrees of +// the DOM if we know there are no patches there. + + +function addDomNodes(domNode, vNode, patches, eventNode) +{ + addDomNodesHelp(domNode, vNode, patches, 0, 0, vNode.descendantsCount, eventNode); +} + + +// assumes `patches` is non-empty and indexes increase monotonically. +function addDomNodesHelp(domNode, vNode, patches, i, low, high, eventNode) +{ + var patch = patches[i]; + var index = patch.index; + + while (index === low) + { + var patchType = patch.type; + + if (patchType === 'p-thunk') + { + addDomNodes(domNode, vNode.node, patch.data, eventNode); + } + else if (patchType === 'p-reorder') + { + patch.domNode = domNode; + patch.eventNode = eventNode; + + var subPatches = patch.data.patches; + if (subPatches.length > 0) + { + addDomNodesHelp(domNode, vNode, subPatches, 0, low, high, eventNode); + } + } + else if (patchType === 'p-remove') + { + patch.domNode = domNode; + patch.eventNode = eventNode; + + var data = patch.data; + if (typeof data !== 'undefined') + { + data.entry.data = domNode; + var subPatches = data.patches; + if (subPatches.length > 0) + { + addDomNodesHelp(domNode, vNode, subPatches, 0, low, high, eventNode); + } + } + } + else + { + patch.domNode = domNode; + patch.eventNode = eventNode; + } + + i++; + + if (!(patch = patches[i]) || (index = patch.index) > high) + { + return i; + } + } + + switch (vNode.type) + { + case 'tagger': + var subNode = vNode.node; + + while (subNode.type === "tagger") + { + subNode = subNode.node; + } + + return addDomNodesHelp(domNode, subNode, patches, i, low + 1, high, domNode.elm_event_node_ref); + + case 'node': + var vChildren = vNode.children; + var childNodes = domNode.childNodes; + for (var j = 0; j < vChildren.length; j++) + { + low++; + var vChild = vChildren[j]; + var nextLow = low + (vChild.descendantsCount || 0); + if (low <= index && index <= nextLow) + { + i = addDomNodesHelp(childNodes[j], vChild, patches, i, low, nextLow, eventNode); + if (!(patch = patches[i]) || (index = patch.index) > high) + { + return i; + } + } + low = nextLow; + } + return i; + + case 'keyed-node': + var vChildren = vNode.children; + var childNodes = domNode.childNodes; + for (var j = 0; j < vChildren.length; j++) + { + low++; + var vChild = vChildren[j]._1; + var nextLow = low + (vChild.descendantsCount || 0); + if (low <= index && index <= nextLow) + { + i = addDomNodesHelp(childNodes[j], vChild, patches, i, low, nextLow, eventNode); + if (!(patch = patches[i]) || (index = patch.index) > high) + { + return i; + } + } + low = nextLow; + } + return i; + + case 'text': + case 'thunk': + throw new Error('should never traverse `text` or `thunk` nodes like this'); + } +} + + + +//////////// APPLY PATCHES //////////// + + +function applyPatches(rootDomNode, oldVirtualNode, patches, eventNode) +{ + if (patches.length === 0) + { + return rootDomNode; + } + + addDomNodes(rootDomNode, oldVirtualNode, patches, eventNode); + return applyPatchesHelp(rootDomNode, patches); +} + +function applyPatchesHelp(rootDomNode, patches) +{ + for (var i = 0; i < patches.length; i++) + { + var patch = patches[i]; + var localDomNode = patch.domNode + var newNode = applyPatch(localDomNode, patch); + if (localDomNode === rootDomNode) + { + rootDomNode = newNode; + } + } + return rootDomNode; +} + +function applyPatch(domNode, patch) +{ + switch (patch.type) + { + case 'p-redraw': + return applyPatchRedraw(domNode, patch.data, patch.eventNode); + + case 'p-facts': + applyFacts(domNode, patch.eventNode, patch.data); + return domNode; + + case 'p-text': + domNode.replaceData(0, domNode.length, patch.data); + return domNode; + + case 'p-thunk': + return applyPatchesHelp(domNode, patch.data); + + case 'p-tagger': + domNode.elm_event_node_ref.tagger = patch.data; + return domNode; + + case 'p-remove-last': + var i = patch.data; + while (i--) + { + domNode.removeChild(domNode.lastChild); + } + return domNode; + + case 'p-append': + var newNodes = patch.data; + for (var i = 0; i < newNodes.length; i++) + { + domNode.appendChild(render(newNodes[i], patch.eventNode)); + } + return domNode; + + case 'p-remove': + var data = patch.data; + if (typeof data === 'undefined') + { + domNode.parentNode.removeChild(domNode); + return domNode; + } + var entry = data.entry; + if (typeof entry.index !== 'undefined') + { + domNode.parentNode.removeChild(domNode); + } + entry.data = applyPatchesHelp(domNode, data.patches); + return domNode; + + case 'p-reorder': + return applyPatchReorder(domNode, patch); + + case 'p-custom': + var impl = patch.data; + return impl.applyPatch(domNode, impl.data); + + default: + throw new Error('Ran into an unknown patch!'); + } +} + + +function applyPatchRedraw(domNode, vNode, eventNode) +{ + var parentNode = domNode.parentNode; + var newNode = render(vNode, eventNode); + + if (typeof newNode.elm_event_node_ref === 'undefined') + { + newNode.elm_event_node_ref = domNode.elm_event_node_ref; + } + + if (parentNode && newNode !== domNode) + { + parentNode.replaceChild(newNode, domNode); + } + return newNode; +} + + +function applyPatchReorder(domNode, patch) +{ + var data = patch.data; + + // remove end inserts + var frag = applyPatchReorderEndInsertsHelp(data.endInserts, patch); + + // removals + domNode = applyPatchesHelp(domNode, data.patches); + + // inserts + var inserts = data.inserts; + for (var i = 0; i < inserts.length; i++) + { + var insert = inserts[i]; + var entry = insert.entry; + var node = entry.tag === 'move' + ? entry.data + : render(entry.vnode, patch.eventNode); + domNode.insertBefore(node, domNode.childNodes[insert.index]); + } + + // add end inserts + if (typeof frag !== 'undefined') + { + domNode.appendChild(frag); + } + + return domNode; +} + + +function applyPatchReorderEndInsertsHelp(endInserts, patch) +{ + if (typeof endInserts === 'undefined') + { + return; + } + + var frag = document.createDocumentFragment(); + for (var i = 0; i < endInserts.length; i++) + { + var insert = endInserts[i]; + var entry = insert.entry; + frag.appendChild(entry.tag === 'move' + ? entry.data + : render(entry.vnode, patch.eventNode) + ); + } + return frag; +} + + + +//////////// PROGRAMS //////////// + + +function programWithFlags(details) +{ + return { + init: details.init, + update: details.update, + subscriptions: details.subscriptions, + view: details.view, + renderer: renderer + }; +} + + +return { + node: node, + text: text, + + custom: custom, + + map: F2(map), + + on: F3(on), + style: style, + property: F2(property), + attribute: F2(attribute), + attributeNS: F3(attributeNS), + + lazy: F2(lazy), + lazy2: F3(lazy2), + lazy3: F4(lazy3), + keyedNode: F3(keyedNode), + + programWithFlags: programWithFlags +}; + +}(); +var _elm_lang$virtual_dom$VirtualDom$programWithFlags = _elm_lang$virtual_dom$Native_VirtualDom.programWithFlags; +var _elm_lang$virtual_dom$VirtualDom$keyedNode = _elm_lang$virtual_dom$Native_VirtualDom.keyedNode; +var _elm_lang$virtual_dom$VirtualDom$lazy3 = _elm_lang$virtual_dom$Native_VirtualDom.lazy3; +var _elm_lang$virtual_dom$VirtualDom$lazy2 = _elm_lang$virtual_dom$Native_VirtualDom.lazy2; +var _elm_lang$virtual_dom$VirtualDom$lazy = _elm_lang$virtual_dom$Native_VirtualDom.lazy; +var _elm_lang$virtual_dom$VirtualDom$defaultOptions = {stopPropagation: false, preventDefault: false}; +var _elm_lang$virtual_dom$VirtualDom$onWithOptions = _elm_lang$virtual_dom$Native_VirtualDom.on; +var _elm_lang$virtual_dom$VirtualDom$on = F2( + function (eventName, decoder) { + return A3(_elm_lang$virtual_dom$VirtualDom$onWithOptions, eventName, _elm_lang$virtual_dom$VirtualDom$defaultOptions, decoder); + }); +var _elm_lang$virtual_dom$VirtualDom$style = _elm_lang$virtual_dom$Native_VirtualDom.style; +var _elm_lang$virtual_dom$VirtualDom$attributeNS = _elm_lang$virtual_dom$Native_VirtualDom.attributeNS; +var _elm_lang$virtual_dom$VirtualDom$attribute = _elm_lang$virtual_dom$Native_VirtualDom.attribute; +var _elm_lang$virtual_dom$VirtualDom$property = _elm_lang$virtual_dom$Native_VirtualDom.property; +var _elm_lang$virtual_dom$VirtualDom$map = _elm_lang$virtual_dom$Native_VirtualDom.map; +var _elm_lang$virtual_dom$VirtualDom$text = _elm_lang$virtual_dom$Native_VirtualDom.text; +var _elm_lang$virtual_dom$VirtualDom$node = _elm_lang$virtual_dom$Native_VirtualDom.node; +var _elm_lang$virtual_dom$VirtualDom$Options = F2( + function (a, b) { + return {stopPropagation: a, preventDefault: b}; + }); +var _elm_lang$virtual_dom$VirtualDom$Node = {ctor: 'Node'}; +var _elm_lang$virtual_dom$VirtualDom$Property = {ctor: 'Property'}; + +var _elm_lang$html$Html$text = _elm_lang$virtual_dom$VirtualDom$text; +var _elm_lang$html$Html$node = _elm_lang$virtual_dom$VirtualDom$node; +var _elm_lang$html$Html$body = _elm_lang$html$Html$node('body'); +var _elm_lang$html$Html$section = _elm_lang$html$Html$node('section'); +var _elm_lang$html$Html$nav = _elm_lang$html$Html$node('nav'); +var _elm_lang$html$Html$article = _elm_lang$html$Html$node('article'); +var _elm_lang$html$Html$aside = _elm_lang$html$Html$node('aside'); +var _elm_lang$html$Html$h1 = _elm_lang$html$Html$node('h1'); +var _elm_lang$html$Html$h2 = _elm_lang$html$Html$node('h2'); +var _elm_lang$html$Html$h3 = _elm_lang$html$Html$node('h3'); +var _elm_lang$html$Html$h4 = _elm_lang$html$Html$node('h4'); +var _elm_lang$html$Html$h5 = _elm_lang$html$Html$node('h5'); +var _elm_lang$html$Html$h6 = _elm_lang$html$Html$node('h6'); +var _elm_lang$html$Html$header = _elm_lang$html$Html$node('header'); +var _elm_lang$html$Html$footer = _elm_lang$html$Html$node('footer'); +var _elm_lang$html$Html$address = _elm_lang$html$Html$node('address'); +var _elm_lang$html$Html$main$ = _elm_lang$html$Html$node('main'); +var _elm_lang$html$Html$p = _elm_lang$html$Html$node('p'); +var _elm_lang$html$Html$hr = _elm_lang$html$Html$node('hr'); +var _elm_lang$html$Html$pre = _elm_lang$html$Html$node('pre'); +var _elm_lang$html$Html$blockquote = _elm_lang$html$Html$node('blockquote'); +var _elm_lang$html$Html$ol = _elm_lang$html$Html$node('ol'); +var _elm_lang$html$Html$ul = _elm_lang$html$Html$node('ul'); +var _elm_lang$html$Html$li = _elm_lang$html$Html$node('li'); +var _elm_lang$html$Html$dl = _elm_lang$html$Html$node('dl'); +var _elm_lang$html$Html$dt = _elm_lang$html$Html$node('dt'); +var _elm_lang$html$Html$dd = _elm_lang$html$Html$node('dd'); +var _elm_lang$html$Html$figure = _elm_lang$html$Html$node('figure'); +var _elm_lang$html$Html$figcaption = _elm_lang$html$Html$node('figcaption'); +var _elm_lang$html$Html$div = _elm_lang$html$Html$node('div'); +var _elm_lang$html$Html$a = _elm_lang$html$Html$node('a'); +var _elm_lang$html$Html$em = _elm_lang$html$Html$node('em'); +var _elm_lang$html$Html$strong = _elm_lang$html$Html$node('strong'); +var _elm_lang$html$Html$small = _elm_lang$html$Html$node('small'); +var _elm_lang$html$Html$s = _elm_lang$html$Html$node('s'); +var _elm_lang$html$Html$cite = _elm_lang$html$Html$node('cite'); +var _elm_lang$html$Html$q = _elm_lang$html$Html$node('q'); +var _elm_lang$html$Html$dfn = _elm_lang$html$Html$node('dfn'); +var _elm_lang$html$Html$abbr = _elm_lang$html$Html$node('abbr'); +var _elm_lang$html$Html$time = _elm_lang$html$Html$node('time'); +var _elm_lang$html$Html$code = _elm_lang$html$Html$node('code'); +var _elm_lang$html$Html$var = _elm_lang$html$Html$node('var'); +var _elm_lang$html$Html$samp = _elm_lang$html$Html$node('samp'); +var _elm_lang$html$Html$kbd = _elm_lang$html$Html$node('kbd'); +var _elm_lang$html$Html$sub = _elm_lang$html$Html$node('sub'); +var _elm_lang$html$Html$sup = _elm_lang$html$Html$node('sup'); +var _elm_lang$html$Html$i = _elm_lang$html$Html$node('i'); +var _elm_lang$html$Html$b = _elm_lang$html$Html$node('b'); +var _elm_lang$html$Html$u = _elm_lang$html$Html$node('u'); +var _elm_lang$html$Html$mark = _elm_lang$html$Html$node('mark'); +var _elm_lang$html$Html$ruby = _elm_lang$html$Html$node('ruby'); +var _elm_lang$html$Html$rt = _elm_lang$html$Html$node('rt'); +var _elm_lang$html$Html$rp = _elm_lang$html$Html$node('rp'); +var _elm_lang$html$Html$bdi = _elm_lang$html$Html$node('bdi'); +var _elm_lang$html$Html$bdo = _elm_lang$html$Html$node('bdo'); +var _elm_lang$html$Html$span = _elm_lang$html$Html$node('span'); +var _elm_lang$html$Html$br = _elm_lang$html$Html$node('br'); +var _elm_lang$html$Html$wbr = _elm_lang$html$Html$node('wbr'); +var _elm_lang$html$Html$ins = _elm_lang$html$Html$node('ins'); +var _elm_lang$html$Html$del = _elm_lang$html$Html$node('del'); +var _elm_lang$html$Html$img = _elm_lang$html$Html$node('img'); +var _elm_lang$html$Html$iframe = _elm_lang$html$Html$node('iframe'); +var _elm_lang$html$Html$embed = _elm_lang$html$Html$node('embed'); +var _elm_lang$html$Html$object = _elm_lang$html$Html$node('object'); +var _elm_lang$html$Html$param = _elm_lang$html$Html$node('param'); +var _elm_lang$html$Html$video = _elm_lang$html$Html$node('video'); +var _elm_lang$html$Html$audio = _elm_lang$html$Html$node('audio'); +var _elm_lang$html$Html$source = _elm_lang$html$Html$node('source'); +var _elm_lang$html$Html$track = _elm_lang$html$Html$node('track'); +var _elm_lang$html$Html$canvas = _elm_lang$html$Html$node('canvas'); +var _elm_lang$html$Html$svg = _elm_lang$html$Html$node('svg'); +var _elm_lang$html$Html$math = _elm_lang$html$Html$node('math'); +var _elm_lang$html$Html$table = _elm_lang$html$Html$node('table'); +var _elm_lang$html$Html$caption = _elm_lang$html$Html$node('caption'); +var _elm_lang$html$Html$colgroup = _elm_lang$html$Html$node('colgroup'); +var _elm_lang$html$Html$col = _elm_lang$html$Html$node('col'); +var _elm_lang$html$Html$tbody = _elm_lang$html$Html$node('tbody'); +var _elm_lang$html$Html$thead = _elm_lang$html$Html$node('thead'); +var _elm_lang$html$Html$tfoot = _elm_lang$html$Html$node('tfoot'); +var _elm_lang$html$Html$tr = _elm_lang$html$Html$node('tr'); +var _elm_lang$html$Html$td = _elm_lang$html$Html$node('td'); +var _elm_lang$html$Html$th = _elm_lang$html$Html$node('th'); +var _elm_lang$html$Html$form = _elm_lang$html$Html$node('form'); +var _elm_lang$html$Html$fieldset = _elm_lang$html$Html$node('fieldset'); +var _elm_lang$html$Html$legend = _elm_lang$html$Html$node('legend'); +var _elm_lang$html$Html$label = _elm_lang$html$Html$node('label'); +var _elm_lang$html$Html$input = _elm_lang$html$Html$node('input'); +var _elm_lang$html$Html$button = _elm_lang$html$Html$node('button'); +var _elm_lang$html$Html$select = _elm_lang$html$Html$node('select'); +var _elm_lang$html$Html$datalist = _elm_lang$html$Html$node('datalist'); +var _elm_lang$html$Html$optgroup = _elm_lang$html$Html$node('optgroup'); +var _elm_lang$html$Html$option = _elm_lang$html$Html$node('option'); +var _elm_lang$html$Html$textarea = _elm_lang$html$Html$node('textarea'); +var _elm_lang$html$Html$keygen = _elm_lang$html$Html$node('keygen'); +var _elm_lang$html$Html$output = _elm_lang$html$Html$node('output'); +var _elm_lang$html$Html$progress = _elm_lang$html$Html$node('progress'); +var _elm_lang$html$Html$meter = _elm_lang$html$Html$node('meter'); +var _elm_lang$html$Html$details = _elm_lang$html$Html$node('details'); +var _elm_lang$html$Html$summary = _elm_lang$html$Html$node('summary'); +var _elm_lang$html$Html$menuitem = _elm_lang$html$Html$node('menuitem'); +var _elm_lang$html$Html$menu = _elm_lang$html$Html$node('menu'); + +var _elm_lang$html$Html_App$programWithFlags = _elm_lang$virtual_dom$VirtualDom$programWithFlags; +var _elm_lang$html$Html_App$program = function (app) { + return _elm_lang$html$Html_App$programWithFlags( + _elm_lang$core$Native_Utils.update( + app, + { + init: function (_p0) { + return app.init; + } + })); +}; +var _elm_lang$html$Html_App$beginnerProgram = function (_p1) { + var _p2 = _p1; + return _elm_lang$html$Html_App$programWithFlags( + { + init: function (_p3) { + return A2( + _elm_lang$core$Platform_Cmd_ops['!'], + _p2.model, + _elm_lang$core$Native_List.fromArray( + [])); + }, + update: F2( + function (msg, model) { + return A2( + _elm_lang$core$Platform_Cmd_ops['!'], + A2(_p2.update, msg, model), + _elm_lang$core$Native_List.fromArray( + [])); + }), + view: _p2.view, + subscriptions: function (_p4) { + return _elm_lang$core$Platform_Sub$none; + } + }); +}; +var _elm_lang$html$Html_App$map = _elm_lang$virtual_dom$VirtualDom$map; + +var _elm_lang$html$Html_Attributes$attribute = _elm_lang$virtual_dom$VirtualDom$attribute; +var _elm_lang$html$Html_Attributes$contextmenu = function (value) { + return A2(_elm_lang$html$Html_Attributes$attribute, 'contextmenu', value); +}; +var _elm_lang$html$Html_Attributes$draggable = function (value) { + return A2(_elm_lang$html$Html_Attributes$attribute, 'draggable', value); +}; +var _elm_lang$html$Html_Attributes$list = function (value) { + return A2(_elm_lang$html$Html_Attributes$attribute, 'list', value); +}; +var _elm_lang$html$Html_Attributes$maxlength = function (n) { + return A2( + _elm_lang$html$Html_Attributes$attribute, + 'maxlength', + _elm_lang$core$Basics$toString(n)); +}; +var _elm_lang$html$Html_Attributes$datetime = function (value) { + return A2(_elm_lang$html$Html_Attributes$attribute, 'datetime', value); +}; +var _elm_lang$html$Html_Attributes$pubdate = function (value) { + return A2(_elm_lang$html$Html_Attributes$attribute, 'pubdate', value); +}; +var _elm_lang$html$Html_Attributes$colspan = function (n) { + return A2( + _elm_lang$html$Html_Attributes$attribute, + 'colspan', + _elm_lang$core$Basics$toString(n)); +}; +var _elm_lang$html$Html_Attributes$rowspan = function (n) { + return A2( + _elm_lang$html$Html_Attributes$attribute, + 'rowspan', + _elm_lang$core$Basics$toString(n)); +}; +var _elm_lang$html$Html_Attributes$property = _elm_lang$virtual_dom$VirtualDom$property; +var _elm_lang$html$Html_Attributes$stringProperty = F2( + function (name, string) { + return A2( + _elm_lang$html$Html_Attributes$property, + name, + _elm_lang$core$Json_Encode$string(string)); + }); +var _elm_lang$html$Html_Attributes$class = function (name) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'className', name); +}; +var _elm_lang$html$Html_Attributes$id = function (name) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'id', name); +}; +var _elm_lang$html$Html_Attributes$title = function (name) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'title', name); +}; +var _elm_lang$html$Html_Attributes$accesskey = function ($char) { + return A2( + _elm_lang$html$Html_Attributes$stringProperty, + 'accessKey', + _elm_lang$core$String$fromChar($char)); +}; +var _elm_lang$html$Html_Attributes$dir = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'dir', value); +}; +var _elm_lang$html$Html_Attributes$dropzone = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'dropzone', value); +}; +var _elm_lang$html$Html_Attributes$itemprop = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'itemprop', value); +}; +var _elm_lang$html$Html_Attributes$lang = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'lang', value); +}; +var _elm_lang$html$Html_Attributes$tabindex = function (n) { + return A2( + _elm_lang$html$Html_Attributes$stringProperty, + 'tabIndex', + _elm_lang$core$Basics$toString(n)); +}; +var _elm_lang$html$Html_Attributes$charset = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'charset', value); +}; +var _elm_lang$html$Html_Attributes$content = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'content', value); +}; +var _elm_lang$html$Html_Attributes$httpEquiv = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'httpEquiv', value); +}; +var _elm_lang$html$Html_Attributes$language = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'language', value); +}; +var _elm_lang$html$Html_Attributes$src = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'src', value); +}; +var _elm_lang$html$Html_Attributes$height = function (value) { + return A2( + _elm_lang$html$Html_Attributes$stringProperty, + 'height', + _elm_lang$core$Basics$toString(value)); +}; +var _elm_lang$html$Html_Attributes$width = function (value) { + return A2( + _elm_lang$html$Html_Attributes$stringProperty, + 'width', + _elm_lang$core$Basics$toString(value)); +}; +var _elm_lang$html$Html_Attributes$alt = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'alt', value); +}; +var _elm_lang$html$Html_Attributes$preload = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'preload', value); +}; +var _elm_lang$html$Html_Attributes$poster = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'poster', value); +}; +var _elm_lang$html$Html_Attributes$kind = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'kind', value); +}; +var _elm_lang$html$Html_Attributes$srclang = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'srclang', value); +}; +var _elm_lang$html$Html_Attributes$sandbox = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'sandbox', value); +}; +var _elm_lang$html$Html_Attributes$srcdoc = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'srcdoc', value); +}; +var _elm_lang$html$Html_Attributes$type$ = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'type', value); +}; +var _elm_lang$html$Html_Attributes$value = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'value', value); +}; +var _elm_lang$html$Html_Attributes$defaultValue = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'defaultValue', value); +}; +var _elm_lang$html$Html_Attributes$placeholder = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'placeholder', value); +}; +var _elm_lang$html$Html_Attributes$accept = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'accept', value); +}; +var _elm_lang$html$Html_Attributes$acceptCharset = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'acceptCharset', value); +}; +var _elm_lang$html$Html_Attributes$action = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'action', value); +}; +var _elm_lang$html$Html_Attributes$autocomplete = function (bool) { + return A2( + _elm_lang$html$Html_Attributes$stringProperty, + 'autocomplete', + bool ? 'on' : 'off'); +}; +var _elm_lang$html$Html_Attributes$autosave = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'autosave', value); +}; +var _elm_lang$html$Html_Attributes$enctype = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'enctype', value); +}; +var _elm_lang$html$Html_Attributes$formaction = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'formAction', value); +}; +var _elm_lang$html$Html_Attributes$minlength = function (n) { + return A2( + _elm_lang$html$Html_Attributes$stringProperty, + 'minLength', + _elm_lang$core$Basics$toString(n)); +}; +var _elm_lang$html$Html_Attributes$method = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'method', value); +}; +var _elm_lang$html$Html_Attributes$name = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'name', value); +}; +var _elm_lang$html$Html_Attributes$pattern = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'pattern', value); +}; +var _elm_lang$html$Html_Attributes$size = function (n) { + return A2( + _elm_lang$html$Html_Attributes$stringProperty, + 'size', + _elm_lang$core$Basics$toString(n)); +}; +var _elm_lang$html$Html_Attributes$for = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'htmlFor', value); +}; +var _elm_lang$html$Html_Attributes$form = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'form', value); +}; +var _elm_lang$html$Html_Attributes$max = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'max', value); +}; +var _elm_lang$html$Html_Attributes$min = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'min', value); +}; +var _elm_lang$html$Html_Attributes$step = function (n) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'step', n); +}; +var _elm_lang$html$Html_Attributes$cols = function (n) { + return A2( + _elm_lang$html$Html_Attributes$stringProperty, + 'cols', + _elm_lang$core$Basics$toString(n)); +}; +var _elm_lang$html$Html_Attributes$rows = function (n) { + return A2( + _elm_lang$html$Html_Attributes$stringProperty, + 'rows', + _elm_lang$core$Basics$toString(n)); +}; +var _elm_lang$html$Html_Attributes$wrap = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'wrap', value); +}; +var _elm_lang$html$Html_Attributes$usemap = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'useMap', value); +}; +var _elm_lang$html$Html_Attributes$shape = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'shape', value); +}; +var _elm_lang$html$Html_Attributes$coords = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'coords', value); +}; +var _elm_lang$html$Html_Attributes$challenge = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'challenge', value); +}; +var _elm_lang$html$Html_Attributes$keytype = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'keytype', value); +}; +var _elm_lang$html$Html_Attributes$align = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'align', value); +}; +var _elm_lang$html$Html_Attributes$cite = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'cite', value); +}; +var _elm_lang$html$Html_Attributes$href = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'href', value); +}; +var _elm_lang$html$Html_Attributes$target = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'target', value); +}; +var _elm_lang$html$Html_Attributes$downloadAs = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'download', value); +}; +var _elm_lang$html$Html_Attributes$hreflang = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'hreflang', value); +}; +var _elm_lang$html$Html_Attributes$media = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'media', value); +}; +var _elm_lang$html$Html_Attributes$ping = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'ping', value); +}; +var _elm_lang$html$Html_Attributes$rel = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'rel', value); +}; +var _elm_lang$html$Html_Attributes$start = function (n) { + return A2( + _elm_lang$html$Html_Attributes$stringProperty, + 'start', + _elm_lang$core$Basics$toString(n)); +}; +var _elm_lang$html$Html_Attributes$headers = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'headers', value); +}; +var _elm_lang$html$Html_Attributes$scope = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'scope', value); +}; +var _elm_lang$html$Html_Attributes$manifest = function (value) { + return A2(_elm_lang$html$Html_Attributes$stringProperty, 'manifest', value); +}; +var _elm_lang$html$Html_Attributes$boolProperty = F2( + function (name, bool) { + return A2( + _elm_lang$html$Html_Attributes$property, + name, + _elm_lang$core$Json_Encode$bool(bool)); + }); +var _elm_lang$html$Html_Attributes$hidden = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'hidden', bool); +}; +var _elm_lang$html$Html_Attributes$contenteditable = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'contentEditable', bool); +}; +var _elm_lang$html$Html_Attributes$spellcheck = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'spellcheck', bool); +}; +var _elm_lang$html$Html_Attributes$async = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'async', bool); +}; +var _elm_lang$html$Html_Attributes$defer = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'defer', bool); +}; +var _elm_lang$html$Html_Attributes$scoped = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'scoped', bool); +}; +var _elm_lang$html$Html_Attributes$autoplay = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'autoplay', bool); +}; +var _elm_lang$html$Html_Attributes$controls = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'controls', bool); +}; +var _elm_lang$html$Html_Attributes$loop = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'loop', bool); +}; +var _elm_lang$html$Html_Attributes$default = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'default', bool); +}; +var _elm_lang$html$Html_Attributes$seamless = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'seamless', bool); +}; +var _elm_lang$html$Html_Attributes$checked = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'checked', bool); +}; +var _elm_lang$html$Html_Attributes$selected = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'selected', bool); +}; +var _elm_lang$html$Html_Attributes$autofocus = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'autofocus', bool); +}; +var _elm_lang$html$Html_Attributes$disabled = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'disabled', bool); +}; +var _elm_lang$html$Html_Attributes$multiple = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'multiple', bool); +}; +var _elm_lang$html$Html_Attributes$novalidate = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'noValidate', bool); +}; +var _elm_lang$html$Html_Attributes$readonly = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'readOnly', bool); +}; +var _elm_lang$html$Html_Attributes$required = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'required', bool); +}; +var _elm_lang$html$Html_Attributes$ismap = function (value) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'isMap', value); +}; +var _elm_lang$html$Html_Attributes$download = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'download', bool); +}; +var _elm_lang$html$Html_Attributes$reversed = function (bool) { + return A2(_elm_lang$html$Html_Attributes$boolProperty, 'reversed', bool); +}; +var _elm_lang$html$Html_Attributes$classList = function (list) { + return _elm_lang$html$Html_Attributes$class( + A2( + _elm_lang$core$String$join, + ' ', + A2( + _elm_lang$core$List$map, + _elm_lang$core$Basics$fst, + A2(_elm_lang$core$List$filter, _elm_lang$core$Basics$snd, list)))); +}; +var _elm_lang$html$Html_Attributes$style = _elm_lang$virtual_dom$VirtualDom$style; + +var _elm_lang$html$Html_Events$keyCode = A2(_elm_lang$core$Json_Decode_ops[':='], 'keyCode', _elm_lang$core$Json_Decode$int); +var _elm_lang$html$Html_Events$targetChecked = A2( + _elm_lang$core$Json_Decode$at, + _elm_lang$core$Native_List.fromArray( + ['target', 'checked']), + _elm_lang$core$Json_Decode$bool); +var _elm_lang$html$Html_Events$targetValue = A2( + _elm_lang$core$Json_Decode$at, + _elm_lang$core$Native_List.fromArray( + ['target', 'value']), + _elm_lang$core$Json_Decode$string); +var _elm_lang$html$Html_Events$defaultOptions = _elm_lang$virtual_dom$VirtualDom$defaultOptions; +var _elm_lang$html$Html_Events$onWithOptions = _elm_lang$virtual_dom$VirtualDom$onWithOptions; +var _elm_lang$html$Html_Events$on = _elm_lang$virtual_dom$VirtualDom$on; +var _elm_lang$html$Html_Events$onFocus = function (msg) { + return A2( + _elm_lang$html$Html_Events$on, + 'focus', + _elm_lang$core$Json_Decode$succeed(msg)); +}; +var _elm_lang$html$Html_Events$onBlur = function (msg) { + return A2( + _elm_lang$html$Html_Events$on, + 'blur', + _elm_lang$core$Json_Decode$succeed(msg)); +}; +var _elm_lang$html$Html_Events$onSubmitOptions = _elm_lang$core$Native_Utils.update( + _elm_lang$html$Html_Events$defaultOptions, + {preventDefault: true}); +var _elm_lang$html$Html_Events$onSubmit = function (msg) { + return A3( + _elm_lang$html$Html_Events$onWithOptions, + 'submit', + _elm_lang$html$Html_Events$onSubmitOptions, + _elm_lang$core$Json_Decode$succeed(msg)); +}; +var _elm_lang$html$Html_Events$onCheck = function (tagger) { + return A2( + _elm_lang$html$Html_Events$on, + 'change', + A2(_elm_lang$core$Json_Decode$map, tagger, _elm_lang$html$Html_Events$targetChecked)); +}; +var _elm_lang$html$Html_Events$onInput = function (tagger) { + return A2( + _elm_lang$html$Html_Events$on, + 'input', + A2(_elm_lang$core$Json_Decode$map, tagger, _elm_lang$html$Html_Events$targetValue)); +}; +var _elm_lang$html$Html_Events$onMouseOut = function (msg) { + return A2( + _elm_lang$html$Html_Events$on, + 'mouseout', + _elm_lang$core$Json_Decode$succeed(msg)); +}; +var _elm_lang$html$Html_Events$onMouseOver = function (msg) { + return A2( + _elm_lang$html$Html_Events$on, + 'mouseover', + _elm_lang$core$Json_Decode$succeed(msg)); +}; +var _elm_lang$html$Html_Events$onMouseLeave = function (msg) { + return A2( + _elm_lang$html$Html_Events$on, + 'mouseleave', + _elm_lang$core$Json_Decode$succeed(msg)); +}; +var _elm_lang$html$Html_Events$onMouseEnter = function (msg) { + return A2( + _elm_lang$html$Html_Events$on, + 'mouseenter', + _elm_lang$core$Json_Decode$succeed(msg)); +}; +var _elm_lang$html$Html_Events$onMouseUp = function (msg) { + return A2( + _elm_lang$html$Html_Events$on, + 'mouseup', + _elm_lang$core$Json_Decode$succeed(msg)); +}; +var _elm_lang$html$Html_Events$onMouseDown = function (msg) { + return A2( + _elm_lang$html$Html_Events$on, + 'mousedown', + _elm_lang$core$Json_Decode$succeed(msg)); +}; +var _elm_lang$html$Html_Events$onDoubleClick = function (msg) { + return A2( + _elm_lang$html$Html_Events$on, + 'dblclick', + _elm_lang$core$Json_Decode$succeed(msg)); +}; +var _elm_lang$html$Html_Events$onClick = function (msg) { + return A2( + _elm_lang$html$Html_Events$on, + 'click', + _elm_lang$core$Json_Decode$succeed(msg)); +}; +var _elm_lang$html$Html_Events$Options = F2( + function (a, b) { + return {stopPropagation: a, preventDefault: b}; + }); + +var _user$project$Picker$pointer = _elm_lang$html$Html_Attributes$style( + _elm_lang$core$Native_List.fromArray( + [ + {ctor: '_Tuple2', _0: 'cursor', _1: 'pointer'} + ])); +var _user$project$Picker$toggle = F2( + function (id, entries) { + var _p0 = entries; + if (_p0.ctor === '[]') { + return _elm_lang$core$Native_List.fromArray( + []); + } else { + var _p2 = _p0._1; + var _p1 = _p0._0; + return _elm_lang$core$Native_Utils.eq(_p1.id, id) ? A2( + _elm_lang$core$List_ops['::'], + _elm_lang$core$Native_Utils.update( + _p1, + { + selected: _elm_lang$core$Basics$not(_p1.selected) + }), + _p2) : A2( + _elm_lang$core$List_ops['::'], + _p1, + A2(_user$project$Picker$toggle, id, _p2)); + } + }); +var _user$project$Picker$start = _elm_lang$core$Native_Platform.outgoingPort( + 'start', + function (v) { + return _elm_lang$core$Native_List.toArray(v).map( + function (v) { + return {name: v.name, version: v.version, url: v.url, optimized: v.optimized}; + }); + }); +var _user$project$Picker$startSelected = function (entries) { + return _user$project$Picker$start( + A2( + _elm_lang$core$List$map, + function (_) { + return _.impl; + }, + A2( + _elm_lang$core$List$filter, + function (_) { + return _.selected; + }, + entries))); +}; +var _user$project$Picker$update = F2( + function (msg, model) { + var _p3 = msg; + switch (_p3.ctor) { + case 'Toggle': + return A2( + _elm_lang$core$Platform_Cmd_ops['!'], + _elm_lang$core$Native_Utils.update( + model, + { + entries: A2(_user$project$Picker$toggle, _p3._0, model.entries) + }), + _elm_lang$core$Native_List.fromArray( + [])); + case 'Start': + return A2( + _elm_lang$core$Platform_Cmd_ops['!'], + _elm_lang$core$Native_Utils.update( + model, + {running: true}), + _elm_lang$core$Native_List.fromArray( + [ + _user$project$Picker$startSelected(model.entries) + ])); + default: + return A2( + _elm_lang$core$Platform_Cmd_ops['!'], + _elm_lang$core$Native_Utils.update( + model, + {running: false}), + _elm_lang$core$Native_List.fromArray( + [])); + } + }); +var _user$project$Picker$end = _elm_lang$core$Native_Platform.incomingPort( + 'end', + _elm_lang$core$Json_Decode$null( + {ctor: '_Tuple0'})); +var _user$project$Picker$Model = F2( + function (a, b) { + return {running: a, entries: b}; + }); +var _user$project$Picker$Entry = F3( + function (a, b, c) { + return {selected: a, id: b, impl: c}; + }); +var _user$project$Picker$init = function (impls) { + return A2( + _elm_lang$core$Platform_Cmd_ops['!'], + { + running: false, + entries: A2( + _elm_lang$core$List$indexedMap, + _user$project$Picker$Entry(false), + impls) + }, + _elm_lang$core$Native_List.fromArray( + [])); +}; +var _user$project$Picker$Impl = F4( + function (a, b, c, d) { + return {name: a, version: b, url: c, optimized: d}; + }); +var _user$project$Picker$End = {ctor: 'End'}; +var _user$project$Picker$subscriptions = function (model) { + return _user$project$Picker$end( + _elm_lang$core$Basics$always(_user$project$Picker$End)); +}; +var _user$project$Picker$Start = {ctor: 'Start'}; +var _user$project$Picker$Toggle = function (a) { + return {ctor: 'Toggle', _0: a}; +}; +var _user$project$Picker$viewEntry = F2( + function (running, _p4) { + var _p5 = _p4; + var _p6 = _p5.impl; + return A2( + _elm_lang$html$Html$li, + running ? _elm_lang$core$Native_List.fromArray( + [_user$project$Picker$pointer]) : _elm_lang$core$Native_List.fromArray( + [ + _user$project$Picker$pointer, + _elm_lang$html$Html_Events$onClick( + _user$project$Picker$Toggle(_p5.id)) + ]), + _elm_lang$core$Native_List.fromArray( + [ + A2( + _elm_lang$html$Html$input, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$type$('checkbox'), + _elm_lang$html$Html_Attributes$checked(_p5.selected), + _elm_lang$html$Html_Attributes$disabled(running) + ]), + _elm_lang$core$Native_List.fromArray( + [])), + _elm_lang$html$Html$text( + A2( + _elm_lang$core$Basics_ops['++'], + ' ', + A2( + _elm_lang$core$Basics_ops['++'], + _p6.name, + A2(_elm_lang$core$Basics_ops['++'], ' ', _p6.version)))), + A2( + _elm_lang$html$Html$span, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$style( + _elm_lang$core$Native_List.fromArray( + [ + {ctor: '_Tuple2', _0: 'color', _1: '#aaa'} + ])) + ]), + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html$text( + _p6.optimized ? ' (optimized)' : '') + ])) + ])); + }); +var _user$project$Picker$view = function (_p7) { + var _p8 = _p7; + var _p9 = _p8.running; + return A2( + _elm_lang$html$Html$div, + _elm_lang$core$Native_List.fromArray( + []), + _elm_lang$core$Native_List.fromArray( + [ + A2( + _elm_lang$html$Html$ul, + _p9 ? _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$style( + _elm_lang$core$Native_List.fromArray( + [ + {ctor: '_Tuple2', _0: 'color', _1: '#aaa'} + ])) + ]) : _elm_lang$core$Native_List.fromArray( + []), + A2( + _elm_lang$core$List$map, + _user$project$Picker$viewEntry(_p9), + _p8.entries)), + A2( + _elm_lang$html$Html$button, + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html_Attributes$style( + _elm_lang$core$Native_List.fromArray( + [ + {ctor: '_Tuple2', _0: 'width', _1: '100%'} + ])), + _elm_lang$html$Html_Attributes$disabled(_p9), + _elm_lang$html$Html_Events$onClick(_user$project$Picker$Start) + ]), + _elm_lang$core$Native_List.fromArray( + [ + _elm_lang$html$Html$text('Run') + ])) + ])); +}; +var _user$project$Picker$main = { + main: _elm_lang$html$Html_App$programWithFlags( + {init: _user$project$Picker$init, view: _user$project$Picker$view, update: _user$project$Picker$update, subscriptions: _user$project$Picker$subscriptions}), + flags: _elm_lang$core$Json_Decode$list( + A2( + _elm_lang$core$Json_Decode$andThen, + A2(_elm_lang$core$Json_Decode_ops[':='], 'name', _elm_lang$core$Json_Decode$string), + function (name) { + return A2( + _elm_lang$core$Json_Decode$andThen, + A2(_elm_lang$core$Json_Decode_ops[':='], 'optimized', _elm_lang$core$Json_Decode$bool), + function (optimized) { + return A2( + _elm_lang$core$Json_Decode$andThen, + A2(_elm_lang$core$Json_Decode_ops[':='], 'url', _elm_lang$core$Json_Decode$string), + function (url) { + return A2( + _elm_lang$core$Json_Decode$andThen, + A2(_elm_lang$core$Json_Decode_ops[':='], 'version', _elm_lang$core$Json_Decode$string), + function (version) { + return _elm_lang$core$Json_Decode$succeed( + {name: name, optimized: optimized, url: url, version: version}); + }); + }); + }); + })) +}; + +var Elm = {}; +Elm['Picker'] = Elm['Picker'] || {}; +_elm_lang$core$Native_Platform.addPublicModule(Elm['Picker'], 'Picker', typeof _user$project$Picker$main === 'undefined' ? null : _user$project$Picker$main); + +if (typeof define === "function" && define['amd']) +{ + define([], function() { return Elm; }); + return; +} + +if (typeof module === "object") +{ + module['exports'] = Elm; + return; +} + +var globalElm = this['Elm']; +if (typeof globalElm === "undefined") +{ + this['Elm'] = Elm; + return; +} + +for (var publicModule in Elm) +{ + if (publicModule in globalElm) + { + throw new Error('There are two Elm modules called `' + publicModule + '` on this page! Rename one of them.'); + } + globalElm[publicModule] = Elm[publicModule]; +} + +}).call(this); + diff --git a/bench/src/runner.js b/bench/src/runner.js new file mode 100755 index 0000000..dd79bd6 --- /dev/null +++ b/bench/src/runner.js @@ -0,0 +1,231 @@ + +// SETUP + +if (!window.performance || !window.performance.now) +{ + throw new Error('These tests use performance.now() which is not supported by your browser.'); +} + + + +// RUNNER + + +function runBenchmarks(impls, suite, callback) +{ + var frame = document.getElementById('benchmark-frame'); + var results = document.getElementById('benchmark-results'); + + frame.style.display = 'block'; + results.style.visibility = 'hidden'; + while (results.lastChild) { + results.removeChild(results.lastChild); + } + + runImplementations(impls, suite, 0, function() { + var canvas = document.createElement('canvas'); + results.appendChild(canvas); + updateChart(canvas, impls); + frame.style.display = 'none'; + results.style.visibility = 'visible'; + callback(); + }); +} + + + +// RUN IMPLEMENTATIONS + + +function runImplementations(impls, suite, index, done) +{ + var impl = impls[index]; + var frame = document.getElementById('benchmark-frame'); + frame.onload = function() + { + withFacts(0, frame.contentDocument, suite.getFacts, function(facts) + { + runSteps(facts, suite.steps, index, 0, [], function(results) + { + impl.results = results; + impl.time = getTotalTime(results); + console.log( + impl.name + ' ' + impl.version + + (impl.optimized ? ' (optimized)' : '') + + ' = ' + trunc(impl.time) + ' ms' + ); + + ++index; + + return (index < impls.length) + ? runImplementations(impls, suite, index, done) + : done(); + }); + }); + } + + frame.src = impl.url; +} + + +function getTotalTime(results) +{ + var total = 0; + for (var i = 0; i < results.length; i++) + { + total += results[i].sync; + total += results[i].async; + } + return total; +} + + +function withFacts(tries, doc, getFacts, callback) +{ + if (tries > 5) + { + throw new Error('Could not get facts for this implementation.'); + } + + setTimeout(function() { + var facts = getFacts(doc); + typeof facts === 'undefined' + ? withFacts(tries + 1, doc, getFacts, callback) + : callback(facts); + }, 16 * Math.pow(2, tries)); +} + + + +/* RUN STEPS ***/ + + +function runSteps(facts, steps, implIndex, index, results, done) +{ + timedStep(steps[index].work, facts, function(syncTime, asyncTime) + { + results.push({ + name: steps[index].name, + sync: syncTime, + async: asyncTime + }); + + ++index; + + if (index < steps.length) + { + return runSteps(facts, steps, implIndex, index, results, done) + } + + return done(results); + }); +} + + +function trunc(time) +{ + return Math.round(time); +} + + +function timedStep(work, facts, callback) +{ + // time all synchronous work + var start = performance.now(); + work(facts); + var end = performance.now(); + var syncTime = end - start; + + // time ONE round of asynchronous work + var asyncStart = performance.now(); + setTimeout(function() { + var asyncEnd = performance.now(); + callback(syncTime, asyncEnd - asyncStart); + }, 0); + + // if anyone does more than one round, we do not capture it! +} + + + +/* SETUP WORK LIST *********/ + + +function setupWorklist(suite) +{ + var impls = suite.impls; + var steps = suite.steps; + + var workList = document.getElementById('work-list'); + + while (workList.lastChild) + { + workList.removeChild(workList.lastChild); + } + + for (var i = 0; i < impls.length; i++) + { + var impl = document.createElement('li'); + var title = document.createTextNode(impls[i].name); + impl.appendChild(title); + workList.appendChild(impl); + } + + var sidebar = document.getElementById('sidebar'); + sidebar.appendChild(workList); +} + + + +/* DRAW CHARTS *************/ + + +function updateChart(canvas, impls) +{ + new Chart(canvas, { + type: 'bar', + data: { + labels: impls.map(toLabel), + datasets: [{ + label: 'ms', + data: impls.map(function(impl) { return trunc(impl.time); }), + backgroundColor: impls.map(toColor) + }] + }, + options: { + defaultFontFamily: 'Source Sans Pro', + title: { + display: true, + text: 'Benchmark Results', + fontSize: 20 + }, + legend: { + display: false + }, + scales: { + yAxes: [{ + scaleLabel: { + display: true, + labelString: 'Milliseconds (lower is better)', + fontSize: 16 + }, + ticks: { + beginAtZero: true + } + }] + } + } + }); +} + +function toLabel(impl) +{ + return impl.name + ' ' + impl.version; +} + +function toColor(impl) +{ + return impl.optimized + ? 'rgba(200, 12, 192, 0.5)' + : 'rgba(75, 192, 192, 0.5)'; +} \ No newline at end of file diff --git a/bench/src/theme.css b/bench/src/theme.css new file mode 100644 index 0000000..c981e73 --- /dev/null +++ b/bench/src/theme.css @@ -0,0 +1,37 @@ + +body { + padding: 0; + margin: 0; + background-color: rgb(253, 253, 253); + font-family: 'Trebuchet MS', 'Lucida Grande', 'Bitstream Vera Sans', 'Helvetica Neue', sans-serif; +} + +#benchmark-frame { + width: 800px; + height: 600px; + border: 1px solid black; + margin: 20px; + display: none; +} + +#sidebar { + top: 20px; + right: 20px; + position: absolute; + padding: 10px; + background-color: rgb(240, 240, 240); + border-radius: 4px; +} + +#sidebar ul { + list-style-type: none; + padding: 2px; + margin: 2px; +} + +#benchmark-results { + width: 800px; + margin: 20px; + border-radius: 4px; + display: block; +} \ No newline at end of file