{"version":3,"file":"main.js","sources":["../../node_modules/tslib/tslib.es6.js","../../node_modules/@lernetz/ts-lib/src/core/lookup/LookupDict.ts","../../node_modules/@lernetz/ts-lib/src/core/js.ts","../../node_modules/@lernetz/ts-lib/src/core/lookup/LookupObject.ts","../../node_modules/@lernetz/ts-lib/src/core/view/Renderer.ts","../../node_modules/@lernetz/ts-lib/src/core/lang/Lang.ts","../../node_modules/@lernetz/ts-lib/src/core/signal/Signal.ts","../../node_modules/@lernetz/ts-lib/src/core/node/Node.ts","../../node_modules/@lernetz/ts-lib/src/core/view/expressions/Expression.ts","../../node_modules/@lernetz/ts-lib/src/core/view/expressions/AttributeExpression.ts","../../node_modules/@lernetz/ts-lib/src/core/view/expressions/CSSExpression.ts","../../node_modules/@lernetz/ts-lib/src/core/view/expressions/TextExpression.ts","../../node_modules/@lernetz/ts-lib/src/core/view/expressions/DataAttributeExpression.ts","../../node_modules/@lernetz/ts-lib/src/core/view/expressions/DataExpression.ts","../../node_modules/@lernetz/ts-lib/src/core/view/expressions/ViewExpression.ts","../../node_modules/@lernetz/ts-lib/src/core/view/Template.ts","../../node_modules/@lernetz/ts-lib/src/core/model/Model.ts","../../node_modules/es6-promise/dist/es6-promise.js","../../node_modules/es6-promise/auto.js","../../node_modules/@lernetz/ts-lib/src/core/request/Request.ts","../../node_modules/@lernetz/ts-lib/src/core/ioc/IoC.ts","../../node_modules/@lernetz/ts-lib/src/core/model/Mapper.ts","../../node_modules/@lernetz/ts-lib/src/core/setup/Asset.ts","../../node_modules/@lernetz/ts-lib/src/core/setup/Setup.ts","../../node_modules/@lernetz/ts-lib/src/core/view/View.ts","../../typescript/connector/scorm/API.ts","../../typescript/connector/scorm/Api1_2.ts","../../typescript/connector/scorm/Api2004.ts","../../typescript/connector/scorm/ApiDebug.ts","../../typescript/connector/Scorm.ts","../../typescript/ScormSingleton.ts","../../node_modules/@lernetz/ts-lib/src/core/list/List.ts","../../node_modules/@lernetz/ts-lib/src/core/list/ModifiableList.ts","../../node_modules/@lernetz/ts-lib/src/core/list/ListRenderer.ts","../../node_modules/@lernetz/ts-lib/src/components/Repeat.ts","../../typescript/components/util/Resolve.ts","../../node_modules/@lernetz/ts-lib/src/components/Show.ts","../../node_modules/@lernetz/ts-lib/src/components/Trans.ts","../../node_modules/@lernetz/ts-lib/src/components/Html.ts","../../typescript/components/util/Placeholder.ts","../../typescript/templates/components/chapter.ts","../../typescript/components/chapter/Chapter.ts","../../typescript/components/chapter/index.ts","../../typescript/components/image/Image.ts","../../typescript/components/image/ImageView.ts","../../typescript/templates/components/image.ts","../../typescript/components/image/ChapterImage.ts","../../typescript/components/image/index.ts","../../typescript/templates/components/module.ts","../../typescript/components/module/ModuleView.ts","../../typescript/components/module/Module.ts","../../typescript/components/module/index.ts","../../typescript/components/text/TextView.ts","../../typescript/components/text/Text.ts","../../typescript/components/text/index.ts","../../typescript/components/toggle/Toggle.ts","../../typescript/components/toggle/ToggleView.ts","../../typescript/components/toggle/SvgToggleView.ts","../../typescript/templates/components/video.ts","../../typescript/components/video/VideoView.ts","../../typescript/components/video/Video.ts","../../typescript/components/video/index.ts","../../typescript/templates/components/stepbystep.ts","../../typescript/components/stepbystep/StepByStep.ts","../../typescript/components/stepbystep/StepTheme.ts","../../typescript/components/stepbystep/index.ts","../../typescript/templates/components/quiz.ts","../../typescript/components/quiz/QuizQuestionView.ts","../../typescript/components/quiz/Summary.ts","../../typescript/components/quiz/Quiz.ts","../../typescript/components/quiz/QuizQuestion.ts","../../typescript/components/quiz/index.ts","../../node_modules/@lernetz/ts-lib/src/components/Resolve.ts","../../node_modules/@lernetz/lernfragen/templates/choice-quiz.ts","../../node_modules/@lernetz/lernfragen/components/choice-quiz/index.ts","../../typescript/components/register.ts","../../typescript/main.ts"],"sourcesContent":["/*! *****************************************************************************\r\nCopyright (c) Microsoft Corporation. All rights reserved.\r\nLicensed under the Apache License, Version 2.0 (the \"License\"); you may not use\r\nthis file except in compliance with the License. You may obtain a copy of the\r\nLicense at http://www.apache.org/licenses/LICENSE-2.0\r\n\r\nTHIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\r\nKIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\r\nWARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\r\nMERCHANTABLITY OR NON-INFRINGEMENT.\r\n\r\nSee the Apache Version 2.0 License for specific language governing permissions\r\nand limitations under the License.\r\n***************************************************************************** */\r\n/* global Reflect, Promise */\r\n\r\nvar extendStatics = function(d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n};\r\n\r\nexport function __extends(d, b) {\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n}\r\n\r\nexport var __assign = function() {\r\n __assign = Object.assign || function __assign(t) {\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments[i];\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\r\n }\r\n return t;\r\n }\r\n return __assign.apply(this, arguments);\r\n}\r\n\r\nexport function __rest(s, e) {\r\n var t = {};\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n t[p] = s[p];\r\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0)\r\n t[p[i]] = s[p[i]];\r\n return t;\r\n}\r\n\r\nexport function __decorate(decorators, target, key, desc) {\r\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\r\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\r\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\r\n return c > 3 && r && Object.defineProperty(target, key, r), r;\r\n}\r\n\r\nexport function __param(paramIndex, decorator) {\r\n return function (target, key) { decorator(target, key, paramIndex); }\r\n}\r\n\r\nexport function __metadata(metadataKey, metadataValue) {\r\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\r\n}\r\n\r\nexport function __awaiter(thisArg, _arguments, P, generator) {\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n}\r\n\r\nexport function __generator(thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n}\r\n\r\nexport function __exportStar(m, exports) {\r\n for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];\r\n}\r\n\r\nexport function __values(o) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator], i = 0;\r\n if (m) return m.call(o);\r\n return {\r\n next: function () {\r\n if (o && i >= o.length) o = void 0;\r\n return { value: o && o[i++], done: !o };\r\n }\r\n };\r\n}\r\n\r\nexport function __read(o, n) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\r\n if (!m) return o;\r\n var i = m.call(o), r, ar = [], e;\r\n try {\r\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\r\n }\r\n catch (error) { e = { error: error }; }\r\n finally {\r\n try {\r\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\r\n }\r\n finally { if (e) throw e.error; }\r\n }\r\n return ar;\r\n}\r\n\r\nexport function __spread() {\r\n for (var ar = [], i = 0; i < arguments.length; i++)\r\n ar = ar.concat(__read(arguments[i]));\r\n return ar;\r\n}\r\n\r\nexport function __await(v) {\r\n return this instanceof __await ? (this.v = v, this) : new __await(v);\r\n}\r\n\r\nexport function __asyncGenerator(thisArg, _arguments, generator) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\r\n return i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i;\r\n function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }\r\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\r\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\r\n function fulfill(value) { resume(\"next\", value); }\r\n function reject(value) { resume(\"throw\", value); }\r\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\r\n}\r\n\r\nexport function __asyncDelegator(o) {\r\n var i, p;\r\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\r\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === \"return\" } : f ? f(v) : v; } : f; }\r\n}\r\n\r\nexport function __asyncValues(o) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var m = o[Symbol.asyncIterator], i;\r\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\r\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\r\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\r\n}\r\n\r\nexport function __makeTemplateObject(cooked, raw) {\r\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\r\n return cooked;\r\n};\r\n\r\nexport function __importStar(mod) {\r\n if (mod && mod.__esModule) return mod;\r\n var result = {};\r\n if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];\r\n result.default = mod;\r\n return result;\r\n}\r\n\r\nexport function __importDefault(mod) {\r\n return (mod && mod.__esModule) ? mod : { default: mod };\r\n}\r\n","\n/**\n * An interface for any source for the LookupDict\n */\nexport interface LookupSource {\n\tlookup( key:string ):any;\n}\n\n\n/**\n * This class provides a key:value lookup mechanism where multiple sources can be added.\n */\nclass LookupDict {\n\n\tprivate sources:LookupSource[] = [];\n\n\t/**\n\t * Adds a new source to the dictionary to search for keys\n\t */\n\tadd( source:LookupSource ) {\n\t\tthis.sources.push( source );\n\t}\n\n\n\t/**\n\t * Returns the value stored behind the given key in the first of all sources\n\t */\n\tget( key:string, fallback?:string ):any {\n\n\t\tvar result, i, s = this.sources;\n\n\t\t// loop over sources to find key.\n\t\tfor( i = 0; i < s.length; i++ ) {\n\t\t\tresult = s[ i ].lookup( key );\n\t\t\tif( result != null ) return result;\n\t\t}\n\n\t\t// if fallback is provided show that\n\t\tif( fallback !== undefined ) return fallback;\n\n\t\t// not found\n\t\treturn '!{' + key + '}';\n\t}\n}\n\n\n\nexport default LookupDict;\n","/**\n * A collection of js specific helper functions.\n */\n\ntype baseTypes = \"Array\" | \"Object\" | \"String\" | \"Date\" | \"RegExp\" | \"Function\" | \"Boolean\" | \"Number\" | \"Null\" | \"Undefined\";\n\n/**\n * Helper function that checks if the given input is any of the given types\n */\nexport function isType( input:any, checkOn:baseTypes | Array ):boolean {\n\n\t// catch single string input\n\tvar types:Array = ( !Array.isArray( checkOn ) ) ? [ checkOn ] : checkOn;\n\n\t// test on object.\n\tif( types.indexOf( \"Object\" ) >= 0 ) {\n\t\tvar match = input && input.constructor == Object;\n\t\tif( match ) return match;\n\n\t\ttypes.splice( types.indexOf( \"Object\" ), 1 );\n\t}\n\n\t// test anything else\n\tvar inputType = Object.prototype.toString.call( input ).slice(8, -1);\n\treturn types.indexOf( inputType ) >= 0;\n}\n\n\n/**\n * This function applies multiple mixins to the given extendedClass.\n */\nexport function mixin( extendedClass: any, mixins: any[] ) {\n\tmixins.forEach( baseCtor => {\n\t\tObject.getOwnPropertyNames( baseCtor.prototype ).forEach( name => {\n\t\t\textendedClass.prototype[name] = baseCtor.prototype[name];\n\t\t});\n\t});\n}\n\n/**\n * Merges multiple objects into one. No deep clone.\n * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign\n */\nexport function assign( target:{} = {}, ...args:Object[] ) {\n\n\tvar copy = Object( target );\n\n\targs.forEach( ( source ) => {\n\t\tif( source ) {\n\t\t\tfor( var nextKey in source ) {\n\t\t\t\tif( source.hasOwnProperty( nextKey ) ) copy[ nextKey ] = source[ nextKey ];\n\t\t\t}\n\t\t}\n\t});\n\n\treturn copy;\n}\n\n\n/**\n * Adapted from: http://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array\n */\nexport function shuffle(array) {\n\tvar i = array.length, t, randomIndex;\n\t// While there remain elements to shuffle...\n\twhile (0 !== i) {\n\t\t// Pick a remaining element...\n\t\trandomIndex = Math.floor(Math.random() * i);\n\t\ti -= 1;\n\t\t// And swap it with the current element.\n\t\tt = array[i];\n\t\tarray[i] = array[randomIndex];\n\t\tarray[randomIndex] = t;\n\t}\n\treturn array;\n}\n\n/**\n * Returns all properties including getter/setter recursive in proptotype chain\n */\nexport function getAccessorDescriptors( obj ):{[name:string]:PropertyDescriptor} {\n\tvar props = {};\n\twhile( obj ) {\n\t\tObject.getOwnPropertyNames( obj ).forEach( function( p ) {\n\t\t\tvar desc = Object.getOwnPropertyDescriptor( obj, p );\n\t\t\tif( desc && ( desc.set || desc.get ) ) props[ p ] = desc;\n\t\t});\n\t\tlet prototype = Object.getPrototypeOf( obj );\n\t\tobj = ( prototype !== Object.prototype ) ? prototype : undefined;\n\t}\n\n\treturn props;\n}\n\n","import { LookupSource } from './LookupDict';\nimport { isType } from '../js';\n\n/**\n * A lookup dictionary source that searches on an object for given keys.\n * It allows to search in nested objects too.\n */\nclass LookupObject implements LookupSource {\n\n\tprivate obj:Object;\n\n\tconstructor( obj:Object ) {\n\t\tthis.replace( obj );\n\t}\n\n\t/**\n\t * lookups in the object for the given key.\n\t */\n\tlookup( key:string ):any {\n\t\tvar keys = key.split( '.' );\n\t\treturn this.search( this.obj, keys );\n\t}\n\n\t/**\n\t * Adds a prefix to the search keys on this object\n\t */\n\tprefix( name:string ):void {\n\t\tvar temp = {};\n\t\ttemp[ name ] = this.obj;\n\t\tthis.obj = temp;\n\t}\n\n\treplace( obj:Object ) {\n\t\tthis.obj = ( isType( obj, 'Object' ) ) ? obj : {};\n\t}\n\n\t/**\n\t * Searches in the given object for the first key in the keys array.\n\t * If there are sub keys it digs deeper into object hierarchy.\n\t */\n\tprivate search = function( current:Object, keys:string[] ) {\n\n\t\tvar top = keys.shift();\n\n\t\t// there are sub keys to search\n\t\tif( keys.length > 0 ) {\n\t\t\treturn ( current[ top ] != undefined ) ? this.search( current[ top ], keys ) : undefined;\n\t\t} else {\n\t\t\treturn current[ top ];\n\t\t}\n\t};\n}\n\nexport default LookupObject;\n","\n/**\n* An interface of the complied template function containing also its source\n*/\ninterface CompliedTemplate {\n\t(...args ):any;\n}\n\ninterface TemplatePass {\n\tregex:RegExp;\n\tmapper:( match:string, inner:string ) => string;\n}\n\n\n/**\n *\n */\nclass Renderer {\n\n\tpublic context:any = { };\n\tpublic logging:boolean = false;\n\n\tpublic pass:TemplatePass = {\n\t\tregex:/\\[\\[([\\s\\S]+?)\\]\\]/g,\n\t\tmapper: function( match, inner ) {\n\t\t\treturn \"function() { try { with( data ) { return \" + inner + \" } } catch (error) { this.log( error ) } }.call( this )\";\n\t\t}\n\t};\n\n\tprivate cache:{} = {};\n\n\t/**\n\t* Renders the given data into the given template string\n\t*/\n\trender( template:string, data:any = {} ):any {\n\t\treturn this.compile(template)( data );\n\t}\n\n\t/**\n\t * Compiles a template string into a template function.\n\t */\n\tcompile( templateString:string, args = 'data' ):CompliedTemplate {\n\n\t\t// handle caching\n\t\tif( this.cache[ templateString ] ) return this.cache[ templateString ]\n\n\t\t// check if template is one single [[ .. ]] expression\n\t\tlet matches = templateString.match( /\\[\\[([\\s\\S]+?)\\]\\]/ );\n\t\tif( matches && matches[0] == templateString ) {\n\t\t\tvar source = this.parseValue( templateString );\n\t\t} else {\n\t\t\tvar source = this.parseString( templateString );\n\t\t}\n\n\t\tvar render = new Function( args, source );\n\t\tvar contx = this.context;\n\n\t\t// wrap function to adjust context\n\t\tvar func = function():any {\n\t\t\treturn render.apply( contx, arguments );\n\t\t}\n\n\t\t// store for caching\n\t\tthis.cache[ templateString ] = func;\n\n\t\treturn func;\n\t}\n\n\t/**\n\t\t* Turns the given template into a function body code.\n\t\t*/\n\tparseString( template:string ):string {\n\n\t\ttemplate = template.replace( this.pass.regex, ( match, inner:string ) => {\n\t\t\treturn \"' + __c.empty( \" + this.pass.mapper( match, inner ) + \" ) + '\";\n\t\t});\n\n\t\t// finalize full template instructions\n\t\ttemplate = \"__t= '\" + template + \"';\\n\";\n\n\t\t// add opt variable for optional access\n\t\treturn 'var __t;\\nvar __c = this;' + template + 'return __t;'\n\t}\n\n\t/**\n\t* Turns the given template into a function body code.\n\t*/\n\tparseValue( template:string ):string {\n\n\t\t// loop over all passes\n\t\ttemplate = template.replace( this.pass.regex, this.pass.mapper );\n\n\t\t// finalize full template instructions\n\t\ttemplate = \"__t = \" + template + \";\\n\";\n\n\t\t// add opt variable for optional access\n\t\treturn 'var __t;\\nvar __c = this;' + template + 'return __t;'\n\t}\n\n\t/**\n\t * Tests if the value of the template is empty or not\n\t */\n\tempty( data:any ):string {\n\t\treturn data || data === 0 ? data : '';\n\t}\n\n\t/**\n\t * Logs errors to the console\n\t */\n\tlog( error ) {\n\t\tif( !this.logging ) return;\n\n\t\tif( console ) {\n\t\t\t( console.trace ) ? console.trace( error ) : console.log( error );\n\t\t}\n\t}\n\n\t/**\n\t * Stops the debugger\n\t */\n\tdebug() {\n\t\tdebugger;\n\t}\n}\n\n\nexport var renderer = new Renderer();\nrenderer.context.empty = renderer.empty;\nrenderer.context.log = renderer.log.bind( renderer );\nrenderer.context.debug = renderer.debug;\n\n\nexport default Renderer;\n","import LookupDict from '../lookup/LookupDict';\nimport LookupObject from '../lookup/LookupObject';\nimport { renderer } from '../view/Renderer';\n\n/**\n * A class that handles translation lookups\n */\nclass Lang {\n\n\n\tprivate lookup:LookupDict;\n\n\tconstructor() {\n\t\tthis.lookup = new LookupDict();\n\t}\n\n\t/**\n\t * translates the given key.\n\t */\n\ttranslate( key:string, opts:{ data?:any, condition?:number } = {} ):any {\n\t\tif( key == undefined ) return '';\n\t\tvar def = this.lookup.get( key, key );\n\t\tif( opts.condition != undefined ) def = this.matchCondition( def, opts.condition );\n\t\tif( opts.data ) def = renderer.render( def, opts.data );\n\t\treturn def;\n\t}\n\n\tmatchCondition( value:string, num:number ) {\n\n\t\tvar parts = value.split( '|' );\n\n\t\t// check conditions\n\t\tvar found = this.parseConditions( parts, num )\n\t\tif( found ) return found.trim();\n\n\t\tif( parts.length == 1 ) return this.clearConditions( parts[0] );\n\n\t\t// check simple | split\n\t\treturn this.clearConditions( parts[ ( num == 1 ) ? 0 : 1 ] );\n\t}\n\n\tparseConditions( parts, number:number ):string {\n\t\t// loop over parts\n\t\tfor( var i = 0; i < parts.length; i++ ) {\n\t\t\tvar regex = /^[\\{\\[]([^\\[\\]\\{\\}]*)[\\}\\]](.*)/;\n\t\t\tvar match = regex.exec( parts[i] );\n\n\t\t\t// no proper condition\n\t\t\tif( match == null || match.length != 3 ) continue;\n\n\t\t\tvar value = match[2];\n\t\t\tvar condition = match[1];\n\t\t\tvar num = number;\n\n\t\t\t// range condition\n\t\t\tif( condition.indexOf( ',' ) > -1 ) {\n\n\t\t\t\tvar [ from , to ] = condition.split( ',' );\n\n\t\t\t\tif ( to == '*' && num >= parseInt( from ) ) {\n\t\t\t\t\treturn value;\n\t\t\t\t} else if ( from == '*' && num <= parseInt( to ) ) {\n\t\t\t\t\treturn value;\n\t\t\t\t} else if ( num >= parseInt( from ) && num <= parseInt( to ) ) {\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\n\t\t\t// exact condition\n\t\t\t} else if( parseInt( condition ) == num ) {\n\t\t\t\treturn value;\n\t\t\t}\n\t\t}\n\t}\n\n\tclearConditions( s:string ):string {\n\t\treturn s.replace( /^[\\{\\[]([^\\[\\]\\{\\}]*)[\\}\\]]/, '' ).trim();\n\t}\n\n\tadd( object:Object ) {\n\t\tthis.lookup.add( new LookupObject( object ) );\n\t}\n}\n\n/**\n * Define singleton for Lang\n */\nvar lang = new Lang();\n\n/**\n * Add translation into context\n */\nrenderer.context.trans = lang.translate.bind( lang );\n\nexport default lang;\n","export type Observer = (arg: T) => void;\n\nexport interface Subscription {\n unsubscribe(): void;\n}\n\nexport class Observable {\n\n private readonly subscribe_: (observer: Observer) => Subscription;\n\n public constructor(subscribe: (observer: Observer) => Subscription) {\n this.subscribe_ = subscribe;\n }\n\n public debounce(wait: number): Observable {\n return new Observable(observer => {\n let timeout;\n return this.subscribe(arg => {\n const later = () => {\n timeout = null;\n observer(arg);\n };\n clearTimeout(timeout);\n timeout = setTimeout(later, wait);\n });\n });\n }\n\n public filter(fn: (arg: T) => boolean): Observable {\n return new Observable(observer => {\n return this.subscribe(arg => {\n if (fn(arg)) {\n observer(arg);\n }\n });\n });\n }\n\n public map(fn: (arg: T) => U): Observable {\n return new Observable(observer => {\n return this.subscribe(arg => {\n observer(fn(arg));\n });\n });\n }\n\n public subscribe(observer: Observer): Subscription {\n return this.subscribe_(observer);\n }\n}\n\nexport class Signal extends Observable {\n\n private observers_?: Observer[];\n\n public constructor() {\n super(observer => {\n if (!this.observers_) {\n this.observers_ = [observer];\n }\n else if (this.observers_.indexOf(observer) < 0) {\n this.observers_.push(observer);\n }\n const observers = this.observers_;\n return {\n unsubscribe: () => {\n const index = observers.indexOf(observer);\n if (index >= 0) {\n observers.splice(index, 1);\n }\n }\n };\n });\n this.observers_ = [];\n }\n\n public dispatch(arg: T) {\n if (this.observers_) {\n for (const observer of this.observers_) {\n observer(arg);\n }\n }\n }\n}\n\n/**\n * Listens to an event target event and creates an observable instance\n * @param el the event target tzo listen to\n * @param event the name of the event to listen to\n */\nexport function observable( event:string, el:EventTarget ):Observable {\n\treturn new Observable( observer => {\n\t\tlet handler = ( event ) => observer( event );\n\t\tel.addEventListener( event, handler );\n\t\treturn {\n\t\t\tunsubscribe:() => {\n\t\t\t\tel.removeEventListener( event, handler );\n\t\t\t}\n\t\t}\n\t});\n}\n","import { Observable, observable } from \"../signal/Signal\";\nimport View from \"../view/View\";\n\n\nexport function node(html: string): NodeWrapper;\nexport function node(view: View): NodeWrapper;\nexport function node(native: Node): NodeWrapper;\nexport function node(arg: string | View | Node): NodeWrapper {\n\tif (typeof arg === 'string') {\n\n\t\t// wrap the content into new node because it can be one root node in template or its content\n\t\tlet temp = document.createElement('div' );\n\t\ttemp.innerHTML = arg;\n\n\t\t// If there is exactly one child the template has one root node - return this one.\n\t\t// otherwise if there are many or no children return the temp div as the root.\n\t\treturn new NodeWrapper( ( temp.children.length == 1 ) ? temp.children[0] : temp );\n\t}\n\telse if (arg instanceof Node) {\n\t\treturn new NodeWrapper( arg as Element );\n\t}\n\telse if ('node' in arg && arg['node'] instanceof Node) {\n\t\treturn new NodeWrapper( arg.node );\n\t}\n\telse {\n\t\treturn null;\n\t}\n}\n\n\nclass NodeWrapper {\n\n\tconstructor( public native:Element ) {}\n\n\tget clicks() {\n\t\treturn observable( 'click', this.native );\n\t}\n\tget scrolls() {\n\t\treturn observable( 'scroll', this.native );\n\t}\n\tget mouseleaves() {\n\t\treturn observable( 'mouseleave', this.native );\n\t}\n\tget mouseenters() {\n\t\treturn observable( 'mouseenter', this.native );\n\t}\n\tget mouseouts() {\n\t\treturn observable( 'mouseout', this.native );\n\t}\n\tget mouseovers() {\n\t\treturn observable( 'mouseover', this.native );\n\t}\n\tget mouseups() {\n\t\treturn observable( 'mouseup', this.native );\n\t}\n\tget mousedowns() {\n\t\treturn observable( 'mousedown', this.native );\n\t}\n\tget mousemoves() {\n\t\treturn observable( 'mousemove', this.native );\n\t}\n\tget keypresses() {\n\t\treturn observable( 'keypress', this.native );\n\t}\n\tget keydowns() {\n\t\treturn observable( 'keydown', this.native );\n\t}\n\tget keyups() {\n\t\treturn observable( 'keyup', this.native );\n\t}\n\tget focuses() {\n\t\treturn observable( 'focus', this.native );\n\t}\n\tget blurs() {\n\t\treturn observable( 'blur', this.native );\n\t}\n\tget changes() {\n\t\treturn observable( 'change', this.native );\n\t}\n\n\t/**\n\t * Removes all element within the native node\n\t */\n\tempty() {\n\t\tfor ( var i = this.native.children.length; i--; ) {\n\t\t\tthis.native.removeChild( this.native.children[i] );\n\t\t}\n\t}\n\n\t/**\n\t * Removes the given element from the dom.\n\t */\n\tremove() {\n\t\tif( this.native.parentElement ) this.native.parentElement.removeChild( this.native );\n\t}\n\n\t/**\n\t * Replaces this native node with the given newNode\n\t * @param newNode The new node to be place on position of the given existingNode\n\t */\n\treplace( newNode:Node ) {\n\t\tthis.native.parentNode.replaceChild( newNode, this.native );\n\t}\n\n\t/**\n\t * Prepends the given node to this node\n\t * @param node the new node to prepend\n\t */\n\tprepend( node:Node ) {\n\t\tthis.native.insertBefore( node, this.native.firstChild );\n\t}\n\n\n\t/**\n\t * Places a node at the given index\n\t * @param node The new node to place\n\t * @param index The index where to place the node\n\t */\n\tinsert( node:Node, index:number ) {\n\t\tthis.native.insertBefore( node, this.native.childNodes[ index ] );\n\t}\n\n\n\t/**\n\t * Check if the classname exists in the classlist of this node\n\t *\n\t * @param classname Classname to be checked\n\t * @return `true` if the class exists, `false` else\n\t */\n\thasClass( classname: string ): boolean {\n\t\treturn this.getClasses().indexOf( classname ) > -1;\n\t}\n\n\n\t/**\n\t * Adds a css class the the class list\n\t * @param name The name of the class to add\n\t */\n\taddClass( name:string ) {\n\t\tthis.setClasses( this.getClasses().concat( [ name ] ) );\n\t}\n\n\t/**\n\t * Removes a class from the list\n\t * @param name The css class to remove\n\t */\n\tremoveClass( name:string ) {\n\t\tthis.setClasses( this.getClasses().filter( current => name != current ) );\n\t}\n\n\t/**\n\t * Toggles a given class name on the node\n\t * @param name the name of the css class to toggle\n\t * @param force a flag to either force to add the class ( true ) or to remove the class (false)\n\t */\n\ttoggleClass( name:string, force?:boolean ) {\n\t\tif( force == undefined ) {\n\t\t\t( this.hasClass( name ) ) ? this.removeClass( name ) : this.addClass( name );\n\t\t} else {\n\t\t\t( force ) ? this.addClass( name ) : this.removeClass( name );\n\t\t}\n\t}\n\n\t/**\n\t * Helper function to set classes distinct\n\t */\n\tprivate setClasses( classList:string[] ) {\n\t\tlet distinct = classList.filter( ( name, index, list ) => name.length > 0 && list.indexOf( name ) === index );\n\t\tthis.native.setAttribute( 'class', distinct.join(' ') );\n\t}\n\n\tprivate getClasses():string[] {\n\t\tlet list = this.native.getAttribute('class');\n\t\treturn ( list ) ? list.split( ' ' ) : [];\n\t}\n\n\n\t/**\n\t * Returns the bounding box of this node including values for top, bottom, left, right relative to the current viewport\n\t */\n\trelativeBounds() {\n\t\tlet c = this.native.getBoundingClientRect();\n\t\tlet r = {  top: c.top, left: c.left, right: c.right, bottom: c.bottom, height: c.height, width: c.width };\n\n\t\tif ( r.height == undefined ) r.height = r.bottom - r.top;\n\t\tif ( r.width == undefined ) r.width = r.right - r.left;\n\n\t\treturn r;\n\t}\n\n\t/**\n\t * Returns the bounding box of this node including values for top, bottom, left, right in absolute document coordinates\n\t */\n\tabsoluteBounds() {\n\t\tlet box = this.relativeBounds();\n\n\t\tbox.top += document.body.scrollTop || document.documentElement.scrollTop;\n\t\tbox.bottom += document.body.scrollTop || document.documentElement.scrollTop;\n\t\tbox.left += document.body.scrollLeft || document.documentElement.scrollLeft;\n\t\tbox.right += document.body.scrollLeft || document.documentElement.scrollLeft;\n\n\t\treturn box;\n\t}\n}\n","import { renderer } from \"../Renderer\";\n\nabstract class Expression {\n\n\tprivate _template:string = \"\";\n\tprivate expressionContent:string;\n\n\tabstract update( data:any, attribute?:string );\n\n\t/**\n\t * Simple test if template has the given attribute in its brankets\n\t * @param name\n\t */\n\thasAttribute( name:string ) {\n\t\tif( name == undefined ) return true;\n\t\treturn this.expressionContent.indexOf( name ) >= 0;\n\t}\n\n\tset template( t:string ) {\n\t\tthis._template = t;\n\t\tthis.expressionContent = '';\n\t\tt.replace( renderer.pass.regex, ( match, inner ) => {\n\t\t\tthis.expressionContent += inner;\n\t\t\treturn '';\n\t\t});\n\t}\n\n\tget template():string {\n\t\treturn this._template;\n\t}\n}\n\nexport function hasExpression( string:string ):boolean {\n\trenderer.pass.regex.lastIndex = 0; // reset global regex\n\treturn renderer.pass.regex.test( string );\n}\nexport function snakeToCamel( string ) {\n\treturn string.replace( /(\\-\\w)/g, match => match[1].toUpperCase() );\n}\n\nexport function camelToSnake( string ) {\n\treturn string.split(/(?=[A-Z])/).join('-').toLowerCase();\n}\n\nexport default Expression;\n","import Expression from './Expression';\nimport { renderer } from '../Renderer';\n\nclass AttributeExpression extends Expression {\n\n\tnode:Element;\n\tattribute:string;\n\ttemplate:string;\n\n\tconstructor( node:Element, attribute:string ) {\n\t\tsuper();\n\t\tthis.node = node;\n\t\tthis.attribute = attribute;\n\t\tthis.template = node.getAttribute( attribute );\n\t}\n\n\tupdate( data:any, name?:string ) {\n\n\t\t// handle input\n\t\tif( this.node instanceof HTMLInputElement && this.attribute == 'value' ) {\n\t\t\tthis.node.value = renderer.render( this.template, data );\n\t\t}\n\n\t\t// default case set attribute\n\t\tthis.node.setAttribute( this.attribute, renderer.render( this.template, data ) );\n\t}\n}\n\nexport default AttributeExpression;\n","import AttributeExpression from './AttributeExpression';\nimport { renderer } from '../Renderer';\n\nclass CSSExpression extends AttributeExpression {\n\n\tconstructor( node:Element ) {\n\t\tsuper( node, 'class' );\n\t}\n\n\tupdate( data:any ) {\n\n\t\tlet css = this.template.replace( renderer.pass.regex, ( match ) => {\n\t\t\tlet value = renderer.render( match, data );\n\t\t\tif( typeof value == 'string' ) return value;\n\t\t\tif( value === undefined || value === null ) return '';\n\t\t\t// if no string we iterate over object\n\t\t\t// filter false values and return keys as string\n\t\t\treturn Object.keys( value ).filter( key => value[key] ).join( ' ' );\n\t\t});\n\n\t\t// default case set attribute\n\t\tthis.node.setAttribute( 'class', css );\n\t}\n}\n\nexport default CSSExpression;\n","import { renderer } from '../Renderer';\nimport Expression from './Expression';\n\nclass TextExpression extends Expression {\n\n\tnode:Node;\n\n\tconstructor( node:Node ) {\n\t\tsuper();\n\t\tthis.node = node;\n\t\tthis.template = node.nodeValue;\n\t}\n\n\tupdate( data:any, name?:string ) {\n\t\tthis.node.nodeValue = renderer.render( this.template, data );\n\t}\n}\n\nexport default TextExpression;\n","import Expression from './Expression';\nimport View from '../View';\nimport { renderer } from '../Renderer';\n\nclass DataAttributeExpression extends Expression {\n\n\ttarget:any;\n\tattribute:string;\n\n\tconstructor( target:any, attribute:string, template:string ) {\n\t\tsuper();\n\t\tthis.template = template;\n\t\tthis.attribute = attribute;\n\t\tthis.target = target;\n\t}\n\n\tupdate( data:any, attribute:string ) {\n\t\tthis.target[ this.attribute ] = renderer.render( this.template, data );\n\t}\n}\n\nexport default DataAttributeExpression;\n","import { renderer } from '../Renderer';\nimport View from '../View';\nimport Expression from './Expression';\n\nclass DataExpression extends Expression {\n\n\ttarget:View;\n\ttemplate:string;\n\n\tconstructor( target:View, template:string ) {\n\t\tsuper();\n\t\tthis.template = template;\n\t\tthis.target = target;\n\t}\n\n\tupdate( data:any, attribute:string ) {\n\t\tthis.target.data = this.value( data );\n\t\tthis.target.update( attribute ); // update target view if its data has changed\n\t}\n\n\tvalue( data:{} ) {\n\t\treturn renderer.render( this.template, data );\n\t}\n}\n\nexport default DataExpression;\n","import { renderer } from '../Renderer';\nimport { ViewFactory } from '../Template';\nimport AttributeExpression from './AttributeExpression';\nimport DataAttributeExpression from './DataAttributeExpression';\nimport Expression, { snakeToCamel, hasExpression } from './Expression';\nimport DataExpression from './DataExpression';\nimport { Observable, observable } from '../../signal/Signal';\n\nclass ViewExpression extends Expression {\n\n\ttarget:Element;\n\tattributes:{[key:string]:string};\n\texpressions:Expression[];\n\tviewFactory:ViewFactory;\n\n\tconstructor( target:Element, viewFactory:ViewFactory ) {\n\t\tsuper();\n\t\tthis.target = target;\n\t\tthis.viewFactory = viewFactory;\n\t\tthis.expressions = [];\n\t\tthis.parseAttributes();\n\t\tthis.template = this.attributes['view'];\n\t}\n\n\tupdate( data:any, attribute?:string ) {\n\n\t\t// check if we have an expression update of the view attribute\n\t\tif( super.hasAttribute( attribute ) ) {\n\n // make sure node is empty\n this.target.innerHTML = '';\n this.expressions = [];\n\n\t\t\tthis.renderView( data );\n\t\t} else {\n\t\t\t// update expressions only\n\t\t\tthis.expressions.forEach( exp => {\n\t\t\t\tif( exp.hasAttribute( attribute ) ) exp.update( data, attribute );\n\t\t\t});\n\t\t}\n\t}\n\n\trenderView( data ) {\n\n\t\tlet node = this.target;\n\n\t\tlet viewName = renderer.render( this.attributes['view'], data );\n\t\tlet view = this.viewFactory( viewName );\n\n\t\t// set data if there is any\n\t\tif( node.hasAttribute( 'data' ) ) {\n\t\t\tlet dataExp = new DataExpression( view, node.getAttribute( 'data' ) );\n\t\t\tview.data = dataExp.value( data );\n this.expressions.push( dataExp );\n\n // remove node attribute\n\t\t\tnode.removeAttribute( 'data' );\n\t\t}\n\n\t\tnode['_lnview'] = view;\n\n\t\t// handle view attributes\n\t\tObject.keys( this.attributes ).forEach( name => {\n\n\t\t\t// ignore special view attribute\n\t\t\tif( name == 'view' || name == 'data' ) return;\n\n\t\t\tlet value = this.attributes[ name ];\n\n\t\t\t// handle events\n\t\t\tif( name.indexOf( 'on-' ) == 0 ) {\n\t\t\t\t// get signal name an subscribe\n\t\t\t\tlet signalName = snakeToCamel( name.replace( 'on-', '' ) );\n\n\t\t\t\t// look on data for signal\n\t\t\t\tif( view.data[ signalName ] instanceof Observable ) {\n\t\t\t\t\tsubscribeTo( view.data[ signalName ], value, data );\n\t\t\t\t// otherwise register on node signal\n\t\t\t\t} else {\n\t\t\t\t\tsubscribeTo( observable( signalName, node ), value, data );\n\t\t\t\t}\n\n\t\t\t\tnode.removeAttribute( name );\n\t\t\t\treturn;\n\t\t\t}\n\n\n\t\t\tlet propName = snakeToCamel( name );\n\n\t\t\t// check if viewModel has property otherwise its a node attribute\n\t\t\tif( view.data instanceof Object && propName in view.data ) {\n\n\t\t\t\tlet dataExp = new DataAttributeExpression( view.data, propName, value );\n\t\t\t\tdataExp.update( data, null );\n\t\t\t\tthis.expressions.push( dataExp );\n\n\t\t\t\t// remove node attribute\n\t\t\t\tnode.removeAttribute( name );\n\n\t\t\t} else if( hasExpression( node.getAttribute( name ) ) ) {\n\t\t\t\tlet expr = new AttributeExpression( node, name );\n\t\t\t\texpr.update( data );\n\t\t\t\tthis.expressions.push( expr );\n\t\t\t}\n\t\t});\n\n\t\tview.render( node );\n\t}\n\n\tparseAttributes() {\n\t\tthis.attributes = {};\n\t\tfor (let i = 0; i < this.target.attributes.length; i++) {\n\t\t\tconst attr = this.target.attributes[i];\n\t\t\tthis.attributes[ attr.name ] = attr.value;\n\t\t}\n\t}\n\n\t/**\n\t * Checks if the view=\"...\" expression and all its sub expression have the attribute to update\n\t * @param name The name of the attribute to check if its in expressions\n\t */\n\thasAttribute( name?:string ) {\n\t\tif( super.hasAttribute( name ) ) return true;\n\t\treturn this.expressions.some( expr => expr.hasAttribute( name ) );\n\t}\n}\n\nexport default ViewExpression;\n\n\n/**\n * Helper function to subscribe to signals\n * @param observable the observable to subscribe\n * @param content the string content of the on-... attribute for the oberserver callback\n * @param data the data/viewModel to look callback functions\n */\nexport function subscribeTo( observable:Observable, content:string, data:{} ) {\n\t// check for valid observable\n\tif( !observable ) return;\n\n\t// event closure\n\tif( hasExpression( content ) ) {\n\n\t\tlet callback = renderer.compile( content, 'event,data' );\n\n\t\tobservable.subscribe( ( event ) => {\n\t\t\tcallback.call( renderer.context, event, data );\n\t\t});\n\n\t// viewModel function\n\t} else if( data[ content ] ) {\n\t\tobservable.subscribe( data[ content ].bind( data ) );\n\t}\n}\n","import { node } from '../node/Node';\nimport AttributeExpression from './expressions/AttributeExpression';\nimport CSSExpression from './expressions/CSSExpression';\nimport Expression, { hasExpression, snakeToCamel } from './expressions/Expression';\nimport TextExpression from './expressions/TextExpression';\nimport ViewExpression, { subscribeTo } from './expressions/ViewExpression';\nimport View from './View';\nimport { observable } from '../signal/Signal';\n\n\nexport interface ViewFactory {\n\t( type:string ):View;\n}\n\n\nclass Template {\n\n\tpublic root:Element;\n\n\tpublic viewFactory:ViewFactory;\n\tpublic dataFactory:()=>{};\n\n\tprivate expressions:Array = [];\n\tprivate content:string;\n\n\tconstructor( content:string ) {\n\t\tthis.content = content;\n\t}\n\n\trender( target?:Element ) {\n\n\t\t// if there a target node given\n\t\tif( target instanceof Element ) {\n\n\t\t\t// if its an empty target node render content string into node\n\t\t\tif( target.innerHTML == '' ) {\n\n\t\t\t\tlet temp = node( this.content ).native;\n\t\t\t\ttarget.innerHTML = temp.innerHTML;\n\n\t\t\t\t// merge css classes\n\t\t\t\tlet css = [];\n\t\t\t\tif( target.getAttribute( 'class' ) ) css = css.concat( target.getAttribute( 'class' ).split( ' ' ) );\n\t\t\t\tif( temp.getAttribute( 'class' ) ) css = css.concat( temp.getAttribute( 'class' ).split( ' ' ) );\n\t\t\t\ttarget.setAttribute( 'class', css.join(' ') );\n\t\t\t}\n\n\t\t} else {\n\t\t\ttarget = node( this.content ).native;\n\t\t}\n\n\t\tthis.root = target;\n\n\t\tthis.processNode( target );\n\t}\n\n\tprocessNode( node:Element|Text ) {\n\n\t\t// do not parse script tags\n\t\tif( node.nodeName.toLowerCase() == 'script' ) return;\n\n\t\tif( isText( node ) ) {\n\t\t\tthis.processTextNode( node );\n\t\t\treturn\n\t\t}\n\n\t\tif( node.getAttribute( 'view' ) && !node['_lnview'] ) {\n\t\t\tthis.processViewNode( node );\n\t\t\treturn;\n\t\t}\n\n\t\tthis.processAttributes( node );\n\t\tthis.processChildren( node );\n\n\t\tfunction isText( node:ChildNode ): node is Text {\n\t\t\treturn node.nodeType === 3 /* Node.TEXT_NODE */;\n\t\t}\n\t}\n\n\tprocessTextNode( node:Node ) {\n\t\tif( hasExpression( node.nodeValue ) ) {\n\t\t\tlet expr = new TextExpression( node );\n\t\t\texpr.update( this.dataFactory() );\n\t\t\tthis.expressions.push( expr );\n\t\t}\n\t}\n\n\tprocessViewNode( node:Element ) {\n\t\tlet expr = new ViewExpression( node, this.viewFactory );\n\t\texpr.renderView( this.dataFactory() );\n\t\tthis.expressions.push( expr );\n\t}\n\n\tprocessAttributes( node:Element ) {\n\n\t\tfor( let i = 0; i < node.attributes.length; i++ ) {\n\n\t\t\tlet name = node.attributes[i].name;\n\n\t\t\t// handle events\n\t\t\tif( name.indexOf( 'on-' ) == 0 ) {\n\n\t\t\t\t// get signal name an subscribe\n\t\t\t\tlet signalName = snakeToCamel( name.replace( 'on-', '' ) );\n\t\t\t\tsubscribeTo( observable( signalName, node ), node.getAttribute( name ), this.dataFactory() );\n\n\t\t\t\t// remove attribute and adjust index so the next attribute won't be skipped\n\t\t\t\tnode.removeAttribute( name );\n\t\t\t\t--i;\n\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// handle attribute expressions\n\t\t\tif( hasExpression( node.getAttribute( name ) ) ) {\n\n\t\t\t\t// handle css special\n\t\t\t\tlet expr = ( name == 'class' ) ? new CSSExpression( node ) : new AttributeExpression( node, name );\n\n\t\t\t\texpr.update( this.dataFactory() );\n\t\t\t\tthis.expressions.push( expr );\n\t\t\t}\n\t\t}\n\t}\n\n\tprocessChildren( node:Element ) {\n\t\tfor (let i = 0; i < node.childNodes.length; i++) {\n\t\t\tthis.processNode( node.childNodes[i] );\n\t\t}\n\t}\n\n\tupdate( data:any, name?:string ) {\n\t\tthis.expressions.forEach( exp => {\n\t\t\tif( exp.hasAttribute( name ) ) exp.update( data, name );\n\t\t});\n\t}\n\n\t/**\n\t * Returns the child view within this template.\n\t * @param name The view with the given name\n\t */\n\tfirst( name:string ) {\n\t\tvar node = this.root.querySelector( '[view=' + name + ']' );\n\t\treturn ( node && node[ '_lnview' ] ) ? node[ '_lnview' ] : null;\n\t}\n}\n\nexport default Template;\n\n\n\n\n\n\n\n\n","import { Observable, Signal } from '../signal/Signal';\nimport { isType } from '../js';\n\n\n/**\n * Checks whether the specified object implements [[AttributeChangeObservable]].\n *\n * @param obj The object that should be tested.\n */\nexport function isAttributeChangeObservable( obj:T ):obj is T&AttributeChangeObservable {\n\treturn obj && obj[ 'change' ] instanceof Observable;\n}\n\n\n/**\n * Describes the payload of the [[AttributeChangeObservable.change]] observable.\n */\nexport interface AttributeChange {\n\tname:string,\n\tnewValue:any,\n\toldValue:any\n}\n\n\n/**\n * Types that implement this interface publish all property value changes as an [[Observable]].\n *\n * @see Model is the main implementation of this interface inside the library.\n */\nexport interface AttributeChangeObservable {\n\n\t/**\n\t * Raised when a property's value has changed.\n\t *\n\t * @event\n\t */\n\tchange:Observable;\n}\n\n\n/**\n * A common model class that has getters and setters\n */\nclass Model implements AttributeChangeObservable {\n\n\tprivate _obj:Object;\n\n\t/**\n\t * Raised when a property's value has changed.\n\t *\n\t * @event\n\t */\n\tpublic change:Signal;\n\n\n\tconstructor( obj:Object = {} ) {\n\t\tthis._obj = obj;\n\t\tthis.change = new Signal();\n\t\tthis.generateAccessors();\n\t}\n\n\t/**\n\t * Returns the value of the model with the given key.\n\t * If the key does not exists the given optional fallback value is returned.\n\t * @param key The key on the model to lookup\n\t * @param fallback The fallback value when the key does not exists.\n\t */\n\tget( key:string, fallback:T = undefined ):T {\n\t\tvar value = this._obj[ key ];\n\t\treturn ( value !== undefined ) ? value : fallback;\n\t}\n\n\t/**\n\t * Sets the given value on the given key in the model.\n\t * @param key The key on the model to adjust its value\n\t * @param value The new value to set of the model\n\t */\n\tset( key:string, value:any ) {\n\n\t\tvar isNew = this._obj[ key ] == undefined;\n\t\tvar old = this._obj[ key ];\n\t\tif( old != value ) {\n\t\t\tthis._obj[ key ] = value;\n\t\t\tthis.change.dispatch( { name:key, newValue:value, oldValue: old } );\n\t\t}\n\t\tif( isNew ) this.generateAccessors();\n\t}\n\n\t/**\n\t * Return a clone of this object\n\t */\n\tpublic object():any{\n\t\tvar obj = {};\n\t\tfor( var attr in this._obj ){\n\t\t\tobj[attr] = this._obj[attr];\n\t\t}\n\t\treturn obj;\n\t}\n\n\t/**\n\t * Syncs the attributes of this model with the given object attributes\n\t * It only syncs builtin types. other types have to sync manually.\n\t */\n\tpublic sync( obj:any ) {\n\t\tfor( var property in obj ) {\n\t\t\tif( isType( obj[property], [ \"String\", \"Date\", \"Boolean\", \"Number\" ] ) ) {\n\t\t\t\tthis.set( property, obj[property] );\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate generateAccessors() {\n\n\t\tvar createProperty = ( name ) => {\n\t\t\tObject.defineProperty( this, name, {\n\t\t\t\tget() {\n\t\t\t\t\treturn this.get( name );\n\t\t\t\t},\n\t\t\t\tset( value ) {\n\t\t\t\t\tthis.set( name, value );\n\t\t\t\t},\n\t\t\t\tenumerable: true,\n\t\t\t\tconfigurable: true\n\t\t\t});\n\t\t}\n\n\t\tfor( var attr in this._obj ){\n\t\t\tif( !( attr in this ) )\tcreateProperty( attr );\n\t\t}\n\t}\n}\n\nexport default Model;\n","/*!\n * @overview es6-promise - a tiny implementation of Promises/A+.\n * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald)\n * @license Licensed under MIT license\n * See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE\n * @version v4.2.6+9869a4bc\n */\n\n(function (global, factory) {\n\ttypeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :\n\ttypeof define === 'function' && define.amd ? define(factory) :\n\t(global.ES6Promise = factory());\n}(this, (function () { 'use strict';\n\nfunction objectOrFunction(x) {\n var type = typeof x;\n return x !== null && (type === 'object' || type === 'function');\n}\n\nfunction isFunction(x) {\n return typeof x === 'function';\n}\n\n\n\nvar _isArray = void 0;\nif (Array.isArray) {\n _isArray = Array.isArray;\n} else {\n _isArray = function (x) {\n return Object.prototype.toString.call(x) === '[object Array]';\n };\n}\n\nvar isArray = _isArray;\n\nvar len = 0;\nvar vertxNext = void 0;\nvar customSchedulerFn = void 0;\n\nvar asap = function asap(callback, arg) {\n queue[len] = callback;\n queue[len + 1] = arg;\n len += 2;\n if (len === 2) {\n // If len is 2, that means that we need to schedule an async flush.\n // If additional callbacks are queued before the queue is flushed, they\n // will be processed by this flush that we are scheduling.\n if (customSchedulerFn) {\n customSchedulerFn(flush);\n } else {\n scheduleFlush();\n }\n }\n};\n\nfunction setScheduler(scheduleFn) {\n customSchedulerFn = scheduleFn;\n}\n\nfunction setAsap(asapFn) {\n asap = asapFn;\n}\n\nvar browserWindow = typeof window !== 'undefined' ? window : undefined;\nvar browserGlobal = browserWindow || {};\nvar BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;\nvar isNode = typeof self === 'undefined' && typeof process !== 'undefined' && {}.toString.call(process) === '[object process]';\n\n// test for web worker but not in IE10\nvar isWorker = typeof Uint8ClampedArray !== 'undefined' && typeof importScripts !== 'undefined' && typeof MessageChannel !== 'undefined';\n\n// node\nfunction useNextTick() {\n // node version 0.10.x displays a deprecation warning when nextTick is used recursively\n // see https://github.com/cujojs/when/issues/410 for details\n return function () {\n return process.nextTick(flush);\n };\n}\n\n// vertx\nfunction useVertxTimer() {\n if (typeof vertxNext !== 'undefined') {\n return function () {\n vertxNext(flush);\n };\n }\n\n return useSetTimeout();\n}\n\nfunction useMutationObserver() {\n var iterations = 0;\n var observer = new BrowserMutationObserver(flush);\n var node = document.createTextNode('');\n observer.observe(node, { characterData: true });\n\n return function () {\n node.data = iterations = ++iterations % 2;\n };\n}\n\n// web worker\nfunction useMessageChannel() {\n var channel = new MessageChannel();\n channel.port1.onmessage = flush;\n return function () {\n return channel.port2.postMessage(0);\n };\n}\n\nfunction useSetTimeout() {\n // Store setTimeout reference so es6-promise will be unaffected by\n // other code modifying setTimeout (like sinon.useFakeTimers())\n var globalSetTimeout = setTimeout;\n return function () {\n return globalSetTimeout(flush, 1);\n };\n}\n\nvar queue = new Array(1000);\nfunction flush() {\n for (var i = 0; i < len; i += 2) {\n var callback = queue[i];\n var arg = queue[i + 1];\n\n callback(arg);\n\n queue[i] = undefined;\n queue[i + 1] = undefined;\n }\n\n len = 0;\n}\n\nfunction attemptVertx() {\n try {\n var vertx = Function('return this')().require('vertx');\n vertxNext = vertx.runOnLoop || vertx.runOnContext;\n return useVertxTimer();\n } catch (e) {\n return useSetTimeout();\n }\n}\n\nvar scheduleFlush = void 0;\n// Decide what async method to use to triggering processing of queued callbacks:\nif (isNode) {\n scheduleFlush = useNextTick();\n} else if (BrowserMutationObserver) {\n scheduleFlush = useMutationObserver();\n} else if (isWorker) {\n scheduleFlush = useMessageChannel();\n} else if (browserWindow === undefined && typeof require === 'function') {\n scheduleFlush = attemptVertx();\n} else {\n scheduleFlush = useSetTimeout();\n}\n\nfunction then(onFulfillment, onRejection) {\n var parent = this;\n\n var child = new this.constructor(noop);\n\n if (child[PROMISE_ID] === undefined) {\n makePromise(child);\n }\n\n var _state = parent._state;\n\n\n if (_state) {\n var callback = arguments[_state - 1];\n asap(function () {\n return invokeCallback(_state, child, callback, parent._result);\n });\n } else {\n subscribe(parent, child, onFulfillment, onRejection);\n }\n\n return child;\n}\n\n/**\n `Promise.resolve` returns a promise that will become resolved with the\n passed `value`. It is shorthand for the following:\n\n ```javascript\n let promise = new Promise(function(resolve, reject){\n resolve(1);\n });\n\n promise.then(function(value){\n // value === 1\n });\n ```\n\n Instead of writing the above, your code now simply becomes the following:\n\n ```javascript\n let promise = Promise.resolve(1);\n\n promise.then(function(value){\n // value === 1\n });\n ```\n\n @method resolve\n @static\n @param {Any} value value that the returned promise will be resolved with\n Useful for tooling.\n @return {Promise} a promise that will become fulfilled with the given\n `value`\n*/\nfunction resolve$1(object) {\n /*jshint validthis:true */\n var Constructor = this;\n\n if (object && typeof object === 'object' && object.constructor === Constructor) {\n return object;\n }\n\n var promise = new Constructor(noop);\n resolve(promise, object);\n return promise;\n}\n\nvar PROMISE_ID = Math.random().toString(36).substring(2);\n\nfunction noop() {}\n\nvar PENDING = void 0;\nvar FULFILLED = 1;\nvar REJECTED = 2;\n\nvar TRY_CATCH_ERROR = { error: null };\n\nfunction selfFulfillment() {\n return new TypeError(\"You cannot resolve a promise with itself\");\n}\n\nfunction cannotReturnOwn() {\n return new TypeError('A promises callback cannot return that same promise.');\n}\n\nfunction getThen(promise) {\n try {\n return promise.then;\n } catch (error) {\n TRY_CATCH_ERROR.error = error;\n return TRY_CATCH_ERROR;\n }\n}\n\nfunction tryThen(then$$1, value, fulfillmentHandler, rejectionHandler) {\n try {\n then$$1.call(value, fulfillmentHandler, rejectionHandler);\n } catch (e) {\n return e;\n }\n}\n\nfunction handleForeignThenable(promise, thenable, then$$1) {\n asap(function (promise) {\n var sealed = false;\n var error = tryThen(then$$1, thenable, function (value) {\n if (sealed) {\n return;\n }\n sealed = true;\n if (thenable !== value) {\n resolve(promise, value);\n } else {\n fulfill(promise, value);\n }\n }, function (reason) {\n if (sealed) {\n return;\n }\n sealed = true;\n\n reject(promise, reason);\n }, 'Settle: ' + (promise._label || ' unknown promise'));\n\n if (!sealed && error) {\n sealed = true;\n reject(promise, error);\n }\n }, promise);\n}\n\nfunction handleOwnThenable(promise, thenable) {\n if (thenable._state === FULFILLED) {\n fulfill(promise, thenable._result);\n } else if (thenable._state === REJECTED) {\n reject(promise, thenable._result);\n } else {\n subscribe(thenable, undefined, function (value) {\n return resolve(promise, value);\n }, function (reason) {\n return reject(promise, reason);\n });\n }\n}\n\nfunction handleMaybeThenable(promise, maybeThenable, then$$1) {\n if (maybeThenable.constructor === promise.constructor && then$$1 === then && maybeThenable.constructor.resolve === resolve$1) {\n handleOwnThenable(promise, maybeThenable);\n } else {\n if (then$$1 === TRY_CATCH_ERROR) {\n reject(promise, TRY_CATCH_ERROR.error);\n TRY_CATCH_ERROR.error = null;\n } else if (then$$1 === undefined) {\n fulfill(promise, maybeThenable);\n } else if (isFunction(then$$1)) {\n handleForeignThenable(promise, maybeThenable, then$$1);\n } else {\n fulfill(promise, maybeThenable);\n }\n }\n}\n\nfunction resolve(promise, value) {\n if (promise === value) {\n reject(promise, selfFulfillment());\n } else if (objectOrFunction(value)) {\n handleMaybeThenable(promise, value, getThen(value));\n } else {\n fulfill(promise, value);\n }\n}\n\nfunction publishRejection(promise) {\n if (promise._onerror) {\n promise._onerror(promise._result);\n }\n\n publish(promise);\n}\n\nfunction fulfill(promise, value) {\n if (promise._state !== PENDING) {\n return;\n }\n\n promise._result = value;\n promise._state = FULFILLED;\n\n if (promise._subscribers.length !== 0) {\n asap(publish, promise);\n }\n}\n\nfunction reject(promise, reason) {\n if (promise._state !== PENDING) {\n return;\n }\n promise._state = REJECTED;\n promise._result = reason;\n\n asap(publishRejection, promise);\n}\n\nfunction subscribe(parent, child, onFulfillment, onRejection) {\n var _subscribers = parent._subscribers;\n var length = _subscribers.length;\n\n\n parent._onerror = null;\n\n _subscribers[length] = child;\n _subscribers[length + FULFILLED] = onFulfillment;\n _subscribers[length + REJECTED] = onRejection;\n\n if (length === 0 && parent._state) {\n asap(publish, parent);\n }\n}\n\nfunction publish(promise) {\n var subscribers = promise._subscribers;\n var settled = promise._state;\n\n if (subscribers.length === 0) {\n return;\n }\n\n var child = void 0,\n callback = void 0,\n detail = promise._result;\n\n for (var i = 0; i < subscribers.length; i += 3) {\n child = subscribers[i];\n callback = subscribers[i + settled];\n\n if (child) {\n invokeCallback(settled, child, callback, detail);\n } else {\n callback(detail);\n }\n }\n\n promise._subscribers.length = 0;\n}\n\nfunction tryCatch(callback, detail) {\n try {\n return callback(detail);\n } catch (e) {\n TRY_CATCH_ERROR.error = e;\n return TRY_CATCH_ERROR;\n }\n}\n\nfunction invokeCallback(settled, promise, callback, detail) {\n var hasCallback = isFunction(callback),\n value = void 0,\n error = void 0,\n succeeded = void 0,\n failed = void 0;\n\n if (hasCallback) {\n value = tryCatch(callback, detail);\n\n if (value === TRY_CATCH_ERROR) {\n failed = true;\n error = value.error;\n value.error = null;\n } else {\n succeeded = true;\n }\n\n if (promise === value) {\n reject(promise, cannotReturnOwn());\n return;\n }\n } else {\n value = detail;\n succeeded = true;\n }\n\n if (promise._state !== PENDING) {\n // noop\n } else if (hasCallback && succeeded) {\n resolve(promise, value);\n } else if (failed) {\n reject(promise, error);\n } else if (settled === FULFILLED) {\n fulfill(promise, value);\n } else if (settled === REJECTED) {\n reject(promise, value);\n }\n}\n\nfunction initializePromise(promise, resolver) {\n try {\n resolver(function resolvePromise(value) {\n resolve(promise, value);\n }, function rejectPromise(reason) {\n reject(promise, reason);\n });\n } catch (e) {\n reject(promise, e);\n }\n}\n\nvar id = 0;\nfunction nextId() {\n return id++;\n}\n\nfunction makePromise(promise) {\n promise[PROMISE_ID] = id++;\n promise._state = undefined;\n promise._result = undefined;\n promise._subscribers = [];\n}\n\nfunction validationError() {\n return new Error('Array Methods must be provided an Array');\n}\n\nvar Enumerator = function () {\n function Enumerator(Constructor, input) {\n this._instanceConstructor = Constructor;\n this.promise = new Constructor(noop);\n\n if (!this.promise[PROMISE_ID]) {\n makePromise(this.promise);\n }\n\n if (isArray(input)) {\n this.length = input.length;\n this._remaining = input.length;\n\n this._result = new Array(this.length);\n\n if (this.length === 0) {\n fulfill(this.promise, this._result);\n } else {\n this.length = this.length || 0;\n this._enumerate(input);\n if (this._remaining === 0) {\n fulfill(this.promise, this._result);\n }\n }\n } else {\n reject(this.promise, validationError());\n }\n }\n\n Enumerator.prototype._enumerate = function _enumerate(input) {\n for (var i = 0; this._state === PENDING && i < input.length; i++) {\n this._eachEntry(input[i], i);\n }\n };\n\n Enumerator.prototype._eachEntry = function _eachEntry(entry, i) {\n var c = this._instanceConstructor;\n var resolve$$1 = c.resolve;\n\n\n if (resolve$$1 === resolve$1) {\n var _then = getThen(entry);\n\n if (_then === then && entry._state !== PENDING) {\n this._settledAt(entry._state, i, entry._result);\n } else if (typeof _then !== 'function') {\n this._remaining--;\n this._result[i] = entry;\n } else if (c === Promise$1) {\n var promise = new c(noop);\n handleMaybeThenable(promise, entry, _then);\n this._willSettleAt(promise, i);\n } else {\n this._willSettleAt(new c(function (resolve$$1) {\n return resolve$$1(entry);\n }), i);\n }\n } else {\n this._willSettleAt(resolve$$1(entry), i);\n }\n };\n\n Enumerator.prototype._settledAt = function _settledAt(state, i, value) {\n var promise = this.promise;\n\n\n if (promise._state === PENDING) {\n this._remaining--;\n\n if (state === REJECTED) {\n reject(promise, value);\n } else {\n this._result[i] = value;\n }\n }\n\n if (this._remaining === 0) {\n fulfill(promise, this._result);\n }\n };\n\n Enumerator.prototype._willSettleAt = function _willSettleAt(promise, i) {\n var enumerator = this;\n\n subscribe(promise, undefined, function (value) {\n return enumerator._settledAt(FULFILLED, i, value);\n }, function (reason) {\n return enumerator._settledAt(REJECTED, i, reason);\n });\n };\n\n return Enumerator;\n}();\n\n/**\n `Promise.all` accepts an array of promises, and returns a new promise which\n is fulfilled with an array of fulfillment values for the passed promises, or\n rejected with the reason of the first passed promise to be rejected. It casts all\n elements of the passed iterable to promises as it runs this algorithm.\n\n Example:\n\n ```javascript\n let promise1 = resolve(1);\n let promise2 = resolve(2);\n let promise3 = resolve(3);\n let promises = [ promise1, promise2, promise3 ];\n\n Promise.all(promises).then(function(array){\n // The array here would be [ 1, 2, 3 ];\n });\n ```\n\n If any of the `promises` given to `all` are rejected, the first promise\n that is rejected will be given as an argument to the returned promises's\n rejection handler. For example:\n\n Example:\n\n ```javascript\n let promise1 = resolve(1);\n let promise2 = reject(new Error(\"2\"));\n let promise3 = reject(new Error(\"3\"));\n let promises = [ promise1, promise2, promise3 ];\n\n Promise.all(promises).then(function(array){\n // Code here never runs because there are rejected promises!\n }, function(error) {\n // error.message === \"2\"\n });\n ```\n\n @method all\n @static\n @param {Array} entries array of promises\n @param {String} label optional string for labeling the promise.\n Useful for tooling.\n @return {Promise} promise that is fulfilled when all `promises` have been\n fulfilled, or rejected if any of them become rejected.\n @static\n*/\nfunction all(entries) {\n return new Enumerator(this, entries).promise;\n}\n\n/**\n `Promise.race` returns a new promise which is settled in the same way as the\n first passed promise to settle.\n\n Example:\n\n ```javascript\n let promise1 = new Promise(function(resolve, reject){\n setTimeout(function(){\n resolve('promise 1');\n }, 200);\n });\n\n let promise2 = new Promise(function(resolve, reject){\n setTimeout(function(){\n resolve('promise 2');\n }, 100);\n });\n\n Promise.race([promise1, promise2]).then(function(result){\n // result === 'promise 2' because it was resolved before promise1\n // was resolved.\n });\n ```\n\n `Promise.race` is deterministic in that only the state of the first\n settled promise matters. For example, even if other promises given to the\n `promises` array argument are resolved, but the first settled promise has\n become rejected before the other promises became fulfilled, the returned\n promise will become rejected:\n\n ```javascript\n let promise1 = new Promise(function(resolve, reject){\n setTimeout(function(){\n resolve('promise 1');\n }, 200);\n });\n\n let promise2 = new Promise(function(resolve, reject){\n setTimeout(function(){\n reject(new Error('promise 2'));\n }, 100);\n });\n\n Promise.race([promise1, promise2]).then(function(result){\n // Code here never runs\n }, function(reason){\n // reason.message === 'promise 2' because promise 2 became rejected before\n // promise 1 became fulfilled\n });\n ```\n\n An example real-world use case is implementing timeouts:\n\n ```javascript\n Promise.race([ajax('foo.json'), timeout(5000)])\n ```\n\n @method race\n @static\n @param {Array} promises array of promises to observe\n Useful for tooling.\n @return {Promise} a promise which settles in the same way as the first passed\n promise to settle.\n*/\nfunction race(entries) {\n /*jshint validthis:true */\n var Constructor = this;\n\n if (!isArray(entries)) {\n return new Constructor(function (_, reject) {\n return reject(new TypeError('You must pass an array to race.'));\n });\n } else {\n return new Constructor(function (resolve, reject) {\n var length = entries.length;\n for (var i = 0; i < length; i++) {\n Constructor.resolve(entries[i]).then(resolve, reject);\n }\n });\n }\n}\n\n/**\n `Promise.reject` returns a promise rejected with the passed `reason`.\n It is shorthand for the following:\n\n ```javascript\n let promise = new Promise(function(resolve, reject){\n reject(new Error('WHOOPS'));\n });\n\n promise.then(function(value){\n // Code here doesn't run because the promise is rejected!\n }, function(reason){\n // reason.message === 'WHOOPS'\n });\n ```\n\n Instead of writing the above, your code now simply becomes the following:\n\n ```javascript\n let promise = Promise.reject(new Error('WHOOPS'));\n\n promise.then(function(value){\n // Code here doesn't run because the promise is rejected!\n }, function(reason){\n // reason.message === 'WHOOPS'\n });\n ```\n\n @method reject\n @static\n @param {Any} reason value that the returned promise will be rejected with.\n Useful for tooling.\n @return {Promise} a promise rejected with the given `reason`.\n*/\nfunction reject$1(reason) {\n /*jshint validthis:true */\n var Constructor = this;\n var promise = new Constructor(noop);\n reject(promise, reason);\n return promise;\n}\n\nfunction needsResolver() {\n throw new TypeError('You must pass a resolver function as the first argument to the promise constructor');\n}\n\nfunction needsNew() {\n throw new TypeError(\"Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.\");\n}\n\n/**\n Promise objects represent the eventual result of an asynchronous operation. The\n primary way of interacting with a promise is through its `then` method, which\n registers callbacks to receive either a promise's eventual value or the reason\n why the promise cannot be fulfilled.\n\n Terminology\n -----------\n\n - `promise` is an object or function with a `then` method whose behavior conforms to this specification.\n - `thenable` is an object or function that defines a `then` method.\n - `value` is any legal JavaScript value (including undefined, a thenable, or a promise).\n - `exception` is a value that is thrown using the throw statement.\n - `reason` is a value that indicates why a promise was rejected.\n - `settled` the final resting state of a promise, fulfilled or rejected.\n\n A promise can be in one of three states: pending, fulfilled, or rejected.\n\n Promises that are fulfilled have a fulfillment value and are in the fulfilled\n state. Promises that are rejected have a rejection reason and are in the\n rejected state. A fulfillment value is never a thenable.\n\n Promises can also be said to *resolve* a value. If this value is also a\n promise, then the original promise's settled state will match the value's\n settled state. So a promise that *resolves* a promise that rejects will\n itself reject, and a promise that *resolves* a promise that fulfills will\n itself fulfill.\n\n\n Basic Usage:\n ------------\n\n ```js\n let promise = new Promise(function(resolve, reject) {\n // on success\n resolve(value);\n\n // on failure\n reject(reason);\n });\n\n promise.then(function(value) {\n // on fulfillment\n }, function(reason) {\n // on rejection\n });\n ```\n\n Advanced Usage:\n ---------------\n\n Promises shine when abstracting away asynchronous interactions such as\n `XMLHttpRequest`s.\n\n ```js\n function getJSON(url) {\n return new Promise(function(resolve, reject){\n let xhr = new XMLHttpRequest();\n\n xhr.open('GET', url);\n xhr.onreadystatechange = handler;\n xhr.responseType = 'json';\n xhr.setRequestHeader('Accept', 'application/json');\n xhr.send();\n\n function handler() {\n if (this.readyState === this.DONE) {\n if (this.status === 200) {\n resolve(this.response);\n } else {\n reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']'));\n }\n }\n };\n });\n }\n\n getJSON('/posts.json').then(function(json) {\n // on fulfillment\n }, function(reason) {\n // on rejection\n });\n ```\n\n Unlike callbacks, promises are great composable primitives.\n\n ```js\n Promise.all([\n getJSON('/posts'),\n getJSON('/comments')\n ]).then(function(values){\n values[0] // => postsJSON\n values[1] // => commentsJSON\n\n return values;\n });\n ```\n\n @class Promise\n @param {Function} resolver\n Useful for tooling.\n @constructor\n*/\n\nvar Promise$1 = function () {\n function Promise(resolver) {\n this[PROMISE_ID] = nextId();\n this._result = this._state = undefined;\n this._subscribers = [];\n\n if (noop !== resolver) {\n typeof resolver !== 'function' && needsResolver();\n this instanceof Promise ? initializePromise(this, resolver) : needsNew();\n }\n }\n\n /**\n The primary way of interacting with a promise is through its `then` method,\n which registers callbacks to receive either a promise's eventual value or the\n reason why the promise cannot be fulfilled.\n ```js\n findUser().then(function(user){\n // user is available\n }, function(reason){\n // user is unavailable, and you are given the reason why\n });\n ```\n Chaining\n --------\n The return value of `then` is itself a promise. This second, 'downstream'\n promise is resolved with the return value of the first promise's fulfillment\n or rejection handler, or rejected if the handler throws an exception.\n ```js\n findUser().then(function (user) {\n return user.name;\n }, function (reason) {\n return 'default name';\n }).then(function (userName) {\n // If `findUser` fulfilled, `userName` will be the user's name, otherwise it\n // will be `'default name'`\n });\n findUser().then(function (user) {\n throw new Error('Found user, but still unhappy');\n }, function (reason) {\n throw new Error('`findUser` rejected and we're unhappy');\n }).then(function (value) {\n // never reached\n }, function (reason) {\n // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'.\n // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'.\n });\n ```\n If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream.\n ```js\n findUser().then(function (user) {\n throw new PedagogicalException('Upstream error');\n }).then(function (value) {\n // never reached\n }).then(function (value) {\n // never reached\n }, function (reason) {\n // The `PedgagocialException` is propagated all the way down to here\n });\n ```\n Assimilation\n ------------\n Sometimes the value you want to propagate to a downstream promise can only be\n retrieved asynchronously. This can be achieved by returning a promise in the\n fulfillment or rejection handler. The downstream promise will then be pending\n until the returned promise is settled. This is called *assimilation*.\n ```js\n findUser().then(function (user) {\n return findCommentsByAuthor(user);\n }).then(function (comments) {\n // The user's comments are now available\n });\n ```\n If the assimliated promise rejects, then the downstream promise will also reject.\n ```js\n findUser().then(function (user) {\n return findCommentsByAuthor(user);\n }).then(function (comments) {\n // If `findCommentsByAuthor` fulfills, we'll have the value here\n }, function (reason) {\n // If `findCommentsByAuthor` rejects, we'll have the reason here\n });\n ```\n Simple Example\n --------------\n Synchronous Example\n ```javascript\n let result;\n try {\n result = findResult();\n // success\n } catch(reason) {\n // failure\n }\n ```\n Errback Example\n ```js\n findResult(function(result, err){\n if (err) {\n // failure\n } else {\n // success\n }\n });\n ```\n Promise Example;\n ```javascript\n findResult().then(function(result){\n // success\n }, function(reason){\n // failure\n });\n ```\n Advanced Example\n --------------\n Synchronous Example\n ```javascript\n let author, books;\n try {\n author = findAuthor();\n books = findBooksByAuthor(author);\n // success\n } catch(reason) {\n // failure\n }\n ```\n Errback Example\n ```js\n function foundBooks(books) {\n }\n function failure(reason) {\n }\n findAuthor(function(author, err){\n if (err) {\n failure(err);\n // failure\n } else {\n try {\n findBoooksByAuthor(author, function(books, err) {\n if (err) {\n failure(err);\n } else {\n try {\n foundBooks(books);\n } catch(reason) {\n failure(reason);\n }\n }\n });\n } catch(error) {\n failure(err);\n }\n // success\n }\n });\n ```\n Promise Example;\n ```javascript\n findAuthor().\n then(findBooksByAuthor).\n then(function(books){\n // found books\n }).catch(function(reason){\n // something went wrong\n });\n ```\n @method then\n @param {Function} onFulfilled\n @param {Function} onRejected\n Useful for tooling.\n @return {Promise}\n */\n\n /**\n `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same\n as the catch block of a try/catch statement.\n ```js\n function findAuthor(){\n throw new Error('couldn't find that author');\n }\n // synchronous\n try {\n findAuthor();\n } catch(reason) {\n // something went wrong\n }\n // async with promises\n findAuthor().catch(function(reason){\n // something went wrong\n });\n ```\n @method catch\n @param {Function} onRejection\n Useful for tooling.\n @return {Promise}\n */\n\n\n Promise.prototype.catch = function _catch(onRejection) {\n return this.then(null, onRejection);\n };\n\n /**\n `finally` will be invoked regardless of the promise's fate just as native\n try/catch/finally behaves\n \n Synchronous example:\n \n ```js\n findAuthor() {\n if (Math.random() > 0.5) {\n throw new Error();\n }\n return new Author();\n }\n \n try {\n return findAuthor(); // succeed or fail\n } catch(error) {\n return findOtherAuther();\n } finally {\n // always runs\n // doesn't affect the return value\n }\n ```\n \n Asynchronous example:\n \n ```js\n findAuthor().catch(function(reason){\n return findOtherAuther();\n }).finally(function(){\n // author was either found, or not\n });\n ```\n \n @method finally\n @param {Function} callback\n @return {Promise}\n */\n\n\n Promise.prototype.finally = function _finally(callback) {\n var promise = this;\n var constructor = promise.constructor;\n\n if (isFunction(callback)) {\n return promise.then(function (value) {\n return constructor.resolve(callback()).then(function () {\n return value;\n });\n }, function (reason) {\n return constructor.resolve(callback()).then(function () {\n throw reason;\n });\n });\n }\n\n return promise.then(callback, callback);\n };\n\n return Promise;\n}();\n\nPromise$1.prototype.then = then;\nPromise$1.all = all;\nPromise$1.race = race;\nPromise$1.resolve = resolve$1;\nPromise$1.reject = reject$1;\nPromise$1._setScheduler = setScheduler;\nPromise$1._setAsap = setAsap;\nPromise$1._asap = asap;\n\n/*global self*/\nfunction polyfill() {\n var local = void 0;\n\n if (typeof global !== 'undefined') {\n local = global;\n } else if (typeof self !== 'undefined') {\n local = self;\n } else {\n try {\n local = Function('return this')();\n } catch (e) {\n throw new Error('polyfill failed because global object is unavailable in this environment');\n }\n }\n\n var P = local.Promise;\n\n if (P) {\n var promiseToString = null;\n try {\n promiseToString = Object.prototype.toString.call(P.resolve());\n } catch (e) {\n // silently ignored\n }\n\n if (promiseToString === '[object Promise]' && !P.cast) {\n return;\n }\n }\n\n local.Promise = Promise$1;\n}\n\n// Strange compat..\nPromise$1.polyfill = polyfill;\nPromise$1.Promise = Promise$1;\n\nreturn Promise$1;\n\n})));\n\n\n\n//# sourceMappingURL=es6-promise.map\n","// This file can be required in Browserify and Node.js for automatic polyfill\n// To use it: require('es6-promise/auto');\n'use strict';\nmodule.exports = require('./').polyfill();\n","import \"es6-promise/auto\";\nimport { Signal } from \"../signal/Signal\";\n\n\ninterface ProgressSignal {\n\tloaded:number,\n\ttotal:number\n}\n\n/**\n * HttpRequest Class\n */\n\nexport class HttpRequest {\n\n\tprotected _method:string = 'GET';\n\tprotected _url:string;\n\tprotected _headers:{} = null;\n\tprotected request:XMLHttpRequest;\n\n\t/** @event */\n\tpublic progress:Signal = new Signal();\n\n\n\t/**\n\t * Create a new instance with the given url\n\t * @param url\n\t */\n\tconstructor( url:string ) {\n\t\tthis._url = url;\n\n\t\tthis.request = new XMLHttpRequest();\n\t\tthis.request.onprogress = ( event ) => {\n\t\t\tthis.progress.dispatch( event );\n\t\t}\n\t}\n\n\t/**\n\t * Set the method for the request\n\t * @param method\n\t */\n\tpublic method( method:string ):HttpRequest {\n\t\tthis._method = method;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Set the headers for the request\n\t * @param headers\n\t */\n\tpublic headers( headers:{} ):HttpRequest {\n\t\tthis._headers = headers;\n\t\treturn this\n\t}\n\n\t/**\n\t * Send/Load the request without sending data\n\t */\n\tpublic load():Promise {\n\t\treturn this.sendRequest().then( this.parseJson );\n\t}\n\n\t/**\n\t * Send the request with the given data\n\t * @param data\n\t */\n\tpublic send( data:any ):Promise {\n\t\treturn this.sendRequest( data ).then( this.parseJson );\n\t}\n\n\tpublic url():string {\n\t\treturn this._url;\n\t}\n\n\t/**\n\t * Open and send the request with the given parameters\n\t * and data\n\t * @param data\n\t */\n\tprivate sendRequest( data:any = null ):Promise {\n\n\t\tvar request = this.request;\n\t\tvar promise = this.promise( request );\n\n\t\trequest.open( this._method, this._url );\n\n\t\tfor( var key in this._headers ){\n\t\t\trequest.setRequestHeader( key, this._headers[key] );\n\t\t}\n\n\t\trequest.send( data );\n\n\t\treturn promise;\n\t}\n\n\t/**\n\t * Create a promise with the request\n\t * The promise resolves in case of a successful request - jejects otherwise\n\t */\n\tprivate promise( request:XMLHttpRequest ) {\n\t\treturn new Promise( ( resolve, reject ) => {\n\n\t\t\tvar errorHandler = function() {\n\t\t\t\tRequest.error.dispatch( { error: request.statusText } );\n\t\t\t\treject( Error( request.statusText ) );\n\t\t\t}\n\n\t\t\trequest.onload = function() {\n\t\t\t\tif( request.status >= 200 && request.status < 300 ) {\n\t\t\t\t\tresolve( request.responseText );\n\t\t\t\t} else {\n\t\t\t\t\terrorHandler();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\trequest.onerror = errorHandler;\n\t\t});\n\t}\n\n\t/**\n\t * tries to parse response otherwise returns original string data\n\t */\n\tprivate parseJson( data:string ):string|{} {\n\t\ttry {\n\t\t\tdata = JSON.parse( data )\n\t\t\treturn data;\n\t\t} catch( e ) {\n\t\t\treturn data;\n\t\t}\n\t}\n}\n\ninterface ErrorSignal {\n\terror:string\n}\n\n/**\n * Static Request Class\n */\nexport class Request {\n\n\t/** @event */\n\tpublic static error:Signal = new Signal();\n\t/**\n\t * Creates a new post HttpRequest\n\t */\n\tpublic static post( url:string ):HttpRequest{\n\t\treturn new HttpRequest( url ).method( 'POST' );\n\t}\n\n\t/**\n\t * Creates a new get HttpRequest\n\t */\n\tpublic static get( url:string ):HttpRequest{\n\t\treturn new HttpRequest( url ).method( 'GET' );\n\t}\n\n\t/**\n\t * Creates a new put HttpRequest\n\t */\n\tpublic static put( url:string ):HttpRequest{\n\t\treturn new HttpRequest( url ).method( 'PUT' );\n\t}\n\n\t/**\n\t * Creates a new delete HttpRequest\n\t */\n\tpublic static delete( url:string ):HttpRequest{\n\t\treturn new HttpRequest( url ).method( 'DELETE' );\n\t}\n}\n\n\nexport default Request;\n","/**\n * A class to register closure functions under a given key\n * ...\n */\nclass IoC{\n\n\tprivate map:{ [index:string]: T };\n\n\tconstructor(){\n\t\tthis.map = {};\n\t}\n\n\t/**\n\t * Registers the given closure under the given key\n\t * @param key The key to register the closure\n\t * @param closure The closure function\n\t */\n\tpublic add( key:string, closure:T ){\n\t\tthis.map[ key ] = closure;\n\t}\n\n\t/**\n\t * Returns the registered closure under the given key\n\t * @param key The key of registerd closure to look for\n\t * @return The closure under the given key or undefined, if\n\t * the key does not exist\n\t */\n\tpublic get( key:string ):T{\n\t\tvar tmp = this.map[ key ];\n\t\ttmp = ( tmp ) ? tmp : this.map[ 'default' ];\n\n\t\tif( !tmp ) throw new Error( \"No key with name: '\" + key + \"' is registered and no default fallback is defined on ioc.\" );\n\n\t\treturn tmp;\n\t}\n\n\t/**\n\t * Returns this key is registered allready\n\t * @param key The key to check if it is registered allready\n\t */\n\tpublic has( key:string ):boolean{\n\t\treturn this.map[ key ] != undefined;\n\t}\n\n\t/**\n\t * Returns all registered keys\n\t * @return Array of all the registered keys\n\t */\n\tpublic keys():string[] {\n\t\treturn Object.keys( this.map );\n\t}\n\n\t/**\n\t * Creates an alias for an already registered closure\n\t * @param newName The alias name\n\t * @param oldName The name of the already registered function\n\t */\n\tpublic alias( newName:string, oldName:string ) {\n\t\tthis.map[ newName ] = this.map[ oldName ];\n\t}\n\n\t/**\n\t * Renames an already registered closure to a new name\n\t * @param newName The new name\n\t * @param oldName The old registered name\n\t */\n\tpublic rename( newName:string, oldName:string ) {\n\t\tthis.alias( newName, oldName );\n\t\tdelete this.map[ oldName ];\n\t}\n}\n\nexport default IoC;\n","import IoC from '../ioc/IoC';\nimport Model from './Model';\nimport { isType } from '../js';\n\nexport interface ModelFactoryFunction {\n\t( json:Object ):any\n}\n\nexport interface JsonFactoryFunction {\n\t( model:Model ):Object\n}\n\n/**\n * A class that helps to map models on a json structure\n */\nclass Mapper {\n\n\tpublic toModel:IoC = new IoC();\n\tpublic toJson:IoC = new IoC();\n\n\tpublic jsonLookup:( json:Object ) => string;\n\tpublic modelLookup:( model:Model ) => string;\n\n\n\tconstructor() {\n\n\t\t// setup default json to model conversion.\n\t\tthis.toModel.add( 'default', function( json:Object, data?:any ) {\n\t\t\treturn json;\n\t\t});\n\n\t\t// setup default model to json conversion\n\t\tthis.toJson.add( 'default', function( model:Model, data?:any ) {\n\t\t\treturn model;\n\t\t});\n\n\t\t// setup default lookup function for json\n\t\tthis.jsonLookup = function( json:Object ) {\n\t\t\treturn json[\"modelName\"];\n\t\t}\n\n\t\t// setup default lookup function for models\n\t\tthis.modelLookup = function( model:Model ) {\n\t\t\treturn ( model instanceof Model ) ? model.get( 'modelName' ) : 'default';\n\t\t}\n\t}\n\n\n\tpublic model( json:any ) {\n\n\t\t// if primitive type is given simply return it\n\t\tif( isType( json, [ \"String\", \"Date\", \"RegExp\", \"Function\", \"Boolean\", \"Number\", \"Null\", \"Undefined\" ] ) ) {\n\t\t\treturn json;\n\t\t}\n\n\t\t// if json array is given map each\n\t\tif( isType( json, \"Array\" ) ) {\n\t\t\treturn ( json as Array ).map( ( item ) => {\n\t\t\t\treturn this.model( item );\n\t\t\t});\n\t\t}\n\n\t\t// Object given make recursion over keys\n\t\tObject.keys( json ).forEach( ( name ) => {\n\t\t\tvar value = json[ name ];\n\n\t\t\t// only follow object or array references\n\t\t\tif( isType( value, [ \"Object\", \"Array\" ] ) ) json[ name ] = this.model( value );\n\t\t});\n\n\t\t// Finally turn object into model with ioc\n\t\treturn this.toModel.get( this.jsonLookup( json ) )( json );\n\t}\n\n\n\tpublic json( model:any ) {\n\n\t\t// if primitive type is given simply return it\n\t\tif( isType( model, [ \"String\", \"Date\", \"RegExp\", \"Function\", \"Boolean\", \"Number\", \"Null\", \"Undefined\" ] ) ) {\n\t\t\treturn model;\n\t\t}\n\n\t\t// if json array is given map each\n\t\tif( isType( model, \"Array\" ) ) {\n\t\t\treturn ( model as Array ).map( ( item ) => {\n\t\t\t\treturn this.json( item );\n\t\t\t});\n\t\t}\n\n\t\t// try to convert it with ioc\n\t\tmodel = this.toJson.get( this.modelLookup( model ) )( model );\n\n\t\t// if object given make recursion over keys\n\t\tObject.keys( model ).forEach( ( name ) => {\n\t\t\tmodel[ name ] = this.json( model[ name ] );\n\t\t});\n\n\t\t// any other types simply return\n\t\treturn model;\n\t}\n}\n\nexport var mapper = new Mapper();\n\nexport default Mapper;\n","\nexport interface AssetConfig {\n\turl: string,\n\ttype?: \"js\" | \"css\",\n}\n\nexport class Asset {\n\n\t// store which assets are already loaded.\n\tstatic promises:{ [index:string]: Promise } = {};\n\n\tconfig:AssetConfig;\n\n\n\tconstructor( config:AssetConfig ) {\n\t\tif( !config.type ) config.type = this.guessType( config.url );\n\t\tthis.config = config;\n\t}\n\n\n\tload():Promise {\n\n\t\t// if not loaded create promise\n\t\tif( !Asset.promises[ this.config.url ] ) {\n\t\t\t( this.config.type == \"js\" ) ? this.loadScript() : this.loadCSS();\n\t\t}\n\n\t\treturn Asset.promises[ this.config.url ];\n\t}\n\n\t/**\n\t * Loads a js file into dom\n\t */\n\tprivate loadScript() {\n\n\t\tvar url = this.config.url;\n\n\t\tAsset.promises[ url ] = new Promise( function( resolve, reject ) {\n\t\t\tvar element = document.createElement( 'script' );\n\t\t\telement.src = url;\n\t\t\telement.addEventListener( 'load', resolve );\n\t\t\telement.addEventListener( 'error', reject );\n\t\t\tdocument.body.appendChild( element );\n\t\t}).then( function( event:Event ) {\n\t\t\tthis.finalize( url );\n\t\t\treturn event;\n\t\t}.bind( this ));\n\t}\n\n\t/**\n\t * Loads a css file into the dom\n\t */\n\tprivate loadCSS() {\n\n\t\tvar url = this.config.url;\n\n\t\tAsset.promises[ url ] = new Promise( function( resolve, reject ) {\n\t\t\tvar element = document.createElement( 'link' );\n\t\t\telement.type = 'text/css';\n\t\t\telement.rel = 'stylesheet';\n\t\t\telement.href = url;\n\t\t\telement.addEventListener( 'load', resolve );\n\t\t\telement.addEventListener( 'error', reject );\n\t\t\tdocument.head.appendChild( element );\n\t\t}).then( function( event:Event ) {\n\t\t\tthis.finalize( url );\n\t\t\treturn event;\n\t\t}.bind( this ));\n\t}\n\n\tprivate finalize( url:string ) {\n\t\tAsset[ url ] = new Promise( function( resolve, reject ) { resolve() } );\n\t}\n\n\t/**\n\t * Guesses the type based on the given url\n\t */\n\tprivate guessType( url:string ):\"js\"|\"css\" {\n\n\t\tif( url.split('.').pop() == \"js\" ) return \"js\";\n\t\tif( url.split('.').pop() == \"css\" ) return \"css\";\n\n\t\treturn \"js\";\n\t}\n}\n\nexport default Asset;\n","import LookupObject from '../lookup/LookupObject';\nimport { HttpRequest } from '../request/Request';\nimport { mapper } from '../model/Mapper';\nimport Asset from './Asset';\nimport { renderer } from '../view/Renderer';\n\nexport interface SetupConfig {\n\troutes?:{ [key:string]:{ url:string, method?:string, headers?:string } },\n\tdata?:{ [key:string]:{} },\n\tassets?:{ [key:string]:{ url:string, type?:'js'|'css' } },\n}\n\n/**\n * A class that manages external routes, data and assets.\n */\nexport class Setup {\n\n\tprivate lookup:LookupObject;\n\n\tconstructor() {\n\t\tthis.lookup = new LookupObject( { data:{}, assets:{}, routes:{} } );\n\t}\n\n\tinit( data:SetupConfig ) {\n\t\tthis.lookup.replace( data );\n\t\tmapper.model( data.data );\n\t\trenderer.context.setup = this;\n\t}\n\n\t/**\n\t * Returns a request that can load an save data to the url defined in the configuration\n\t * @param key The key under the routes definition\n\t * @param urlParams The parameters for the url\n\t */\n\troute( key:string, urlParams:{} = {} ):HttpRequest {\n\n\t\tvar config = this.search( \"routes.\" + key );\n\t\tvar url = renderer.render( config.url, urlParams );\n\t\tvar request = new HttpRequest( url );\n\n\t\tif( config.method ) request.method( config.method );\n\t\tif( config.headers ) request.headers( config.headers );\n\n\t\treturn request;\n\t}\n\n\t/**\n\t * Returns any data that is defined under the data configuration\n\t */\n\tdata( key?:string ):any {\n\t\tif( key === undefined ) return this.search( 'data' );\n\t\treturn this.search( \"data.\" + key );\n\t}\n\n\t/**\n\t * Returns a asset loader that can load additional scripts and css files.\n\t */\n\tasset( key:string ):Asset {\n\t\treturn new Asset( this.search( \"assets.\" + key ) );\n\t}\n\n\tprivate search( key ):any {\n\t\tvar config = this.lookup.lookup( key );\n\t\tif( typeof config === 'undefined' ) throw new Error( \"Could not find definition for api with key: \" + key );\n\t\treturn config;\n\t}\n}\n\n\nexport var setup = new Setup();\nexport default Setup;\n","import Template from './Template';\nimport { isAttributeChangeObservable } from '../model/Model';\nimport { setup } from '../setup/Setup';\n\n\nexport interface ViewConstructor {\n\tnew( config:ViewConfig ):View;\n}\n\nexport interface ViewDefinition {\n\ttemplate:string;\n\tregistrations?:ViewRegistrations;\n\tgetData?():TData;\n\tinit?( this: View ):void;\n\tupdate?( this:View, name?:string ):void;\n}\n\nexport interface ViewFactory {\n\t():View;\n}\n\nexport interface ViewRegistrations {\n\t[ name:string ]:ViewConstructor|ViewDefinition|ViewFactory;\n}\n\nfunction convertToViewFactory( registration:ViewConstructor|ViewDefinition|ViewFactory ):ViewFactory {\n\n\tif( isViewDefinition( registration ) ) {\n\t\tconst viewClass = class extends View {};\n\t\tif( registration.init ) {\n\t\t\tviewClass.prototype['init'] = registration.init;\n\t\t}\n\t\tif( registration.update ) {\n\t\t\tviewClass.prototype['update'] = registration.update;\n\t\t}\n\t\treturn () => new viewClass({ ...registration, data:registration.getData && registration.getData() });\n\t}\n\telse if( isViewConstructor( registration ) ) {\n\t\treturn () => new registration({});\n\t}\n\telse {\n\t\treturn registration;\n\t}\n\n\tfunction isViewDefinition( registration:ViewConstructor|ViewDefinition|ViewFactory ):registration is ViewDefinition {\n\t\treturn typeof registration === 'object';\n\t}\n\n\tfunction isViewConstructor( registration:ViewConstructor|ViewFactory ):registration is ViewConstructor {\n\t\tfor ( let proto = Object.getPrototypeOf( registration ); proto; proto = Object.getPrototypeOf( proto ) ) {\n\t\t\tif( proto === View ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n}\n\n\nconst registrations:ViewRegistrations = {};\n\n\n/**\n * Deprecated. Use `register` instead.\n * @deprecated */\nexport const ioc = new class {\n\n\t/** Deprecated. Use `ioc[name] = factory` instead.\n\t * @deprecated\n\t */\n\tpublic add( name:string, factory:ViewFactory ):void {\n\t\tregistrations[ name ] = factory;\n\t}\n\n\t/** Deprecated. Use `ioc[name]` instead.\n\t * @deprecated\n\t*/\n\tpublic has( name:string ):boolean {\n\t\treturn name in registrations;\n\t}\n\n\t/** Deprecated. Use `name in ioc` instead.\n\t * @deprecated\n\t*/\n\tpublic get( name:string ):ViewConstructor|ViewDefinition|ViewFactory {\n\t\treturn registrations[ name ];\n\t}\n};\n\n\n/**\n * Registers the `View` class specified by `constructor` under the given `name`\n * such that it can be instantiated in templates using e.g. `
`.\n *\n * ### Example:\n *\n * @example\n```typescript\n class Foo extends View { ... }\n register('Foo', Foo);\n```\n *\n * Once thus registered, you will be able to instantiate `Foo` in templates e.g. as follows:\n *\n```html\n
\n```\n *\n * @param name The registration name which should be associated with the given `View` class.\n * @param constructorOrFactory The `View` class to associate with `name`, or a parameterless closure (of type `ViewFactory`) that creates a `View` instance.\n */\nexport function register( name:string, constructorOrFactory:ViewConstructor|ViewFactory );\n\n/**\n * Registers an ad-hoc `View` class created from the specified `definition` under the given `name`\n * such that it can be instantiated in templates using e.g. `
`.\n *\n * For simple views, this overload can spare you the work of writing a full-blown class.\n *\n * ### Example:\n *\n * @example\n```typescript\n register('Foo', {\n template: `
Greetings, [[name]].
`,\n data: {\n name: 'stranger'\n }\n });\n```\n *\n * Once thus registered, you will be able to instantiate `Foo` in templates e.g. as follows:\n *\n```html\n
\n```\n *\n * ### Remarks:\n *\n * Note that data binding will not work for the above component because `data` is a plain object\n * whose properties will not dispatch `change` signals. If you want data binding to work,\n * set `data` to an instance of `Model` instead of a plain object.\n *\n * @param name The registration name which should be associated with the ad-hoc `View` class.\n * @param definition Definition of the ad-hoc `View` class. You must specify at least its `template`.\n */\nexport function register( name:string, definition:ViewDefinition );\n\n/**\n * Registers the specified view registrations.\n *\n * @param registrations The registrations to register.\n */\nexport function register( registrations:ViewRegistrations ):void;\n\nexport function register( nameOrRegistrations:string|ViewRegistrations, registration?:ViewConstructor|ViewDefinition|ViewFactory ) {\n\tif( typeof nameOrRegistrations === 'string' ) {\n\t\tregistrations[nameOrRegistrations] = convertToViewFactory( registration );\n\t}\n\telse {\n\t\tfor( const name in nameOrRegistrations ) {\n\t\t\tconst registration = nameOrRegistrations[ name ];\n\t\t\tif( typeof registration === 'object' ) {\n\t\t\t\tregister( name, registration );\n\t\t\t}\n\t\t\telse {\n\t\t\t\tregister(name, registration );\n\t\t\t}\n\t\t}\n\t}\n}\n\nexport function scan( root:Element, registrations?:ViewRegistrations ) {\n\tvar temp = new View( { data:setup.data(), registrations } );\n\ttemp.render( root );\n}\n\nexport interface ViewConfig {\n\tdata?:TData,\n\tregistrations?:ViewRegistrations,\n\ttemplate?:string\n}\n\n/**\n * A common view class that has a container to render content/template into.\n */\nexport class View {\n\n\tprotected _data:TData;\n\n\tpublic template:Template;\n\tpublic parent:View<{}>;\n\tpublic readonly registrations:ViewRegistrations;\n\n\tconstructor( config:ViewConfig ) {\n\n\t\tthis.registrations = config.registrations;\n\n\t\tthis.template = new Template( config.template );\n\t\tthis.template.viewFactory = this.createChild.bind( this );\n\t\tthis.template.dataFactory = () => this._data;\n\n\t\tthis._data = config.data;\n\t}\n\n\n\t/**\n\t * Renders the view template.\n\t * If an empty target is given, the template is rendered into to given target.\n\t * If the target is not empty, the content of the target is used as the template.\n\t */\n\tpublic render( target?:Element ) {\n\n\t\tthis.template.render( target );\n\n\t\t// register databinding if model is given\n\t\tif( isAttributeChangeObservable( this.data ) ) {\n\t\t\tthis.data.change.subscribe( ( change ) => {\n\t\t\t\tthis.update( change.name );\n\t\t\t});\n\t\t}\n\n\t\t// everything is ready now we can invoke view's init\n\t\tthis.init();\n\t}\n\n\t/**\n\t * The init function is automatically called after the render function.\n\t * So everything is rendered and the node is ready to be used.\n\t * Overwrite the init function for custom dom manipulations.\n\t */\n\tprotected init() {\n\n\t}\n\n\n\t/**\n\t * Returns the root node of the view\n\t */\n\tpublic get node():Element {\n\t\treturn this.template.root;\n\t}\n\n\t/**\n\t * Updates the view if data attribute has changed\n\t */\n\tpublic update( name?:string ) {\n\t\tthis.template.update( this._data, name );\n\t}\n\n\tpublic child( name:string ):T {\n\t\treturn this.template.first( name ) as T;\n\t}\n\n\tpublic createChild( type:string ) {\n\t\tvar view = convertToViewFactory( this.resolve( type ) )();\n\t\tview.parent = this;\n\t\treturn view;\n\t}\n\n\tset data( data:TData ) {\n\t\tthis._data = data;\n\t}\n\tget data():TData {\n\t\treturn this._data;\n\t}\n\n\tprivate resolve( name:string ):ViewConstructor|ViewDefinition|ViewFactory {\n\t\tif( this.registrations && name in this.registrations ) {\n\t\t\treturn this.registrations[ name ];\n\t\t}\n\t\telse if( this.parent ) {\n\t\t\treturn this.parent.resolve( name );\n\t\t}\n\t\telse if( name in registrations ) {\n\t\t\treturn registrations[ name ];\n\t\t}\n\t\telse if( name !== 'default' ) {\n\t\t\treturn this.resolve( 'default' );\n\t\t}\n\t\telse {\n\t\t\tthrow new Error( `There is no view registration named '${name}', nor is there a 'default' fallback.` );\n\t\t}\n\t}\n}\n\nexport default View;\n","export type CompletionStatus = 'completed' | 'incomplete' | 'not attempted' | 'unknown';\nexport type SuccessStatus = 'passed' | 'failed' | 'unknown';\nexport type Exit = 'timeout' | 'suspend' | 'logout' | 'normal' | '';\n\n/**\n * Common class for all SCORM API versions\n */\n abstract class Api {\n\n\tprotected connection: any = null;\n\tprotected startTime: Date;\n\n\tconstructor( connection:any ) {\n\t\tthis.connection = connection;\n\t}\n\n\tpublic start():boolean {\n\n\t\tthis.initialize();\n\t\tthis.score = 0;\n\t\tthis.minScore = 0;\n\t\tthis.maxScore = 100;\n\n\t\tthis.startTime = new Date();\n\t\treturn true;\n\t}\n\n\tpublic finish() {\n\n\t\t// set session time.\n\t\tlet now = new Date();\n\t\tthis.sessionTime = new Date( now.getTime() - this.startTime.getTime() )\n\n\t\t// set the exit attribute to 'suspend' in order to force the lms to store and reload the data in the next attempt\n\t\tthis.exit = 'suspend';\n\n\t\t// terminate session\n\t\tthis.terminate();\n\t}\n\n\t/**\n\t * Begins a communication session with the LMS.\n\t */\n\tabstract initialize():boolean;\n\n\t/**\n\t * Ends a communication session with the LMS.\n\t */\n\tabstract terminate();\n\n\t /**\n\t * Commits/Stores values set with setValue (some LMS (1.2) seem to needs this)\n\t */\n\tabstract commit():boolean;\n\n\n\t/**\n\t * Sets a value to the LMS.\n\t * @param element Possible values see: http://scorm.com/scorm-explained/technical-scorm/run-time/run-time-reference/\n\t * @param value The value\n\t */\n\tabstract setValue( element: string, value: string ): string;\n\t/**\n\t * Retrieves a value from the LMS\n\t * @param element Possible values see: http://scorm.com/scorm-explained/technical-scorm/run-time/run-time-reference/\n\t */\n\n\tabstract getValue( element: string ):string;\n\tabstract getLastError():string;\n\tabstract getErrorString( errorCode: string ):string;\n\tabstract getDiagnostic( errorCode: string ):string;\n\n\n\t/**\n\t * Sets the score\n\t * @param score Number that reflects the performance of the learner relative to the range bounded by the values of min and max\n\t */\n\tabstract set score( score: number );\n\n\t/** \n\t * Gets the score\n\t */\n\tabstract get score(): number;\n\n\t/**\n\t * Setus the maximum score\n\t * @param maxScore Maximum value in the range for the score\n\t */\n\tabstract set maxScore( maxScore: number );\n\n\t/**\n\t * Gets the maximum score\n\t */\n\tabstract get maxScore(): number;\n\n\t/**\n\t * Setus the minimum score\n\t * @param minScore Minimum value in the range for the score\n\t */\n\tabstract set minScore( minScore: number );\n\n\t/**\n\t * Gets the minimum score\n\t */\n\tabstract get minScore(): number;\n\n\t/**\n\t * Set the completion status\n\t * @param CompletionStatus Indicates whether the learner has completed the SCO\n\t */\n\tabstract set completionStatus( completionStatus: CompletionStatus );\n\n\t/**\n\t * Gets the completion status\n\t */\n\tabstract get completionStatus():CompletionStatus;\n\n\t/**\n\t * Sets the success status\n\t * @param successStatus SuccessStatus Indicates whether the learner has mastered the SCO\n\t */\n\tabstract set successStatus( successStatus: SuccessStatus );\n\n\t/**\n\t * Gets the success status\n\t */\n\tabstract get successStatus(): SuccessStatus;\n\n\t/**\n\t * Sets the exit value\n\t * @param exit Exit Indicates how or why the learner left the SCO\n\t */\n\tabstract set exit( exit: Exit );\n\t/**\n\t * Sets the elapsed session time\n\t */\n\tabstract set sessionTime( now: Date );\n\n\t/**\n\t * Sets the location value\n\t * @param l string The learner’s current location in the SCO\n\t */\n\tabstract set location( l: string );\n\n\t/**\n\t * Gets the location value\n\t */\n\tabstract get location(): string;\n\n\t/**\n\t * Sets the suspend data value\n\t * @param d string Provides space to store and retrieve data between learner sessions\n\t */\n\tabstract set suspendData( d: string );\n\n\t/**\n\t * Gets the suspend data value\n\t */\n\tabstract get suspendData(): string;\n\n\n\t\n}\n\nexport function searchConnection( name:string ) {\n\tvar connection = scanFor( window, name, 10 );\n\treturn ( connection ) ? connection : scanFor( window.opener, name, 10 );\n}\n\nfunction scanFor( obj:any, name:string, iteration:number = 10 ) {\n\t// nothing found \n\tif( !obj ) return null;\n\n\t// test if we can access the obj property - cross-origin issue\n\ttry { \n\t\tobj[name]\n\t} catch( e ) {\n\t\t// if there is an exception - no success\n\t\treturn null;\n\t}\n\n\t// test we found it\n\tif( obj[name] ) return obj[name];\n\n\t// test if iterations are over\n\tif( iteration == 0 ) return null;\n\t// test if there is no parent anymore\n\tif( obj.parent == null ) return null;\n\n\treturn scanFor( obj.parent, name, --iteration );\n}\n\nexport default Api;\n","import Api, { CompletionStatus, SuccessStatus, Exit, searchConnection } from \"./API\";\n\nclass Api1_2 extends Api {\n\n\n\t/**\n\t * Begins a communication session with the LMS.\n\t */\n\tinitialize():boolean {\n\t\treturn this.connection.LMSInitialize('');\n\t}\n\t\n\t/**\n\t * Ends a communication session with the LMS.\n\t */\n\tterminate() {\n\t\treturn this.connection.LMSFinish('');\n\t}\n\t\n\t/**\n\t * Commits/Stores values set with setValue (some LMS (1.2) seem to needs this)\n\t */\n\tcommit():boolean{\n\t\treturn this.connection.LMSCommit('');\n\t}\n\t\n\t\n\t/**\n\t * Sets a value to the LMS.\n\t * @param element Possible values see: http://scorm.com/scorm-explained/technical-scorm/run-time/run-time-reference/\n\t * @param value The value\n\t */\n\tsetValue( element: string, value: string ): string {\n\t\treturn this.connection.LMSSetValue( element, value );\n\t}\n\t/**\n\t * Retrieves a value from the LMS\n\t * @param element Possible values see: http://scorm.com/scorm-explained/technical-scorm/run-time/run-time-reference/\n\t */\n\t\n\tgetValue( element: string ):string {\n\t\treturn this.connection.LMSGetValue( element );\n\t}\n\t\n\tgetLastError():string {\n\t\treturn this.connection.LMSGetLastError('');\n\t\t\n\t}\n\tgetErrorString( errorCode: string ):string {\n\t\treturn this.connection.LMSGetErrorString( errorCode );\n\t}\n\t\n\tgetDiagnostic( errorCode: string ):string {\n\t\treturn this.connection.LMSGetDiagnostic( errorCode );\n\t}\n\n\n\t/**\n\t * Sets the score\n\t * @param score Number that reflects the performance of the learner relative to the range bounded by the values of min and max\n\t */\n\tset score( score: number ) {\n\t\tthis.setValue( 'cmi.core.score.raw', score.toString() );\n\t}\n\t\n\t/** \n\t * Gets the score\n\t */\n\tget score(): number {\n\t\treturn parseInt( this.getValue( 'cmi.core.score.raw' ) );\n\t}\n\t\n\t/**\n\t * Setus the maximum score\n\t * @param maxScore Maximum value in the range for the score\n\t */\n\tset maxScore( maxScore: number ) {\n\t\tthis.setValue( 'cmi.core.score.max', maxScore.toString() );\n\t}\n\t\n\t/**\n\t * Gets the maximum score\n\t */\n\tget maxScore(): number {\n\t\treturn parseInt( this.getValue( 'cmi.core.score.max' ) );\n\t}\n\t\n\t/**\n\t * Setus the minimum score\n\t * @param minScore Minimum value in the range for the score\n\t */\n\tset minScore( minScore: number ) {\n\t\tthis.setValue( 'cmi.core.score.min', minScore.toString() );\n\t}\n\t\n\t/**\n\t * Gets the minimum score\n\t */\n\tget minScore(): number {\n\t\treturn parseInt( this.getValue( 'cmi.core.score.min' ) );\n\t}\n\t\n\t/**\n\t * Set the completion status\n\t * @param CompletionStatus Indicates whether the learner has completed the SCO\n\t */\n\tset completionStatus( completionStatus:CompletionStatus ) {\n\t\tthis.setValue( 'cmi.core.lesson_status', completionStatus );\n\t}\n\t\n\t/**\n\t * Gets the completion status\n\t */\n\tget completionStatus():CompletionStatus {\n\t\treturn this.getValue( 'cmi.core.lesson_status' ) as CompletionStatus;\n\t}\n\t\n\t/**\n\t * Sets the success status\n\t * @param successStatus SuccessStatus Indicates whether the learner has mastered the SCO\n\t */\n\tset successStatus( successStatus: SuccessStatus ) {\n\t\tthis.setValue( 'cmi.core.lesson_status', successStatus );\n\t}\n\t\n\t/**\n\t * Gets the success status\n\t */\n\tget successStatus(): SuccessStatus {\n\t\treturn this.getValue( 'cmi.core.lesson_status' ) as SuccessStatus;\n\t}\n\t\n\t/**\n\t * Sets the exit value\n\t * @param exit Exit Indicates how or why the learner left the SCO\n\t */\n\tset exit( exit: Exit ) {\n\t\tthis.setValue( 'cmi.core.exit', exit );\n\t}\n\t\n\t/**\n\t * Sets the elapsed session time\n\t */\n\tset sessionTime( time: Date ) {\n\t\tthis.setValue( 'cmi.core.session_time', 'PT' + time.getHours() + 'H' + time.getMinutes() + 'M' + time.getSeconds() + 'S' );\n\t}\n\t\n\t/**\n\t * Sets the location value\n\t * @param l string The learner’s current location in the SCO\n\t */\n\tset location( l: string ) {\n\t\tthis.setValue( 'cmi.core.lesson_location', l );\n\t}\n\t\n\t/**\n\t * Gets the location value\n\t */\n\tget location(): string {\n\t\treturn this.getValue( 'cmi.core.lesson_location' );\n\t}\n\t\n\t/**\n\t * Sets the suspend data value\n\t * @param d string Provides space to store and retrieve data between learner sessions\n\t */\n\tset suspendData( d: string ) {\n\t\tthis.setValue( 'cmi.suspend_data', d );\n\t}\n\t\n\t/**\n\t * Gets the suspend data value\n\t */\n\tget suspendData(): string {\n\t\treturn this.getValue( 'cmi.suspend_data' );\n\t}\n\n\tstatic find() {\n\t\tvar connection = searchConnection( 'API' );\n\t\treturn ( connection ) ? new Api1_2( connection ) : null;\n\t}\n}\n\nexport default Api1_2;\n\n","import Api, { CompletionStatus, SuccessStatus, Exit, searchConnection } from \"./API\";\n\nclass Api2004 extends Api {\n\n\n\t/**\n\t * Begins a communication session with the LMS.\n\t */\n\tinitialize():boolean {\n\t\treturn this.connection.Initialize('');\n\t}\n\t\n\t/**\n\t * Ends a communication session with the LMS.\n\t */\n\tterminate() {\n\t\treturn this.connection.Terminate('');\n\t}\n\t\n\t/**\n\t * Commits/Stores values set with setValue (some LMS (1.2) seem to needs this)\n\t */\n\tcommit():boolean{\n\t\treturn this.connection.Commit('');\n\t}\n\t\n\t\n\t/**\n\t * Sets a value to the LMS.\n\t * @param element Possible values see: http://scorm.com/scorm-explained/technical-scorm/run-time/run-time-reference/\n\t * @param value The value\n\t */\n\tsetValue( element: string, value: string ): string {\n\t\treturn this.connection.SetValue( element, value );\n\t}\n\t/**\n\t * Retrieves a value from the LMS\n\t * @param element Possible values see: http://scorm.com/scorm-explained/technical-scorm/run-time/run-time-reference/\n\t */\n\t\n\tgetValue( element: string ):string {\n\t\treturn this.connection.GetValue( element );\n\t}\n\t\n\tgetLastError():string {\n\t\treturn this.connection.GetLastError('');\n\t\t\n\t}\n\tgetErrorString( errorCode: string ):string {\n\t\treturn this.connection.GetErrorString( errorCode );\n\t}\n\t\n\tgetDiagnostic( errorCode: string ):string {\n\t\treturn this.connection.GetDiagnostic( errorCode );\n\t}\n\n\n\t/**\n\t * Sets the score\n\t * @param score Number that reflects the performance of the learner relative to the range bounded by the values of min and max\n\t */\n\tset score( score: number ) {\n\t\tthis.setValue( 'cmi.score.raw', score.toString() );\n\t}\n\t\n\t/** \n\t * Gets the score\n\t */\n\tget score(): number {\n\t\treturn parseInt( this.getValue( 'cmi.score.raw' ) );\n\t}\n\t\n\t/**\n\t * Setus the maximum score\n\t * @param maxScore Maximum value in the range for the score\n\t */\n\tset maxScore( maxScore: number ) {\n\t\tthis.setValue( 'cmi.score.max', maxScore.toString() );\n\t}\n\t\n\t/**\n\t * Gets the maximum score\n\t */\n\tget maxScore(): number {\n\t\treturn parseInt( this.getValue( 'cmi.score.max' ) );\n\t}\n\t\n\t/**\n\t * Setus the minimum score\n\t * @param minScore Minimum value in the range for the score\n\t */\n\tset minScore( minScore: number ) {\n\t\tthis.setValue( 'cmi.score.min', minScore.toString() );\n\t}\n\t\n\t/**\n\t * Gets the minimum score\n\t */\n\tget minScore(): number {\n\t\treturn parseInt( this.getValue( 'cmi.score.min' ) );\n\t}\n\t\n\t/**\n\t * Set the completion status\n\t * @param CompletionStatus Indicates whether the learner has completed the SCO\n\t */\n\tset completionStatus( completionStatus:CompletionStatus ) {\n\t\tthis.setValue( 'cmi.completion_status', completionStatus );\n\t}\n\t\n\t/**\n\t * Gets the completion status\n\t */\n\tget completionStatus():CompletionStatus {\n\t\treturn this.getValue( 'cmi.completion_status' ) as CompletionStatus;\n\t}\n\t\n\t/**\n\t * Sets the success status\n\t * @param successStatus SuccessStatus Indicates whether the learner has mastered the SCO\n\t */\n\tset successStatus( successStatus: SuccessStatus ) {\n\t\tthis.setValue( 'cmi.success_status', successStatus );\n\t}\n\t\n\t/**\n\t * Gets the success status\n\t */\n\tget successStatus(): SuccessStatus {\n\t\treturn this.getValue( 'cmi.success_status' ) as SuccessStatus;\n\t}\n\t\n\t/**\n\t * Sets the exit value\n\t * @param exit Exit Indicates how or why the learner left the SCO\n\t */\n\tset exit( exit: Exit ) {\n\t\tthis.setValue( 'cmi.exit', exit );\n\t}\n\t\n\t/**\n\t * Sets the elapsed session time\n\t */\n\tset sessionTime( time: Date ) {\n\t\tthis.setValue( 'cmi.session_time', 'PT' + time.getHours() + 'H' + time.getMinutes() + 'M' + time.getSeconds() + 'S' );\n\t}\n\t\n\t/**\n\t * Sets the location value\n\t * @param l string The learner’s current location in the SCO\n\t */\n\tset location( l: string ) {\n\t\tthis.setValue( 'cmi.location', l );\n\t}\n\t\n\t/**\n\t * Gets the location value\n\t */\n\tget location(): string {\n\t\treturn this.getValue( 'cmi.location' );\n\t}\n\t\n\t/**\n\t * Sets the suspend data value\n\t * @param d string Provides space to store and retrieve data between learner sessions\n\t */\n\tset suspendData( d: string ) {\n\t\tthis.setValue( 'cmi.suspend_data', d );\n\t}\n\t\n\t/**\n\t * Gets the suspend data value\n\t */\n\tget suspendData(): string {\n\t\treturn this.getValue( 'cmi.suspend_data' );\n\t}\n\n\tstatic find() {\n\t\tvar connection = searchConnection( 'API_1484_11' );\n\t\treturn ( connection ) ? new Api2004( connection ) : null;\n\t}\n}\n\nexport default Api2004;\n\n","import Api, { CompletionStatus, SuccessStatus, Exit, searchConnection } from \"./API\";\n\nclass ApiDebug extends Api {\n\n\tconstructor( ) {\n\t\tsuper( null );\n\t\tthis.log( \"Could not find any SCORM Api switch to Debug mode\" );\n\t}\n\n\t/**\n\t * Begins a communication session with the LMS.\n\t */\n\tinitialize():boolean {\n\t\tthis.log( 'Initialize' );\n\t\treturn true;\n\t}\n\t\n\t/**\n\t * Ends a communication session with the LMS.\n\t */\n\tterminate() {\n\t\tthis.log( 'Terminate' );\n\t}\n\t\n\t/**\n\t * Commits/Stores values set with setValue (some LMS (1.2) seem to needs this)\n\t */\n\tcommit():boolean {\n\t\tthis.log( 'Commit' );\n\t\treturn true;\n\t}\n\t\n\t\n\t/**\n\t * Sets a value to the LMS.\n\t * @param element Possible values see: http://scorm.com/scorm-explained/technical-scorm/run-time/run-time-reference/\n\t * @param value The value\n\t */\n\tsetValue( element: string, value: string ): string {\n\t\tthis.log( \"SetValue: \", element, value );\n\t\treturn value;\n\t}\n\t/**\n\t * Retrieves a value from the LMS\n\t * @param element Possible values see: http://scorm.com/scorm-explained/technical-scorm/run-time/run-time-reference/\n\t */\n\t\n\tgetValue( element: string ):string {\n\t\tthis.log( \"GetValue: \", element );\n\t\treturn \"\";\n\t}\n\t\n\tgetLastError():string {\n\t\tthis.log( \"GetLastError\");\n\t\treturn '';\n\t\t\n\t}\n\tgetErrorString( errorCode: string ):string {\n\t\tthis.log( \"GetErrorString: \", errorCode );\n\t\treturn '';\n\t}\n\t\n\tgetDiagnostic( errorCode: string ):string {\n\t\tthis.log( \"GetDiagnostic: \", errorCode );\n\t\treturn '';\n\t}\n\t\n\t\n\t/**\n\t * Sets the score\n\t * @param score Number that reflects the performance of the learner relative to the range bounded by the values of min and max\n\t */\n\tset score( score: number ) {\n\t\tthis.setValue( 'cmi.score.raw', score.toString() );\n\t}\n\t\n\t/** \n\t * Gets the score\n\t */\n\tget score(): number {\n\t\treturn parseInt( this.getValue( 'cmi.score.raw' ) );\n\t}\n\t\n\t/**\n\t * Setus the maximum score\n\t * @param maxScore Maximum value in the range for the score\n\t */\n\tset maxScore( maxScore: number ) {\n\t\tthis.setValue( 'cmi.score.max', maxScore.toString() );\n\t}\n\t\n\t/**\n\t * Gets the maximum score\n\t */\n\tget maxScore(): number {\n\t\treturn parseInt( this.getValue( 'cmi.score.max' ) );\n\t}\n\t\n\t/**\n\t * Setus the minimum score\n\t * @param minScore Minimum value in the range for the score\n\t */\n\tset minScore( minScore: number ) {\n\t\tthis.setValue( 'cmi.score.min', minScore.toString() );\n\t}\n\t\n\t/**\n\t * Gets the minimum score\n\t */\n\tget minScore(): number {\n\t\treturn parseInt( this.getValue( 'cmi.score.min' ) );\n\t}\n\t\n\t/**\n\t * Set the completion status\n\t * @param CompletionStatus Indicates whether the learner has completed the SCO\n\t */\n\tset completionStatus( completionStatus:CompletionStatus ) {\n\t\tthis.setValue( 'cmi.completion_status', completionStatus );\n\t}\n\t\n\t/**\n\t * Gets the completion status\n\t */\n\tget completionStatus():CompletionStatus {\n\t\treturn this.getValue( 'cmi.completion_status' ) as CompletionStatus;\n\t}\n\t\n\t/**\n\t * Sets the success status\n\t * @param successStatus SuccessStatus Indicates whether the learner has mastered the SCO\n\t */\n\tset successStatus( successStatus: SuccessStatus ) {\n\t\tthis.setValue( 'cmi.success_status', successStatus );\n\t}\n\t\n\t/**\n\t * Gets the success status\n\t */\n\tget successStatus(): SuccessStatus {\n\t\treturn this.getValue( 'cmi.success_status' ) as SuccessStatus;\n\t}\n\t\n\t/**\n\t * Sets the exit value\n\t * @param exit Exit Indicates how or why the learner left the SCO\n\t */\n\tset exit( exit: Exit ) {\n\t\tthis.setValue( 'cmi.exit', exit );\n\t}\n\t\n\t/**\n\t * Sets the elapsed session time\n\t */\n\tset sessionTime( time: Date ) {\n\t\tthis.setValue( 'cmi.session_time', 'PT' + time.getHours() + 'H' + time.getMinutes() + 'M' + time.getSeconds() + 'S' );\n\t}\n\t\n\t/**\n\t * Sets the location value\n\t * @param l string The learner’s current location in the SCO\n\t */\n\tset location( l: string ) {\n\t\tthis.setValue( 'cmi.location', l );\n\t}\n\t\n\t/**\n\t * Gets the location value\n\t */\n\tget location(): string {\n\t\treturn this.getValue( 'cmi.location' );\n\t}\n\t\n\t/**\n\t * Sets the suspend data value\n\t * @param d string Provides space to store and retrieve data between learner sessions\n\t */\n\tset suspendData( d: string ) {\n\t\tthis.setValue( 'cmi.suspend_data', d );\n\t}\n\t\n\t/**\n\t * Gets the suspend data value\n\t */\n\tget suspendData(): string {\n\t\treturn this.getValue( 'cmi.suspend_data' );\n\t}\n\n\tlog( ...args ) {\n\t\tconsole.log( ...args );\n\t}\n}\n\nexport default ApiDebug;\n\n","import Api from './scorm/Api';\nimport Api1_2 from './scorm/Api1_2';\nimport Api2004 from './scorm/Api2004';\nimport ApiDebug from './scorm/ApiDebug';\n\n/**\n * A connector that sends tracker data to the SCORM API. \n */\nclass Scorm {\n\n\tpublic api: Api;\n\n\tconstructor(api: Api) {\n\t\tthis.api = api;\n\t\tthis.start();\n\t}\n\n\n\tstart() {\n\n\t\tthis.api.start();\n\n\t\t// set the elapsed time and close session, when user closes window\n\t\twindow.addEventListener('beforeunload', (e: Event) => {\n\t\t\tthis.api.finish();\n\t\t});\n\t}\n\n\n\n\t/* trackSuspendData(renderer: SlideRenderer, root: any) {\n\t\t// register suspend data tracker\n\t\tvar tracker: SuspendData = new SuspendData(this, root);\n\t\trenderer.userInput.add(tracker.update.bind(tracker));\n\n\t\treturn tracker;\n\t} */\n\n\n\t/* trackLocation(renderer: SlideRenderer) {\n\n\t\t// register tracker\n\t\tvar tracker: Location = new Location(this);\n\t\trenderer.slideChanged.add(tracker.update.bind(tracker));\n\n\t\treturn tracker;\n\t} */\n\n\n\t/* trackVisibleProgress( renderer: SlideRenderer, threshold:number = 0.8 ) {\n\t\t// register tracker\n\t\tvar tracker: VisibleProgress = new VisibleProgress(this, threshold );\n\t\trenderer.slideChanged.add(tracker.update.bind(tracker));\n\n\t\treturn tracker;\n\t} */\n\n\n\t/* trackAnsweredProgress( renderer: SlideRenderer, threshold:number = 0.8 ) {\n\t\t// register tracker\n\t\tvar tracker: AnsweredProgress = new AnsweredProgress( this, threshold );\n\t\trenderer.userAnswered.add(tracker.update.bind(tracker));\n\n\t\treturn tracker;\n\t} */\n\n\tstatic find() {\n\n\t\t// search for apis\n\t\tvar api = Api1_2.find();\n\t\tif (!api) api = Api2004.find();\n\n\t\t// fallback to debugger\n\t\tif (!api) api = new ApiDebug();\n\n\t\tvar scorm = new Scorm(api);\n\t\treturn scorm;\n\t}\n}\n\nexport default Scorm;","import Scorm from './connector/Scorm';\n\nexport var ScormSingleton = Scorm.find();\n\nexport interface ISuspendData{\n chapters:{\n [id:string]:boolean,\n },\n attempts:number\n}\n\nexport var suspendData:{ data:ISuspendData } = { data: { chapters:{}, attempts:0 } };\n\nexport function updateSuspendData(){\n ScormSingleton.api.suspendData = JSON.stringify( suspendData.data );\n ScormSingleton.api.commit();\n}","import { Signal } from '../signal/Signal';\n\n\n/**\n * An interface that defines what is required as a source for the ListRenderer.\n */\nexport interface IList {\n\t/** @event */\n\tadded: Signal>;\n\t/** @event */\n\tfilled: Signal>;\n\t/** @event */\n\tremoved: Signal>;\n\t/** @event */\n\tsorted: Signal>;\n\tall(): T[];\n\tfill(data: T[]);\n}\n\n\n/**\n * Function interface for listeners on the 'add' Signal.\n */\nexport interface ListAddedListener {\n\tnewItem:T,\n\tindex?:number\n}\n\n/**\n * Function interface for listeners on the 'remove' Signal.\n */\nexport interface ListRemovedListener {\n\tremovedItem:T,\n\tindex:number\n}\n\n/**\n * Function interface for listeners on the 'filled' Signal.\n */\nexport interface ListFilledListener {\n\titems:T[]\n}\n\n\n/**\n * A generic representation of a list that throws event on add, remove and fill\n *\n */\nexport class List implements IList {\n\n\t/** @event */\n\tpublic added:Signal>;\n\t/** @event */\n\tpublic removed:Signal>;\n\t/** @event */\n\tpublic filled:Signal>;\n\t/** @event */\n\tpublic sorted:Signal>;\n\n\tprotected items:T[];\n\n\tconstructor( items?:T[] ) {\n\t\tthis.added = new Signal>();\n\t\tthis.removed = new Signal>();\n\t\tthis.filled = new Signal>();\n\t\tthis.sorted = new Signal>();\n\n\t\tthis.items = ( items ) ? items : [];\n\t}\n\n\t/**\n\t * Returns a copy of the internal array.\n\t */\n\tall():T[] {\n\t\treturn this.items.slice();\n\t}\n\n\t/**\n\t * Refill the list with items\n\t * @param items to fill the list with\n\t */\n\tfill( items:T[], silent:boolean = false ) {\n\t\tthis.items = items; // do not add the original array.\n\t\tif( !silent ) this.filled.dispatch( { items: items } );\n\t}\n\n\n\t/**\n\t * Adds an item to the list at the given index. If the index is outside of the array the item is appended at the end\n\t * @param item The item to be added\n\t * @param index The index at which the item is added.\n\t */\n\tadd( item:T, index:number ):number {\n\n\t\t// make sure index is in array length\n\t\tindex = Math.max( Math.min( index, this.items.length ), 0 );\n\n\t\tthis.items.splice( index, 0, item );\n\t\tthis.added.dispatch( { newItem: item, index: index } );\n\t\treturn index;\n\t}\n\n\t/**\n\t * Removes the item at the given index\n\t * @param index The index at which the item will be removed\n\t */\n\tremove( item:T ):boolean {\n\n\t\tvar index = this.index( item );\n\n\t\tif( index >= 0 ) return this.removeAt( index );\n\n\t\treturn false;\n\t}\n\n\t/**\n\t * Removes an item at the given index\n\t */\n\tremoveAt( index:number ):boolean {\n\n\t\tvar res = this.items.splice( index, 1 );\n\t\tvar item = res[0];\n\n\t\tif( item ) {\n\t\t\tthis.removed.dispatch( { removedItem: item, index: index } );\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t/**\n\t * Appends a new item to the list\n\t */\n\tappend( item:T ) {\n\t\tthis.add( item, this.items.length );\n\t}\n\n\t/**\n\t * Prepends a new item to the list\n\t */\n\tprepend( item:T ) {\n\t\tthis.add( item, 0 );\n\t}\n\n\t/**\n\t * Get the item with the given index\n\t * @param index The index of the item\n\t */\n\tget( index:number ):T {\n\t\treturn this.items[ index ];\n\t}\n\n\t/**\n\t * Returns the first item in the list\n\t */\n\tfirst():T {\n\t\treturn this.items[0];\n\t}\n\n\t/**\n\t * Returns the last item in the list\n\t */\n\tlast():T {\n\t\treturn this.items[ this.items.length - 1 ];\n\t}\n\n\t/**\n\t * Shortcut to empty the list\n\t */\n\tempty() {\n\t\tthis.fill( [] );\n\t}\n\n\t/**\n\t * Finds an element in the list with the given closure\n\t */\n\tfind( closure:( item:T, index?:number, array?:Array ) => boolean ) {\n\t\treturn this.all().filter( closure )[ 0 ];\n }\n\n\n\n\t/**\n\t * Returns the index of the given item\n\t */\n\tindex( searchItem:T ):number {\n\t\tvar index = -1;\n\t\tthis.items.forEach( ( item, i ) => {\n\t\t\tif( item === searchItem ) index = i;\n\t\t});\n\t\treturn index;\n\t}\n\n\t/**\n\t * Tests if the given item exists in the list\n\t */\n\tcontains( item:T ):boolean {\n\t\treturn this.index( item ) >= 0;\n\t}\n\n\t/**\n\t * Returns the length of the list\n\t */\n\tget length():number {\n\t\treturn this.items.length;\n\t}\n\n\t/**\n\t * Resorts the items based on the given array of items\n\t */\n\tsort( items:T[] ) {\n\n\t\t// check if items size match\n\t\t// no check for same instances...\n\t\tif( this.items.length != items.length ) throw \"Sort items should be the same size\";\n\n\t\tthis.items = items;\n\t\tthis.sorted.dispatch( { items: items } );\n\t}\n\n\t/**\n\t * Sorts the list by the closures return value\n\t */\n\tsortBy( closure:( item:T )=>any ) {\n\t\tvar items = this.items.map( function( x:T ) {\n\t\t\treturn [ x, closure( x ) ];\n\t\t}).sort(function (a, b) {\n\t\t\treturn a[1] < b[1] ? -1 : a[1] > b[1] ? 1 : 0;\n\t\t}).map(function (x) {\n\t\t\treturn x[0];\n\t\t});\n\t\tthis.sort( items );\n\t}\n}\n\nexport default List;\n","import { Signal } from '../signal/Signal';\nimport { IList, List, ListAddedListener, ListFilledListener, ListRemovedListener } from './List';\n\nexport interface ModifierClosure {\n\t( items:T[] ):T[]\n}\n/**\n * A generic representation of a modifiable (fiterable, sortable) list.\n *\n */\nexport class ModifiableList implements IList {\n\n\t/** @event */\n\tpublic added:Signal>;\n\t/** @event */\n\tpublic removed:Signal>;\n\t/** @event */\n\tpublic filled:Signal>;\n\t/** @event */\n\tpublic sorted:Signal>;\n\n\tpublic modifiers:List>;\n\tpublic originals:List;\n\n\tprivate cache:List;\n\n\tconstructor( items?:T[] ) {\n\n\t\tthis.added = new Signal>();\n\t\tthis.removed = new Signal>();\n\t\tthis.filled = new Signal>();\n\t\tthis.sorted = new Signal>();\n\n\t\tthis.modifiers = new List>();\n\t\tthis.modifiers.added.subscribe( this.onModifiersChanged.bind( this ) );\n\t\tthis.modifiers.removed.subscribe( this.onModifiersChanged.bind( this ) );\n\t\tthis.modifiers.filled.subscribe( this.onModifiersChanged.bind( this ) );\n\n\t\tthis.originals = new List( items );\n\t\tthis.originals.added.subscribe( this.onOriginalsAdded.bind( this ) );\n\t\tthis.originals.removed.subscribe( this.onOriginalsRemoved.bind( this ) );\n\t\tthis.originals.filled.subscribe( this.onOriginalsFilled.bind( this ) );\n\n\t\tthis.update();\n\t}\n\n\t/**\n\t * Returns only the modified items\n\t */\n\tall():T[] {\n\t\treturn this.cache.all();\n\t}\n\n\t/**\n\t * Delegate\n\t */\n\tfill( items:T[] ) {\n\t\tthis.originals.fill( items );\n\t}\n\n\t/**\n\t * Delegate\n\t */\n\tfind( closure:( item:T, index?:number, array?:Array ) => boolean ) {\n\t\treturn this.originals.find( closure );\n\t}\n\n\t/**\n\t * Delegate\n\t */\n\tsort( items:T[] ) {\n\t\tthis.originals.sort( items );\n\t\tthis.sorted.dispatch( { items: items } );\n\t}\n\n\t/**\n\t * forces to reapply modifiers\n\t */\n\tupdate() {\n\t\tthis.buildCache();\n\t\tthis.filled.dispatch( { items: this.cache.all() } );\n\t}\n\n\t/**\n\t * Callback when the modifies list has changed.\n\t */\n\tprivate onModifiersChanged() {\n\t\tthis.update();\n\t}\n\n\t/**\n\t * Callback when something is added to the originals\n\t * Check it needs to be added to the modified items\n\t */\n\tprivate onOriginalsAdded( event:{ newItem:T, index:number } ) {\n\t\tthis.buildCache();\n\n\t\t// check if it should be displayed\n\t\tvar modIndex = this.cache.index( event.newItem );\n\t\tif( modIndex >= 0 ) this.added.dispatch( { newItem:event.newItem, index:modIndex } );\n\t}\n\n\t/**\n\t * Callback when something is removed from the originals\n\t * Check it needs to be removed from the modified items\n\t */\n\tprivate onOriginalsRemoved( event:{ removedItem:T, index:number } ) {\n\n\t\tvar oldIndex = this.cache.index( event.removedItem );\n\n\t\tthis.buildCache();\n\n\t\tif( oldIndex >= 0 ) this.removed.dispatch( { removedItem: event.removedItem, index: oldIndex } );\n\t}\n\n\t/**\n\t * Callback when list is filled\n\t */\n\tprivate onOriginalsFilled( item:T[] ) {\n\t\tthis.onModifiersChanged();\n\t}\n\n\n\t/**\n\t * Updates the results of the modifications into the cache var\n\t */\n\tprivate buildCache() {\n\n\t\tvar data = this.originals.all();\n\t\tthis.modifiers.all().forEach( function( modifier ) {\n\t\t\tdata = modifier( data );\n\t\t});\n\n\t\tthis.cache = new List( data );\n\t}\n}\n\nexport default ModifiableList;\n","import IoC from '../ioc/IoC';\nimport Model from '../model/Model';\nimport { IList, List } from '../list/List';\nimport { ModifiableList } from '../list/ModifiableList';\n\n/**\n * Specific interface for closure function used in the ioc\n */\nexport interface IoCFactoryFunction {\n\t( item:T, index?:number ): { node:Element };\n}\n\n/**\n * A function that defines how to a map the registered keywords in the ioc with the item:T\n * Example if T is Model:\n * \t\tfunction( model:Model ) {\n * \t\t\treturn model.modelName;\n * \t\t}\n *\n */\nexport interface IoCSelectorFunction {\n\t( item: T ): string;\n}\n\n\n/**\n * An interface for links that combine the node and its item\n */\nexport interface ILink {\n\tnode: Node;\n\titem: T;\n}\n\n\n/** Abstract base class for `ListRenderer` and `ModifiableListRenderer`.\n *\n * @hidden */\nabstract class ListRendererBase {\n\n\tpublic ioc: IoC> = new IoC>();\n\tpublic selectorFunction: IoCSelectorFunction;\n\tpublic links = new List>();\n\tpublic container:Element;\n\n\tprivate _source: IList;\n\tprivate subscriptions:{};\n\n\tconstructor( initialSource: IList, container?: Element ) {\n\t\tthis.container = container;\n\n\t\t// the default selector function to use without ioc definitions.\n\t\tthis.selectorFunction = function( item:T ) {\n\t\t\treturn ( item instanceof Model ) ? item.get( 'modelName' ) : 'default';\n\t\t}\n\n\t\tthis.setSource(initialSource);\n\t}\n\n\t/** @hidden */\n\tprotected getSource(): IList {\n\t\treturn this._source;\n\t}\n\n\t/** @hidden */\n\tprotected setSource( items: IList ) {\n\t\tif( this._source ) this.removeListeners();\n\t\tthis._source = items;\n\t\tthis.addListeners();\n\n\t\tif( this.container ) this.onFilled( { items: items.all() } );\n\t}\n\n\tpublic defaultRender( closure:IoCFactoryFunction ) {\n\t\tthis.ioc.add( 'default', closure );\n\t}\n\n\tprotected addListeners(){\n\t\tthis.subscriptions = {\n\t\t\tfilled: this._source.filled.subscribe( this.onFilled.bind( this ) ),\n\t\t\tadded: this._source.added.subscribe( this.onAdded.bind( this ) ),\n\t\t\tremoved: this._source.removed.subscribe( this.onRemoved.bind( this ) ),\n\t\t\tsorted: this._source.sorted.subscribe( this.onSorted.bind( this ) ),\n\t\t};\n\t}\n\n\tprotected removeListeners() {\n\t\tObject.keys( this.subscriptions ).forEach( type => {\n\t\t\tthis.subscriptions[ type ].unsubscribe();\n\t\t});\n\t}\n\n\tprotected renderList( items:T[] ) {\n\n\t\tvar fragment = document.createDocumentFragment();\n\n\t\titems.forEach( function( item, index ) {\n\n\t\t\tvar obj = >this.ioc.get( this.selectorFunction( item ) )( item, index );\n\t\t\tobj.item = item; // inject item\n\t\t\tthis.links.append( obj );\n\n\t\t\t// add to fragment\n\t\t\tfragment.appendChild( obj.node );\n\t\t}, this);\n\n\t\t// append fragment to container.\n\t\tthis.container.appendChild( fragment );\n\t}\n\n\tprotected onFilled( event:{ items:T[] } ) {\n\t\t// remove all links\n\t\tthis.links.all().forEach( link => {\n\t\t\tlink.node.parentNode.removeChild( link.node );\n\t\t});\n\n\t\tthis.links.empty();\n\t\tthis.renderList( event.items );\n\t}\n\n\tprotected onAdded( event:{ newItem:T, index:number } ) {\n\t\tvar obj = > this.ioc.get( this.selectorFunction( event.newItem ) )( event.newItem, event.index );\n\t\tobj.item = event.newItem;\n\t\tthis.container.insertBefore( obj.node, this.container.childNodes[ event.index ] || null );\n\t\tthis.links.add( obj, event.index );\n\t}\n\n\tprotected onRemoved( event:{ removedItem:T, index:number } ) {\n\t\tvar link = this.links.get( event.index );\n\t\tthis.links.removeAt( event.index );\n\t\tthis.container.removeChild( link.node );\n\t\tlink.node = undefined;\n\t}\n\n\tprotected onSorted( event:{ items:T[] } ) {\n\t\tvar links = [];\n\t\tfor( var i = 0; i < event.items.length; i++ ) {\n\t\t\tvar link = this.linkOf( event.items[i] );\n\t\t\tthis.container.insertBefore( link.node, this.container.childNodes[ i ] || null );\n\t\t\tlinks.push( link );\n\t\t}\n\t\tthis.links.fill( links );\n\t}\n\n\tpublic linkOf( item:T | Node ):ILink {\n\n\t\t// define on which attribute to check\n\t\tvar attr = ( item instanceof Node ) ? \"node\" : \"item\";\n\n\t\treturn this.links.find( function( link ) {\n\t\t\treturn link[attr] === item;\n\t\t});\n\t}\n}\n\n\n/**\n * Renders a `List` list with items of type `T` into a template. Listens on list signals for rerendering.\n * The rendering of the list items is defined through an ioc for simpler usage with a render function.\n *\n *\n * ### Examples\n *\n *\n * #### Rendering a list of strings\n *\n * @example\n * ```typescript\n *\n * // Instantiate the ListRenderer and provide a node the listRenedrer is rendered to\n * const listRenderer = new ListRenderer( Node.js( 'targetNode' ) );\n *\n * // Define the closure a list item is rendered with\n * listRenderer.defaultRender( function( item:string ) {\n * \tconst myView = new MyView( item ).render();\n * \treturn { node: myView.node }\n * });\n *\n * // Fill in the source with items. This invokes the render function of the listRenderer\n * listRenderer.source.fill( [ 'one', 'two', 'three' ] );\n *\n * // Append a new element. The list is rerenderer after all list manipulations\n * listRenderer.source.append( 'four' );\n * ```\n *  \n *\n * #### Rendering models\n *\n * @example\n * ```typescript\n *\n * // Instantiate a ListRenderer with type \"Model\"\n * const listRenderer = new ListRenderer( Node.js( 'targetNode' ) );\n *\n * // Define how a Title model is rendered\n * listRenderer.renderer.ioc.add( 'Title', function( model:TitleModel ) {\n * \tconst titleView = new TitleView( model ).render();\n * \treturn { node: titleView.node }\n * });\n *\n * // Define how a Paragraph model is rendered\n * listRenderer.renderer.ioc.add( 'Paragraph', function( model:ParagraphModel ) {\n * \tconst paragraphView = new ParagraphView( model ).render();\n * \treturn { node: paragraphView.node }\n * });\n *\n * // Define how to distinguish between the models\n * // This step is optional in this case. The selectorFunction is predefined\n * listRenderer.selectorFunction = function( model:Model ) {\n * \treturn model.get( 'modelName' );\n * }\n *\n * // Fill the source of the ListRenderer with models.\n * listRenderer.source.fill( [ new TitleModel(), new ParagraphModel(), new ParagraphModel() ] )\n * ```\n *\n *\n * ### See also\n *\n * @see ModifiableListRenderer for a list renderer that uses a `ModifiableList` as its data source.\n */\nexport class ListRenderer extends ListRendererBase {\n\n\tconstructor(container?: Element) {\n\t\tsuper(new List([]), container);\n\t}\n\n\tget source(): List {\n\t\treturn super.getSource() as List;\n\t}\n\n\tset source(value: List) {\n\t\tsuper.setSource(value);\n\t}\n}\n\n\n/**\n * Renders a `ModifiableList` list with items of type `T` into a template. Listens on list signals for rerendering.\n * The rendering of the list items is defined through an ioc for simpler usage with a render function.\n *\n *\n * ### Example\n *\n *\n * #### Using a `ModifiableList` instead of a `List` as source\n *\n * @example\n * ```typescript\n *\n * // Instantiate a ModifiableListRenderer with type string, containing a source with type ModifiableList\n * const listRenderer = new ModifiableListRenderer( Node.js( \"content\" ) );\n *\n * // Define the closure a list item is rendererd with\n * listRenderer.defaultRender( function( item:string ) {\n *\t\tconst node = Node.fromTag( 'div' );\n *\t\tnode.html = item;\n *\t\treturn { node: node };\n *\t});\n *\n * // Instantiate a fresh ModifiableList as new source\n * listRenderer.source = new ModifiableList();\n *\n * // Fill in the source\n * listRenderer.source.fill( [ \"eins\", \"zwei\", \"drei\", \"vier\", \"fünf\", \"sechs\" ] );\n *\n * // Define a modifier for the ModifiableList\n * // Filter the list in order to display only items with less than 5 letters\n * // Appending a modifier applies the modifier and rerenders the list\n * listRenderer.source.modifiers.append( function( items ) {\n * \treturn items.filter( item => item.length < 5);\n * });\n * ```\n *\n *\n * ### See also\n *\n * @see ListRenderer for a list renderer that uses a `List` as its data source.\n */\nexport class ModifiableListRenderer extends ListRendererBase {\n\n\tconstructor(container?: Element) {\n\t\tsuper(new ModifiableList([]), container);\n\t}\n\n\tget source(): ModifiableList {\n\t\treturn super.getSource() as ModifiableList;\n\t}\n\n\tset source(value: ModifiableList) {\n\t\tsuper.setSource(value);\n\t}\n}\n\n\nexport default ListRenderer;\n","import Model, { isAttributeChangeObservable } from '../core/model/Model';\nimport ListRenderer from '../core/list/ListRenderer';\nimport View from '../core/view/View';\nimport { node } from '../core/node/Node';\nimport Template from '../core/view/Template';\n\n/**\n * A helper view that repeats its inner HTML once for each item of a given collection.\n * Set its `items` attribute to the collection, and specify the iteration variable's name in the `as` attribute.\n * Within the repaet block you can access the context of the component with parent\n *\n * ### Basic usage:\n *\n ```typescript\n
\n\t\n
\n ```\n */\nexport default class Repeat extends View {\n\n\titemTemplate:string;\n\trenderer:ListRenderer;\n\n\tconstructor() {\n\t\tsuper( { template:'', data:new RepeatModel( { as:'', items:[] } ) } );\n\t}\n\n\trender( target?:Element ) {\n\n\t\t// before render get inner html for item template.\n\t\tthis.itemTemplate = target.innerHTML;\n\t\ttarget.innerHTML = '';\n\n\t\tsuper.render( target );\n\t}\n\n\tinit() {\n\t\tthis.renderItems();\n\t\tthis.data.change.filter( c => c.name == 'items' ).subscribe( this.renderItems.bind( this ) );\n\t}\n\n\trenderItems() {\n\n\t\tnode( this.node ).empty();\n\n\n\t\t// check for valid array\n\t\tlet items = this.data.items;\n\t\tif( !Array.isArray( items ) ) return;\n\n\t\tthis.renderer = new ListRenderer( this.node );\n\t\tthis.renderer.defaultRender( ( item, index ) => {\n\t\t\tlet data = {\n\t\t\t\tparent:this.parent.data,\n\t\t\t\tindex:index,\n\t\t\t};\n\n\t\t\t// inject item\n\t\t\tdata[this.data.as] = item;\n\n\t\t\tvar temp = new Template( this.itemTemplate );\n\t\t\ttemp.viewFactory = ( type:string ) => this.parent.createChild( type );\n\t\t\ttemp.dataFactory = () => data;\n\t\t\ttemp.render();\n\n\t\t\t// setup proper updates with prefix name\n\t\t\tif( isAttributeChangeObservable( item ) ) {\n\t\t\t\titem.change.subscribe( ( change ) => {\n\t\t\t\t\ttemp.update( data, this.data.as + '.' + change.name );\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn { node: temp.root };\n\t\t} );\n\n\t\tthis.renderer.source.fill( items );\n\t}\n\n}\n\n\nclass RepeatModel extends Model {\n\tas:string;\n\titems:[];\n}\n","import View from 'ln/view/View';\nimport { node } from 'ln/node/Node';\n\n\n/**\n * THIS COPY OF THE RESOLVE CLASS FIXES THE APPENDCHILD BUG!\n */\n\n/**\n * If an object implements this interface, the `resolve` helper view will be able to\n * create a suitable `View` instance for it.\n *\n * #### Basic usage:\n *\n```typescript\n register('SomeView', class extends View { ... });\n\n class SomeViewModel implements Resolvable {\n public getViewName(): string {\n return 'SomeView';\n }\n }\n```\n *\n * #### See also:\n *\n * * The `register` function exported by the `.../view/View` module,\n * which is used to establish a relationship between a registration name\n * (as returned by `getViewName`) and a `View` class.\n */\nexport interface Resolvable {\n\t/**\n\t * Returns a registration name of the `View` class that should be used for this object.\n\t */\n\tgetViewName(): string;\n}\n\nfunction isResolvable(data: any): data is Resolvable {\n\treturn data && typeof data.getViewName !== 'undefined';\n}\n\n/**\n * A helper view that creates a suitable `View` instance for the given `data`.\n * `data` must implement a `getViewName(): string` method that returns the registration name\n * of the `View` class to use.\n *\n * #### Basic usage:\n *\n```html\n \n
\n```\n *\n * Don't forget to register the helper view before use, e.g. by importing this module:\n *\n```typescript\n import Resolve from '.../components/Resolve';\n register('resolve', Resolve);\n```\n *\n * #### See also:\n *\n * * The `Resolvable` interface exported by this module, which defines the contract\n * (i.e. the `getViewName(): string` method) that `data` objects must implement\n * in order to work together with this helper view.\n */\nexport class Resolve extends View {\n\n\tpublic constructor() {\n\t\tsuper({ template: '
' });\n\t}\n\n\tpublic get data(): Resolvable {\n\t\treturn this._data;\n\t}\n\n\tpublic set data(value: Resolvable) {\n\t\tif (!value) return;\n\t\tconst previousValue = this._data;\n\t\tthis._data = value;\n\t\tif (value !== previousValue) {\n\t\t\tthis.update();\n\t\t}\n\t}\n\n\tprotected init() {\n\t\tthis.update();\n\t}\n\n\tpublic update() {\n\t\tif (!this.node) return;\n\t\tconst viewName = isResolvable(this._data) ? this._data.getViewName() : 'default';\n\t\tconst view: View = this.createChild( viewName );\n\t\tif (view) {\n\t\t\tview.data = this._data;\n\t\t\tview.render();\n\t\t\tnode( this.node ).empty();\n\t\t\tthis.node.appendChild(view.node);\n\t\t}\n\t}\n}\n\n\nexport default Resolve;\n","import View from '../core/view/View';\nimport Model from '../core/model/Model';\nimport { node } from '../core/node/Node';\n\n/**\n * A helper view that simple renders html\n */\nexport default class Show extends View {\n\n\tprivate placeholder:Comment;\n\n\tconstructor( ) {\n\t\tsuper( { template:'', data:new ShowModel( { if:true } ) } );\n\n\t\tthis.placeholder = document.createComment('');\n\n\t\tthis.template.dataFactory = () => {\n\t\t\treturn this.parent.data;\n\t\t}\n\t}\n\n\tinit() {\n\t\tthis.checkVisibility();\n\n\t\tthis.data.change.filter( c => c.name == 'if' ).subscribe( this.onModelChange.bind( this ) );\n\t}\n\n\tonModelChange() {\n\t\tthis.checkVisibility();\n\t}\n\n\tcheckVisibility() {\n\t\tif( this.data.if && this.placeholder.parentNode ) node( this.placeholder ).replace( this.node );\n\t\tif( !this.data.if && this.node.parentNode ) node( this.node ).replace( this.placeholder );\n\t}\n}\n\nclass ShowModel extends Model {\n\tif:boolean;\n}\n","import View from '../core/view/View';\nimport Lang from '../core/lang/Lang';\nimport Model from '../core/model/Model';\n\n/**\n * A helper view that simple renders html\n */\nexport default class Trans extends View {\n\n\n\tprivate _condition:number;\n\tprivate transTemplate:string;\n\n\tconstructor() {\n\t\tsuper( { template:'', data:new TransModel( { condition:null, params:null } ) } );\n\t}\n\n\trender( target?:Element ) {\n\n\t\t// before render get inner html for item template.\n\t\tthis.transTemplate = target.innerHTML;\n\n\t\tsuper.render( target );\n\t}\n\n\tinit() {\n\t\tthis.data.change.subscribe( this.onModelChange.bind( this ) );\n\n\t\tthis.renderTranslation();\n\t}\n\n\tonModelChange() {\n\t\tthis.renderTranslation();\n\t}\n\n\trenderTranslation() {\n\t\tvar opt:any = {};\n\t\tif( this.data.condition != null ) opt.condition = this.data.condition;\n\t\topt.data = ( this.data.params ) ? this.data.params : this.parent.template.dataFactory();\n\n\t\tthis.node.innerHTML = Lang.translate( this.transTemplate, opt );\n\t}\n\n}\n\nclass TransModel extends Model {\n\tcondition:number;\n\tparams:any;\n}\n","import View from '../core/view/View';\n\n/**\n * A helper view that simply renders html into the component node\n */\nexport class Html extends View {\n\n\tconstructor() {\n\t\tsuper( { template:'', data:'' } );\n\t}\n\n\tinit() {\n\t\tthis.node.innerHTML = this.data;\n\t}\n\n\tupdate() {\n\t\tthis.node.innerHTML = this.data;\n\t}\n}\n\n\nexport default Html;\n","import {node} from 'ln/node/Node';\nimport View from 'ln/view/View';\n\nexport default class Placeholder extends View {\n\n public constructor() {\n super({ template: '
' })\n }\n\n protected init() {\n this.node.appendChild(node(`
${this.data.modelName}
`).native);\n }\n}\n","/* Auto generated by gulp-typescript-template */\n\nexport const Chapter = `

[[title]] [[module.title]]

[[this.trans('mark-chapter-as-completed')]]
[[ this.trans( 'go-to-overview' ) ]]
[[ this.trans( 'next-task' ) ]]
`;\nexport const ChapterCard = `

[[title]]

[[summary]]

  • [[ this.trans( tag ) ]]
`;\n","import Model from 'ln/model/Model';\nimport { Resolvable } from 'ln/components/Resolve';\nimport { suspendData, updateSuspendData } from '../../ScormSingleton';\n\nimport { Module } from '../module';\nimport { Asset } from '../../Asset';\n\nexport interface ChapterElement extends Resolvable{\n chapter:Chapter\n}\n\nexport class Chapter extends Model implements Resolvable {\n\n public completed:boolean;\n public hideCloseButton:boolean;\n public readonly elements:ChapterElement[];\n public readonly image:Asset;\n public module:Module;\n public readonly summary:string;\n public readonly tags:string[];\n public readonly title:string;\n\n constructor(json: object) {\n super({\n completed: false,\n hideCloseButton: false,\n elements:[],\n image: null,\n summary: '',\n tags:[],\n title: '',\n ...json\n });\n\n // inject chapter into elements\n this.elements.forEach( ( element ) => {\n element.chapter = this;\n });\n\n if( suspendData.data.chapters[this.get( 'id' )] ) this.completed = suspendData.data.chapters[this.get( 'id' )];\n }\n\n public getViewName(): string {\n return 'Chapter';\n }\n\n public toggleCompleted(): void {\n this.completed = !this.completed;\n suspendData.data.chapters[this.get( 'id')] = this.completed;\n\n updateSuspendData();\n }\n\n private isNotLastChapter(){\n return !(this.module.chapters.indexOf( this ) == this.module.chapters.length - 1);\n }\n\n private nextChapter(){\n let currentIndex = this.module.chapters.indexOf( this );\n if( currentIndex < this.module.chapters.length - 1 ) this.module.openChapter( this.module.chapters[ currentIndex + 1 ] );\n }\n\n private closeChapter(){\n this.module.closeChapter();\n }\n}\n","import {Chapter as template, ChapterCard as cardTemplate} from 'templates/components/chapter';\n\n\nexport {Chapter, ChapterElement} from './Chapter';\n\n\nexport const chapterRegistrations = {\n 'Chapter': { template },\n 'ChapterCard': { template: cardTemplate }\n};\n","import Model from 'ln/model/Model';\n\nimport {Asset} from '../../Asset';\n\n\nexport class Image extends Model {\n\n public constructor(json: object ) {\n super({\n asset: null,\n classIfMissing: '-missing',\n ext: 'png',\n preset: 'large',\n ...json\n });\n }\n\n public asset: Asset;\n public classIfMissing: string;\n public ext: string;\n public preset: string;\n}\n","import {renderer} from 'ln/view/Renderer';\nimport View from 'ln/view/View';\n\nimport {Image} from './Image';\n\n\nexport class ImageView extends View {\n\n public constructor() {\n super({ template: '', data: new Image({}) });\n\n this.data.change.subscribe(this.update.bind(this));\n }\n\n protected init(): void {\n this.update();\n }\n\n public update(): void {\n const node = this.node;\n if (node) {\n const asset = this.data && this.data.asset;\n if (asset) {\n const {preset, ext} = this.data;\n node.style.backgroundImage = `url(\"${renderer.context.imageUri(asset, preset, ext)}\")`;\n }\n node.classList.toggle(this.data.classIfMissing, !asset);\n }\n }\n}\n","/* Auto generated by gulp-typescript-template */\n\nexport const ChapterImage = `
`;\n","import {Image} from './Image';\n\nexport class ChapterImage extends Image {\n\n public getViewName(): string {\n return 'ChapterImage';\n }\n}\n","import {ImageView} from './ImageView';\nimport {ChapterImage as chapterImageTemplate } from 'templates/components/image';\n\nexport {Image} from './Image';\nexport {ChapterImage} from './ChapterImage';\n\n\nexport const imageRegistrations = {\n 'Image': ImageView,\n 'ChapterImage': { template: chapterImageTemplate }\n}\n","/* Auto generated by gulp-typescript-template */\n\nexport const Module = `

[[title]]

[[completionCount]]/[[chapters.length]] [[this.trans('chapters-completed', { condition: chapters.length })]]
`;\n","import View from 'ln/view/View';\n\nimport {Module, ModuleRequestHandler} from './Module';\nimport {Module as template} from 'templates/components/module';\n\n\nexport class ModuleView extends View implements ModuleRequestHandler {\n\n private lastKnownScrollPosition_: number;\n\n public constructor() {\n super({ template });\n }\n\n protected init(): void {\n this.data.request = this;\n\n window.addEventListener('scroll', () => {\n let scroll = window.scrollY / (window.innerHeight * 0.33);\n if (scroll > 1) scroll = 1;\n let opacity = 1 - Math.pow(scroll, 2);\n this.data.scrollHintOpacity = opacity;\n });\n }\n\n public navigateToChapterList(): void {\n const top = window.scrollY + document.querySelector('#chapters').getBoundingClientRect().top - 5;\n window.scrollTo({ behavior: 'smooth', top });\n }\n\n public restoreScroll(): void {\n window.scrollTo(0, this.lastKnownScrollPosition_);\n }\n\n public saveScroll(): void {\n this.lastKnownScrollPosition_ = window.scrollY;\n }\n\n public scrollToTop(): void {\n window.scrollTo(0, 0);\n }\n}\n","import Model from 'ln/model/Model';\nimport {Resolvable} from 'ln/components/Resolve';\n\nimport {Asset} from '../../Asset';\nimport {Chapter} from '../chapter';\nimport { StepByStep } from 'components/stepbystep';\n\n\nexport interface ModuleRequestHandler {\n navigateToChapterList(): void;\n restoreScroll(): void;\n saveScroll(): void;\n scrollToTop(): void;\n}\n\n\nexport class Module extends Model implements Resolvable {\n\n public constructor(json: object) {\n super({\n chapters: [],\n completionCount: 0,\n completionInPercent: 0,\n image: null,\n scrollHintOpacity: 1,\n selectedChapter: null,\n showSelectedChapter: false,\n title: '',\n ...json\n });\n\n if (this.chapters.length) {\n for (const chapter of this.chapters) {\n chapter.module = this;\n chapter.change.filter(property => property.name === 'completed')\n .subscribe(() => this.onChapterCompletionChanged(chapter));\n }\n this.selectedChapter = this.chapters[0];\n }\n }\n\n public readonly chapters: Chapter[];\n public completionCount: number;\n public completionInPercent: number;\n public readonly image: Asset;\n public request: ModuleRequestHandler;\n public scrollHintOpacity: number;\n public selectedChapter: Chapter;\n public showSelectedChapter: boolean;\n public readonly title: string;\n\n public getViewName(): string {\n return 'Module';\n }\n\n public closeChapter(): void {\n this.showSelectedChapter = false;\n this.request.restoreScroll();\n }\n\n public navigateToChapterList(): void {\n this.request.navigateToChapterList();\n }\n\n public openChapter(chapter: Chapter): void {\n this.request.saveScroll();\n this.selectedChapter = chapter;\n this.showSelectedChapter = true;\n this.request.scrollToTop();\n }\n\n private onChapterCompletionChanged(chapter: Chapter): void {\n if (chapter === this.selectedChapter) {\n /* if (chapter.completed) {\n setTimeout(this.closeChapter.bind(this), 500);\n } */\n this.completionCount = this.chapters.filter(ch => ch.completed).length;\n this.completionInPercent = Math.trunc(100 * this.completionCount / this.chapters.length);\n }\n }\n}\n","import {ModuleView} from './ModuleView';\n\nexport {Module} from './Module';\n\n\nexport const moduleRegistrations = {\n 'Module': ModuleView,\n};\n","import {node} from 'ln/node/Node';\nimport View from 'ln/view/View';\nimport {Text} from './Text';\nimport {renderer} from 'ln/view/Renderer';\n\n\nexport class TextView extends View {\n\n public constructor() {\n super({ template: '
' })\n }\n\n protected init(): void {\n let { level, text } = this.data;\n this.node.classList.add(level ? '-h' + level : '-p');\n text = renderer.context.downloadPath( text );\n this.node.appendChild(node(text).native);\n }\n}\n","import {Resolvable} from 'ln/components/Resolve';\nimport Model from 'ln/model/Model';\n\n\nexport class Text extends Model implements Resolvable {\n\n public constructor(json: object) {\n super({\n level: null,\n text: '',\n ...json\n });\n }\n\n public readonly text: string;\n\n public get level(): number|null {\n return Number(this.get('level') || 0) || null;\n }\n\n public getViewName(): string {\n return 'Text';\n }\n}\n","import {TextView} from './TextView';\n\n\nexport {Text} from './Text';\n\n\nexport const textRegistrations = {\n 'Text': TextView,\n};\n","import Model from 'ln/model/Model';\n\nexport class Toggle extends Model {\n\n public constructor() {\n super({ checked: false });\n }\n\n public checked: boolean;\n}\n","import View from 'ln/view/View';\n\nimport {Toggle} from './Toggle';\n\nexport class ToggleView extends View {\n\n private readonly checkedTemplate_: string;\n private readonly uncheckedTemplate_: string;\n\n public constructor(checkedTemplate: string, uncheckedTemplate: string) {\n super({ template: ``, data: new Toggle() });\n this.checkedTemplate_ = checkedTemplate;\n this.uncheckedTemplate_ = uncheckedTemplate;\n }\n\n protected init() {\n this.data.change.filter(ch => ch.name === 'checked')\n .subscribe(_ => this.updateIcon());\n this.updateIcon();\n }\n\n private updateIcon(): void {\n if (!this.node || !this.data) return;\n this.node.innerHTML = this.data.checked ? this.checkedTemplate_\n : this.uncheckedTemplate_;\n }\n}\n","import {ToggleView} from './ToggleView';\n\nexport class SvgToggleView extends ToggleView {\n\n public constructor(checkedHref: string, uncheckedHref: string) {\n super(\n ``,\n ``);\n }\n}\n","/* Auto generated by gulp-typescript-template */\n\nexport const Video = `
[[title]]
[[index + 1]]. [[chapter.title]]
`;\n","import View from 'ln/view/View';\n\nimport {Video} from './Video';\nimport {Video as template} from 'templates/components/video';\n\n\nexport class VideoView extends View