From 2e08b638081ca733196bae6e4e1252b40b3c2f0d Mon Sep 17 00:00:00 2001 From: Tucker Whitehouse Date: Sat, 7 Sep 2013 22:46:56 -0400 Subject: [PATCH] Upgrade to 0.3.6 --- ajax/libs/ractive.js/0.3.6/ractive.js | 9198 +++++++++++++++++++++ ajax/libs/ractive.js/0.3.6/ractive.min.js | 3 + ajax/libs/ractive.js/package.json | 2 +- 3 files changed, 9202 insertions(+), 1 deletion(-) create mode 100755 ajax/libs/ractive.js/0.3.6/ractive.js create mode 100755 ajax/libs/ractive.js/0.3.6/ractive.min.js diff --git a/ajax/libs/ractive.js/0.3.6/ractive.js b/ajax/libs/ractive.js/0.3.6/ractive.js new file mode 100755 index 000000000..b615a287c --- /dev/null +++ b/ajax/libs/ractive.js/0.3.6/ractive.js @@ -0,0 +1,9198 @@ +/*! Ractive - v0.3.6 - 2013-08-22 +* Next-generation DOM manipulation + +* http://ractivejs.org +* Copyright (c) 2013 Rich Harris; Licensed MIT */ + +/*jslint eqeq: true, plusplus: true */ +/*global document, HTMLElement */ + + +(function ( global ) { + +'use strict'; + +var Ractive, + +// current version +VERSION = '0.3.6', + +doc = global.document || null, + +// Ractive prototype +proto = {}, + +// properties of the public Ractive object +adaptors = {}, +eventDefinitions = {}, +easing, +extend, +parse, +interpolate, +interpolators, +transitions = {}, + + +// internal utils - instance-specific +teardown, +clearCache, +registerDependant, +unregisterDependant, +notifyDependants, +notifyMultipleDependants, +notifyDependantsByPriority, +resolveRef, +processDeferredUpdates, + + +// internal utils +splitKeypath, +toString, +isArray, +isObject, +isNumeric, +isEqual, +getEl, +insertHtml, +reassignFragments, +executeTransition, +getPartialDescriptor, +getComponentConstructor, +isStringFragmentSimple, +makeTransitionManager, +requestAnimationFrame, +defineProperty, +defineProperties, +create, +createFromNull, +hasOwn = {}.hasOwnProperty, +noop = function () {}, +addEventProxies, +addEventProxy, +appendElementChildren, +bindElement, +createElementAttributes, +getElementNamespace, +updateAttribute, +bindAttribute, +console = global.console || { log: noop, warn: noop }, + + +// internally used caches +keypathCache = {}, + + +// internally used constructors +DomFragment, +DomElement, +DomAttribute, +DomPartial, +DomComponent, +DomInterpolator, +DomTriple, +DomSection, +DomText, + +StringFragment, +StringInterpolator, +StringSection, +StringText, + +ExpressionResolver, +Evaluator, +Animation, + + +// internally used regexes +leadingWhitespace = /^\s+/, +trailingWhitespace = /\s+$/, + + +// other bits and pieces +render, + +initMustache, +updateMustache, +resolveMustache, + +initFragment, +updateSection, + +animationCollection, + + +// array modification +registerKeypathToArray, +unregisterKeypathFromArray, + + +// parser and tokenizer +getFragmentStubFromTokens, +getToken, +tokenize, +stripCommentTokens, +stripHtmlComments, +stripStandalones, + + +// error messages +missingParser = 'Missing Ractive.parse - cannot parse template. Either preparse or use the version that includes the parser', + + +// constants +TEXT = 1, +INTERPOLATOR = 2, +TRIPLE = 3, +SECTION = 4, +INVERTED = 5, +CLOSING = 6, +ELEMENT = 7, +PARTIAL = 8, +COMMENT = 9, +DELIMCHANGE = 10, +MUSTACHE = 11, +TAG = 12, + +COMPONENT = 15, + +NUMBER_LITERAL = 20, +STRING_LITERAL = 21, +ARRAY_LITERAL = 22, +OBJECT_LITERAL = 23, +BOOLEAN_LITERAL = 24, + +GLOBAL = 26, +KEY_VALUE_PAIR = 27, + + +REFERENCE = 30, +REFINEMENT = 31, +MEMBER = 32, +PREFIX_OPERATOR = 33, +BRACKETED = 34, +CONDITIONAL = 35, +INFIX_OPERATOR = 36, + +INVOCATION = 40, + +UNSET = { unset: true }, + +testDiv = ( doc ? doc.createElement( 'div' ) : null ), +noMagic, + + +// namespaces +namespaces = { + html: 'http://www.w3.org/1999/xhtml', + mathml: 'http://www.w3.org/1998/Math/MathML', + svg: 'http://www.w3.org/2000/svg', + xlink: 'http://www.w3.org/1999/xlink', + xml: 'http://www.w3.org/XML/1998/namespace', + xmlns: 'http://www.w3.org/2000/xmlns/' +}; + + + +// we're creating a defineProperty function here - we don't want to add +// this to _legacy.js since it's not a polyfill. It won't allow us to set +// non-enumerable properties. That shouldn't be a problem, unless you're +// using for...in on a (modified) array, in which case you deserve what's +// coming anyway +try { + Object.defineProperty({}, 'test', { value: 0 }); + Object.defineProperties({}, { test: { value: 0 } }); + + if ( doc ) { + Object.defineProperty( testDiv, 'test', { value: 0 }); + Object.defineProperties( testDiv, { test: { value: 0 } }); + } + + defineProperty = Object.defineProperty; + defineProperties = Object.defineProperties; +} catch ( err ) { + // Object.defineProperty doesn't exist, or we're in IE8 where you can + // only use it with DOM objects (what the fuck were you smoking, MSFT?) + defineProperty = function ( obj, prop, desc ) { + obj[ prop ] = desc.value; + }; + + defineProperties = function ( obj, props ) { + var prop; + + for ( prop in props ) { + if ( props.hasOwnProperty( prop ) ) { + defineProperty( obj, prop, props[ prop ] ); + } + } + }; + + noMagic = true; +} + + +try { + Object.create( null ); + + create = Object.create; + + createFromNull = function () { + return Object.create( null ); + }; +} catch ( err ) { + // sigh + create = (function () { + var F = function () {}; + + return function ( proto, props ) { + var obj; + + F.prototype = proto; + obj = new F(); + + if ( props ) { + Object.defineProperties( obj, props ); + } + + return obj; + }; + }()); + + createFromNull = function () { + return {}; // hope you're not modifying the Object prototype + }; +} + + + +var hyphenate = function ( str ) { + return str.replace( /[A-Z]/g, function ( match ) { + return '-' + match.toLowerCase(); + }); +}; + +// determine some facts about our environment +var cssTransitionsEnabled, transition, transitionend; + +(function () { + + if ( !doc ) { + return; + } + + if ( testDiv.style.transition !== undefined ) { + transition = 'transition'; + transitionend = 'transitionend'; + cssTransitionsEnabled = true; + } else if ( testDiv.style.webkitTransition !== undefined ) { + transition = 'webkitTransition'; + transitionend = 'webkitTransitionEnd'; + cssTransitionsEnabled = true; + } else { + cssTransitionsEnabled = false; + } + +}()); +(function () { + + var getInterpolator, + updateModel, + getBinding, + inheritProperties, + arrayContentsMatch, + MultipleSelectBinding, + SelectBinding, + RadioNameBinding, + CheckboxNameBinding, + CheckedBinding, + FileListBinding, + GenericBinding; + + bindAttribute = function () { + var node = this.parentNode, interpolator, binding; + + if ( !this.fragment ) { + return false; // report failure + } + + interpolator = getInterpolator( this ); + + if ( !interpolator ) { + return false; // report failure + } + + this.interpolator = interpolator; + + // Hmmm. Not sure if this is the best way to handle this ambiguity... + // + // Let's say we were given `value="{{bar}}"`. If the context stack was + // context stack was `["foo"]`, and `foo.bar` *wasn't* `undefined`, the + // keypath would be `foo.bar`. Then, any user input would result in + // `foo.bar` being updated. + // + // If, however, `foo.bar` *was* undefined, and so was `bar`, we would be + // left with an unresolved partial keypath - so we are forced to make an + // assumption. That assumption is that the input in question should + // be forced to resolve to `bar`, and any user input would affect `bar` + // and not `foo.bar`. + // + // Did that make any sense? No? Oh. Sorry. Well the moral of the story is + // be explicit when using two-way data-binding about what keypath you're + // updating. Using it in lists is probably a recipe for confusion... + this.keypath = interpolator.keypath || interpolator.descriptor.r; + + //this.updateModel = getUpdater( this ); + binding = getBinding( this ); + + if ( !binding ) { + return false; + } + + node._ractive.binding = binding; + this.twoway = true; + + return true; + }; + + updateModel = function () { + this._ractive.binding.update(); + }; + + getInterpolator = function ( attribute ) { + var item; + + // TODO refactor this? Couldn't the interpolator have got a keypath via an expression? + // Check this is a suitable candidate for two-way binding - i.e. it is + // a single interpolator, which isn't an expression + if ( attribute.fragment.items.length !== 1 ) { + return null; + } + + item = attribute.fragment.items[0]; + + if ( item.type !== INTERPOLATOR ) { + return null; + } + + if ( !item.keypath && !item.ref ) { + return null; + } + + return item; + }; + + getBinding = function ( attribute ) { + var node = attribute.parentNode; + + if ( node.tagName === 'SELECT' ) { + return ( node.multiple ? new MultipleSelectBinding( attribute, node ) : new SelectBinding( attribute, node ) ); + } + + if ( node.type === 'checkbox' || node.type === 'radio' ) { + if ( attribute.propertyName === 'name' ) { + if ( node.type === 'checkbox' ) { + return new CheckboxNameBinding( attribute, node ); + } + + if ( node.type === 'radio' ) { + return new RadioNameBinding( attribute, node ); + } + } + + if ( attribute.propertyName === 'checked' ) { + return new CheckedBinding( attribute, node ); + } + + return null; + } + + if ( attribute.propertyName !== 'value' ) { + console.warn( 'This is... odd' ); + } + + if ( attribute.parentNode.type === 'file' ) { + return new FileListBinding( attribute, node ); + } + + return new GenericBinding( attribute, node ); + }; + + MultipleSelectBinding = function ( attribute, node ) { + inheritProperties( this, attribute, node ); + node.addEventListener( 'change', updateModel, false ); + }; + + MultipleSelectBinding.prototype = { + update: function () { + var attribute, value, selectedOptions, i, previousValue, changed, len; + + attribute = this.attr; + previousValue = attribute.value || []; + + value = []; + selectedOptions = this.node.querySelectorAll( 'option:checked' ); + len = selectedOptions.length; + + for ( i=0; i + if ( this.isFileInputValue ) { + this.update = updateFileInputValue; // save ourselves the trouble next time + return this; + } + + // special case - + if ( this.twoway && this.name === 'name' ) { + if ( node.type === 'radio' ) { + this.update = updateRadioName; + return this.update(); + } + + if ( node.type === 'checkbox' ) { + this.update = updateCheckboxName; + return this.update(); + } + } + + this.update = updateEverythingElse; + return this.update(); + }; + + updateFileInputValue = function () { + return this; // noop - file inputs are readonly + }; + + initSelect = function () { + // we're now in a position to decide whether this is a select-one or select-multiple + this.deferredUpdate = ( this.parentNode.multiple ? updateMultipleSelect : updateSelect ); + this.deferredUpdate(); + }; + + deferSelect = function () { + // because select values depend partly on the values of their children, and their + // children may be entering and leaving the DOM, we wait until updates are + // complete before updating + this.root._defSelectValues.push( this ); + return this; + }; + + updateSelect = function () { + var value = this.fragment.getValue(), options, option, i; + + this.value = value; + + options = this.parentNode.querySelectorAll( 'option' ); + i = options.length; + + while ( i-- ) { + option = options[i]; + + if ( option._ractive.value === value ) { + option.selected = true; + return this; + } + } + + // if we're still here, it means the new value didn't match any of the options... + // TODO figure out what to do in this situation + + return this; + }; + + updateMultipleSelect = function () { + var value = this.fragment.getValue(), options, i; + + if ( !isArray( value ) ) { + value = [ value ]; + } + + options = this.parentNode.querySelectorAll( 'option' ); + i = options.length; + + while ( i-- ) { + options[i].selected = ( value.indexOf( options[i]._ractive.value ) !== -1 ); + } + + this.value = value; + + return this; + }; + + updateRadioName = function () { + var node, value; + + node = this.parentNode; + value = this.fragment.getValue(); + + node.checked = ( value === node._ractive.value ); + + return this; + }; + + updateCheckboxName = function () { + var node, value; + + node = this.parentNode; + value = this.fragment.getValue(); + + if ( !isArray( value ) ) { + node.checked = ( value === node._ractive.value ); + return this; + } + + node.checked = ( value.indexOf( node._ractive.value ) !== -1 ); + + return this; + }; + + updateEverythingElse = function () { + var node, value; + + node = this.parentNode; + value = this.fragment.getValue(); + + // store actual value, so it doesn't get coerced to a string + if ( this.isValueAttribute ) { + node._ractive.value = value; + } + + if ( value === undefined ) { + value = ''; + } + + if ( value !== this.value ) { + if ( this.useProperty ) { + + // with two-way binding, only update if the change wasn't initiated by the user + // otherwise the cursor will often be sent to the wrong place + if ( !this.receiving ) { + node[ this.propertyName ] = value; + } + + this.value = value; + + return this; + } + + if ( this.namespace ) { + node.setAttributeNS( this.namespace, this.name, value ); + this.value = value; + + return this; + } + + if ( this.name === 'id' ) { + if ( this.value !== undefined ) { + this.root.nodes[ this.value ] = undefined; + } + + this.root.nodes[ value ] = node; + } + + node.setAttribute( this.name, value ); + + this.value = value; + } + + return this; + }; + +}()); +addEventProxies = function ( element, proxies ) { + var i, eventName, eventNames; + + for ( eventName in proxies ) { + if ( hasOwn.call( proxies, eventName ) ) { + eventNames = eventName.split( '-' ); + i = eventNames.length; + + while ( i-- ) { + addEventProxy( element, eventNames[i], proxies[ eventName ], element.parentFragment.contextStack ); + } + } + } +}; +(function () { + + var MasterEventHandler, + ProxyEvent, + firePlainEvent, + fireEventWithArgs, + fireEventWithDynamicArgs, + customHandlers, + genericHandler, + getCustomHandler; + + addEventProxy = function ( element, triggerEventName, proxyDescriptor, contextStack, indexRefs ) { + var events, master; + + events = element.ractify().events; + master = events[ triggerEventName ] || ( events[ triggerEventName ] = new MasterEventHandler( element, triggerEventName, contextStack, indexRefs ) ); + + master.add( proxyDescriptor ); + }; + + MasterEventHandler = function ( element, eventName, contextStack ) { + var definition; + + this.element = element; + this.root = element.root; + this.node = element.node; + this.name = eventName; + this.contextStack = contextStack; // TODO do we need to pass contextStack down everywhere? Doesn't it belong to the parentFragment? + this.proxies = []; + + if ( definition = ( this.root.eventDefinitions[ eventName ] || Ractive.eventDefinitions[ eventName ] ) ) { + this.custom = definition( this.node, getCustomHandler( eventName ) ); + } else { + this.node.addEventListener( eventName, genericHandler, false ); + } + }; + + MasterEventHandler.prototype = { + add: function ( proxy ) { + this.proxies[ this.proxies.length ] = new ProxyEvent( this.element, this.root, proxy, this.contextStack ); + }, + + // TODO teardown when element torn down + teardown: function () { + var i; + + if ( this.custom ) { + this.custom.teardown(); + } else { + this.node.removeEventListener( this.name, genericHandler, false ); + } + + i = this.proxies.length; + while ( i-- ) { + this.proxies[i].teardown(); + } + }, + + fire: function ( event ) { + var i = this.proxies.length; + + while ( i-- ) { + this.proxies[i].fire( event ); + } + } + }; + + ProxyEvent = function ( element, ractive, descriptor, contextStack ) { + var name; + + this.root = ractive; + + name = descriptor.n || descriptor; + + if ( typeof name === 'string' ) { + this.n = name; + } else { + this.n = new StringFragment({ + descriptor: descriptor.n, + root: this.root, + owner: element, + contextStack: contextStack + }); + } + + if ( descriptor.a ) { + this.a = descriptor.a; + this.fire = fireEventWithArgs; + return; + } + + if ( descriptor.d ) { + this.d = new StringFragment({ + descriptor: descriptor.d, + root: this.root, + owner: element, + contextStack: contextStack + }); + this.fire = fireEventWithDynamicArgs; + return; + } + + this.fire = firePlainEvent; + }; + + ProxyEvent.prototype = { + teardown: function () { + if ( this.n.teardown) { + this.n.teardown(); + } + + if ( this.d ) { + this.d.teardown(); + } + }, + + bubble: noop // TODO can we get rid of this? + }; + + // the ProxyEvent instance fire method could be any of these + firePlainEvent = function ( event ) { + this.root.fire( this.n.toString(), event ); + }; + + fireEventWithArgs = function ( event ) { + this.root.fire( this.n.toString(), event, this.a ); + }; + + fireEventWithDynamicArgs = function ( event ) { + this.root.fire( this.n.toString(), event, this.d.toJSON() ); + }; + + // all native DOM events dealt with by Ractive share a single handler + genericHandler = function ( event ) { + var storage = this._ractive; + + storage.events[ event.type ].fire({ + node: this, + original: event, + index: storage.index, + keypath: storage.keypath, + context: storage.root.get( storage.keypath ) + }); + }; + + customHandlers = {}; + + getCustomHandler = function ( eventName ) { + if ( customHandlers[ eventName ] ) { + return customHandlers[ eventName ]; + } + + return customHandlers[ eventName ] = function ( event ) { + var storage = event.node._ractive; + + event.index = storage.index; + event.keypath = storage.keypath; + event.context = storage.root.get( storage.keypath ); + + storage.events[ eventName ].fire( event ); + }; + }; + +}()); +appendElementChildren = function ( element, node, descriptor, docFrag ) { + if ( typeof descriptor.f === 'string' && ( !node || ( !node.namespaceURI || node.namespaceURI === namespaces.html ) ) ) { + // great! we can use innerHTML + element.html = descriptor.f; + + if ( docFrag ) { + node.innerHTML = element.html; + } + } + + else { + // once again, everyone has to suffer because of IE bloody 8 + if ( descriptor.e === 'style' && node.styleSheet !== undefined ) { + element.fragment = new StringFragment({ + descriptor: descriptor.f, + root: element.root, + contextStack: element.parentFragment.contextStack, + owner: element + }); + + if ( docFrag ) { + element.bubble = function () { + node.styleSheet.cssText = element.fragment.toString(); + }; + } + } + + else { + element.fragment = new DomFragment({ + descriptor: descriptor.f, + root: element.root, + parentNode: node, + contextStack: element.parentFragment.contextStack, + owner: element + }); + + if ( docFrag ) { + node.appendChild( element.fragment.docFrag ); + } + } + } +}; +bindElement = function ( element, attributes ) { + element.ractify(); + + // an element can only have one two-way attribute + switch ( element.descriptor.e ) { + case 'select': + case 'textarea': + if ( attributes.value ) { + attributes.value.bind(); + } + return; + + case 'input': + + if ( element.node.type === 'radio' || element.node.type === 'checkbox' ) { + // we can either bind the name attribute, or the checked attribute - not both + if ( attributes.name && attributes.name.bind() ) { + element.node._ractive.binding.update(); + return; + } + + if ( attributes.checked && attributes.checked.bind() ) { + return; + } + } + + if ( attributes.value && attributes.value.bind() ) { + return; + } + } +}; +createElementAttributes = function ( element, attributes ) { + var attrName, attrValue, attr; + + element.attributes = []; + + for ( attrName in attributes ) { + if ( hasOwn.call( attributes, attrName ) ) { + attrValue = attributes[ attrName ]; + + attr = new DomAttribute({ + element: element, + name: attrName, + value: attrValue, + root: element.root, + parentNode: element.node, + contextStack: element.parentFragment.contextStack + }); + + element.attributes[ element.attributes.length ] = attr; + + // name, value and checked attributes are potentially bindable + if ( attrName === 'value' || attrName === 'name' || attrName === 'checked' ) { + element.attributes[ attrName ] = attr; + } + + // The name attribute is a special case - it is the only two-way attribute that updates + // the viewmodel based on the value of another attribute. For that reason it must wait + // until the node has been initialised, and the viewmodel has had its first two-way + // update, before updating itself (otherwise it may disable a checkbox or radio that + // was enabled in the template) + if ( attrName !== 'name' ) { + attr.update(); + } + } + } + + return element.attributes; +}; +getElementNamespace = function ( descriptor, parentNode ) { + // if the element has an xmlns attribute, use that + if ( descriptor.a && descriptor.a.xmlns ) { + return descriptor.a.xmlns; + } + + // otherwise, use the svg namespace if this is an svg element, or inherit namespace from parent + return ( descriptor.e.toLowerCase() === 'svg' ? namespaces.svg : parentNode.namespaceURI ); +}; +executeTransition = function ( descriptor, root, owner, contextStack, isIntro ) { + var transitionName, transitionParams, fragment, transitionManager, transition; + + if ( !root.transitionsEnabled ) { + return; + } + + if ( typeof descriptor === 'string' ) { + transitionName = descriptor; + } else { + transitionName = descriptor.n; + + if ( descriptor.a ) { + transitionParams = descriptor.a; + } else if ( descriptor.d ) { + fragment = new StringFragment({ + descriptor: descriptor.d, + root: root, + owner: owner, + contextStack: owner.parentFragment.contextStack + }); + + transitionParams = fragment.toJSON(); + fragment.teardown(); + } + } + + transition = root.transitions[ transitionName ] || Ractive.transitions[ transitionName ]; + + if ( transition ) { + transitionManager = root._transitionManager; + + transitionManager.push( owner.node ); + transition.call( root, owner.node, function () { + transitionManager.pop( owner.node ); + }, transitionParams, isIntro ); + } +}; +getComponentConstructor = function ( root, name ) { + // TODO... write this properly! + return root.components[ name ]; +}; +insertHtml = function ( html, docFrag ) { + var div, nodes = []; + + div = doc.createElement( 'div' ); + div.innerHTML = html; + + while ( div.firstChild ) { + nodes[ nodes.length ] = div.firstChild; + docFrag.appendChild( div.firstChild ); + } + + return nodes; +}; +(function () { + + var reassignFragment, reassignElement, reassignMustache; + + reassignFragments = function ( root, section, start, end, by ) { + var i, fragment, indexRef, oldIndex, newIndex, oldKeypath, newKeypath; + + indexRef = section.descriptor.i; + + for ( i=start; i{{/section}}) need to cascade + // down the tree + if ( parentFragment ) { + parentRefs = parentFragment.indexRefs; + + if ( parentRefs ) { + fragment.indexRefs = createFromNull(); // avoids need for hasOwnProperty + + for ( ref in parentRefs ) { + fragment.indexRefs[ ref ] = parentRefs[ ref ]; + } + } + } + + // inherit priority + fragment.priority = ( parentFragment ? parentFragment.priority + 1 : 0 ); + + if ( options.indexRef ) { + if ( !fragment.indexRefs ) { + fragment.indexRefs = {}; + } + + fragment.indexRefs[ options.indexRef ] = options.index; + } + + // Time to create this fragment's child items; + fragment.items = []; + + numItems = ( options.descriptor ? options.descriptor.length : 0 ); + for ( i=0; i section.length ) { + // add any new ones + for ( i=section.length; i 1 ) { + fragmentsToRemove = section.fragments.splice( 1 ); + + while ( fragmentsToRemove.length ) { + fragmentsToRemove.pop().teardown( true ); + } + } + } + + else if ( section.length ) { + section.teardownFragments( true ); + section.length = 0; + } + }; + +}()); +var getItem; + +(function () { + + var getText, getMustache, getElement; + + getItem = function ( parser, preserveWhitespace ) { + if ( !parser.next() ) { + return null; + } + + return getText( parser, preserveWhitespace ) + || getMustache( parser, preserveWhitespace ) + || getElement( parser, preserveWhitespace ); + }; + + getText = function ( parser, preserveWhitespace ) { + var next = parser.next(); + + if ( next.type === TEXT ) { + parser.pos += 1; + return new TextStub( next, preserveWhitespace ); + } + + return null; + }; + + getMustache = function ( parser, preserveWhitespace ) { + var next = parser.next(); + + if ( next.type === MUSTACHE || next.type === TRIPLE ) { + if ( next.mustacheType === SECTION || next.mustacheType === INVERTED ) { + return new SectionStub( next, parser, preserveWhitespace ); + } + + return new MustacheStub( next, parser ); + } + + return null; + }; + + getElement = function ( parser, preserveWhitespace ) { + var next = parser.next(), stub; + + if ( next.type === TAG ) { + stub = new ElementStub( next, parser, preserveWhitespace ); + + // sanitize + if ( parser.options.sanitize && parser.options.sanitize.elements ) { + if ( parser.options.sanitize.elements.indexOf( stub.lcTag ) !== -1 ) { + return null; + } + } + + return stub; + } + + return null; + }; + +}()); +var jsonifyStubs = function ( items, noStringify ) { + var str, json; + + if ( !noStringify ) { + str = stringifyStubs( items ); + if ( str !== false ) { + return str; + } + } + + json = items.map( function ( item ) { + return item.toJSON( noStringify ); + }); + + return json; +}; +var stringifyStubs = function ( items ) { + var str = '', itemStr, i, len; + + if ( !items ) { + return ''; + } + + for ( i=0, len=items.length; i' ); + + // no comments? great + if ( commentStart === -1 && commentEnd === -1 ) { + processed += html; + break; + } + + // comment start but no comment end + if ( commentStart !== -1 && commentEnd === -1 ) { + throw 'Illegal HTML - expected closing comment sequence (\'-->\')'; + } + + // comment end but no comment start, or comment end before comment start + if ( ( commentEnd !== -1 && commentStart === -1 ) || ( commentEnd < commentStart ) ) { + throw 'Illegal HTML - unexpected closing comment sequence (\'-->\')'; + } + + processed += html.substr( 0, commentStart ); + html = html.substring( commentEnd + 3 ); + } + + return processed; +}; +stripStandalones = function ( tokens ) { + var i, current, backOne, backTwo, leadingLinebreak, trailingLinebreak; + + leadingLinebreak = /^\s*\r?\n/; + trailingLinebreak = /\r?\n\s*$/; + + for ( i=2; i 1 ) { + key = accumulated[ accumulated.length ] = keys.shift(); + + // If this branch doesn't exist yet, create a new one - if the next + // key matches /^\s*[0-9]+\s*$/, assume we want an array branch rather + // than an object + if ( !obj[ key ] ) { + + // if we're creating a new branch, we may need to clear the upstream + // keypath + if ( !keypathToClear ) { + keypathToClear = accumulated.join( '.' ); + } + + obj[ key ] = ( /^\s*[0-9]+\s*$/.test( keys[0] ) ? [] : {} ); + } + + obj = obj[ key ]; + } + + key = keys[0]; + + obj[ key ] = value; + + root.muggleSet = false; + } + } + + else { + // if value is a primitive, we don't need to do anything else + if ( typeof value !== 'object' ) { + return; + } + } + + + // Clear cache + clearCache( root, keypathToClear || keypath ); + + // add this keypath to the notification queue + queue[ queue.length ] = keypath; + + + // add upstream keypaths to the upstream notification queue + while ( keysClone.length > 1 ) { + keysClone.pop(); + keypath = keysClone.join( '.' ); + + if ( upstreamQueue.indexOf( keypath ) === -1 ) { + upstreamQueue[ upstreamQueue.length ] = keypath; + } + } + + }; + + attemptKeypathResolution = function ( root ) { + var i, unresolved, keypath; + + // See if we can resolve any of the unresolved keypaths (if such there be) + i = root._pendingResolution.length; + while ( i-- ) { // Work backwards, so we don't go in circles! + unresolved = root._pendingResolution.splice( i, 1 )[0]; + + if ( keypath = resolveRef( root, unresolved.ref, unresolved.contextStack ) ) { + // If we've resolved the keypath, we can initialise this item + unresolved.resolve( keypath ); + + } else { + // If we can't resolve the reference, add to the back of + // the queue (this is why we're working backwards) + root._pendingResolution[ root._pendingResolution.length ] = unresolved; + } + } + }; + +}( proto )); +// Teardown. This goes through the root fragment and all its children, removing observers +// and generally cleaning up after itself +proto.teardown = function ( complete ) { + var keypath, transitionManager, previousTransitionManager; + + this.fire( 'teardown' ); + + previousTransitionManager = this._transitionManager; + this._transitionManager = transitionManager = makeTransitionManager( this, complete ); + + this.fragment.teardown( true ); + + // Cancel any animations in progress + while ( this._animations[0] ) { + this._animations[0].stop(); // it will remove itself from the index + } + + // Clear cache - this has the side-effect of unregistering keypaths from modified arrays. + for ( keypath in this._cache ) { + clearCache( this, keypath ); + } + + // Teardown any bindings + while ( this._bound.length ) { + this.unbind( this._bound.pop() ); + } + + // transition manager has finished its work + this._transitionManager = previousTransitionManager; + transitionManager.ready(); +}; +proto.toggleFullscreen = function () { + if ( Ractive.isFullscreen( this.el ) ) { + this.cancelFullscreen(); + } else { + this.requestFullscreen(); + } +}; +proto.unbind = function ( adaptor ) { + var bound = this._bound, index; + + index = bound.indexOf( adaptor ); + + if ( index !== -1 ) { + bound.splice( index, 1 ); + adaptor.teardown( this ); + } +}; +proto.update = function ( keypath, complete ) { + var transitionManager, previousTransitionManager; + + if ( typeof keypath === 'function' ) { + complete = keypath; + } + + // manage transitions + previousTransitionManager = this._transitionManager; + this._transitionManager = transitionManager = makeTransitionManager( this, complete ); + + clearCache( this, keypath || '' ); + notifyDependants( this, keypath || '' ); + + processDeferredUpdates( this ); + + // transition manager has finished its work + this._transitionManager = previousTransitionManager; + transitionManager.ready(); + + if ( typeof keypath === 'string' ) { + this.fire( 'update', keypath ); + } else { + this.fire( 'update' ); + } + + return this; +}; +adaptors.backbone = function ( model, path ) { + var settingModel, settingView, setModel, setView, pathMatcher, pathLength, prefix; + + if ( path ) { + path += '.'; + pathMatcher = new RegExp( '^' + path.replace( /\./g, '\\.' ) ); + pathLength = path.length; + } + + + return { + init: function ( view ) { + + // if no path specified... + if ( !path ) { + setView = function ( model ) { + if ( !settingModel ) { + settingView = true; + view.set( model.changed ); + settingView = false; + } + }; + + setModel = function ( keypath, value ) { + if ( !settingView ) { + settingModel = true; + model.set( keypath, value ); + settingModel = false; + } + }; + } + + else { + prefix = function ( attrs ) { + var attr, result; + + result = {}; + + for ( attr in attrs ) { + if ( hasOwn.call( attrs, attr ) ) { + result[ path + attr ] = attrs[ attr ]; + } + } + + return result; + }; + + setView = function ( model ) { + if ( !settingModel ) { + settingView = true; + view.set( prefix( model.changed ) ); + settingView = false; + } + }; + + setModel = function ( keypath, value ) { + if ( !settingView ) { + if ( pathMatcher.test( keypath ) ) { + settingModel = true; + model.set( keypath.substring( pathLength ), value ); + settingModel = false; + } + } + }; + } + + model.on( 'change', setView ); + view.on( 'set', setModel ); + + // initialise + view.set( path ? prefix( model.attributes ) : model.attributes ); + }, + + teardown: function ( view ) { + model.off( 'change', setView ); + view.off( 'set', setModel ); + } + }; +}; +adaptors.backboneCollection = function ( collection, path ) { + var settingCollection, settingView, setCollection, setView, pathMatcher, pathLength, prefix; + + if ( path ) { + path += '.'; + pathMatcher = new RegExp( '^' + path.replace( /\./g, '\\.' ) ); + pathLength = path.length; + } + + + return { + init: function ( view ) { + + // if no path specified... + if ( !path ) { + setView = function ( collection ) { + if ( !settingCollection ) { + settingView = true; + view.set( collection.collection.toJSON() ); + settingView = false; + } + }; + + setCollection = function ( keypath, value ) { + if ( !settingView ) { + settingCollection = true; + collection.reset(value); + settingCollection = false; + } + }; + } + + else { + prefix = function ( models ) { + var result, i; + + result = {}; + + for ( i=0; i= distanceThreshold ) || ( Math.abs( event.clientY - y ) >= distanceThreshold ) ) { + cancel(); + } + }; + + cancel = function () { + node.removeEventListener( 'MSPointerUp', up, false ); + doc.removeEventListener( 'MSPointerMove', move, false ); + doc.removeEventListener( 'MSPointerCancel', cancel, false ); + node.removeEventListener( 'pointerup', up, false ); + doc.removeEventListener( 'pointermove', move, false ); + doc.removeEventListener( 'pointercancel', cancel, false ); + node.removeEventListener( 'click', up, false ); + doc.removeEventListener( 'mousemove', move, false ); + }; + + if ( window.navigator.pointerEnabled ) { + node.addEventListener( 'pointerup', up, false ); + doc.addEventListener( 'pointermove', move, false ); + doc.addEventListener( 'pointercancel', cancel, false ); + } else if ( window.navigator.msPointerEnabled ) { + node.addEventListener( 'MSPointerUp', up, false ); + doc.addEventListener( 'MSPointerMove', move, false ); + doc.addEventListener( 'MSPointerCancel', cancel, false ); + } else { + node.addEventListener( 'click', up, false ); + doc.addEventListener( 'mousemove', move, false ); + } + + setTimeout( cancel, timeThreshold ); + }; + + if ( window.navigator.pointerEnabled ) { + node.addEventListener( 'pointerdown', mousedown, false ); + } else if ( window.navigator.msPointerEnabled ) { + node.addEventListener( 'MSPointerDown', mousedown, false ); + } else { + node.addEventListener( 'mousedown', mousedown, false ); + } + + + touchstart = function ( event ) { + var currentTarget, x, y, touch, finger, move, up, cancel; + + if ( event.touches.length !== 1 ) { + return; + } + + touch = event.touches[0]; + + x = touch.clientX; + y = touch.clientY; + currentTarget = this; + + finger = touch.identifier; + + up = function ( event ) { + var touch; + + touch = event.changedTouches[0]; + if ( touch.identifier !== finger ) { + cancel(); + } + + event.preventDefault(); // prevent compatibility mouse event + fire({ + node: currentTarget, + original: event + }); + + cancel(); + }; + + move = function ( event ) { + var touch; + + if ( event.touches.length !== 1 || event.touches[0].identifier !== finger ) { + cancel(); + } + + touch = event.touches[0]; + if ( ( Math.abs( touch.clientX - x ) >= distanceThreshold ) || ( Math.abs( touch.clientY - y ) >= distanceThreshold ) ) { + cancel(); + } + }; + + cancel = function () { + node.removeEventListener( 'touchend', up, false ); + window.removeEventListener( 'touchmove', move, false ); + window.removeEventListener( 'touchcancel', cancel, false ); + }; + + node.addEventListener( 'touchend', up, false ); + window.addEventListener( 'touchmove', move, false ); + window.addEventListener( 'touchcancel', cancel, false ); + + setTimeout( cancel, timeThreshold ); + }; + + node.addEventListener( 'touchstart', touchstart, false ); + + + return { + teardown: function () { + node.removeEventListener( 'pointerdown', mousedown, false ); + node.removeEventListener( 'MSPointerDown', mousedown, false ); + node.removeEventListener( 'mousedown', mousedown, false ); + node.removeEventListener( 'touchstart', touchstart, false ); + } + }; +}; + +(function () { + + var fillGaps, + clone, + augment, + + inheritFromParent, + wrapMethod, + inheritFromChildProps, + conditionallyParseTemplate, + extractInlinePartials, + conditionallyParsePartials, + initChildInstance, + + extendable, + inheritable, + blacklist; + + extend = function ( childProps ) { + + var Parent = this, Child; + + // create Child constructor + Child = function ( options ) { + initChildInstance( this, Child, options || {}); + }; + + Child.prototype = create( Parent.prototype ); + + // inherit options from parent, if we're extending a subclass + if ( Parent !== Ractive ) { + inheritFromParent( Child, Parent ); + } + + // apply childProps + inheritFromChildProps( Child, childProps ); + + // parse template and any partials that need it + conditionallyParseTemplate( Child ); + extractInlinePartials( Child, childProps ); + conditionallyParsePartials( Child ); + + Child.extend = Parent.extend; + + return Child; + }; + + extendable = [ 'data', 'partials', 'transitions', 'eventDefinitions', 'components' ]; + inheritable = [ 'el', 'template', 'complete', 'modifyArrays', 'twoway', 'lazy', 'append', 'preserveWhitespace', 'sanitize', 'noIntro', 'transitionsEnabled' ]; + blacklist = extendable.concat( inheritable ); + + inheritFromParent = function ( Child, Parent ) { + extendable.forEach( function ( property ) { + if ( Parent[ property ] ) { + Child[ property ] = clone( Parent[ property ] ); + } + }); + + inheritable.forEach( function ( property ) { + if ( Parent[ property ] !== undefined ) { + Child[ property ] = Parent[ property ]; + } + }); + }; + + wrapMethod = function ( method, superMethod ) { + if ( /_super/.test( method ) ) { + return function () { + var _super = this._super, result; + this._super = superMethod; + + result = method.apply( this, arguments ); + + this._super = _super; + return result; + }; + } + + else { + return method; + } + }; + + inheritFromChildProps = function ( Child, childProps ) { + var key, member; + + extendable.forEach( function ( property ) { + var value = childProps[ property ]; + + if ( value ) { + if ( Child[ property ] ) { + augment( Child[ property ], value ); + } + + else { + Child[ property ] = value; + } + } + }); + + inheritable.forEach( function ( property ) { + if ( childProps[ property ] !== undefined ) { + Child[ property ] = childProps[ property ]; + } + }); + + // Blacklisted properties don't extend the child, as they are part of the initialisation options + for ( key in childProps ) { + if ( hasOwn.call( childProps, key ) && !hasOwn.call( Child.prototype, key ) && blacklist.indexOf( key ) === -1 ) { + member = childProps[ key ]; + + // if this is a method that overwrites a prototype method, we may need + // to wrap it + if ( typeof member === 'function' && typeof Child.prototype[ key ] === 'function' ) { + Child.prototype[ key ] = wrapMethod( member, Child.prototype[ key ] ); + } else { + Child.prototype[ key ] = member; + } + } + } + }; + + conditionallyParseTemplate = function ( Child ) { + var templateEl; + + if ( typeof Child.template === 'string' ) { + if ( !Ractive.parse ) { + throw new Error( missingParser ); + } + + if ( Child.template.charAt( 0 ) === '#' && doc ) { + templateEl = doc.getElementById( Child.template.substring( 1 ) ); + if ( templateEl && templateEl.tagName === 'SCRIPT' ) { + Child.template = Ractive.parse( templateEl.innerHTML, Child ); + } else { + throw new Error( 'Could not find template element (' + Child.template + ')' ); + } + } else { + Child.template = Ractive.parse( Child.template, Child ); // all the relevant options are on Child + } + } + }; + + extractInlinePartials = function ( Child, childProps ) { + // does our template contain inline partials? + if ( isObject( Child.template ) ) { + if ( !Child.partials ) { + Child.partials = {}; + } + + // get those inline partials + augment( Child.partials, Child.template.partials ); + + // but we also need to ensure that any explicit partials override inline ones + if ( childProps.partials ) { + augment( Child.partials, childProps.partials ); + } + + // move template to where it belongs + Child.template = Child.template.main; + } + }; + + conditionallyParsePartials = function ( Child ) { + var key, partial; + + // Parse partials, if necessary + if ( Child.partials ) { + for ( key in Child.partials ) { + if ( hasOwn.call( Child.partials, key ) ) { + if ( typeof Child.partials[ key ] === 'string' ) { + if ( !Ractive.parse ) { + throw new Error( missingParser ); + } + + partial = Ractive.parse( Child.partials[ key ], Child ); + } else { + partial = Child.partials[ key ]; + } + + Child.partials[ key ] = partial; + } + } + } + }; + + initChildInstance = function ( child, Child, options ) { + + // Add template to options, if necessary + if ( !options.template && Child.template ) { + options.template = Child.template; + } + + extendable.forEach( function ( property ) { + if ( !options[ property ] ) { + if ( Child[ property ] ) { + options[ property ] = clone( Child[ property ] ); + } + } else { + fillGaps( options[ property ], Child[ property ] ); + } + }); + + inheritable.forEach( function ( property ) { + if ( options[ property ] === undefined && Child[ property ] !== undefined ) { + options[ property ] = Child[ property ]; + } + }); + + if ( child.beforeInit ) { + child.beforeInit.call( child, options ); + } + + Ractive.call( child, options ); + + if ( child.init ) { + child.init.call( child, options ); + } + }; + + fillGaps = function ( target, source ) { + var key; + + for ( key in source ) { + if ( hasOwn.call( source, key ) && !hasOwn.call( target, key ) ) { + target[ key ] = source[ key ]; + } + } + }; + + clone = function ( source ) { + var target = {}, key; + + for ( key in source ) { + if ( hasOwn.call( source, key ) ) { + target[ key ] = source[ key ]; + } + } + + return target; + }; + + augment = function ( target, source ) { + var key; + + for ( key in source ) { + if ( hasOwn.call( source, key ) ) { + target[ key ] = source[ key ]; + } + } + }; + +}()); +// TODO short circuit values that stay the same +interpolate = function ( from, to ) { + if ( isNumeric( from ) && isNumeric( to ) ) { + return Ractive.interpolators.number( +from, +to ); + } + + if ( isArray( from ) && isArray( to ) ) { + return Ractive.interpolators.array( from, to ); + } + + if ( isObject( from ) && isObject( to ) ) { + return Ractive.interpolators.object( from, to ); + } + + return function () { return to; }; +}; +interpolators = { + number: function ( from, to ) { + var delta = to - from; + + if ( !delta ) { + return function () { return from; }; + } + + return function ( t ) { + return from + ( t * delta ); + }; + }, + + array: function ( from, to ) { + var intermediate, interpolators, len, i; + + intermediate = []; + interpolators = []; + + i = len = Math.min( from.length, to.length ); + while ( i-- ) { + interpolators[i] = Ractive.interpolate( from[i], to[i] ); + } + + // surplus values - don't interpolate, but don't exclude them either + for ( i=len; i tag + templateEl = doc.getElementById( template.substring( 1 ) ); + if ( templateEl ) { + parsedTemplate = Ractive.parse( templateEl.innerHTML, options ); + } + + else { + throw new Error( 'Could not find template element (' + template + ')' ); + } + } + + else { + parsedTemplate = Ractive.parse( template, options ); + } + } else { + parsedTemplate = template; + } + + // deal with compound template + if ( isObject( parsedTemplate ) ) { + this.partials = parsedTemplate.partials; + parsedTemplate = parsedTemplate.main; + } + + // If the template was an array with a single string member, that means + // we can use innerHTML - we just need to unpack it + if ( parsedTemplate && ( parsedTemplate.length === 1 ) && ( typeof parsedTemplate[0] === 'string' ) ) { + parsedTemplate = parsedTemplate[0]; + } + + this.template = parsedTemplate; + + + // If we were given unparsed partials, parse them + if ( options.partials ) { + for ( key in options.partials ) { + if ( hasOwn.call( options.partials, key ) ) { + partial = options.partials[ key ]; + + if ( typeof partial === 'string' ) { + if ( !Ractive.parse ) { + throw new Error( missingParser ); + } + + partial = Ractive.parse( partial, options ); + } + + this.partials[ key ] = partial; + } + } + } + + + // temporarily disable transitions, if noIntro flag is set + this.transitionsEnabled = ( options.noIntro ? false : options.transitionsEnabled ); + + render( this, { el: this.el, append: options.append, complete: options.complete }); + + // reset transitionsEnabled + this.transitionsEnabled = options.transitionsEnabled; +}; + +(function () { + + var getOriginalComputedStyles, setStyle, augment, makeTransition; + + // no point executing this code on the server + if ( !doc ) { + return; + } + + getOriginalComputedStyles = function ( computedStyle, properties ) { + var original = {}, i; + + i = properties.length; + while ( i-- ) { + original[ properties[i] ] = computedStyle[ properties[i] ]; + } + + return original; + }; + + setStyle = function ( node, properties, map, params ) { + var i = properties.length, prop; + + while ( i-- ) { + prop = properties[i]; + if ( map && map[ prop ] ) { + if ( typeof map[ prop ] === 'function' ) { + node.style[ prop ] = map[ prop ]( params ); + } else { + node.style[ prop ] = map[ prop ]; + } + } + + else { + node.style[ prop ] = 0; + } + } + }; + + augment = function ( target, source ) { + var key; + + if ( !source ) { + return target; + } + + for ( key in source ) { + if ( hasOwn.call( source, key ) ) { + target[ key ] = source[ key ]; + } + } + + return target; + }; + + if ( cssTransitionsEnabled ) { + makeTransition = function ( properties, defaults, outside, inside ) { + if ( typeof properties === 'string' ) { + properties = [ properties ]; + } + + return function ( node, complete, params, isIntro ) { + var transitionEndHandler, + computedStyle, + originalComputedStyles, + startTransition, + originalStyle, + duration, + delay, + start, + end, + positionStyle, + visibilityStyle; + + params = parseTransitionParams( params ); + + duration = params.duration || defaults.duration; + easing = hyphenate( params.easing || defaults.easing ); + delay = params.delay || 0; + + start = ( isIntro ? outside : inside ); + end = ( isIntro ? inside : outside ); + + computedStyle = window.getComputedStyle( node ); + originalStyle = node.getAttribute( 'style' ); + + // if this is an intro, we need to transition TO the original styles + if ( isIntro ) { + // hide, to avoid flashes + positionStyle = node.style.position; + visibilityStyle = node.style.visibility; + node.style.position = 'absolute'; + node.style.visibility = 'hidden'; + + // we need to wait a beat before we can actually get values from computedStyle. + // Yeah, I know, WTF browsers + setTimeout( function () { + originalComputedStyles = getOriginalComputedStyles( computedStyle, properties ); + + start = outside; + end = augment( originalComputedStyles, inside ); + + // starting style + node.style.position = positionStyle; + node.style.visibility = visibilityStyle; + + setStyle( node, properties, start, params ); + + setTimeout( startTransition, 0 ); + }, delay ); + } + + // otherwise we need to transition FROM them + else { + setTimeout( function () { + originalComputedStyles = getOriginalComputedStyles( computedStyle, properties ); + + start = augment( originalComputedStyles, inside ); + end = outside; + + // ending style + setStyle( node, properties, start, params ); + + setTimeout( startTransition, 0 ); + }, delay ); + } + + startTransition = function () { + node.style[ transition + 'Duration' ] = ( duration / 1000 ) + 's'; + node.style[ transition + 'Properties' ] = properties.map( hyphenate ).join( ',' ); + node.style[ transition + 'TimingFunction' ] = easing; + + transitionEndHandler = function () { + node.removeEventListener( transitionend, transitionEndHandler, false ); + + if ( isIntro ) { + node.setAttribute( 'style', originalStyle || '' ); + } + + complete(); + }; + + node.addEventListener( transitionend, transitionEndHandler, false ); + + setStyle( node, properties, end, params ); + }; + }; + }; + + transitions.slide = makeTransition([ + 'height', + 'borderTopWidth', + 'borderBottomWidth', + 'paddingTop', + 'paddingBottom', + 'overflowY' + ], { duration: 400, easing: 'easeInOut' }, { overflowY: 'hidden' }, { overflowY: 'hidden' }); + + transitions.fade = makeTransition( 'opacity', { + duration: 300, + easing: 'linear' + }); + + transitions.fly = makeTransition([ 'opacity', 'left', 'position' ], { + duration: 400, easing: 'easeOut' + }, { position: 'relative', left: '-500px' }, { position: 'relative', left: 0 }); + } + + + +}()); +var parseTransitionParams = function ( params ) { + if ( params === 'fast' ) { + return { duration: 200 }; + } + + if ( params === 'slow' ) { + return { duration: 600 }; + } + + if ( isNumeric( params ) ) { + return { duration: +params }; + } + + return params || {}; +}; +(function ( transitions ) { + + var typewriter, typewriteNode, typewriteTextNode; + + if ( !doc ) { + return; + } + + typewriteNode = function ( node, complete, interval ) { + var children, next; + + if ( node.nodeType === 1 ) { + node.style.display = node._display; + } + + if ( node.nodeType === 3 ) { + typewriteTextNode( node, complete, interval ); + return; + } + + children = Array.prototype.slice.call( node.childNodes ); + + next = function () { + if ( !children.length ) { + if ( node.nodeType === 1 ) { + node.setAttribute( 'style', node._style || '' ); + } + + complete(); + return; + } + + typewriteNode( children.shift(), next, interval ); + }; + + next(); + }; + + typewriteTextNode = function ( node, complete, interval ) { + var str, len, loop, i; + + // text node + str = node._hiddenData; + len = str.length; + + if ( !len ) { + complete(); + return; + } + + i = 0; + + loop = setInterval( function () { + var substr, remaining, match, remainingNonWhitespace, filler; + + substr = str.substr( 0, i ); + remaining = str.substring( i ); + + match = /^\w+/.exec( remaining ); + remainingNonWhitespace = ( match ? match[0].length : 0 ); + + // add some non-breaking whitespace corresponding to the remaining length of the + // current word (only really works with monospace fonts, but better than nothing) + filler = new Array( remainingNonWhitespace + 1 ).join( '\u00a0' ); + + node.data = substr + filler; + if ( i === len ) { + clearInterval( loop ); + delete node._hiddenData; + complete(); + } + + i += 1; + }, interval ); + }; + + // TODO differentiate between intro and outro + typewriter = function ( node, complete, params ) { + var interval, style, computedStyle, hide; + + params = parseTransitionParams( params ); + + interval = params.interval || ( params.speed ? 1000 / params.speed : ( params.duration ? node.textContent.length / params.duration : 4 ) ); + + style = node.getAttribute( 'style' ); + computedStyle = window.getComputedStyle( node ); + + node.style.visibility = 'hidden'; + + setTimeout( function () { + var computedHeight, computedWidth, computedVisibility; + + computedWidth = computedStyle.width; + computedHeight = computedStyle.height; + computedVisibility = computedStyle.visibility; + + hide( node ); + + setTimeout( function () { + node.style.width = computedWidth; + node.style.height = computedHeight; + node.style.visibility = 'visible'; + + typewriteNode( node, function () { + node.setAttribute( 'style', style || '' ); + complete(); + }, interval ); + }, params.delay || 0 ); + }); + + hide = function ( node ) { + var children, i; + + if ( node.nodeType === 1 ) { + node._style = node.getAttribute( 'style' ); + node._display = window.getComputedStyle( node ).display; + + node.style.display = 'none'; + } + + if ( node.nodeType === 3 ) { + node._hiddenData = '' + node.data; + node.data = ''; + + return; + } + + children = Array.prototype.slice.call( node.childNodes ); + i = children.length; + while ( i-- ) { + hide( children[i] ); + } + }; + }; + + transitions.typewriter = typewriter; + +}( transitions )); +(function ( Ractive ) { + + var requestFullscreen, cancelFullscreen, fullscreenElement; + + if ( !doc ) { + return; + } + + Ractive.fullscreenEnabled = doc.fullscreenEnabled || doc.mozFullScreenEnabled || doc.webkitFullscreenEnabled; + + if ( !Ractive.fullscreenEnabled ) { + Ractive.requestFullscreen = Ractive.cancelFullscreen = noop; + return; + } + + // get prefixed name of requestFullscreen method + if ( testDiv.requestFullscreen ) { + requestFullscreen = 'requestFullscreen'; + } else if ( testDiv.mozRequestFullScreen ) { + requestFullscreen = 'mozRequestFullScreen'; + } else if ( testDiv.webkitRequestFullscreen ) { + requestFullscreen = 'webkitRequestFullscreen'; + } + + Ractive.requestFullscreen = function ( el ) { + if ( el[ requestFullscreen ] ) { + el[ requestFullscreen ](); + } + }; + + // get prefixed name of cancelFullscreen method + if ( doc.cancelFullscreen ) { + cancelFullscreen = 'cancelFullscreen'; + } else if ( doc.mozCancelFullScreen ) { + cancelFullscreen = 'mozCancelFullScreen'; + } else if ( doc.webkitCancelFullScreen ) { + cancelFullscreen = 'webkitCancelFullScreen'; + } + + Ractive.cancelFullscreen = function () { + doc[ cancelFullscreen ](); + }; + + // get prefixed name of fullscreenElement property + if ( doc.fullscreenElement !== undefined ) { + fullscreenElement = 'fullscreenElement'; + } else if ( doc.mozFullScreenElement !== undefined ) { + fullscreenElement = 'mozFullScreenElement'; + } else if ( doc.webkitFullscreenElement !== undefined ) { + fullscreenElement = 'webkitFullscreenElement'; + } + + Ractive.isFullscreen = function ( el ) { + return el === doc[ fullscreenElement ]; + }; + +}( Ractive )); +Animation = function ( options ) { + var key; + + this.startTime = Date.now(); + + // from and to + for ( key in options ) { + if ( hasOwn.call( options, key ) ) { + this[ key ] = options[ key ]; + } + } + + this.interpolator = Ractive.interpolate( this.from, this.to ); + this.running = true; +}; + +Animation.prototype = { + tick: function () { + var elapsed, t, value, timeNow, index; + + if ( this.running ) { + timeNow = Date.now(); + elapsed = timeNow - this.startTime; + + if ( elapsed >= this.duration ) { + this.root.set( this.keypath, this.to ); + + if ( this.step ) { + this.step( 1, this.to ); + } + + if ( this.complete ) { + this.complete( 1, this.to ); + } + + index = this.root._animations.indexOf( this ); + + // TODO remove this check, once we're satisifed this never happens! + if ( index === -1 && console && console.warn ) { + console.warn( 'Animation was not found' ); + } + + this.root._animations.splice( index, 1 ); + + this.running = false; + return false; + } + + t = this.easing ? this.easing ( elapsed / this.duration ) : ( elapsed / this.duration ); + value = this.interpolator( t ); + + this.root.set( this.keypath, value ); + + if ( this.step ) { + this.step( t, value ); + } + + return true; + } + + return false; + }, + + stop: function () { + var index; + + this.running = false; + + index = this.root._animations.indexOf( this ); + + // TODO remove this check, once we're satisifed this never happens! + if ( index === -1 && console && console.warn ) { + console.warn( 'Animation was not found' ); + } + + this.root._animations.splice( index, 1 ); + } +}; +animationCollection = { + animations: [], + + tick: function () { + var i, animation; + + for ( i=0; i + if ( this.parentNode.tagName === 'INPUT' && this.parentNode.type === 'file' ) { + this.isFileInputValue = true; + } + } + + + // can we establish this attribute's property name equivalent? + determinePropertyName( this, options ); + + // determine whether this attribute can be marked as self-updating + this.selfUpdating = isStringFragmentSimple( this.fragment ); + + // mark as ready + this.ready = true; + }; + + DomAttribute.prototype = { + bind: bindAttribute, + update: updateAttribute, + + updateBindings: function () { + // if the fragment this attribute belongs to gets reassigned (as a result of + // as section being updated via an array shift, unshift or splice), this + // attribute needs to recognise that its keypath has changed + this.keypath = this.interpolator.keypath || this.interpolator.r; // TODO is this right? .r? + + // if we encounter the special case described above, update the name attribute + if ( this.propertyName === 'name' ) { + // replace actual name attribute + this.parentNode.name = '{{' + this.keypath + '}}'; + } + }, + + teardown: function () { + var i; + + if ( this.boundEvents ) { + i = this.boundEvents.length; + + while ( i-- ) { + this.parentNode.removeEventListener( this.boundEvents[i], this.updateModel, false ); + } + } + + // ignore non-dynamic attributes + if ( this.fragment ) { + this.fragment.teardown(); + } + }, + + bubble: function () { + // If an attribute's text fragment contains a single item, we can + // update the DOM immediately... + if ( this.selfUpdating ) { + this.update(); + } + + // otherwise we want to register it as a deferred attribute, to be + // updated once all the information is in, to prevent unnecessary + // DOM manipulation + else if ( !this.deferred && this.ready ) { + this.root._defAttrs[ this.root._defAttrs.length ] = this; + this.deferred = true; + } + }, + + toString: function () { + var str; + + if ( this.value === null ) { + return this.name; + } + + // TODO don't use JSON.stringify? + + if ( !this.fragment ) { + return this.name + '=' + JSON.stringify( this.value ); + } + + // TODO deal with boolean attributes correctly + str = this.fragment.toString(); + + return this.name + '=' + JSON.stringify( str ); + } + }; + + + // Helper functions + determineNameAndNamespace = function ( attribute, name ) { + var colonIndex, namespacePrefix; + + // are we dealing with a namespaced attribute, e.g. xlink:href? + colonIndex = name.indexOf( ':' ); + if ( colonIndex !== -1 ) { + + // looks like we are, yes... + namespacePrefix = name.substr( 0, colonIndex ); + + // ...unless it's a namespace *declaration*, which we ignore (on the assumption + // that only valid namespaces will be used) + if ( namespacePrefix !== 'xmlns' ) { + name = name.substring( colonIndex + 1 ); + + attribute.name = name; + attribute.namespace = namespaces[ namespacePrefix ]; + + if ( !attribute.namespace ) { + throw 'Unknown namespace ("' + namespacePrefix + '")'; + } + + return; + } + } + + attribute.name = name; + }; + + setStaticAttribute = function ( attribute, options ) { + if ( options.parentNode ) { + if ( attribute.namespace ) { + options.parentNode.setAttributeNS( attribute.namespace, options.name, options.value ); + } else { + options.parentNode.setAttribute( options.name, options.value ); + } + + if ( attribute.name === 'id' ) { + options.root.nodes[ options.value ] = options.parentNode; + } + + if ( attribute.name === 'value' ) { + attribute.element.ractify().value = options.value; + } + } + + attribute.value = options.value; + }; + + determinePropertyName = function ( attribute, options ) { + var propertyName; + + if ( attribute.parentNode && !attribute.namespace && ( !options.parentNode.namespaceURI || options.parentNode.namespaceURI === namespaces.html ) ) { + propertyName = propertyNames[ attribute.name ] || attribute.name; + + if ( options.parentNode[ propertyName ] !== undefined ) { + attribute.propertyName = propertyName; + } + + // is attribute a boolean attribute or 'value'? If so we're better off doing e.g. + // node.selected = true rather than node.setAttribute( 'selected', '' ) + if ( typeof options.parentNode[ propertyName ] === 'boolean' || propertyName === 'value' ) { + attribute.useProperty = true; + } + } + }; + +}()); +(function () { + + var ComponentParameter; + + // TODO support server environments + DomComponent = function ( options ) { + var self = this, + parentFragment = this.parentFragment = options.parentFragment, + root, + Component, + twoway, + partials, + instance, + keypath, + data, + mappings, + i, + pair, + observeParent, + observeChild, + settingParent, + settingChild, + key, + initFalse, + processKeyValuePair, + eventName, + propagateEvent; + + root = parentFragment.root; + + this.type = COMPONENT; + this.name = options.descriptor.r; + + Component = getComponentConstructor( parentFragment.root, options.descriptor.e ); + twoway = ( Component.twoway !== false ); + + data = {}; + mappings = []; + + this.complexParameters = []; + + processKeyValuePair = function ( key, value ) { + var parameter; + + // if this is a static value, great + if ( typeof value === 'string' ) { + try { + data[ key ] = JSON.parse( value ); + } catch ( err ) { + data[ key ] = value; + } + return; + } + + // if null, we treat is as a boolean attribute (i.e. true) + if ( value === null ) { + data[ key ] = true; + return; + } + + // if a regular interpolator, we bind to it + if ( value.length === 1 && value[0].t === INTERPOLATOR && value[0].r ) { + + // is it an index reference? + if ( parentFragment.indexRefs && parentFragment.indexRefs[ value[0].r ] !== undefined ) { + data[ key ] = parentFragment.indexRefs[ value[0].r ]; + return; + } + + keypath = resolveRef( root, value[0].r, parentFragment.contextStack ) || value[0].r; + + data[ key ] = root.get( keypath ); + mappings[ mappings.length ] = [ key, keypath ]; + return; + } + + parameter = new ComponentParameter( root, self, key, value, parentFragment.contextStack ); + self.complexParameters[ self.complexParameters.length ] = parameter; + + data[ key ] = parameter.value; + }; + + if ( options.descriptor.a ) { + for ( key in options.descriptor.a ) { + if ( options.descriptor.a.hasOwnProperty( key ) ) { + processKeyValuePair( key, options.descriptor.a[ key ] ); + } + } + } + + partials = {}; + if ( options.descriptor.f ) { + partials.content = options.descriptor.f; + } + + instance = this.instance = new Component({ + append: true, + el: parentFragment.parentNode, + data: data, + partials: partials + }); + + self.observers = []; + initFalse = { init: false }; + + observeParent = function ( pair ) { + var observer = root.observe( pair[1], function ( value ) { + if ( !settingParent ) { + settingChild = true; + instance.set( pair[0], value ); + settingChild = false; + } + }, initFalse ); + + self.observers[ self.observers.length ] = observer; + }; + + if ( twoway ) { + observeChild = function ( pair ) { + var observer = instance.observe( pair[0], function ( value ) { + if ( !settingChild ) { + settingParent = true; + root.set( pair[1], value ); + settingParent = false; + } + }, initFalse ); + + self.observers[ self.observers.length ] = observer; + }; + } + + + i = mappings.length; + while ( i-- ) { + pair = mappings[i]; + + observeParent( pair ); + + if ( twoway ) { + observeChild( pair ); + } + } + + + // proxy events + propagateEvent = function ( eventName, proxy ) { + instance.on( eventName, function () { + var args = Array.prototype.slice.call( arguments ); + args.unshift( proxy ); + + root.fire.apply( root, args ); + }); + }; + + if ( options.descriptor.v ) { + for ( eventName in options.descriptor.v ) { + if ( options.descriptor.v.hasOwnProperty( eventName ) ) { + propagateEvent( eventName, options.descriptor.v[ eventName ] ); + } + } + } + }; + + DomComponent.prototype = { + firstNode: function () { + return this.instance.fragment.firstNode(); + }, + + findNextNode: function () { + return this.parentFragment.findNextNode( this ); + }, + + teardown: function () { + while ( this.complexParameters.length ) { + this.complexParameters.pop().teardown(); + } + + while ( this.observers.length ) { + this.observers.pop().cancel(); + } + + this.instance.teardown(); + }, + + toString: function () { + return this.instance.fragment.toString(); + } + }; + + + ComponentParameter = function ( root, component, key, value, contextStack ) { + + this.parentFragment = component.parentFragment; + this.component = component; + this.key = key; + + this.fragment = new StringFragment({ + descriptor: value, + root: root, + owner: this, + contextStack: contextStack + }); + + this.selfUpdating = isStringFragmentSimple( this.fragment ); + this.value = this.fragment.getValue(); + }; + + ComponentParameter.prototype = { + bubble: function () { + // If there's a single item, we can update the component immediately... + if ( this.selfUpdating ) { + this.update(); + } + + // otherwise we want to register it as a deferred component, to be + // updated once all the information is in, to prevent unnecessary + // DOM manipulation + else if ( !this.deferred && this.ready ) { + this.root._defAttrs[ this.root._defAttrs.length ] = this; + this.deferred = true; + } + }, + + update: function () { + var value = this.fragment.getValue(); + + this.component.set( this.key, value ); + this.value = value; + } + }; + + +}()); +// Element +DomElement = function ( options, docFrag ) { + + var parentFragment, + descriptor, + namespace, + attributes, + root; + + this.type = ELEMENT; + + // stuff we'll need later + parentFragment = this.parentFragment = options.parentFragment; + descriptor = this.descriptor = options.descriptor; + + this.root = root = parentFragment.root; + this.parentNode = parentFragment.parentNode; + this.index = options.index; + + this.eventListeners = []; + this.customEventListeners = []; + + // get namespace, if we're actually rendering (not server-side stringifying) + if ( this.parentNode ) { + namespace = getElementNamespace( descriptor, this.parentNode ); + + // create the DOM node + this.node = doc.createElementNS( namespace, descriptor.e ); + } + + + // append children, if there are any + if ( descriptor.f ) { + appendElementChildren( this, this.node, descriptor, docFrag ); + } + + + // create event proxies + if ( docFrag && descriptor.v ) { + addEventProxies( this, descriptor.v ); + } + + // set attributes + attributes = createElementAttributes( this, descriptor.a ); + + + // if we're actually rendering (i.e. not server-side stringifying), proceed + if ( docFrag ) { + // deal with two-way bindings + if ( root.twoway ) { + bindElement( this, attributes ); + } + + // name attributes are deferred, because they're a special case + if ( attributes.name ) { + attributes.name.update(); + } + + docFrag.appendChild( this.node ); + + // trigger intro transition + if ( descriptor.t1 ) { + executeTransition( descriptor.t1, root, this, parentFragment.contextStack, true ); + } + } +}; + +DomElement.prototype = { + teardown: function ( detach ) { + var eventName; + + // Children first. that way, any transitions on child elements will be + // handled by the current transitionManager + if ( this.fragment ) { + this.fragment.teardown( false ); + } + + while ( this.attributes.length ) { + this.attributes.pop().teardown(); + } + + if ( this.node._ractive ) { + for ( eventName in this.node._ractive.events ) { + this.node._ractive.events[ eventName ].teardown(); + } + } + + if ( this.descriptor.t2 ) { + executeTransition( this.descriptor.t2, this.root, this, this.parentFragment.contextStack, false ); + } + + if ( detach ) { + this.root._transitionManager.detachWhenReady( this.node ); + } + }, + + firstNode: function () { + return this.node; + }, + + findNextNode: function () { + return null; + }, + + // TODO can we get rid of this? + bubble: noop, // just so event proxy and transition fragments have something to call! + + toString: function () { + var str, i, len; + + // TODO void tags + str = '' + + '<' + this.descriptor.e; + + len = this.attributes.length; + for ( i=0; i'; + + return str; + }, + + ractify: function () { + var contextStack = this.parentFragment.contextStack; + + if ( !this.node._ractive ) { + defineProperty( this.node, '_ractive', { + value: { + keypath: ( contextStack.length ? contextStack[ contextStack.length - 1 ] : '' ), + index: this.parentFragment.indexRefs, + events: createFromNull(), + root: this.root + } + }); + } + + return this.node._ractive; + } +}; +DomFragment = function ( options ) { + if ( options.parentNode ) { + this.docFrag = doc.createDocumentFragment(); + } + + // if we have an HTML string, our job is easy. + if ( typeof options.descriptor === 'string' ) { + this.html = options.descriptor; + + if ( this.docFrag ) { + this.nodes = insertHtml( options.descriptor, this.docFrag ); + } + + return; // prevent the rest of the init sequence + } + + // otherwise we need to make a proper fragment + initFragment( this, options ); +}; + +DomFragment.prototype = { + createItem: function ( options ) { + if ( typeof options.descriptor === 'string' ) { + return new DomText( options, this.docFrag ); + } + + switch ( options.descriptor.t ) { + case INTERPOLATOR: return new DomInterpolator( options, this.docFrag ); + case SECTION: return new DomSection( options, this.docFrag ); + case TRIPLE: return new DomTriple( options, this.docFrag ); + + case ELEMENT: return new DomElement( options, this.docFrag ); + case PARTIAL: return new DomPartial( options, this.docFrag ); + case COMPONENT: return new DomComponent( options, this.docFrag ); + + default: throw new Error( 'WTF? not sure what happened here...' ); + } + }, + + teardown: function ( detach ) { + var node; + + // if this was built from HTML, we just need to remove the nodes + if ( detach && this.nodes ) { + while ( this.nodes.length ) { + node = this.nodes.pop(); + node.parentNode.removeChild( node ); + } + return; + } + + // otherwise we need to do a proper teardown + if ( !this.items ) { + return; + } + + while ( this.items.length ) { + this.items.pop().teardown( detach ); + } + }, + + firstNode: function () { + if ( this.items && this.items[0] ) { + return this.items[0].firstNode(); + } else if ( this.nodes ) { + return this.nodes[0] || null; + } + + return null; + }, + + findNextNode: function ( item ) { + var index = item.index; + + if ( this.items[ index + 1 ] ) { + return this.items[ index + 1 ].firstNode(); + } + + // if this is the root fragment, and there are no more items, + // it means we're at the end + if ( this.owner === this.root ) { + return null; + } + + return this.owner.findNextNode( this ); + }, + + toString: function () { + var html, i, len, item; + + if ( this.html ) { + return this.html; + } + + html = ''; + + if ( !this.items ) { + return html; + } + + len = this.items.length; + + for ( i=0; i', '>' ); + } +}; +// Partials +DomPartial = function ( options, docFrag ) { + var parentFragment = this.parentFragment = options.parentFragment, descriptor; + + this.type = PARTIAL; + this.name = options.descriptor.r; + + descriptor = getPartialDescriptor( parentFragment.root, options.descriptor.r ); + + this.fragment = new DomFragment({ + descriptor: descriptor, + root: parentFragment.root, + parentNode: parentFragment.parentNode, + contextStack: parentFragment.contextStack, + owner: this + }); + + if ( docFrag ) { + docFrag.appendChild( this.fragment.docFrag ); + } +}; + +DomPartial.prototype = { + firstNode: function () { + return this.fragment.firstNode(); + }, + + findNextNode: function () { + return this.parentFragment.findNextNode( this ); + }, + + teardown: function ( detach ) { + this.fragment.teardown( detach ); + }, + + toString: function () { + return this.fragment.toString(); + } +}; +// Section +DomSection = function ( options, docFrag ) { + this.type = SECTION; + + this.fragments = []; + this.length = 0; // number of times this section is rendered + + if ( docFrag ) { + this.docFrag = doc.createDocumentFragment(); + } + + this.initialising = true; + initMustache( this, options ); + + if ( docFrag ) { + docFrag.appendChild( this.docFrag ); + } + + this.initialising = false; +}; + +DomSection.prototype = { + update: updateMustache, + resolve: resolveMustache, + + smartUpdate: function ( methodName, args ) { + var fragmentOptions; + + if ( methodName === 'push' || methodName === 'unshift' || methodName === 'splice' ) { + fragmentOptions = { + descriptor: this.descriptor.f, + root: this.root, + parentNode: this.parentNode, + owner: this + }; + + if ( this.descriptor.i ) { + fragmentOptions.indexRef = this.descriptor.i; + } + } + + if ( this[ methodName ] ) { // if not, it's sort or reverse, which doesn't affect us (i.e. our length) + this[ methodName ]( fragmentOptions, args ); + } + }, + + pop: function () { + // teardown last fragment + if ( this.length ) { + this.fragments.pop().teardown( true ); + this.length -= 1; + } + }, + + push: function ( fragmentOptions, args ) { + var start, end, i; + + // append list item to context stack + start = this.length; + end = start + args.length; + + for ( i=start; i items.3 - the keypaths, + // context stacks and index refs will have changed) + reassignStart = ( start + addedItems ); + + reassignFragments( this.root, this, reassignStart, this.length, balance ); + }, + + teardown: function ( detach ) { + this.teardownFragments( detach ); + + teardown( this ); + }, + + firstNode: function () { + if ( this.fragments[0] ) { + return this.fragments[0].firstNode(); + } + + return this.parentFragment.findNextNode( this ); + }, + + findNextNode: function ( fragment ) { + if ( this.fragments[ fragment.index + 1 ] ) { + return this.fragments[ fragment.index + 1 ].firstNode(); + } + + return this.parentFragment.findNextNode( this ); + }, + + teardownFragments: function ( detach ) { + var id; + + while ( this.fragments.length ) { + this.fragments.shift().teardown( detach ); + } + + if ( this.fragmentsById ) { + for ( id in this.fragmentsById ) { + this.fragmentsById[ id ].teardown(); + this.fragmentsById[ id ] = null; + } + } + }, + + render: function ( value ) { + var next; + + // prevent sections from rendering multiple times (happens if + // evaluators evaluate while update is happening) + if ( this.rendering ) { + return; + } + + this.rendering = true; + updateSection( this, value ); + this.rendering = false; + + // if we have no new nodes to insert (i.e. the section length stayed the + // same, or shrank), we don't need to go any further + if ( this.docFrag && !this.docFrag.childNodes.length ) { + return; + } + + // if this isn't the initial render, we need to insert any new nodes in + // the right place + if ( !this.initialising ) { + + // Normally this is just a case of finding the next node, and inserting + // items before it... + next = this.parentFragment.findNextNode( this ); + + if ( next && ( next.parentNode === this.parentNode ) ) { + this.parentNode.insertBefore( this.docFrag, next ); + } + + // ...but in some edge cases the next node will not have been attached to + // the DOM yet, in which case we append to the end of the parent node + else { + // TODO could there be a situation in which later nodes could have + // been attached to the parent node, i.e. we need to find a sibling + // to insert before? + this.parentNode.appendChild( this.docFrag ); + } + } + }, + + createFragment: function ( options ) { + var fragment = new DomFragment( options ); + + if ( this.docFrag ) { + this.docFrag.appendChild( fragment.docFrag ); + } + + return fragment; + }, + + toString: function () { + var str, i, len; + + str = ''; + + i = 0; + len = this.length; + + for ( i=0; i', '>' ); + } +}; +// Triple +DomTriple = function ( options, docFrag ) { + this.type = TRIPLE; + + if ( docFrag ) { + this.nodes = []; + this.docFrag = doc.createDocumentFragment(); + } + + this.initialising = true; + initMustache( this, options ); + if ( docFrag ) { + docFrag.appendChild( this.docFrag ); + } + this.initialising = false; +}; + +DomTriple.prototype = { + update: updateMustache, + resolve: resolveMustache, + + teardown: function ( detach ) { + var node; + + // remove child nodes from DOM + if ( detach ) { + while ( this.nodes.length ) { + node = this.nodes.pop(); + node.parentNode.removeChild( node ); + } + } + + teardown( this ); + }, + + firstNode: function () { + if ( this.nodes[0] ) { + return this.nodes[0]; + } + + return this.parentFragment.findNextNode( this ); + }, + + render: function ( html ) { + var node; + + if ( !this.nodes ) { + // looks like we're in a server environment... + // nothing to see here, move along + return; + } + + // remove existing nodes + while ( this.nodes.length ) { + node = this.nodes.pop(); + node.parentNode.removeChild( node ); + } + + if ( html === undefined ) { + this.nodes = []; + return; + } + + // get new nodes + this.nodes = insertHtml( html, this.docFrag ); + + if ( !this.initialising ) { + this.parentNode.insertBefore( this.docFrag, this.parentFragment.findNextNode( this ) ); + } + }, + + toString: function () { + return ( this.value !== undefined ? this.value : '' ); + } +}; +StringFragment = function ( options ) { + initFragment( this, options ); +}; + +StringFragment.prototype = { + createItem: function ( options ) { + if ( typeof options.descriptor === 'string' ) { + return new StringText( options.descriptor ); + } + + switch ( options.descriptor.t ) { + case INTERPOLATOR: return new StringInterpolator( options ); + case TRIPLE: return new StringInterpolator( options ); + case SECTION: return new StringSection( options ); + + default: throw 'Something went wrong in a rather interesting way'; + } + }, + + + bubble: function () { + this.owner.bubble(); + }, + + teardown: function () { + var numItems, i; + + numItems = this.items.length; + for ( i=0; i element, preserve whitespace within + preserveWhitespace = ( preserveWhitespace || this.lcTag === 'pre' ); + + if ( firstToken.attrs ) { + filtered = filterAttrs( firstToken.attrs ); + + attrs = filtered.attrs; + proxies = filtered.proxies; + + // remove event attributes (e.g. onclick='doSomething()') if we're sanitizing + if ( parser.options.sanitize && parser.options.sanitize.eventAttributes ) { + attrs = attrs.filter( sanitize ); + } + + if ( attrs.length ) { + this.attributes = attrs.map( getFrag ); + } + + if ( proxies.length ) { + this.proxies = proxies.map( processProxy ); + } + + // TODO rename this helper function + if ( filtered.intro ) { + this.intro = processProxy( filtered.intro ); + } + + if ( filtered.outro ) { + this.outro = processProxy( filtered.outro ); + } + } + + if ( firstToken.selfClosing ) { + this.selfClosing = true; + } + + if ( voidElementNames.indexOf( this.lcTag ) !== -1 ) { + this.isVoid = true; + } + + // if self-closing or a void element, close + if ( this.selfClosing || this.isVoid ) { + return; + } + + this.siblings = siblingsByTagName[ this.lcTag ]; + + this.items = []; + + next = parser.next(); + while ( next ) { + + // section closing mustache should also close this element, e.g. + //
    {{#items}}
  • {{content}}{{/items}}
+ if ( next.mustacheType === CLOSING ) { + break; + } + + if ( next.type === TAG ) { + + // closing tag + if ( next.closing ) { + // it's a closing tag, which means this element is closed... + if ( next.name.toLowerCase() === this.lcTag ) { + parser.pos += 1; + } + + break; + } + + // sibling element, which closes this element implicitly + else if ( this.siblings && ( this.siblings.indexOf( next.name.toLowerCase() ) !== -1 ) ) { + break; + } + + } + + this.items[ this.items.length ] = getItem( parser ); + + next = parser.next(); + } + + + // if we're not preserving whitespace, we can eliminate inner leading and trailing whitespace + if ( !preserveWhitespace ) { + item = this.items[0]; + if ( item && item.type === TEXT ) { + item.text = item.text.replace( leadingWhitespace, '' ); + if ( !item.text ) { + this.items.shift(); + } + } + + item = this.items[ this.items.length - 1 ]; + if ( item && item.type === TEXT ) { + item.text = item.text.replace( trailingWhitespace, '' ); + if ( !item.text ) { + this.items.pop(); + } + } + } + }; + + ElementStub.prototype = { + toJSON: function ( noStringify ) { + var json, name, value, proxy, i, len; + + if ( this[ 'json_' + noStringify ] ) { + return this[ 'json_' + noStringify ]; + } + + if ( this.tag.substr( 0, 3 ) === 'rv-' ) { + json = { + t: COMPONENT, + e: this.tag.substr( 3 ) + }; + } else { + json = { + t: ELEMENT, + e: this.tag + }; + } + + if ( this.attributes && this.attributes.length ) { + json.a = {}; + + len = this.attributes.length; + for ( i=0; i`]/.test( attrValueStr ) ) { + attrStr += '"' + attrValueStr.replace( /"/g, '"' ) + '"'; + } else { + attrStr += attrValueStr; + } + } + } + + str += attrStr; + } + } + + // if this isn't a void tag, but is self-closing, add a solidus. Aaaaand, we're done + if ( this.selfClosing && !isVoid ) { + str += '/>'; + return ( this.str = str ); + } + + str += '>'; + + // void element? we're done + if ( isVoid ) { + return ( this.str = str ); + } + + // if this has children, add them + str += fragStr; + + str += ''; + return ( this.str = str ); + } + }; + + + voidElementNames = 'area base br col command embed hr img input keygen link meta param source track wbr'.split( ' ' ); + allElementNames = 'a abbr acronym address applet area b base basefont bdo big blockquote body br button caption center cite code col colgroup dd del dfn dir div dl dt em fieldset font form frame frameset h1 h2 h3 h4 h5 h6 head hr html i iframe img input ins isindex kbd label legend li link map menu meta noframes noscript object ol p param pre q s samp script select small span strike strong style sub sup textarea title tt u ul var article aside audio bdi canvas command data datagrid datalist details embed eventsource figcaption figure footer header hgroup keygen mark meter nav output progress ruby rp rt section source summary time track video wbr'.split( ' ' ); + closedByParentClose = 'li dd rt rp optgroup option tbody tfoot tr td th'.split( ' ' ); + + svgCamelCaseElements = 'altGlyph altGlyphDef altGlyphItem animateColor animateMotion animateTransform clipPath feBlend feColorMatrix feComponentTransfer feComposite feConvolveMatrix feDiffuseLighting feDisplacementMap feDistantLight feFlood feFuncA feFuncB feFuncG feFuncR feGaussianBlur feImage feMerge feMergeNode feMorphology feOffset fePointLight feSpecularLighting feSpotLight feTile feTurbulence foreignObject glyphRef linearGradient radialGradient textPath vkern'.split( ' ' ); + svgCamelCaseAttributes = 'attributeName attributeType baseFrequency baseProfile calcMode clipPathUnits contentScriptType contentStyleType diffuseConstant edgeMode externalResourcesRequired filterRes filterUnits glyphRef glyphRef gradientTransform gradientTransform gradientUnits gradientUnits kernelMatrix kernelUnitLength kernelUnitLength kernelUnitLength keyPoints keySplines keyTimes lengthAdjust limitingConeAngle markerHeight markerUnits markerWidth maskContentUnits maskUnits numOctaves pathLength patternContentUnits patternTransform patternUnits pointsAtX pointsAtY pointsAtZ preserveAlpha preserveAspectRatio primitiveUnits refX refY repeatCount repeatDur requiredExtensions requiredFeatures specularConstant specularExponent specularExponent spreadMethod spreadMethod startOffset stdDeviation stitchTiles surfaceScale surfaceScale systemLanguage tableValues targetX targetY textLength textLength viewBox viewTarget xChannelSelector yChannelSelector zoomAndPan'.split( ' ' ); + + mapToLowerCase = function ( items ) { + var map = {}, i = items.length; + while ( i-- ) { + map[ items[i].toLowerCase() ] = items[i]; + } + return map; + }; + + svgCamelCaseElementsMap = mapToLowerCase( svgCamelCaseElements ); + svgCamelCaseAttributesMap = mapToLowerCase( svgCamelCaseAttributes ); + + siblingsByTagName = { + li: [ 'li' ], + dt: [ 'dt', 'dd' ], + dd: [ 'dt', 'dd' ], + p: 'address article aside blockquote dir div dl fieldset footer form h1 h2 h3 h4 h5 h6 header hgroup hr menu nav ol p pre section table ul'.split( ' ' ), + rt: [ 'rt', 'rp' ], + rp: [ 'rp', 'rt' ], + optgroup: [ 'optgroup' ], + option: [ 'option', 'optgroup' ], + thead: [ 'tbody', 'tfoot' ], + tbody: [ 'tbody', 'tfoot' ], + tr: [ 'tr' ], + td: [ 'td', 'th' ], + th: [ 'td', 'th' ] + }; + + onPattern = /^on[a-zA-Z]/; + + sanitize = function ( attr ) { + var valid = !onPattern.test( attr.name ); + return valid; + }; + + filterAttrs = function ( items ) { + var attrs, proxies, filtered, i, len, item; + + filtered = {}; + attrs = []; + proxies = []; + + len = items.length; + for ( i=0; i colonIndex + 1 ) { + proxyArgs[0] = { + type: TEXT, + value: token.value.substring( colonIndex + 1 ) + }; + } + + break; + } + } + + else { + proxyName[ proxyName.length ] = token; + } + } + + proxyArgs = proxyArgs.concat( tokens ); + + if ( proxyName.length === 1 && proxyName[0].type === TEXT ) { + processed.name = proxyName[0].value; + } else { + processed.name = proxyName; + } + + if ( proxyArgs.length ) { + if ( proxyArgs.length === 1 && proxyArgs[0].type === TEXT ) { + try { + processed.args = JSON.parse( proxyArgs[0].value ); + } catch ( err ) { + processed.args = proxyArgs[0].value; + } + } + + else { + processed.dynamicArgs = proxyArgs; + } + } + + return processed; + }; + + jsonifyProxy = function ( proxy ) { + var result, name; + + if ( typeof proxy.name === 'string' ) { + if ( !proxy.args && !proxy.dynamicArgs ) { + return proxy.name; + } + + name = proxy.name; + } else { + name = getFragmentStubFromTokens( proxy.name ).toJSON(); + } + + result = { n: name }; + + if ( proxy.args ) { + result.a = proxy.args; + return result; + } + + if ( proxy.dynamicArgs ) { + result.d = getFragmentStubFromTokens( proxy.dynamicArgs ).toJSON(); + } + + return result; + }; + + +}()); +var ExpressionStub; + +(function () { + + var getRefs, stringify, stringifyKey, identifier; + + ExpressionStub = function ( token ) { + this.refs = []; + + getRefs( token, this.refs ); + this.str = stringify( token, this.refs ); + }; + + ExpressionStub.prototype = { + toJSON: function () { + if ( this.json ) { + return this.json; + } + + this.json = { + r: this.refs, + s: this.str + }; + + return this.json; + } + }; + + + // TODO maybe refactor this? + getRefs = function ( token, refs ) { + var i, list; + + if ( token.t === REFERENCE ) { + if ( refs.indexOf( token.n ) === -1 ) { + refs.unshift( token.n ); + } + } + + list = token.o || token.m; + if ( list ) { + if ( isObject( list ) ) { + getRefs( list, refs ); + } else { + i = list.length; + while ( i-- ) { + getRefs( list[i], refs ); + } + } + } + + if ( token.x ) { + getRefs( token.x, refs ); + } + + if ( token.r ) { + getRefs( token.r, refs ); + } + + if ( token.v ) { + getRefs( token.v, refs ); + } + }; + + + stringify = function ( token, refs ) { + var map = function ( item ) { + return stringify( item, refs ); + }; + + switch ( token.t ) { + case BOOLEAN_LITERAL: + case GLOBAL: + case NUMBER_LITERAL: + return token.v; + + case STRING_LITERAL: + return "'" + token.v.replace( /'/g, "\\'" ) + "'"; + + case ARRAY_LITERAL: + return '[' + ( token.m ? token.m.map( map ).join( ',' ) : '' ) + ']'; + + case OBJECT_LITERAL: + return '{' + ( token.m ? token.m.map( map ).join( ',' ) : '' ) + '}'; + + case KEY_VALUE_PAIR: + return stringifyKey( token.k ) + ':' + stringify( token.v, refs ); + + case PREFIX_OPERATOR: + return ( token.s === 'typeof' ? 'typeof ' : token.s ) + stringify( token.o, refs ); + + case INFIX_OPERATOR: + return stringify( token.o[0], refs ) + ( token.s.substr( 0, 2 ) === 'in' ? ' ' + token.s + ' ' : token.s ) + stringify( token.o[1], refs ); + + case INVOCATION: + return stringify( token.x, refs ) + '(' + ( token.o ? token.o.map( map ).join( ',' ) : '' ) + ')'; + + case BRACKETED: + return '(' + stringify( token.x, refs ) + ')'; + + case MEMBER: + return stringify( token.x, refs ) + stringify( token.r, refs ); + + case REFINEMENT: + return ( token.n ? '.' + token.n : '[' + stringify( token.x, refs ) + ']' ); + + case CONDITIONAL: + return stringify( token.o[0], refs ) + '?' + stringify( token.o[1], refs ) + ':' + stringify( token.o[2], refs ); + + case REFERENCE: + return '${' + refs.indexOf( token.n ) + '}'; + + default: + console.log( token ); + throw new Error( 'Could not stringify expression token. This error is unexpected' ); + } + }; + + stringifyKey = function ( key ) { + if ( key.t === STRING_LITERAL ) { + return identifier.test( key.v ) ? key.v : '"' + key.v.replace( /"/g, '\\"' ) + '"'; + } + + if ( key.t === NUMBER_LITERAL ) { + return key.v; + } + + return key; + }; + + identifier = /^[a-zA-Z_$][a-zA-Z_$0-9]*$/; + +}()); +var FragmentStub = function ( parser, preserveWhitespace ) { + var items, item; + + items = this.items = []; + + item = getItem( parser, preserveWhitespace ); + while ( item !== null ) { + items[ items.length ] = item; + item = getItem( parser, preserveWhitespace ); + } +}; + +FragmentStub.prototype = { + toJSON: function ( noStringify ) { + var json; + + if ( this[ 'json_' + noStringify ] ) { + return this[ 'json_' + noStringify ]; + } + + json = this[ 'json_' + noStringify ] = jsonifyStubs( this.items, noStringify ); + return json; + }, + + toString: function () { + if ( this.str !== undefined ) { + return this.str; + } + + this.str = stringifyStubs( this.items ); + return this.str; + } +}; +var MustacheStub = function ( token, parser ) { + this.type = ( token.type === TRIPLE ? TRIPLE : token.mustacheType ); + + if ( token.ref ) { + this.ref = token.ref; + } + + if ( token.expression ) { + this.expr = new ExpressionStub( token.expression ); + } + + parser.pos += 1; +}; + +MustacheStub.prototype = { + toJSON: function () { + var json; + + if ( this.json ) { + return this.json; + } + + json = { + t: this.type + }; + + if ( this.ref ) { + json.r = this.ref; + } + + if ( this.expr ) { + json.x = this.expr.toJSON(); + } + + this.json = json; + return json; + }, + + toString: function () { + // mustaches cannot be stringified + return false; + } +}; +var SectionStub = function ( firstToken, parser, preserveWhitespace ) { + var next; + + this.ref = firstToken.ref; + this.indexRef = firstToken.indexRef; + + this.inverted = ( firstToken.mustacheType === INVERTED ); + + if ( firstToken.expression ) { + this.expr = new ExpressionStub( firstToken.expression ); + } + + parser.pos += 1; + + this.items = []; + next = parser.next(); + + while ( next ) { + if ( next.mustacheType === CLOSING ) { + if ( ( next.ref.trim() === this.ref ) || this.expr ) { + parser.pos += 1; + break; + } + + else { + throw new Error( 'Could not parse template: Illegal closing section' ); + } + } + + this.items[ this.items.length ] = getItem( parser, preserveWhitespace ); + next = parser.next(); + } +}; + +SectionStub.prototype = { + toJSON: function ( noStringify ) { + var json; + + if ( this.json ) { + return this.json; + } + + json = { t: SECTION }; + + if ( this.ref ) { + json.r = this.ref; + } + + if ( this.indexRef ) { + json.i = this.indexRef; + } + + if ( this.inverted ) { + json.n = true; + } + + if ( this.expr ) { + json.x = this.expr.toJSON(); + } + + if ( this.items.length ) { + json.f = jsonifyStubs( this.items, noStringify ); + } + + this.json = json; + return json; + }, + + toString: function () { + // sections cannot be stringified + return false; + } +}; +var TextStub; + +(function () { + + var htmlEntities, decodeCharacterReferences, whitespace; + + TextStub = function ( token, preserveWhitespace ) { + this.type = TEXT; + this.text = ( preserveWhitespace ? token.value : token.value.replace( whitespace, ' ' ) ); + }; + + TextStub.prototype = { + toJSON: function () { + // this will be used within HTML, so we need to decode things like & + return this.decoded || ( this.decoded = decodeCharacterReferences( this.text) ); + }, + + toString: function () { + // this will be used as straight text + return this.text; + } + }; + + htmlEntities = { quot: 34, amp: 38, apos: 39, lt: 60, gt: 62, nbsp: 160, iexcl: 161, cent: 162, pound: 163, curren: 164, yen: 165, brvbar: 166, sect: 167, uml: 168, copy: 169, ordf: 170, laquo: 171, not: 172, shy: 173, reg: 174, macr: 175, deg: 176, plusmn: 177, sup2: 178, sup3: 179, acute: 180, micro: 181, para: 182, middot: 183, cedil: 184, sup1: 185, ordm: 186, raquo: 187, frac14: 188, frac12: 189, frac34: 190, iquest: 191, Agrave: 192, Aacute: 193, Acirc: 194, Atilde: 195, Auml: 196, Aring: 197, AElig: 198, Ccedil: 199, Egrave: 200, Eacute: 201, Ecirc: 202, Euml: 203, Igrave: 204, Iacute: 205, Icirc: 206, Iuml: 207, ETH: 208, Ntilde: 209, Ograve: 210, Oacute: 211, Ocirc: 212, Otilde: 213, Ouml: 214, times: 215, Oslash: 216, Ugrave: 217, Uacute: 218, Ucirc: 219, Uuml: 220, Yacute: 221, THORN: 222, szlig: 223, agrave: 224, aacute: 225, acirc: 226, atilde: 227, auml: 228, aring: 229, aelig: 230, ccedil: 231, egrave: 232, eacute: 233, ecirc: 234, euml: 235, igrave: 236, iacute: 237, icirc: 238, iuml: 239, eth: 240, ntilde: 241, ograve: 242, oacute: 243, ocirc: 244, otilde: 245, ouml: 246, divide: 247, oslash: 248, ugrave: 249, uacute: 250, ucirc: 251, uuml: 252, yacute: 253, thorn: 254, yuml: 255, OElig: 338, oelig: 339, Scaron: 352, scaron: 353, Yuml: 376, fnof: 402, circ: 710, tilde: 732, Alpha: 913, Beta: 914, Gamma: 915, Delta: 916, Epsilon: 917, Zeta: 918, Eta: 919, Theta: 920, Iota: 921, Kappa: 922, Lambda: 923, Mu: 924, Nu: 925, Xi: 926, Omicron: 927, Pi: 928, Rho: 929, Sigma: 931, Tau: 932, Upsilon: 933, Phi: 934, Chi: 935, Psi: 936, Omega: 937, alpha: 945, beta: 946, gamma: 947, delta: 948, epsilon: 949, zeta: 950, eta: 951, theta: 952, iota: 953, kappa: 954, lambda: 955, mu: 956, nu: 957, xi: 958, omicron: 959, pi: 960, rho: 961, sigmaf: 962, sigma: 963, tau: 964, upsilon: 965, phi: 966, chi: 967, psi: 968, omega: 969, thetasym: 977, upsih: 978, piv: 982, ensp: 8194, emsp: 8195, thinsp: 8201, zwnj: 8204, zwj: 8205, lrm: 8206, rlm: 8207, ndash: 8211, mdash: 8212, lsquo: 8216, rsquo: 8217, sbquo: 8218, ldquo: 8220, rdquo: 8221, bdquo: 8222, dagger: 8224, Dagger: 8225, bull: 8226, hellip: 8230, permil: 8240, prime: 8242, Prime: 8243, lsaquo: 8249, rsaquo: 8250, oline: 8254, frasl: 8260, euro: 8364, image: 8465, weierp: 8472, real: 8476, trade: 8482, alefsym: 8501, larr: 8592, uarr: 8593, rarr: 8594, darr: 8595, harr: 8596, crarr: 8629, lArr: 8656, uArr: 8657, rArr: 8658, dArr: 8659, hArr: 8660, forall: 8704, part: 8706, exist: 8707, empty: 8709, nabla: 8711, isin: 8712, notin: 8713, ni: 8715, prod: 8719, sum: 8721, minus: 8722, lowast: 8727, radic: 8730, prop: 8733, infin: 8734, ang: 8736, and: 8743, or: 8744, cap: 8745, cup: 8746, 'int': 8747, there4: 8756, sim: 8764, cong: 8773, asymp: 8776, ne: 8800, equiv: 8801, le: 8804, ge: 8805, sub: 8834, sup: 8835, nsub: 8836, sube: 8838, supe: 8839, oplus: 8853, otimes: 8855, perp: 8869, sdot: 8901, lceil: 8968, rceil: 8969, lfloor: 8970, rfloor: 8971, lang: 9001, rang: 9002, loz: 9674, spades: 9824, clubs: 9827, hearts: 9829, diams: 9830 }; + + decodeCharacterReferences = function ( html ) { + var result; + + // named entities + result = html.replace( /&([a-zA-Z]+);/, function ( match, name ) { + if ( htmlEntities[ name ] ) { + return String.fromCharCode( htmlEntities[ name ] ); + } + + return match; + }); + + // hex references + result = result.replace( /&#x([0-9]+);/, function ( match, hex ) { + return String.fromCharCode( parseInt( hex, 16 ) ); + }); + + // decimal references + result = result.replace( /&#([0-9]+);/, function ( match, num ) { + return String.fromCharCode( num ); + }); + + return result; + }; + + whitespace = /\s+/g; + +}()); +getFragmentStubFromTokens = function ( tokens, options, preserveWhitespace ) { + var parser, stub; + + parser = { + pos: 0, + tokens: tokens || [], + next: function () { + return parser.tokens[ parser.pos ]; + }, + options: options + }; + + stub = new FragmentStub( parser, preserveWhitespace ); + + return stub; +}; +var getExpression; + +// expression +(function () { + var getExpressionList, + makePrefixSequenceMatcher, + makeInfixSequenceMatcher, + getBracketedExpression, + getPrimary, + getMember, + getInvocation, + getInvocationRefinement, + getTypeOf, + getLogicalOr, + getConditional, + + getDigits, + getExponent, + getFraction, + getInteger, + + getReference, + getRefinement, + + getLiteral, + getArrayLiteral, + getBooleanLiteral, + getNumberLiteral, + getStringLiteral, + getObjectLiteral, + getGlobal, + + getKeyValuePairs, + getKeyValuePair, + getKey, + + getName, + + getDotRefinement, + getArrayRefinement, + getArrayMember, + + globals; + + getExpression = function ( tokenizer ) { + // The conditional operator is the lowest precedence operator (except yield, + // assignment operators, and commas, none of which are supported), so we + // start there. If it doesn't match, it 'falls through' to progressively + // higher precedence operators, until it eventually matches (or fails to + // match) a 'primary' - a literal or a reference. This way, the abstract syntax + // tree has everything in its proper place, i.e. 2 + 3 * 4 === 14, not 20. + return getConditional( tokenizer ); + }; + + getExpressionList = function ( tokenizer ) { + var start, expressions, expr, next; + + start = tokenizer.pos; + + allowWhitespace( tokenizer ); + + expr = getExpression( tokenizer ); + + if ( expr === null ) { + return null; + } + + expressions = [ expr ]; + + // allow whitespace between expression and ',' + allowWhitespace( tokenizer ); + + if ( getStringMatch( tokenizer, ',' ) ) { + next = getExpressionList( tokenizer ); + if ( next === null ) { + tokenizer.pos = start; + return null; + } + + expressions = expressions.concat( next ); + } + + return expressions; + }; + + getBracketedExpression = function ( tokenizer ) { + var start, expr; + + start = tokenizer.pos; + + if ( !getStringMatch( tokenizer, '(' ) ) { + return null; + } + + allowWhitespace( tokenizer ); + + expr = getExpression( tokenizer ); + if ( !expr ) { + tokenizer.pos = start; + return null; + } + + allowWhitespace( tokenizer ); + + if ( !getStringMatch( tokenizer, ')' ) ) { + tokenizer.pos = start; + return null; + } + + return { + t: BRACKETED, + x: expr + }; + }; + + getPrimary = function ( tokenizer ) { + return getLiteral( tokenizer ) + || getReference( tokenizer ) + || getBracketedExpression( tokenizer ); + }; + + getMember = function ( tokenizer ) { + var expression, refinement, member; + + expression = getPrimary( tokenizer ); + if ( !expression ) { + return null; + } + + refinement = getRefinement( tokenizer ); + if ( !refinement ) { + return expression; + } + + while ( refinement !== null ) { + member = { + t: MEMBER, + x: expression, + r: refinement + }; + + expression = member; + refinement = getRefinement( tokenizer ); + } + + return member; + }; + + getInvocation = function ( tokenizer ) { + var start, expression, expressionList, result; + + expression = getMember( tokenizer ); + if ( !expression ) { + return null; + } + + start = tokenizer.pos; + + if ( !getStringMatch( tokenizer, '(' ) ) { + return expression; + } + + allowWhitespace( tokenizer ); + expressionList = getExpressionList( tokenizer ); + + allowWhitespace( tokenizer ); + + if ( !getStringMatch( tokenizer, ')' ) ) { + tokenizer.pos = start; + return expression; + } + + result = { + t: INVOCATION, + x: expression + }; + + if ( expressionList ) { + result.o = expressionList; + } + + return result; + }; + + getInvocationRefinement = function ( tokenizer ) { + var expression, refinement, member; + + expression = getInvocation( tokenizer ); + if ( !expression ) { + return null; + } + + if ( expression.t !== INVOCATION ) { + return expression; + } + + refinement = getRefinement( tokenizer ); + if ( !refinement ) { + return expression; + } + + while ( refinement !== null ) { + member = { + t: MEMBER, + x: expression, + r: refinement + }; + + expression = member; + refinement = getRefinement( tokenizer ); + } + + return member; + }; + + // right-to-left + makePrefixSequenceMatcher = function ( symbol, fallthrough ) { + return function ( tokenizer ) { + var start, expression; + + if ( !getStringMatch( tokenizer, symbol ) ) { + return fallthrough( tokenizer ); + } + + start = tokenizer.pos; + + allowWhitespace( tokenizer ); + + expression = getExpression( tokenizer ); + if ( !expression ) { + fail( tokenizer, 'an expression' ); + } + + return { + s: symbol, + o: expression, + t: PREFIX_OPERATOR + }; + }; + }; + + // create all prefix sequence matchers + (function () { + var i, len, matcher, prefixOperators, fallthrough; + + prefixOperators = '! ~ + - typeof'.split( ' ' ); + + // An invocation refinement is higher precedence than logical-not + fallthrough = getInvocationRefinement; + for ( i=0, len=prefixOperators.length; i tokenizer.delimiters[0].length ) { + return getTriple( tokenizer ) || getMustache( tokenizer ); + } + + return getMustache( tokenizer ) || getTriple( tokenizer ); + }; + + getMustache = function ( tokenizer ) { + var start = tokenizer.pos, content; + + if ( !getStringMatch( tokenizer, tokenizer.delimiters[0] ) ) { + return null; + } + + // delimiter change? + content = getDelimiterChange( tokenizer ); + if ( content ) { + // find closing delimiter or abort... + if ( !getStringMatch( tokenizer, tokenizer.delimiters[1] ) ) { + tokenizer.pos = start; + return null; + } + + // ...then make the switch + tokenizer.delimiters = content; + return { type: MUSTACHE, mustacheType: DELIMCHANGE }; + } + + content = getMustacheContent( tokenizer ); + + if ( content === null ) { + tokenizer.pos = start; + return null; + } + + // allow whitespace before closing delimiter + allowWhitespace( tokenizer ); + + if ( !getStringMatch( tokenizer, tokenizer.delimiters[1] ) ) { + fail( tokenizer, '"' + tokenizer.delimiters[1] + '"' ); + } + + return content; + }; + + getTriple = function ( tokenizer ) { + var start = tokenizer.pos, content; + + if ( !getStringMatch( tokenizer, tokenizer.tripleDelimiters[0] ) ) { + return null; + } + + // delimiter change? + content = getDelimiterChange( tokenizer ); + if ( content ) { + // find closing delimiter or abort... + if ( !getStringMatch( tokenizer, tokenizer.tripleDelimiters[1] ) ) { + tokenizer.pos = start; + return null; + } + + // ...then make the switch + tokenizer.tripleDelimiters = content; + return { type: MUSTACHE, mustacheType: DELIMCHANGE }; + } + + // allow whitespace between opening delimiter and reference + allowWhitespace( tokenizer ); + + content = getMustacheContent( tokenizer, true ); + + if ( content === null ) { + tokenizer.pos = start; + return null; + } + + // allow whitespace between reference and closing delimiter + allowWhitespace( tokenizer ); + + if ( !getStringMatch( tokenizer, tokenizer.tripleDelimiters[1] ) ) { + tokenizer.pos = start; + return null; + } + + return content; + }; + + getMustacheContent = function ( tokenizer, isTriple ) { + var start, mustache, type, expr, i, remaining, index; + + start = tokenizer.pos; + + mustache = { type: isTriple ? TRIPLE : MUSTACHE }; + + // mustache type + if ( !isTriple ) { + type = getMustacheType( tokenizer ); + mustache.mustacheType = type || INTERPOLATOR; // default + + // if it's a comment or a section closer, allow any contents except '}}' + if ( type === COMMENT || type === CLOSING ) { + remaining = tokenizer.remaining(); + index = remaining.indexOf( tokenizer.delimiters[1] ); + + if ( index !== -1 ) { + mustache.ref = remaining.substr( 0, index ); + tokenizer.pos += index; + return mustache; + } + } + } + + // allow whitespace + allowWhitespace( tokenizer ); + + // get expression + expr = getExpression( tokenizer ); + + while ( expr.t === BRACKETED && expr.x ) { + expr = expr.x; + } + + if ( expr.t === REFERENCE ) { + mustache.ref = expr.n; + } else { + mustache.expression = expr; + } + + // optional index reference + i = getIndexRef( tokenizer ); + if ( i !== null ) { + mustache.indexRef = i; + } + + return mustache; + }; + + mustacheTypes = { + '#': SECTION, + '^': INVERTED, + '/': CLOSING, + '>': PARTIAL, + '!': COMMENT, + '&': INTERPOLATOR + }; + + getMustacheType = function ( tokenizer ) { + var type = mustacheTypes[ tokenizer.str.charAt( tokenizer.pos ) ]; + + if ( !type ) { + return null; + } + + tokenizer.pos += 1; + return type; + }; + + getIndexRef = getRegexMatcher( /^\s*:\s*([a-zA-Z_$][a-zA-Z_$0-9]*)/ ); + + getDelimiter = getRegexMatcher( /^[^\s=]+/ ); + + getDelimiterChange = function ( tokenizer ) { + var start, opening, closing; + + if ( !getStringMatch( tokenizer, '=' ) ) { + return null; + } + + start = tokenizer.pos; + + // allow whitespace before new opening delimiter + allowWhitespace( tokenizer ); + + opening = getDelimiter( tokenizer ); + if ( !opening ) { + tokenizer.pos = start; + return null; + } + + // allow whitespace (in fact, it's necessary...) + allowWhitespace( tokenizer ); + + closing = getDelimiter( tokenizer ); + if ( !closing ) { + tokenizer.pos = start; + return null; + } + + // allow whitespace before closing '=' + allowWhitespace( tokenizer ); + + if ( !getStringMatch( tokenizer, '=' ) ) { + tokenizer.pos = start; + return null; + } + + return [ opening, closing ]; + }; + +}()); +var getTag; + +(function () { + var getOpeningTag, + getClosingTag, + getTagName, + getAttributes, + getAttribute, + getAttributeName, + getAttributeValue, + getUnquotedAttributeValue, + getUnquotedAttributeValueToken, + getUnquotedAttributeValueText, + getSingleQuotedAttributeValue, + getSingleQuotedStringToken, + getDoubleQuotedAttributeValue, + getDoubleQuotedStringToken; + + getTag = function ( tokenizer ) { + return ( getOpeningTag( tokenizer ) || getClosingTag( tokenizer ) ); + }; + + getOpeningTag = function ( tokenizer ) { + var start, tag, attrs; + + start = tokenizer.pos; + + if ( !getStringMatch( tokenizer, '<' ) ) { + return null; + } + + tag = { + type: TAG + }; + + // tag name + tag.name = getTagName( tokenizer ); + if ( !tag.name ) { + tokenizer.pos = start; + return null; + } + + // attributes + attrs = getAttributes( tokenizer ); + if ( attrs ) { + tag.attrs = attrs; + } + + // allow whitespace before closing solidus + allowWhitespace( tokenizer ); + + // self-closing solidus? + if ( getStringMatch( tokenizer, '/' ) ) { + tag.selfClosing = true; + } + + // closing angle bracket + if ( !getStringMatch( tokenizer, '>' ) ) { + tokenizer.pos = start; + return null; + } + + return tag; + }; + + getClosingTag = function ( tokenizer ) { + var start, tag; + + start = tokenizer.pos; + + if ( !getStringMatch( tokenizer, '<' ) ) { + return null; + } + + tag = { type: TAG, closing: true }; + + // closing solidus + if ( !getStringMatch( tokenizer, '/' ) ) { + throw new Error( 'Unexpected character ' + tokenizer.remaining().charAt( 0 ) + ' (expected "/")' ); + } + + // tag name + tag.name = getTagName( tokenizer ); + if ( !tag.name ) { + throw new Error( 'Unexpected character ' + tokenizer.remaining().charAt( 0 ) + ' (expected tag name)' ); + } + + // closing angle bracket + if ( !getStringMatch( tokenizer, '>' ) ) { + throw new Error( 'Unexpected character ' + tokenizer.remaining().charAt( 0 ) + ' (expected ">")' ); + } + + return tag; + }; + + getTagName = getRegexMatcher( /^[a-zA-Z][a-zA-Z0-9\-]*/ ); + + getAttributes = function ( tokenizer ) { + var start, attrs, attr; + + start = tokenizer.pos; + + allowWhitespace( tokenizer ); + + attr = getAttribute( tokenizer ); + + if ( !attr ) { + tokenizer.pos = start; + return null; + } + + attrs = []; + + while ( attr !== null ) { + attrs[ attrs.length ] = attr; + + allowWhitespace( tokenizer ); + attr = getAttribute( tokenizer ); + } + + return attrs; + }; + + getAttribute = function ( tokenizer ) { + var attr, name, value; + + name = getAttributeName( tokenizer ); + if ( !name ) { + return null; + } + + attr = { + name: name + }; + + value = getAttributeValue( tokenizer ); + if ( value ) { + attr.value = value; + } + + return attr; + }; + + getAttributeName = getRegexMatcher( /^[^\s"'>\/=]+/ ); + + + + getAttributeValue = function ( tokenizer ) { + var start, value; + + start = tokenizer.pos; + + allowWhitespace( tokenizer ); + + if ( !getStringMatch( tokenizer, '=' ) ) { + tokenizer.pos = start; + return null; + } + + value = getSingleQuotedAttributeValue( tokenizer ) || getDoubleQuotedAttributeValue( tokenizer ) || getUnquotedAttributeValue( tokenizer ); + + if ( value === null ) { + tokenizer.pos = start; + return null; + } + + return value; + }; + + getUnquotedAttributeValueText = getRegexMatcher( /^[^\s"'=<>`]+/ ); + + getUnquotedAttributeValueToken = function ( tokenizer ) { + var start, text, index; + + start = tokenizer.pos; + + text = getUnquotedAttributeValueText( tokenizer ); + + if ( !text ) { + return null; + } + + if ( ( index = text.indexOf( tokenizer.delimiters[0] ) ) !== -1 ) { + text = text.substr( 0, index ); + tokenizer.pos = start + text.length; + } + + return { + type: TEXT, + value: text + }; + }; + + getUnquotedAttributeValue = function ( tokenizer ) { + var tokens, token; + + tokens = []; + + token = getMustacheOrTriple( tokenizer ) || getUnquotedAttributeValueToken( tokenizer ); + while ( token !== null ) { + tokens[ tokens.length ] = token; + token = getMustacheOrTriple( tokenizer ) || getUnquotedAttributeValueToken( tokenizer ); + } + + if ( !tokens.length ) { + return null; + } + + return tokens; + }; + + + getSingleQuotedStringToken = function ( tokenizer ) { + var start, text, index; + + start = tokenizer.pos; + + text = getSingleQuotedString( tokenizer ); + + if ( !text ) { + return null; + } + + if ( ( index = text.indexOf( tokenizer.delimiters[0] ) ) !== -1 ) { + text = text.substr( 0, index ); + tokenizer.pos = start + text.length; + } + + return { + type: TEXT, + value: text + }; + }; + + getSingleQuotedAttributeValue = function ( tokenizer ) { + var start, tokens, token; + + start = tokenizer.pos; + + if ( !getStringMatch( tokenizer, "'" ) ) { + return null; + } + + tokens = []; + + token = getMustacheOrTriple( tokenizer ) || getSingleQuotedStringToken( tokenizer ); + while ( token !== null ) { + tokens[ tokens.length ] = token; + token = getMustacheOrTriple( tokenizer ) || getSingleQuotedStringToken( tokenizer ); + } + + if ( !getStringMatch( tokenizer, "'" ) ) { + tokenizer.pos = start; + return null; + } + + return tokens; + + }; + + getDoubleQuotedStringToken = function ( tokenizer ) { + var start, text, index; + + start = tokenizer.pos; + + text = getDoubleQuotedString( tokenizer ); + + if ( !text ) { + return null; + } + + if ( ( index = text.indexOf( tokenizer.delimiters[0] ) ) !== -1 ) { + text = text.substr( 0, index ); + tokenizer.pos = start + text.length; + } + + return { + type: TEXT, + value: text + }; + }; + + getDoubleQuotedAttributeValue = function ( tokenizer ) { + var start, tokens, token; + + start = tokenizer.pos; + + if ( !getStringMatch( tokenizer, '"' ) ) { + return null; + } + + tokens = []; + + token = getMustacheOrTriple( tokenizer ) || getDoubleQuotedStringToken( tokenizer ); + while ( token !== null ) { + tokens[ tokens.length ] = token; + token = getMustacheOrTriple( tokenizer ) || getDoubleQuotedStringToken( tokenizer ); + } + + if ( !getStringMatch( tokenizer, '"' ) ) { + tokenizer.pos = start; + return null; + } + + return tokens; + + }; +}()); +var getText = function ( tokenizer ) { + var minIndex, text; + + minIndex = tokenizer.str.length; + + // anything goes except opening delimiters or a '<' + [ tokenizer.delimiters[0], tokenizer.tripleDelimiters[0], '<' ].forEach( function ( substr ) { + var index = tokenizer.str.indexOf( substr, tokenizer.pos ); + + if ( index !== -1 ) { + minIndex = Math.min( index, minIndex ); + } + }); + + if ( minIndex === tokenizer.pos ) { + return null; + } + + text = tokenizer.str.substring( tokenizer.pos, minIndex ); + tokenizer.pos = minIndex; + + return { + type: TEXT, + value: text + }; + +}; +getToken = function ( tokenizer ) { + var token = getMustacheOrTriple( tokenizer ) || + getTag( tokenizer ) || + getText( tokenizer ); + + return token; +}; +var getDoubleQuotedString = function ( tokenizer ) { + var start, string, escaped, unescaped, next; + + start = tokenizer.pos; + + string = ''; + + escaped = getEscapedChars( tokenizer ); + if ( escaped ) { + string += escaped; + } + + unescaped = getUnescapedDoubleQuotedChars( tokenizer ); + if ( unescaped ) { + string += unescaped; + } + + if ( !string ) { + return ''; + } + + next = getDoubleQuotedString( tokenizer ); + while ( next !== '' ) { + string += next; + } + + return string; +}; + +var getUnescapedDoubleQuotedChars = getRegexMatcher( /^[^\\"]+/ ); +var getEscapedChar = function ( tokenizer ) { + var character; + + if ( !getStringMatch( tokenizer, '\\' ) ) { + return null; + } + + character = tokenizer.str.charAt( tokenizer.pos ); + tokenizer.pos += 1; + + return character; +}; +var getEscapedChars = function ( tokenizer ) { + var chars = '', character; + + character = getEscapedChar( tokenizer ); + while ( character ) { + chars += character; + character = getEscapedChar( tokenizer ); + } + + return chars || null; +}; +var getSingleQuotedString = function ( tokenizer ) { + var start, string, escaped, unescaped, next; + + start = tokenizer.pos; + + string = ''; + + escaped = getEscapedChars( tokenizer ); + if ( escaped ) { + string += escaped; + } + + unescaped = getUnescapedSingleQuotedChars( tokenizer ); + if ( unescaped ) { + string += unescaped; + } + if ( string ) { + next = getSingleQuotedString( tokenizer ); + while ( next ) { + string += next; + next = getSingleQuotedString( tokenizer ); + } + } + + return string; +}; + +var getUnescapedSingleQuotedChars = getRegexMatcher( /^[^\\']+/ ); +// Ractive.parse +// =============== +// +// Takes in a string, and returns an object representing the parsed template. +// A parsed template is an array of 1 or more 'descriptors', which in some +// cases have children. +// +// The format is optimised for size, not readability, however for reference the +// keys for each descriptor are as follows: +// +// * r - Reference, e.g. 'mustache' in {{mustache}} +// * t - Type code (e.g. 1 is text, 2 is interpolator...) +// * f - Fragment. Contains a descriptor's children +// * e - Element name +// * a - map of element Attributes, or proxy event/transition Arguments +// * d - Dynamic proxy event/transition arguments +// * n - indicates an iNverted section +// * i - Index reference, e.g. 'num' in {{#section:num}}content{{/section}} +// * v - eVent proxies (i.e. when user e.g. clicks on a node, fire proxy event) +// * c - Conditionals (e.g. ['yes', 'no'] in {{condition ? yes : no}}) +// * x - eXpressions +// * t1 - intro Transition +// * t2 - outro Transition + +(function () { + + var onlyWhitespace, inlinePartialStart, inlinePartialEnd, parseCompoundTemplate; + + onlyWhitespace = /^\s*$/; + + inlinePartialStart = //; + inlinePartialEnd = //; + + parse = function ( template, options ) { + var tokens, fragmentStub, json, token; + + options = options || {}; + + // does this template include inline partials? + if ( inlinePartialStart.test( template ) ) { + return parseCompoundTemplate( template, options ); + } + + + if ( options.sanitize === true ) { + options.sanitize = { + // blacklist from https://code.google.com/p/google-caja/source/browse/trunk/src/com/google/caja/lang/html/html4-elements-whitelist.json + elements: 'applet base basefont body frame frameset head html isindex link meta noframes noscript object param script style title'.split( ' ' ), + eventAttributes: true + }; + } + + tokens = tokenize( template, options ); + + if ( !options.preserveWhitespace ) { + // remove first token if it only contains whitespace + token = tokens[0]; + if ( token && ( token.type === TEXT ) && onlyWhitespace.test( token.value ) ) { + tokens.shift(); + } + + // ditto last token + token = tokens[ tokens.length - 1 ]; + if ( token && ( token.type === TEXT ) && onlyWhitespace.test( token.value ) ) { + tokens.pop(); + } + } + + fragmentStub = getFragmentStubFromTokens( tokens, options, options.preserveWhitespace ); + + json = fragmentStub.toJSON(); + + if ( typeof json === 'string' ) { + // If we return it as a string, Ractive will attempt to reparse it! + // Instead we wrap it in an array. Ractive knows what to do then + return [ json ]; + } + + return json; + }; + + + parseCompoundTemplate = function ( template, options ) { + var mainTemplate, remaining, partials, name, startMatch, endMatch; + + partials = {}; + + mainTemplate = ''; + remaining = template; + + while ( startMatch = inlinePartialStart.exec( remaining ) ) { + name = startMatch[1]; + + mainTemplate += remaining.substr( 0, startMatch.index ); + remaining = remaining.substring( startMatch.index + startMatch[0].length ); + + endMatch = inlinePartialEnd.exec( remaining ); + + if ( !endMatch || endMatch[1] !== name ) { + throw new Error( 'Inline partials must have a closing delimiter, and cannot be nested' ); + } + + partials[ name ] = parse( remaining.substr( 0, endMatch.index ), options ); + + remaining = remaining.substring( endMatch.index + endMatch[0].length ); + } + + return { + main: parse( mainTemplate, options ), + partials: partials + }; + }; + +}()); +tokenize = function ( template, options ) { + var tokenizer, tokens, token, last20, next20; + + options = options || {}; + + tokenizer = { + str: stripHtmlComments( template ), + pos: 0, + delimiters: options.delimiters || [ '{{', '}}' ], + tripleDelimiters: options.tripleDelimiters || [ '{{{', '}}}' ], + remaining: function () { + return tokenizer.str.substring( tokenizer.pos ); + } + }; + + tokens = []; + + while ( tokenizer.pos < tokenizer.str.length ) { + token = getToken( tokenizer ); + + if ( token === null && tokenizer.remaining() ) { + last20 = tokenizer.str.substr( 0, tokenizer.pos ).substr( -20 ); + if ( last20.length === 20 ) { + last20 = '...' + last20; + } + + next20 = tokenizer.remaining().substr( 0, 20 ); + if ( next20.length === 20 ) { + next20 = next20 + '...'; + } + + throw new Error( 'Could not parse template: ' + ( last20 ? last20 + '<- ' : '' ) + 'failed at character ' + tokenizer.pos + ' ->' + next20 ); + } + + tokens[ tokens.length ] = token; + } + + stripStandalones( tokens ); + stripCommentTokens( tokens ); + + return tokens; +}; +Ractive.prototype = proto; + +Ractive.adaptors = adaptors; +Ractive.eventDefinitions = eventDefinitions; +Ractive.partials = {}; + +Ractive.easing = easing; +Ractive.extend = extend; +Ractive.interpolate = interpolate; +Ractive.interpolators = interpolators; +Ractive.parse = parse; + +// TODO add some more transitions +Ractive.transitions = transitions; + +Ractive.VERSION = VERSION; + + +// export as Common JS module... +if ( typeof module !== "undefined" && module.exports ) { + module.exports = Ractive; +} + +// ... or as AMD module +else if ( typeof define === "function" && define.amd ) { + define( function () { + return Ractive; + }); +} + +// ... or as browser global +else { + global.Ractive = Ractive; +} + +}( typeof window !== 'undefined' ? window : this )); \ No newline at end of file diff --git a/ajax/libs/ractive.js/0.3.6/ractive.min.js b/ajax/libs/ractive.js/0.3.6/ractive.min.js new file mode 100755 index 000000000..7a607954c --- /dev/null +++ b/ajax/libs/ractive.js/0.3.6/ractive.min.js @@ -0,0 +1,3 @@ +!function(a){"use strict";var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,$,_,ab,bb,cb,db,eb,fb,gb,hb,ib,jb,kb,lb,mb,nb,ob,pb,qb,rb,sb,tb,ub,vb="0.3.6",wb=a.document||null,xb={},yb={},zb={},Ab={},Bb={}.hasOwnProperty,Cb=function(){},Db=a.console||{log:Cb,warn:Cb},Eb={},Fb=/^\s+/,Gb=/\s+$/,Hb="Missing Ractive.parse - cannot parse template. Either preparse or use the version that includes the parser",Ib=1,Jb=2,Kb=3,Lb=4,Mb=5,Nb=6,Ob=7,Pb=8,Qb=9,Rb=10,Sb=11,Tb=12,Ub=15,Vb=20,Wb=21,Xb=22,Yb=23,Zb=24,$b=26,_b=27,ac=30,bc=31,cc=32,dc=33,ec=34,fc=35,gc=36,hc=40,ic={unset:!0},jc=wb?wb.createElement("div"):null,kc={html:"http://www.w3.org/1999/xhtml",mathml:"http://www.w3.org/1998/Math/MathML",svg:"http://www.w3.org/2000/svg",xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"};try{Object.defineProperty({},"test",{value:0}),Object.defineProperties({},{test:{value:0}}),wb&&(Object.defineProperty(jc,"test",{value:0}),Object.defineProperties(jc,{test:{value:0}})),F=Object.defineProperty,G=Object.defineProperties}catch(lc){F=function(a,b,c){a[b]=c.value},G=function(a,b){var c;for(c in b)b.hasOwnProperty(c)&&F(a,c,b[c])},ub=!0}try{Object.create(null),H=Object.create,I=function(){return Object.create(null)}}catch(lc){H=function(){var a=function(){};return function(b,c){var d;return a.prototype=b,d=new a,c&&Object.defineProperties(d,c),d}}(),I=function(){return{}}}var mc,nc,oc,pc=function(a){return a.replace(/[A-Z]/g,function(a){return"-"+a.toLowerCase()})};!function(){wb&&(void 0!==jc.style.transition?(nc="transition",oc="transitionend",mc=!0):void 0!==jc.style.webkitTransition?(nc="webkitTransition",oc="webkitTransitionEnd",mc=!0):mc=!1)}(),function(){var a,b,c,d,e,f,g,h,i,j,k,l;Q=function(){var b,d,e=this.parentNode;return this.fragment?(b=a(this))?(this.interpolator=b,this.keypath=b.keypath||b.descriptor.r,(d=c(this))?(e._ractive.binding=d,this.twoway=!0,!0):!1):!1:!1},b=function(){this._ractive.binding.update()},a=function(a){var b;return 1!==a.fragment.items.length?null:(b=a.fragment.items[0],b.type!==Jb?null:b.keypath||b.ref?b:null)},c=function(a){var b=a.parentNode;if("SELECT"===b.tagName)return b.multiple?new f(a,b):new g(a,b);if("checkbox"===b.type||"radio"===b.type){if("name"===a.propertyName){if("checkbox"===b.type)return new i(a,b);if("radio"===b.type)return new h(a,b)}return"checked"===a.propertyName?new j(a,b):null}return"value"!==a.propertyName&&Db.warn("This is... odd"),"file"===a.parentNode.type?new k(a,b):new l(a,b)},f=function(a,c){d(this,a,c),c.addEventListener("change",b,!1)},f.prototype={update:function(){var a,b,c,d,e,f,g;for(a=this.attr,e=a.value||[],b=[],c=this.node.querySelectorAll("option:checked"),g=c.length,d=0;g>d;d+=1)b[b.length]=c[d]._ractive.value;for(f=g!==e.length,d=b.length;d--;)b[d]!==e[d]&&(f=!0);(f=!0)&&(a.receiving=!0,a.value=b,this.root.set(this.keypath,b),a.receiving=!1)},teardown:function(){this.node.removeEventListener("change",b,!1)}},g=function(a,c){d(this,a,c),c.addEventListener("change",b,!1)},g.prototype={update:function(){var a,b;a=this.node.querySelector("option:checked"),a&&(b=a._ractive.value,this.attr.receiving=!0,this.attr.value=b,this.root.set(this.keypath,b),this.attr.receiving=!1)},teardown:function(){this.node.removeEventListener("change",b,!1)}},h=function(a,c){d(this,a,c),c.name="{{"+a.keypath+"}}",c.addEventListener("change",b,!1),c.attachEvent&&c.addEventListener("click",b,!1)},h.prototype={update:function(){var a=this.node;a.checked&&(this.attr.receiving=!0,this.root.set(this.keypath,a._ractive?a._ractive.value:a.value),this.attr.receiving=!1)},teardown:function(){this.node.removeEventListener("change",b,!1),this.node.removeEventListener("click",b,!1)}},i=function(a,c){d(this,a,c),c.name="{{"+this.keypath+"}}",this.query='input[type="checkbox"][name="'+c.name+'"]',c.addEventListener("change",b,!1),c.attachEvent&&c.addEventListener("click",b,!1)},i.prototype={update:function(){var a,b,c,d,f,g;for(a=this.root.get(this.keypath),c=this.root.el.querySelectorAll(this.query),d=c.length,b=[],f=0;d>f;f+=1)g=c[f],g.checked&&(b[b.length]=g._ractive.value);e(a,b)||(this.attr.receiving=!0,this.root.set(this.keypath,b),this.attr.receiving=!1)},teardown:function(){this.node.removeEventListener("change",b,!1),this.node.removeEventListener("click",b,!1)}},j=function(a,c){d(this,a,c),c.addEventListener("change",b,!1),c.attachEvent&&c.addEventListener("click",b,!1)},j.prototype={update:function(){this.attr.receiving=!0,this.root.set(this.keypath,this.node.checked),this.attr.receiving=!1},teardown:function(){this.node.removeEventListener("change",b,!1),this.node.removeEventListener("click",b,!1)}},k=function(a,c){d(this,a,c),c.addEventListener("change",b,!1)},k.prototype={update:function(){this.attr.root.set(this.attr.keypath,this.attr.parentNode.files)},teardown:function(){this.node.removeEventListener("change",b,!1)}},l=function(a,c){d(this,a,c),c.addEventListener("change",b,!1),this.root.lazy||(c.addEventListener("input",b,!1),c.attachEvent&&c.addEventListener("keyup",b,!1))},l.prototype={update:function(){var a=this.attr,b=a.parentNode.value;+b+""===b&&-1===b.indexOf("e")&&(b=+b),a.receiving=!0,a.root.set(a.keypath,b),a.receiving=!1},teardown:function(){this.node.removeEventListener("change",b,!1),this.node.removeEventListener("input",b,!1),this.node.removeEventListener("keyup",b,!1)}},d=function(a,b,c){a.attr=b,a.node=c,a.root=b.root,a.keypath=b.keypath},e=function(a,b){var c;if(!s(a)||!s(b))return!1;if(a.length!==b.length)return!1;for(c=a.length;c--;)if(a[c]!==b[c])return!1;return!0}}(),function(){var a,b,c,d,e,f,g,h;P=function(){var d;if(!this.ready)return this;if(d=this.parentNode,"SELECT"===d.tagName&&"value"===this.name)return this.update=b,this.deferredUpdate=c,this.update();if(this.isFileInputValue)return this.update=a,this;if(this.twoway&&"name"===this.name){if("radio"===d.type)return this.update=f,this.update();if("checkbox"===d.type)return this.update=g,this.update()}return this.update=h,this.update()},a=function(){return this},c=function(){this.deferredUpdate=this.parentNode.multiple?e:d,this.deferredUpdate()},b=function(){return this.root._defSelectValues.push(this),this},d=function(){var a,b,c,d=this.fragment.getValue();for(this.value=d,a=this.parentNode.querySelectorAll("option"),c=a.length;c--;)if(b=a[c],b._ractive.value===d)return b.selected=!0,this;return this},e=function(){var a,b,c=this.fragment.getValue();for(s(c)||(c=[c]),a=this.parentNode.querySelectorAll("option"),b=a.length;b--;)a[b].selected=-1!==c.indexOf(a[b]._ractive.value);return this.value=c,this},f=function(){var a,b;return a=this.parentNode,b=this.fragment.getValue(),a.checked=b===a._ractive.value,this},g=function(){var a,b;return a=this.parentNode,b=this.fragment.getValue(),s(b)?(a.checked=-1!==b.indexOf(a._ractive.value),this):(a.checked=b===a._ractive.value,this)},h=function(){var a,b;if(a=this.parentNode,b=this.fragment.getValue(),this.isValueAttribute&&(a._ractive.value=b),void 0===b&&(b=""),b!==this.value){if(this.useProperty)return this.receiving||(a[this.propertyName]=b),this.value=b,this;if(this.namespace)return a.setAttributeNS(this.namespace,this.name,b),this.value=b,this;"id"===this.name&&(void 0!==this.value&&(this.root.nodes[this.value]=void 0),this.root.nodes[b]=a),a.setAttribute(this.name,b),this.value=b}return this}}(),J=function(a,b){var c,d,e;for(d in b)if(Bb.call(b,d))for(e=d.split("-"),c=e.length;c--;)K(a,e[c],b[d],a.parentFragment.contextStack)},function(){var a,c,d,e,f,g,h,i;K=function(b,c,d,e,f){var g,h;g=b.ractify().events,h=g[c]||(g[c]=new a(b,c,e,f)),h.add(d)},a=function(a,c,d){var e;this.element=a,this.root=a.root,this.node=a.node,this.name=c,this.contextStack=d,this.proxies=[],(e=this.root.eventDefinitions[c]||b.eventDefinitions[c])?this.custom=e(this.node,i(c)):this.node.addEventListener(c,h,!1)},a.prototype={add:function(a){this.proxies[this.proxies.length]=new c(this.element,this.root,a,this.contextStack)},teardown:function(){var a;for(this.custom?this.custom.teardown():this.node.removeEventListener(this.name,h,!1),a=this.proxies.length;a--;)this.proxies[a].teardown()},fire:function(a){for(var b=this.proxies.length;b--;)this.proxies[b].fire(a)}},c=function(a,b,c,g){var h;return this.root=b,h=c.n||c,this.n="string"==typeof h?h:new $({descriptor:c.n,root:this.root,owner:a,contextStack:g}),c.a?(this.a=c.a,this.fire=e,void 0):c.d?(this.d=new $({descriptor:c.d,root:this.root,owner:a,contextStack:g}),this.fire=f,void 0):(this.fire=d,void 0)},c.prototype={teardown:function(){this.n.teardown&&this.n.teardown(),this.d&&this.d.teardown()},bubble:Cb},d=function(a){this.root.fire(this.n.toString(),a)},e=function(a){this.root.fire(this.n.toString(),a,this.a)},f=function(a){this.root.fire(this.n.toString(),a,this.d.toJSON())},h=function(a){var b=this._ractive;b.events[a.type].fire({node:this,original:a,index:b.index,keypath:b.keypath,context:b.root.get(b.keypath)})},g={},i=function(a){return g[a]?g[a]:g[a]=function(b){var c=b.node._ractive;b.index=c.index,b.keypath=c.keypath,b.context=c.root.get(c.keypath),c.events[a].fire(b)}}}(),L=function(a,b,c,d){"string"!=typeof c.f||b&&b.namespaceURI&&b.namespaceURI!==kc.html?"style"===c.e&&void 0!==b.styleSheet?(a.fragment=new $({descriptor:c.f,root:a.root,contextStack:a.parentFragment.contextStack,owner:a}),d&&(a.bubble=function(){b.styleSheet.cssText=a.fragment.toString()})):(a.fragment=new R({descriptor:c.f,root:a.root,parentNode:b,contextStack:a.parentFragment.contextStack,owner:a}),d&&b.appendChild(a.fragment.docFrag)):(a.html=c.f,d&&(b.innerHTML=a.html))},M=function(a,b){switch(a.ractify(),a.descriptor.e){case"select":case"textarea":return b.value&&b.value.bind(),void 0;case"input":if("radio"===a.node.type||"checkbox"===a.node.type){if(b.name&&b.name.bind())return a.node._ractive.binding.update(),void 0;if(b.checked&&b.checked.bind())return}if(b.value&&b.value.bind())return}},N=function(a,b){var c,d,e;a.attributes=[];for(c in b)Bb.call(b,c)&&(d=b[c],e=new T({element:a,name:c,value:d,root:a.root,parentNode:a.node,contextStack:a.parentFragment.contextStack}),a.attributes[a.attributes.length]=e,("value"===c||"name"===c||"checked"===c)&&(a.attributes[c]=e),"name"!==c&&e.update());return a.attributes},O=function(a,b){return a.a&&a.a.xmlns?a.a.xmlns:"svg"===a.e.toLowerCase()?kc.svg:b.namespaceURI},z=function(a,c,d,e,f){var g,h,i,j,k;c.transitionsEnabled&&("string"==typeof a?g=a:(g=a.n,a.a?h=a.a:a.d&&(i=new $({descriptor:a.d,root:c,owner:d,contextStack:d.parentFragment.contextStack}),h=i.toJSON(),i.teardown())),k=c.transitions[g]||b.transitions[g],k&&(j=c._transitionManager,j.push(d.node),k.call(c,d.node,function(){j.pop(d.node)},h,f)))},B=function(a,b){return a.components[b]},x=function(a,b){var c,d=[];for(c=wb.createElement("div"),c.innerHTML=a;c.firstChild;)d[d.length]=c.firstChild,b.appendChild(c.firstChild);return d},function(){var a,b,c;y=function(b,c,d,e,f){var g,h,i,j,k,l,m;for(i=c.descriptor.i,g=d;e>g;g+=1)h=c.fragments[g],j=g-f,k=g,l=c.keypath+"."+(g-f),m=c.keypath+"."+g,h.index+=f,a(h,i,j,k,f,l,m);p(b)},a=function(d,e,f,g,h,i,j){var k,l,m;for(d.indexRefs&&void 0!==d.indexRefs[e]&&(d.indexRefs[e]=g),k=d.contextStack.length;k--;)m=d.contextStack[k],m.substr(0,i.length)===i&&(d.contextStack[k]=m.replace(i,j));for(k=d.items.length;k--;)switch(l=d.items[k],l.type){case Ob:b(l,e,f,g,h,i,j);break;case Pb:a(l.fragment,e,f,g,h,i,j);break;case Lb:case Jb:case Kb:c(l,e,f,g,h,i,j)}},b=function(b,c,d,e,f,g,h){var i,j;for(i=b.attributes.length;i--;)j=b.attributes[i],j.fragment&&(a(j.fragment,c,d,e,f,g,h),j.twoway&&j.updateBindings());if(b.proxyFrags)for(i=b.proxyFrags.length;i--;)a(b.proxyFrags[i],c,d,e,f,g,h);b.node._ractive&&(b.node._ractive.keypath.substr(0,g.length)===g&&(b.node._ractive.keypath=b.node._ractive.keypath.replace(g,h)),void 0!==c&&(b.node._ractive.index[c]=e)),b.fragment&&a(b.fragment,c,d,e,f,g,h)},c=function(b,c,d,e,f,g,h){var i;if(b.descriptor.x&&(b.keypath&&k(b),b.expressionResolver&&b.expressionResolver.teardown(),b.expressionResolver=new cb(b)),b.keypath?b.keypath.substr(0,g.length)===g&&(k(b),b.keypath=b.keypath.replace(g,h),j(b)):b.indexRef===c&&(b.value=e,b.render(e)),b.fragments)for(i=b.fragments.length;i--;)a(b.fragments[i],c,d,e,f,g,h)}}(),function(a){var b,c,d,e;db=function(a,d,e,f,g){var h,i;for(this.root=a,this.keypath=d,this.fn=c(e,f.length),this.values=[],this.refs=[],h=f.length;h--;)i=f[h],i[0]?this.values[h]=i[1]:this.refs[this.refs.length]=new b(a,i[1],this,h,g);this.selfUpdating=this.refs.length<=1},db.prototype={bubble:function(){this.selfUpdating?this.update():this.deferred||(this.root._defEvals[this.root._defEvals.length]=this,this.deferred=!0)},update:function(){var a;if(this.evaluating)return this;this.evaluating=!0;try{a=this.fn.apply(null,this.values)}catch(b){if(this.root.debug)throw b;a=void 0}return v(a,this.value)||(i(this.root,this.keypath),this.root._cache[this.keypath]=a,l(this.root,this.keypath),this.value=a),this.evaluating=!1,this},teardown:function(){for(;this.refs.length;)this.refs.pop().teardown();i(this.root,this.keypath),this.root._evaluators[this.keypath]=null},refresh:function(){this.selfUpdating||(this.deferred=!0);for(var a=this.refs.length;a--;)this.refs[a].update();this.deferred&&(this.update(),this.deferred=!1)}},b=function(a,b,c,d,f){var g;this.evaluator=c,this.keypath=b,this.root=a,this.argNum=d,this.type=ac,this.priority=f,g=a.get(b),"function"==typeof g&&(g=g._wrapped||e(g,a)),this.value=c.values[d]=g,j(this)},b.prototype={update:function(){var a=this.root.get(this.keypath);"function"==typeof a&&(a=a._wrapped||e(a,this.root)),v(a,this.value)||(this.evaluator.values[this.argNum]=a,this.evaluator.bubble(),this.value=a)},teardown:function(){k(this)}},c=function(b,c){var d,e;if(b=b.replace(/\$\{([0-9]+)\}/g,"_$1"),a[b])return a[b];for(e=[];c--;)e[c]="_"+c;return d=new Function(e.join(","),"return("+b+")"),a[b]=d,d},d=/this/,e=function(a,b){var c;if(!d.test(a.toString()))return a._wrapped=a;F(a,"_wrapped",{value:function(){return a.apply(b,arguments)},writable:!0});for(c in a)Bb.call(a,c)&&(a._wrapped[c]=a[c]);return a._wrapped}}({}),function(){var a,b;cb=function(b){var c,d,e,f,g;for(this.root=b.root,this.mustache=b,this.args=[],this.scouts=[],c=b.descriptor.x,g=b.parentFragment.indexRefs,this.str=c.s,e=this.unresolved=c.r?c.r.length:0,e||this.init(),d=0;e>d;d+=1)f=c.r[d],g&&void 0!==g[f]?this.resolveRef(d,!0,g[f]):this.scouts[this.scouts.length]=new a(this,f,b.contextStack,d)},cb.prototype={init:function(){this.keypath=b(this.str,this.args),this.createEvaluator(),this.mustache.resolve(this.keypath)},teardown:function(){for(;this.scouts.length;)this.scouts.pop().teardown()},resolveRef:function(a,b,c){this.args[a]=[b,c],--this.unresolved||this.init()},createEvaluator:function(){this.root._evaluators[this.keypath]?this.root._evaluators[this.keypath].refresh():(this.root._evaluators[this.keypath]=new db(this.root,this.keypath,this.str,this.args,this.mustache.priority),this.root._evaluators[this.keypath].update())}},a=function(a,b,c,d){var e,f;f=this.root=a.root,e=o(f,b,c),e?a.resolveRef(d,!1,e):(this.ref=b,this.argNum=d,this.resolver=a,this.contextStack=c,f._pendingResolution[f._pendingResolution.length]=this)},a.prototype={resolve:function(a){this.keypath=a,this.resolver.resolveRef(this.argNum,!1,a)},teardown:function(){this.keypath||h(this)}},b=function(a,b){var c;return c=a.replace(/\$\{([0-9]+)\}/g,function(a,c){return b[c][1]}),"("+c.replace(/[\.\[\]]/g,"-")+")"}}(),function(){var a,c;A=function(d,e){var f,g;if(g=a(d,e))return g;if(g=a(b,e))return g;if(wb&&(f=wb.getElementById(e),f&&"SCRIPT"===f.tagName)){if(!b.parse)throw new Error(Hb);b.partials[e]=b.parse(f.innerHTML)}return g=b.partials[e],g?c(g):(d.debug&&Db&&Db.warn&&Db.warn('Could not find descriptor for partial "'+e+'"'),[])},a=function(a,d){if(a.partials[d]){if("string"==typeof a.partials[d]){if(!b.parse)throw new Error(Hb);a.partials[d]=b.parse(a.partials[d])}return c(a.partials[d])}},c=function(a){return 1===a.length&&"string"==typeof a[0]?a[0]:a}}(),jb=function(a,b){var c,d,e,f,g;if(a.owner=b.owner,e=a.owner.parentFragment,a.root=b.root,a.parentNode=b.parentNode,a.contextStack=b.contextStack||[],a.owner.type===Lb&&(a.index=b.index),e&&(f=e.indexRefs)){a.indexRefs=I();for(g in f)a.indexRefs[g]=f[g]}for(a.priority=e?e.priority+1:0,b.indexRef&&(a.indexRefs||(a.indexRefs={}),a.indexRefs[b.indexRef]=b.index),a.items=[],c=b.descriptor?b.descriptor.length:0,d=0;c>d;d+=1)a.items[a.items.length]=a.createItem({parentFragment:a,descriptor:b.descriptor[d],index:d})},C=function(a){var b,c,d;for(b=a.items.length;b--;)if(c=a.items[b],c.type!==Ib){if(c.type!==Jb)return!1;if(d)return!1;d=!0}return!0},gb=function(a,b){var c,d,e;e=a.parentFragment=b.parentFragment,a.root=e.root,a.contextStack=e.contextStack,a.descriptor=b.descriptor,a.index=b.index||0,a.priority=e.priority,e.parentNode&&(a.parentNode=e.parentNode),a.type=b.descriptor.t,b.descriptor.r&&(e.indexRefs&&void 0!==e.indexRefs[b.descriptor.r]?(d=e.indexRefs[b.descriptor.r],a.indexRef=b.descriptor.r,a.value=d,a.render(a.value)):(c=o(a.root,b.descriptor.r,a.contextStack),c?a.resolve(c):(a.ref=b.descriptor.r,a.root._pendingResolution[a.root._pendingResolution.length]=a,a.descriptor.n&&a.render(!1)))),b.descriptor.x&&(a.expressionResolver=new cb(a))},hb=function(){var a;a=this.root.get(this.keypath,!0),v(a,this.value)||(this.render(a),this.value=a)},ib=function(a){this.keypath=a,j(this),this.update(),this.expressionResolver&&(this.expressionResolver=null)},function(){var a,b,c,d;kb=function(e,f){var g;return g={descriptor:e.descriptor.f,root:e.root,parentNode:e.parentNode,owner:e},e.descriptor.n?(d(e,f,!0,g),void 0):(s(f)?a(e,f,g):t(f)?e.descriptor.i?b(e,f,g):c(e,g):d(e,f,!1,g),void 0)},a=function(a,b,c){var d,e,f;if(e=b.length,ea.length)for(d=a.length;e>d;d+=1)c.contextStack=a.contextStack.concat(a.keypath+"."+d),c.index=d,a.descriptor.i&&(c.indexRef=a.descriptor.i),a.fragments[d]=a.createFragment(c);a.length=e},b=function(a,b,c){var d,e;e=a.fragmentsById||(a.fragmentsById=I());for(d in e)void 0===b[d]&&(e[d].teardown(!0),e[d]=null);for(d in b)void 0===b[d]||e[d]||(c.contextStack=a.contextStack.concat(a.keypath+"."+d),c.index=d,a.descriptor.i&&(c.indexRef=a.descriptor.i),e[d]=a.createFragment(c))},c=function(a,b){a.length||(b.contextStack=a.contextStack.concat(a.keypath),b.index=0,a.fragments[0]=a.createFragment(b),a.length=1)},d=function(a,b,c,d){var e,f,g;if(f=s(b)&&0===b.length,e=c?f||!b:b&&!f){if(a.length||(d.contextStack=a.contextStack,d.index=0,a.fragments[0]=a.createFragment(d),a.length=1),a.length>1)for(g=a.fragments.splice(1);g.length;)g.pop().teardown(!0)}else a.length&&(a.teardownFragments(!0),a.length=0)}}();var qc;!function(){var a,b,c;qc=function(d,e){return d.next()?a(d,e)||b(d,e)||c(d,e):null},a=function(a,b){var c=a.next();return c.type===Ib?(a.pos+=1,new Ec(c,b)):null},b=function(a,b){var c=a.next();return c.type===Sb||c.type===Kb?c.mustacheType===Lb||c.mustacheType===Mb?new Dc(c,a,b):new Cc(c,a):null},c=function(a,b){var c,d=a.next();return d.type===Tb?(c=new zc(d,a,b),a.options.sanitize&&a.options.sanitize.elements&&-1!==a.options.sanitize.elements.indexOf(c.lcTag)?null:c):null}}();var rc=function(a,b){var c,d;return b||(c=sc(a),c===!1)?d=a.map(function(a){return a.toJSON(b)}):c},sc=function(a){var b,c,d,e="";if(!a)return"";for(c=0,d=a.length;d>c;c+=1){if(b=a[c].toString(),b===!1)return!1;e+=b}return e},tc=function(a){var b=Fb.exec(a.str.substring(a.pos));return b?(a.pos+=b[0].length,b[0]):null},uc=function(a,b){var c=a.remaining().substr(0,40);throw 40===c.length&&(c+="..."),new Error('Tokenizer failed: unexpected string "'+c+'" (expected '+b+")")},vc=function(a){return function(b){var c=a.exec(b.str.substring(b.pos));return c?(b.pos+=c[0].length,c[1]||c[0]):null}},wc=function(a,b){var c;return c=a.str.substr(a.pos,b.length),c===b?(a.pos+=b.length,b):null};rb=function(a){var b,c,d,e;for(b=0;b"),-1===b&&-1===c){d+=a;break}if(-1!==b&&-1===c)throw"Illegal HTML - expected closing comment sequence ('-->')";if(-1!==c&&-1===b||b>c)throw"Illegal HTML - unexpected closing comment sequence ('-->')";d+=a.substr(0,b),a=a.substring(c+3)}return d},tb=function(a){var b,c,d,e,f,g;for(f=/^\s*\r?\n/,g=/\r?\n\s*$/,b=2;bc;c+=1)e[c].apply(this,b)},function(a){var b;a.get=function(a){var c,d,e,f,g,h,i,j,k;if(!a)return this.data;if(c=this._cache,s(a)){if(!a.length)return this.data;e=a.slice(),f=e.join("."),k=!0}else{if(Bb.call(c,a)&&c[a]!==ic)return c[a];e=q(a),f=e.join(".")}return!Bb.call(c,f)||c[f]===ic||void 0===c[f]&&k?this._evaluators[f]?(j=this._evaluators[f].value,c[f]=j,j):(g=e.pop(),h=e.join("."),i=e.length?this.get(e):this.data,null!==i&&void 0!==i&&i!==ic?(this.magic&&"object"==typeof i&&Bb.call(i,g)&&(this._wrapped[f]||(this._wrapped[f]=b(i,g,this,f))),(d=this._cacheMap[h])?-1===d.indexOf(f)&&(d[d.length]=f):this._cacheMap[h]=[f],j=i[g],this.modifyArrays&&("("===f.charAt(0)||!s(j)||j._ractive&&j._ractive.setting||mb(j,f,this)),c[f]=j,j):void 0):c[f]},b=function(a,b,c,d){var e,f,g,h,i,j,k,l;if(f=Object.getOwnPropertyDescriptor(a,b)){if(f.set&&(k=f.set.ractives))return-1===k.indexOf(c)&&(k[k.length]=c),l=f.set[c._guid]||(f.set[c._guid]=[]),-1===l.indexOf(d)&&(l[l.length]=d),void 0;if(!f.configurable)throw new Error("Cannot configure property")}if(!f||Bb.call(f,"value"))f&&(e=f.value),g=function(){return e},h=function(a){var b,c,d,f,g;for(e=a,b=h.ractives,f=b.length;f--;)if(c=b[f],!c.muggleSet){for(c.magicSet=!0,d=h[c._guid],g=d.length;g--;)c.set(d[g],a);c.magicSet=!1}},h.ractives=[c],h[c._guid]=[d],Object.defineProperty(a,b,{get:g,set:h,enumerable:!0,configurable:!0});else{if(f.set&&!f.get||!f.set&&f.get)throw new Error("Property with getter but no setter, or vice versa. I am confused.");if(f.set._ractive)return;i=f.get,j=f.set,h=function(a){j(a),c.muggleSet||(c.magicSet=!0,c.set(d,i()),c.magicSet=!1)},h[c._guid+d]=!0,Object.defineProperty(a,b,{get:i,set:h,enumerable:!0,configurable:!0})}return{teardown:function(){var c=a[b];Object.defineProperty(a,b,f),a[b]=c}}}}(xb),i=function(a,b){var c,d,e,f;if(a.modifyArrays&&"("!==b.charAt(0)&&(c=a._cache[b],s(c)&&!c._ractive.setting&&nb(c,b,a)),a._cache[b]=ic,d=a._cacheMap[b])for(;d.length;)e=d.pop(),i(a,e),f=a._wrapped[e],f&&f.teardown(),a._wrapped[e]=null},l=function(a,b,c){var d;for(d=0;d1;)h=l[l.length]=c.shift(),j[h]||(m||(m=l.join(".")),j[h]=/^\s*[0-9]+\s*$/.test(c[0])?[]:{}),j=j[h];h=c[0],j[h]=d,a.muggleSet=!1}}else if("object"!=typeof d)return;for(i(a,m||b),e[e.length]=b;k.length>1;)k.pop(),b=k.join("."),-1===f.indexOf(b)&&(f[f.length]=b)},c=function(a){var b,c,d;for(b=a._pendingResolution.length;b--;)c=a._pendingResolution.splice(b,1)[0],(d=o(a,c.ref,c.contextStack))?c.resolve(d):a._pendingResolution[a._pendingResolution.length]=c}}(xb),xb.teardown=function(a){var b,c,d;for(this.fire("teardown"),d=this._transitionManager,this._transitionManager=c=D(this,a),this.fragment.teardown(!0);this._animations[0];)this._animations[0].stop();for(b in this._cache)i(this,b);for(;this._bound.length;)this.unbind(this._bound.pop());this._transitionManager=d,c.ready()},xb.toggleFullscreen=function(){b.isFullscreen(this.el)?this.cancelFullscreen():this.requestFullscreen()},xb.unbind=function(a){var b,c=this._bound;b=c.indexOf(a),-1!==b&&(c.splice(b,1),a.teardown(this))},xb.update=function(a,b){var c,d;return"function"==typeof a&&(b=a),d=this._transitionManager,this._transitionManager=c=D(this,b),i(this,a||""),l(this,a||""),p(this),this._transitionManager=d,c.ready(),"string"==typeof a?this.fire("update",a):this.fire("update"),this},yb.backbone=function(a,b){var c,d,e,f,g,h,i;return b&&(b+=".",g=new RegExp("^"+b.replace(/\./g,"\\.")),h=b.length),{init:function(j){b?(i=function(a){var c,d;d={};for(c in a)Bb.call(a,c)&&(d[b+c]=a[c]);return d},f=function(a){c||(d=!0,j.set(i(a.changed)),d=!1)},e=function(b,e){d||g.test(b)&&(c=!0,a.set(b.substring(h),e),c=!1)}):(f=function(a){c||(d=!0,j.set(a.changed),d=!1)},e=function(b,e){d||(c=!0,a.set(b,e),c=!1)}),a.on("change",f),j.on("set",e),j.set(b?i(a.attributes):a.attributes)},teardown:function(b){a.off("change",f),b.off("set",e)}}},yb.backboneCollection=function(a,b){var c,d,e,f,g,h,i;return b&&(b+=".",g=new RegExp("^"+b.replace(/\./g,"\\.")),h=b.length),{init:function(h){b?(i=function(a){var c,d;for(c={},d=0;d=e||Math.abs(a.clientY-h)>=e)&&l()},l=function(){a.removeEventListener("MSPointerUp",j,!1),wb.removeEventListener("MSPointerMove",k,!1),wb.removeEventListener("MSPointerCancel",l,!1),a.removeEventListener("pointerup",j,!1),wb.removeEventListener("pointermove",k,!1),wb.removeEventListener("pointercancel",l,!1),a.removeEventListener("click",j,!1),wb.removeEventListener("mousemove",k,!1)},window.navigator.pointerEnabled?(a.addEventListener("pointerup",j,!1),wb.addEventListener("pointermove",k,!1),wb.addEventListener("pointercancel",l,!1)):window.navigator.msPointerEnabled?(a.addEventListener("MSPointerUp",j,!1),wb.addEventListener("MSPointerMove",k,!1),wb.addEventListener("MSPointerCancel",l,!1)):(a.addEventListener("click",j,!1),wb.addEventListener("mousemove",k,!1)),setTimeout(l,f))},window.navigator.pointerEnabled?a.addEventListener("pointerdown",c,!1):window.navigator.msPointerEnabled?a.addEventListener("MSPointerDown",c,!1):a.addEventListener("mousedown",c,!1),d=function(c){var d,g,h,i,j,k,l,m;1===c.touches.length&&(i=c.touches[0],g=i.clientX,h=i.clientY,d=this,j=i.identifier,l=function(a){var c;c=a.changedTouches[0],c.identifier!==j&&m(),a.preventDefault(),b({node:d,original:a}),m()},k=function(a){var b;(1!==a.touches.length||a.touches[0].identifier!==j)&&m(),b=a.touches[0],(Math.abs(b.clientX-g)>=e||Math.abs(b.clientY-h)>=e)&&m()},m=function(){a.removeEventListener("touchend",l,!1),window.removeEventListener("touchmove",k,!1),window.removeEventListener("touchcancel",m,!1)},a.addEventListener("touchend",l,!1),window.addEventListener("touchmove",k,!1),window.addEventListener("touchcancel",m,!1),setTimeout(m,f))},a.addEventListener("touchstart",d,!1),{teardown:function(){a.removeEventListener("pointerdown",c,!1),a.removeEventListener("MSPointerDown",c,!1),a.removeEventListener("mousedown",c,!1),a.removeEventListener("touchstart",d,!1)}}},function(){var a,c,e,f,g,h,i,j,k,l,m,n,o;d=function(a){var c,d=this;return c=function(a){l(this,c,a||{})},c.prototype=H(d.prototype),d!==b&&f(c,d),h(c,a),i(c),j(c,a),k(c),c.extend=d.extend,c},m=["data","partials","transitions","eventDefinitions","components"],n=["el","template","complete","modifyArrays","twoway","lazy","append","preserveWhitespace","sanitize","noIntro","transitionsEnabled"],o=m.concat(n),f=function(a,b){m.forEach(function(d){b[d]&&(a[d]=c(b[d]))}),n.forEach(function(c){void 0!==b[c]&&(a[c]=b[c])})},g=function(a,b){return/_super/.test(a)?function(){var c,d=this._super;return this._super=b,c=a.apply(this,arguments),this._super=d,c}:a},h=function(a,b){var c,d;m.forEach(function(c){var d=b[c];d&&(a[c]?e(a[c],d):a[c]=d)}),n.forEach(function(c){void 0!==b[c]&&(a[c]=b[c])});for(c in b)Bb.call(b,c)&&!Bb.call(a.prototype,c)&&-1===o.indexOf(c)&&(d=b[c],a.prototype[c]="function"==typeof d&&"function"==typeof a.prototype[c]?g(d,a.prototype[c]):d)},i=function(a){var c;if("string"==typeof a.template){if(!b.parse)throw new Error(Hb);if("#"===a.template.charAt(0)&&wb){if(c=wb.getElementById(a.template.substring(1)),!c||"SCRIPT"!==c.tagName)throw new Error("Could not find template element ("+a.template+")");a.template=b.parse(c.innerHTML,a)}else a.template=b.parse(a.template,a)}},j=function(a,b){t(a.template)&&(a.partials||(a.partials={}),e(a.partials,a.template.partials),b.partials&&e(a.partials,b.partials),a.template=a.template.main)},k=function(a){var c,d;if(a.partials)for(c in a.partials)if(Bb.call(a.partials,c)){if("string"==typeof a.partials[c]){if(!b.parse)throw new Error(Hb);d=b.parse(a.partials[c],a)}else d=a.partials[c];a.partials[c]=d}},l=function(d,e,f){!f.template&&e.template&&(f.template=e.template),m.forEach(function(b){f[b]?a(f[b],e[b]):e[b]&&(f[b]=c(e[b]))}),n.forEach(function(a){void 0===f[a]&&void 0!==e[a]&&(f[a]=e[a])}),d.beforeInit&&d.beforeInit.call(d,f),b.call(d,f),d.init&&d.init.call(d,f)},a=function(a,b){var c;for(c in b)Bb.call(b,c)&&!Bb.call(a,c)&&(a[c]=b[c])},c=function(a){var b,c={};for(b in a)Bb.call(a,b)&&(c[b]=a[b]);return c},e=function(a,b){var c;for(c in b)Bb.call(b,c)&&(a[c]=b[c])}}(),f=function(a,c){return u(a)&&u(c)?b.interpolators.number(+a,+c):s(a)&&s(c)?b.interpolators.array(a,c):t(a)&&t(c)?b.interpolators.object(a,c):function(){return c}},g={number:function(a,b){var c=b-a;return c?function(b){return a+b*c}:function(){return a}},array:function(a,c){var d,e,f,g;for(d=[],e=[],g=f=Math.min(a.length,c.length);g--;)e[g]=b.interpolate(a[g],c[g]);for(g=f;g=this.duration?(this.root.set(this.keypath,this.to),this.step&&this.step(1,this.to),this.complete&&this.complete(1,this.to),e=this.root._animations.indexOf(this),-1===e&&Db&&Db.warn&&Db.warn("Animation was not found"),this.root._animations.splice(e,1),this.running=!1,!1):(b=this.easing?this.easing(a/this.duration):a/this.duration,c=this.interpolator(b),this.root.set(this.keypath,c),this.step&&this.step(b,c),!0)):!1},stop:function(){var a;this.running=!1,a=this.root._animations.indexOf(this),-1===a&&Db&&Db.warn&&Db.warn("Animation was not found"),this.root._animations.splice(a,1)}},lb={animations:[],tick:function(){var a,b;for(a=0;ab;b+=1)a+=" "+this.attributes[b].toString();return a+=">",this.html?a+=this.html:this.fragment&&(a+=this.fragment.toString()),a+=""},ractify:function(){var a=this.parentFragment.contextStack;return this.node._ractive||F(this.node,"_ractive",{value:{keypath:a.length?a[a.length-1]:"",index:this.parentFragment.indexRefs,events:I(),root:this.root}}),this.node._ractive}},R=function(a){return a.parentNode&&(this.docFrag=wb.createDocumentFragment()),"string"==typeof a.descriptor?(this.html=a.descriptor,this.docFrag&&(this.nodes=x(a.descriptor,this.docFrag)),void 0):(jb(this,a),void 0)},R.prototype={createItem:function(a){if("string"==typeof a.descriptor)return new Z(a,this.docFrag);switch(a.descriptor.t){case Jb:return new W(a,this.docFrag);case Lb:return new Y(a,this.docFrag);case Kb:return new X(a,this.docFrag);case Ob:return new S(a,this.docFrag);case Pb:return new U(a,this.docFrag);case Ub:return new V(a,this.docFrag);default:throw new Error("WTF? not sure what happened here...")}},teardown:function(a){var b;if(a&&this.nodes)for(;this.nodes.length;)b=this.nodes.pop(),b.parentNode.removeChild(b);else if(this.items)for(;this.items.length;)this.items.pop().teardown(a)},firstNode:function(){return this.items&&this.items[0]?this.items[0].firstNode():this.nodes?this.nodes[0]||null:null},findNextNode:function(a){var b=a.index;return this.items[b+1]?this.items[b+1].firstNode():this.owner===this.root?null:this.owner.findNextNode(this)},toString:function(){var a,b,c,d;if(this.html)return this.html;if(a="",!this.items)return a;for(c=this.items.length,b=0;c>b;b+=1)d=this.items[b],a+=d.toString();return a}},W=function(a,b){this.type=Jb,b&&(this.node=wb.createTextNode(""),b.appendChild(this.node)),gb(this,a)},W.prototype={update:hb,resolve:ib,teardown:function(a){h(this),a&&this.node.parentNode.removeChild(this.node)},render:function(a){this.node&&(this.node.data=void 0===a?"":a)},firstNode:function(){return this.node},toString:function(){var a=void 0!==this.value?""+this.value:"";return a.replace("<","<").replace(">",">")}},U=function(a,b){var c,d=this.parentFragment=a.parentFragment;this.type=Pb,this.name=a.descriptor.r,c=A(d.root,a.descriptor.r),this.fragment=new R({descriptor:c,root:d.root,parentNode:d.parentNode,contextStack:d.contextStack,owner:this}),b&&b.appendChild(this.fragment.docFrag)},U.prototype={firstNode:function(){return this.fragment.firstNode()},findNextNode:function(){return this.parentFragment.findNextNode(this)},teardown:function(a){this.fragment.teardown(a)},toString:function(){return this.fragment.toString()}},Y=function(a,b){this.type=Lb,this.fragments=[],this.length=0,b&&(this.docFrag=wb.createDocumentFragment()),this.initialising=!0,gb(this,a),b&&b.appendChild(this.docFrag),this.initialising=!1},Y.prototype={update:hb,resolve:ib,smartUpdate:function(a,b){var c;("push"===a||"unshift"===a||"splice"===a)&&(c={descriptor:this.descriptor.f,root:this.root,parentNode:this.parentNode,owner:this},this.descriptor.i&&(c.indexRef=this.descriptor.i)),this[a]&&this[a](c,b)},pop:function(){this.length&&(this.fragments.pop().teardown(!0),this.length-=1)},push:function(a,b){var c,d,e;for(c=this.length,d=c+b.length,e=c;d>e;e+=1)a.contextStack=this.contextStack.concat(this.keypath+"."+e),a.index=e,this.fragments[e]=this.createFragment(a);this.length+=b.length,this.parentNode.insertBefore(this.docFrag,this.parentFragment.findNextNode(this))},shift:function(){this.splice(null,[0,1])},unshift:function(a,b){this.splice(a,[0,0].concat(new Array(b.length)))},splice:function(a,b){var c,d,e,f,g,h,i,j,k;if(b.length&&(h=+(b[0]<0?this.length+b[0]:b[0]),d=Math.max(0,b.length-2),e=void 0!==b[1]?b[1]:this.length-h,f=d-e)){if(0>f){for(i=h-f,g=h;i>g;g+=1)this.fragments[g].teardown(!0);this.fragments.splice(h,-f)}else{for(i=h+f,c=this.fragments[h]?this.fragments[h].firstNode():this.parentFragment.findNextNode(this),j=[h,0].concat(new Array(f)),this.fragments.splice.apply(this.fragments,j),g=h;i>g;g+=1)a.contextStack=this.contextStack.concat(this.keypath+"."+g),a.index=g,this.fragments[g]=this.createFragment(a);this.parentNode.insertBefore(this.docFrag,c)}this.length+=f,k=h+d,y(this.root,this,k,this.length,f)}},teardown:function(a){this.teardownFragments(a),h(this)},firstNode:function(){return this.fragments[0]?this.fragments[0].firstNode():this.parentFragment.findNextNode(this)},findNextNode:function(a){return this.fragments[a.index+1]?this.fragments[a.index+1].firstNode():this.parentFragment.findNextNode(this)},teardownFragments:function(a){for(var b;this.fragments.length;)this.fragments.shift().teardown(a);if(this.fragmentsById)for(b in this.fragmentsById)this.fragmentsById[b].teardown(),this.fragmentsById[b]=null},render:function(a){var b;this.rendering||(this.rendering=!0,kb(this,a),this.rendering=!1,(!this.docFrag||this.docFrag.childNodes.length)&&(this.initialising||(b=this.parentFragment.findNextNode(this),b&&b.parentNode===this.parentNode?this.parentNode.insertBefore(this.docFrag,b):this.parentNode.appendChild(this.docFrag))))},createFragment:function(a){var b=new R(a);return this.docFrag&&this.docFrag.appendChild(b.docFrag),b},toString:function(){var a,b,c;for(a="",b=0,c=this.length,b=0;c>b;b+=1)a+=this.fragments[b].toString();return a}},Z=function(a,b){this.type=Ib,this.descriptor=a.descriptor,b&&(this.node=wb.createTextNode(a.descriptor),this.parentNode=a.parentFragment.parentNode,b.appendChild(this.node))},Z.prototype={teardown:function(a){a&&this.node.parentNode.removeChild(this.node)},firstNode:function(){return this.node},toString:function(){return(""+this.descriptor).replace("<","<").replace(">",">")}},X=function(a,b){this.type=Kb,b&&(this.nodes=[],this.docFrag=wb.createDocumentFragment()),this.initialising=!0,gb(this,a),b&&b.appendChild(this.docFrag),this.initialising=!1},X.prototype={update:hb,resolve:ib,teardown:function(a){var b;if(a)for(;this.nodes.length;)b=this.nodes.pop(),b.parentNode.removeChild(b);h(this)},firstNode:function(){return this.nodes[0]?this.nodes[0]:this.parentFragment.findNextNode(this)},render:function(a){var b;if(this.nodes){for(;this.nodes.length;)b=this.nodes.pop(),b.parentNode.removeChild(b);if(void 0===a)return this.nodes=[],void 0;this.nodes=x(a,this.docFrag),this.initialising||this.parentNode.insertBefore(this.docFrag,this.parentFragment.findNextNode(this))}},toString:function(){return void 0!==this.value?this.value:""}},$=function(a){jb(this,a)},$.prototype={createItem:function(a){if("string"==typeof a.descriptor)return new bb(a.descriptor);switch(a.descriptor.t){case Jb:return new _(a);case Kb:return new _(a);case Lb:return new ab(a);default:throw"Something went wrong in a rather interesting way"}},bubble:function(){this.owner.bubble()},teardown:function(){var a,b;for(a=this.items.length,b=0;a>b;b+=1)this.items[b].teardown()},getValue:function(){var a;return 1===this.items.length&&this.items[0].type===Jb&&(a=this.items[0].value,void 0!==a)?a:this.toString()},toString:function(){return this.items.join("")},toJSON:function(){var a,b;a=this.toString();try{b=JSON.parse(a)}catch(c){b=a}return b}},_=function(a){this.type=Jb,gb(this,a)},_.prototype={update:hb,resolve:ib,render:function(a){this.value=a,this.parentFragment.bubble()},teardown:function(){h(this)},toString:function(){return void 0===this.value?"":this.value}},ab=function(a){this.type=Lb,this.fragments=[],this.length=0,gb(this,a)},ab.prototype={update:hb,resolve:ib,teardown:function(){this.teardownFragments(),h(this)},teardownFragments:function(){for(;this.fragments.length;)this.fragments.shift().teardown();this.length=0},bubble:function(){this.value=this.fragments.join(""),this.parentFragment.bubble()},render:function(a){kb(this,a),this.parentFragment.bubble()},createFragment:function(a){return new $(a)},toString:function(){return this.fragments.join("")}},bb=function(a){this.type=Ib,this.text=a},bb.prototype={toString:function(){return this.text},teardown:function(){}},w=function(a){var b;return"undefined"!=typeof window&&wb&&a?a.nodeType?a:"string"==typeof a&&(b=wb.getElementById(a),!b&&wb.querySelector&&(b=wb.querySelector(a)),b.nodeType)?b:a[0]&&a[0].nodeType?a[0]:null:null},r=Object.prototype.toString,s=function(a){return"[object Array]"===r.call(a)},v=function(a,b){return null===a&&null===b?!0:"object"==typeof a||"object"==typeof b?!1:a===b},u=function(a){return!isNaN(parseFloat(a))&&isFinite(a)},t=function(a){return"object"==typeof a&&"[object Object]"===r.call(a)},D=function(a,b){var c,d,e,f;return d=[],e=function(){var a,b;for(a=d.length;a--;)b=d[a],f(b)&&(b.parentNode.removeChild(b),d.splice(a,1))},f=function(a){var b,d;for(b=c.active.length;b--;)if(d=c.active[b],a.contains(d))return!1;return!0},c={active:[],push:function(a){c.active[c.active.length]=a},pop:function(a){c.active.splice(c.active.indexOf(a),1),e(),!c.active.length&&c._ready&&c.complete()},complete:function(){b&&b.call(a)},ready:function(){e(),c._ready=!0,c.active.length||c.complete()},detachWhenReady:function(a){d[d.length]=a}}},q=function(a){var b,c,d,e,f;if(Eb[a])return Eb[a].concat();for(d=[],e=a,c=0;e.length;){if(b=e.indexOf(".",c),-1===b)f=e,e="";else{if("\\"===e.charAt(b-1)&&"\\"!==e.charAt(b-2)){c=b+1;continue}f=e.substr(0,b),c=0}/\[/.test(f)?d=d.concat(f.replace(/\[\s*([0-9]+)\s*\]/g,".$1").split(".")):d[d.length]=f,e=e.substring(b+1)}return Eb[a]=d,d.concat()};var zc;!function(){var a,b,c,d,e,f,g,h,i,j,k,l,m,n,o;zc=function(b,c,d){var f,g,h,j,o;if(this.lcTag=b.name.toLowerCase(),this.tag=e[this.lcTag]?e[this.lcTag]:this.lcTag,c.pos+=1,d=d||"pre"===this.lcTag,b.attrs&&(h=l(b.attrs),g=h.attrs,j=h.proxies,c.options.sanitize&&c.options.sanitize.eventAttributes&&(g=g.filter(k)),g.length&&(this.attributes=g.map(m)),j.length&&(this.proxies=j.map(n)),h.intro&&(this.intro=n(h.intro)),h.outro&&(this.outro=n(h.outro))),b.selfClosing&&(this.selfClosing=!0),-1!==a.indexOf(this.lcTag)&&(this.isVoid=!0),!this.selfClosing&&!this.isVoid){for(this.siblings=i[this.lcTag],this.items=[],f=c.next();f&&f.mustacheType!==Nb;){if(f.type===Tb){if(f.closing){f.name.toLowerCase()===this.lcTag&&(c.pos+=1);break}if(this.siblings&&-1!==this.siblings.indexOf(f.name.toLowerCase()))break}this.items[this.items.length]=qc(c),f=c.next()}d||(o=this.items[0],o&&o.type===Ib&&(o.text=o.text.replace(Fb,""),o.text||this.items.shift()),o=this.items[this.items.length-1],o&&o.type===Ib&&(o.text=o.text.replace(Gb,""),o.text||this.items.pop()))}},zc.prototype={toJSON:function(a){var b,c,d,e,f,g;if(this["json_"+a])return this["json_"+a];if(b="rv-"===this.tag.substr(0,3)?{t:Ub,e:this.tag.substr(3)}:{t:Ob,e:this.tag},this.attributes&&this.attributes.length)for(b.a={},g=this.attributes.length,f=0;g>f;f+=1){if(c=this.attributes[f].name,b.a[c])throw new Error("You cannot have multiple elements with the same name");d=null===this.attributes[f].value?null:rc(this.attributes[f].value.items,a),b.a[c]=d}if(this.items&&this.items.length&&(b.f=rc(this.items,a)),this.proxies&&this.proxies.length)for(b.v={},g=this.proxies.length,f=0;g>f;f+=1)e=this.proxies[f],b.v[e.domEventName]=o(e);return this.intro&&(b.t1=this.intro.args?{n:this.intro.name,a:this.intro.args}:this.intro.dynamicArgs?{n:this.intro.name,d:rc(this.intro.dynamicArgs.items,a)}:this.intro.name),this.outro&&(b.t2=this.outro.args?{n:this.outro.name,a:this.outro.args}:this.outro.dynamicArgs?{n:this.outro.name,d:rc(this.outro.dynamicArgs.items,a)}:this.outro.name),this["json_"+a]=b,b +},toString:function(){var c,d,e,f,g,h,i,j;if(void 0!==this.str)return this.str;if(-1===b.indexOf(this.tag.toLowerCase()))return this.str=!1;if(this.proxies||this.intro||this.outro)return this.str=!1;if(i=sc(this.items),i===!1)return this.str=!1;if(j=-1!==a.indexOf(this.tag.toLowerCase()),c="<"+this.tag,this.attributes)for(d=0,e=this.attributes.length;e>d;d+=1){if(g=this.attributes[d].name,-1!==g.indexOf(":"))return this.str=!1;if("id"===g||"intro"===g||"outro"===g)return this.str=!1;if(f=" "+g,null!==this.attributes[d].value){if(h=this.attributes[d].value.toString(),h===!1)return this.str=!1;""!==h&&(f+="=",f+=/[\s"'=<>`]/.test(h)?'"'+h.replace(/"/g,""")+'"':h)}c+=f}return this.selfClosing&&!j?(c+="/>",this.str=c):(c+=">",j?this.str=c:(c+=i,c+="",this.str=c))}},a="area base br col command embed hr img input keygen link meta param source track wbr".split(" "),b="a abbr acronym address applet area b base basefont bdo big blockquote body br button caption center cite code col colgroup dd del dfn dir div dl dt em fieldset font form frame frameset h1 h2 h3 h4 h5 h6 head hr html i iframe img input ins isindex kbd label legend li link map menu meta noframes noscript object ol p param pre q s samp script select small span strike strong style sub sup textarea title tt u ul var article aside audio bdi canvas command data datagrid datalist details embed eventsource figcaption figure footer header hgroup keygen mark meter nav output progress ruby rp rt section source summary time track video wbr".split(" "),h="li dd rt rp optgroup option tbody tfoot tr td th".split(" "),d="altGlyph altGlyphDef altGlyphItem animateColor animateMotion animateTransform clipPath feBlend feColorMatrix feComponentTransfer feComposite feConvolveMatrix feDiffuseLighting feDisplacementMap feDistantLight feFlood feFuncA feFuncB feFuncG feFuncR feGaussianBlur feImage feMerge feMergeNode feMorphology feOffset fePointLight feSpecularLighting feSpotLight feTile feTurbulence foreignObject glyphRef linearGradient radialGradient textPath vkern".split(" "),f="attributeName attributeType baseFrequency baseProfile calcMode clipPathUnits contentScriptType contentStyleType diffuseConstant edgeMode externalResourcesRequired filterRes filterUnits glyphRef glyphRef gradientTransform gradientTransform gradientUnits gradientUnits kernelMatrix kernelUnitLength kernelUnitLength kernelUnitLength keyPoints keySplines keyTimes lengthAdjust limitingConeAngle markerHeight markerUnits markerWidth maskContentUnits maskUnits numOctaves pathLength patternContentUnits patternTransform patternUnits pointsAtX pointsAtY pointsAtZ preserveAlpha preserveAspectRatio primitiveUnits refX refY repeatCount repeatDur requiredExtensions requiredFeatures specularConstant specularExponent specularExponent spreadMethod spreadMethod startOffset stdDeviation stitchTiles surfaceScale surfaceScale systemLanguage tableValues targetX targetY textLength textLength viewBox viewTarget xChannelSelector yChannelSelector zoomAndPan".split(" "),c=function(a){for(var b={},c=a.length;c--;)b[a[c].toLowerCase()]=a[c];return b},e=c(d),g=c(f),i={li:["li"],dt:["dt","dd"],dd:["dt","dd"],p:"address article aside blockquote dir div dl fieldset footer form h1 h2 h3 h4 h5 h6 header hgroup hr menu nav ol p pre section table ul".split(" "),rt:["rt","rp"],rp:["rp","rt"],optgroup:["optgroup"],option:["option","optgroup"],thead:["tbody","tfoot"],tbody:["tbody","tfoot"],tr:["tr"],td:["td","th"],th:["td","th"]},j=/^on[a-zA-Z]/,k=function(a){var b=!j.test(a.name);return b},l=function(a){var b,c,d,e,f,g;for(d={},b=[],c=[],f=a.length,e=0;f>e;e+=1)if(g=a[e],"intro"===g.name){if(d.intro)throw new Error("An element can only have one intro transition");d.intro=g}else if("outro"===g.name){if(d.outro)throw new Error("An element can only have one outro transition");d.outro=g}else"proxy-"===g.name.substr(0,6)?(g.name=g.name.substring(6),c[c.length]=g):"on-"===g.name.substr(0,3)?(g.name=g.name.substring(3),c[c.length]=g):b[b.length]=g;return d.attrs=b,d.proxies=c,d},m=function(a){var b=a.name.toLowerCase();return{name:g[b]?g[b]:b,value:a.value?ob(a.value):null}},n=function(a){var b,c,d,e,f,g,h;for(f=function(){throw new Error("Illegal proxy event")},a.name&&a.value||f(),b={domEventName:a.name},c=a.value,g=[],h=[];c.length;)if(d=c.shift(),d.type===Ib){if(e=d.value.indexOf(":"),-1!==e){e&&(g[g.length]={type:Ib,value:d.value.substr(0,e)}),d.value.length>e+1&&(h[0]={type:Ib,value:d.value.substring(e+1)});break}g[g.length]=d}else g[g.length]=d;if(h=h.concat(c),b.name=1===g.length&&g[0].type===Ib?g[0].value:g,h.length)if(1===h.length&&h[0].type===Ib)try{b.args=JSON.parse(h[0].value)}catch(i){b.args=h[0].value}else b.dynamicArgs=h;return b},o=function(a){var b,c;if("string"==typeof a.name){if(!a.args&&!a.dynamicArgs)return a.name;c=a.name}else c=ob(a.name).toJSON();return b={n:c},a.args?(b.a=a.args,b):(a.dynamicArgs&&(b.d=ob(a.dynamicArgs).toJSON()),b)}}();var Ac;!function(){var a,b,c,d;Ac=function(c){this.refs=[],a(c,this.refs),this.str=b(c,this.refs)},Ac.prototype={toJSON:function(){return this.json?this.json:(this.json={r:this.refs,s:this.str},this.json)}},a=function(b,c){var d,e;if(b.t===ac&&-1===c.indexOf(b.n)&&c.unshift(b.n),e=b.o||b.m)if(t(e))a(e,c);else for(d=e.length;d--;)a(e[d],c);b.x&&a(b.x,c),b.r&&a(b.r,c),b.v&&a(b.v,c)},b=function(a,d){var e=function(a){return b(a,d)};switch(a.t){case Zb:case $b:case Vb:return a.v;case Wb:return"'"+a.v.replace(/'/g,"\\'")+"'";case Xb:return"["+(a.m?a.m.map(e).join(","):"")+"]";case Yb:return"{"+(a.m?a.m.map(e).join(","):"")+"}";case _b:return c(a.k)+":"+b(a.v,d);case dc:return("typeof"===a.s?"typeof ":a.s)+b(a.o,d);case gc:return b(a.o[0],d)+("in"===a.s.substr(0,2)?" "+a.s+" ":a.s)+b(a.o[1],d);case hc:return b(a.x,d)+"("+(a.o?a.o.map(e).join(","):"")+")";case ec:return"("+b(a.x,d)+")";case cc:return b(a.x,d)+b(a.r,d);case bc:return a.n?"."+a.n:"["+b(a.x,d)+"]";case fc:return b(a.o[0],d)+"?"+b(a.o[1],d)+":"+b(a.o[2],d);case ac:return"${"+d.indexOf(a.n)+"}";default:throw Db.log(a),new Error("Could not stringify expression token. This error is unexpected")}},c=function(a){return a.t===Wb?d.test(a.v)?a.v:'"'+a.v.replace(/"/g,'\\"')+'"':a.t===Vb?a.v:a},d=/^[a-zA-Z_$][a-zA-Z_$0-9]*$/}();var Bc=function(a,b){var c,d;for(c=this.items=[],d=qc(a,b);null!==d;)c[c.length]=d,d=qc(a,b)};Bc.prototype={toJSON:function(a){var b;return this["json_"+a]?this["json_"+a]:b=this["json_"+a]=rc(this.items,a)},toString:function(){return void 0!==this.str?this.str:(this.str=sc(this.items),this.str)}};var Cc=function(a,b){this.type=a.type===Kb?Kb:a.mustacheType,a.ref&&(this.ref=a.ref),a.expression&&(this.expr=new Ac(a.expression)),b.pos+=1};Cc.prototype={toJSON:function(){var a;return this.json?this.json:(a={t:this.type},this.ref&&(a.r=this.ref),this.expr&&(a.x=this.expr.toJSON()),this.json=a,a)},toString:function(){return!1}};var Dc=function(a,b,c){var d;for(this.ref=a.ref,this.indexRef=a.indexRef,this.inverted=a.mustacheType===Mb,a.expression&&(this.expr=new Ac(a.expression)),b.pos+=1,this.items=[],d=b.next();d;){if(d.mustacheType===Nb){if(d.ref.trim()===this.ref||this.expr){b.pos+=1;break}throw new Error("Could not parse template: Illegal closing section")}this.items[this.items.length]=qc(b,c),d=b.next()}};Dc.prototype={toJSON:function(a){var b;return this.json?this.json:(b={t:Lb},this.ref&&(b.r=this.ref),this.indexRef&&(b.i=this.indexRef),this.inverted&&(b.n=!0),this.expr&&(b.x=this.expr.toJSON()),this.items.length&&(b.f=rc(this.items,a)),this.json=b,b)},toString:function(){return!1}};var Ec;!function(){var a,b,c;Ec=function(a,b){this.type=Ib,this.text=b?a.value:a.value.replace(c," ")},Ec.prototype={toJSON:function(){return this.decoded||(this.decoded=b(this.text))},toString:function(){return this.text}},a={quot:34,amp:38,apos:39,lt:60,gt:62,nbsp:160,iexcl:161,cent:162,pound:163,curren:164,yen:165,brvbar:166,sect:167,uml:168,copy:169,ordf:170,laquo:171,not:172,shy:173,reg:174,macr:175,deg:176,plusmn:177,sup2:178,sup3:179,acute:180,micro:181,para:182,middot:183,cedil:184,sup1:185,ordm:186,raquo:187,frac14:188,frac12:189,frac34:190,iquest:191,Agrave:192,Aacute:193,Acirc:194,Atilde:195,Auml:196,Aring:197,AElig:198,Ccedil:199,Egrave:200,Eacute:201,Ecirc:202,Euml:203,Igrave:204,Iacute:205,Icirc:206,Iuml:207,ETH:208,Ntilde:209,Ograve:210,Oacute:211,Ocirc:212,Otilde:213,Ouml:214,times:215,Oslash:216,Ugrave:217,Uacute:218,Ucirc:219,Uuml:220,Yacute:221,THORN:222,szlig:223,agrave:224,aacute:225,acirc:226,atilde:227,auml:228,aring:229,aelig:230,ccedil:231,egrave:232,eacute:233,ecirc:234,euml:235,igrave:236,iacute:237,icirc:238,iuml:239,eth:240,ntilde:241,ograve:242,oacute:243,ocirc:244,otilde:245,ouml:246,divide:247,oslash:248,ugrave:249,uacute:250,ucirc:251,uuml:252,yacute:253,thorn:254,yuml:255,OElig:338,oelig:339,Scaron:352,scaron:353,Yuml:376,fnof:402,circ:710,tilde:732,Alpha:913,Beta:914,Gamma:915,Delta:916,Epsilon:917,Zeta:918,Eta:919,Theta:920,Iota:921,Kappa:922,Lambda:923,Mu:924,Nu:925,Xi:926,Omicron:927,Pi:928,Rho:929,Sigma:931,Tau:932,Upsilon:933,Phi:934,Chi:935,Psi:936,Omega:937,alpha:945,beta:946,gamma:947,delta:948,epsilon:949,zeta:950,eta:951,theta:952,iota:953,kappa:954,lambda:955,mu:956,nu:957,xi:958,omicron:959,pi:960,rho:961,sigmaf:962,sigma:963,tau:964,upsilon:965,phi:966,chi:967,psi:968,omega:969,thetasym:977,upsih:978,piv:982,ensp:8194,emsp:8195,thinsp:8201,zwnj:8204,zwj:8205,lrm:8206,rlm:8207,ndash:8211,mdash:8212,lsquo:8216,rsquo:8217,sbquo:8218,ldquo:8220,rdquo:8221,bdquo:8222,dagger:8224,Dagger:8225,bull:8226,hellip:8230,permil:8240,prime:8242,Prime:8243,lsaquo:8249,rsaquo:8250,oline:8254,frasl:8260,euro:8364,image:8465,weierp:8472,real:8476,trade:8482,alefsym:8501,larr:8592,uarr:8593,rarr:8594,darr:8595,harr:8596,crarr:8629,lArr:8656,uArr:8657,rArr:8658,dArr:8659,hArr:8660,forall:8704,part:8706,exist:8707,empty:8709,nabla:8711,isin:8712,notin:8713,ni:8715,prod:8719,sum:8721,minus:8722,lowast:8727,radic:8730,prop:8733,infin:8734,ang:8736,and:8743,or:8744,cap:8745,cup:8746,"int":8747,there4:8756,sim:8764,cong:8773,asymp:8776,ne:8800,equiv:8801,le:8804,ge:8805,sub:8834,sup:8835,nsub:8836,sube:8838,supe:8839,oplus:8853,otimes:8855,perp:8869,sdot:8901,lceil:8968,rceil:8969,lfloor:8970,rfloor:8971,lang:9001,rang:9002,loz:9674,spades:9824,clubs:9827,hearts:9829,diams:9830},b=function(b){var c;return c=b.replace(/&([a-zA-Z]+);/,function(b,c){return a[c]?String.fromCharCode(a[c]):b}),c=c.replace(/&#x([0-9]+);/,function(a,b){return String.fromCharCode(parseInt(b,16))}),c=c.replace(/&#([0-9]+);/,function(a,b){return String.fromCharCode(b)})},c=/\s+/g}(),ob=function(a,b,c){var d,e;return d={pos:0,tokens:a||[],next:function(){return d.tokens[d.pos]},options:b},e=new Bc(d,c)};var Fc;!function(){var a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F;Fc=function(a){return k(a)},a=function(b){var c,d,e,f;if(c=b.pos,tc(b),e=Fc(b),null===e)return null;if(d=[e],tc(b),wc(b,",")){if(f=a(b),null===f)return b.pos=c,null;d=d.concat(f)}return d},d=function(a){var b,c;return b=a.pos,wc(a,"(")?(tc(a),(c=Fc(a))?(tc(a),wc(a,")")?{t:ec,x:c}:(a.pos=b,null)):(a.pos=b,null)):null},e=function(a){return r(a)||p(a)||d(a)},f=function(a){var b,c,d;if(b=e(a),!b)return null;if(c=q(a),!c)return b;for(;null!==c;)d={t:cc,x:b,r:c},b=d,c=q(a);return d},g=function(b){var c,d,e,g;return(d=f(b))?(c=b.pos,wc(b,"(")?(tc(b),e=a(b),tc(b),wc(b,")")?(g={t:hc,x:d},e&&(g.o=e),g):(b.pos=c,d)):d):null},h=function(a){var b,c,d;if(b=g(a),!b)return null;if(b.t!==hc)return b;if(c=q(a),!c)return b;for(;null!==c;)d={t:cc,x:b,r:c},b=d,c=q(a);return d},b=function(a,b){return function(c){var d,e;return wc(c,a)?(d=c.pos,tc(c),e=Fc(c),e||uc(c,"an expression"),{s:a,o:e,t:dc}):b(c)}},function(){var a,c,d,e,f;for(e="! ~ + - typeof".split(" "),f=h,a=0,c=e.length;c>a;a+=1)d=b(e[a],f),f=d;i=f}(),c=function(a,b){return function(c){var d,e,f;return(e=b(c))?(d=c.pos,tc(c),wc(c,a)?"in"===a&&/[a-zA-Z_$0-9]/.test(c.remaining().charAt(0))?(c.pos=d,e):(tc(c),f=Fc(c),f?{t:gc,s:a,o:[e,f]}:(c.pos=d,e)):(c.pos=d,e)):null}},function(){var a,b,d,e,f;for(e="* / % + - << >> >>> < <= > >= in instanceof == != === !== & ^ | && ||".split(" "),f=i,a=0,b=e.length;b>a;a+=1)d=c(e[a],f),f=d;j=f}(),k=function(a){var b,c,d,e;return(c=j(a))?(b=a.pos,tc(a),wc(a,"?")?(tc(a),(d=Fc(a))?(tc(a),wc(a,":")?(tc(a),e=Fc(a),e?{t:fc,o:[c,d,e]}:(a.pos=b,c)):(a.pos=b,c)):(a.pos=b,c)):(a.pos=b,c)):null},l=vc(/^[0-9]+/),m=vc(/^[eE][\-+]?[0-9]+/),n=vc(/^\.[0-9]+/),o=vc(/^(0|[1-9][0-9]*)/),p=function(a){var b,c,d,e,f,g;if(b=a.pos,d=wc(a,".")||"",c=B(a)||"","this"===c&&(c=".",b+=3),e=d+c,!e)return null;for(;f=C(a)||D(a);)e+=f;return wc(a,"(")&&(g=e.lastIndexOf("."),-1!==g?(e=e.substr(0,g),a.pos=b+e.length):a.pos-=1),{t:ac,n:e}},q=function(a){var b,c,d;if(b=a.pos,tc(a),wc(a,".")){if(tc(a),c=B(a))return{t:bc,n:c};uc(a,"a property name")}return wc(a,"[")?(tc(a),d=Fc(a),d||uc(a,"an expression"),tc(a),wc(a,"]")||uc(a,'"]"'),{t:bc,x:d}):null},r=function(a){var b=u(a)||t(a)||x(a)||v(a)||w(a)||s(a);return b},s=function(b){var c,d;return c=b.pos,tc(b),wc(b,"[")?(d=a(b),wc(b,"]")?{t:Xb,m:d}:(b.pos=c,null)):(b.pos=c,null)},t=function(a){var b=a.remaining();return"true"===b.substr(0,4)?(a.pos+=4,{t:Zb,v:"true"}):"false"===b.substr(0,5)?(a.pos+=5,{t:Zb,v:"false"}):null},F=/^(?:Array|Date|RegExp|decodeURIComponent|decodeURI|encodeURIComponent|encodeURI|isFinite|isNaN|parseFloat|parseInt|JSON|Math|NaN|undefined|null)/,x=function(a){var b,c,d;return b=a.pos,(c=B(a))?(d=F.exec(c))?(a.pos=b+d[0].length,{t:$b,v:d[0]}):(a.pos=b,null):null},u=function(a){var b,c;return b=a.pos,(c=n(a))?{t:Vb,v:c}:(c=o(a),null===c?null:(c+=n(a)||"",c+=m(a)||"",{t:Vb,v:c}))},w=function(a){var b,c;return b=a.pos,tc(a),wc(a,"{")?(c=y(a),tc(a),wc(a,"}")?{t:Yb,m:c}:(a.pos=b,null)):(a.pos=b,null)},y=function(a){var b,c,d,e;return b=a.pos,d=z(a),null===d?null:(c=[d],wc(a,",")?(e=y(a),e?c.concat(e):(a.pos=b,null)):c)},z=function(a){var b,c,d;return b=a.pos,tc(a),c=A(a),null===c?(a.pos=b,null):(tc(a),wc(a,":")?(tc(a),d=Fc(a),null===d?(a.pos=b,null):{t:_b,k:c,v:d}):(a.pos=b,null))},A=function(a){return B(a)||v(a)||u(a)},v=function(a){var b,c;return b=a.pos,wc(a,'"')?(c=Jc(a),wc(a,'"')?{t:Wb,v:c}:(a.pos=b,null)):wc(a,"'")?(c=Nc(a),wc(a,"'")?{t:Wb,v:c}:(a.pos=b,null)):null},B=vc(/^[a-zA-Z_$][a-zA-Z_$0-9]*/),C=vc(/^\.[a-zA-Z_$0-9]+/),D=function(a){var b=E(a);return b?"."+b:null},E=vc(/^\[(0|[1-9][0-9]*)\]/)}();var Gc;!function(){var a,b,c,d,e,f,g,h;Gc=function(c){return c.tripleDelimiters[0].length>c.delimiters[0].length?b(c)||a(c):a(c)||b(c)},a=function(a){var b,d=a.pos;return wc(a,a.delimiters[0])?(b=h(a))?wc(a,a.delimiters[1])?(a.delimiters=b,{type:Sb,mustacheType:Rb}):(a.pos=d,null):(b=c(a),null===b?(a.pos=d,null):(tc(a),wc(a,a.delimiters[1])||uc(a,'"'+a.delimiters[1]+'"'),b)):null},b=function(a){var b,d=a.pos;return wc(a,a.tripleDelimiters[0])?(b=h(a))?wc(a,a.tripleDelimiters[1])?(a.tripleDelimiters=b,{type:Sb,mustacheType:Rb}):(a.pos=d,null):(tc(a),b=c(a,!0),null===b?(a.pos=d,null):(tc(a),wc(a,a.tripleDelimiters[1])?b:(a.pos=d,null))):null},c=function(a,b){var c,f,g,h,i,j,k;if(c=a.pos,f={type:b?Kb:Sb},!b&&(g=d(a),f.mustacheType=g||Jb,(g===Qb||g===Nb)&&(j=a.remaining(),k=j.indexOf(a.delimiters[1]),-1!==k)))return f.ref=j.substr(0,k),a.pos+=k,f;for(tc(a),h=Fc(a);h.t===ec&&h.x;)h=h.x;return h.t===ac?f.ref=h.n:f.expression=h,i=e(a),null!==i&&(f.indexRef=i),f},f={"#":Lb,"^":Mb,"/":Nb,">":Pb,"!":Qb,"&":Jb},d=function(a){var b=f[a.str.charAt(a.pos)];return b?(a.pos+=1,b):null},e=vc(/^\s*:\s*([a-zA-Z_$][a-zA-Z_$0-9]*)/),g=vc(/^[^\s=]+/),h=function(a){var b,c,d;return wc(a,"=")?(b=a.pos,tc(a),(c=g(a))?(tc(a),(d=g(a))?(tc(a),wc(a,"=")?[c,d]:(a.pos=b,null)):(a.pos=b,null)):(a.pos=b,null)):null}}();var Hc;!function(){var a,b,c,d,e,f,g,h,i,j,k,l,m,n;Hc=function(c){return a(c)||b(c)},a=function(a){var b,e,f;return b=a.pos,wc(a,"<")?(e={type:Tb},e.name=c(a),e.name?(f=d(a),f&&(e.attrs=f),tc(a),wc(a,"/")&&(e.selfClosing=!0),wc(a,">")?e:(a.pos=b,null)):(a.pos=b,null)):null},b=function(a){var b,d;if(b=a.pos,!wc(a,"<"))return null;if(d={type:Tb,closing:!0},!wc(a,"/"))throw new Error("Unexpected character "+a.remaining().charAt(0)+' (expected "/")');if(d.name=c(a),!d.name)throw new Error("Unexpected character "+a.remaining().charAt(0)+" (expected tag name)");if(!wc(a,">"))throw new Error("Unexpected character "+a.remaining().charAt(0)+' (expected ">")');return d},c=vc(/^[a-zA-Z][a-zA-Z0-9\-]*/),d=function(a){var b,c,d;if(b=a.pos,tc(a),d=e(a),!d)return a.pos=b,null;for(c=[];null!==d;)c[c.length]=d,tc(a),d=e(a);return c},e=function(a){var b,c,d;return(c=f(a))?(b={name:c},d=g(a),d&&(b.value=d),b):null},f=vc(/^[^\s"'>\/=]+/),g=function(a){var b,c;return b=a.pos,tc(a),wc(a,"=")?(c=k(a)||m(a)||h(a),null===c?(a.pos=b,null):c):(a.pos=b,null)},j=vc(/^[^\s"'=<>`]+/),i=function(a){var b,c,d;return b=a.pos,(c=j(a))?(-1!==(d=c.indexOf(a.delimiters[0]))&&(c=c.substr(0,d),a.pos=b+c.length),{type:Ib,value:c}):null},h=function(a){var b,c;for(b=[],c=Gc(a)||i(a);null!==c;)b[b.length]=c,c=Gc(a)||i(a);return b.length?b:null},l=function(a){var b,c,d;return b=a.pos,(c=Nc(a))?(-1!==(d=c.indexOf(a.delimiters[0]))&&(c=c.substr(0,d),a.pos=b+c.length),{type:Ib,value:c}):null},k=function(a){var b,c,d;if(b=a.pos,!wc(a,"'"))return null;for(c=[],d=Gc(a)||l(a);null!==d;)c[c.length]=d,d=Gc(a)||l(a);return wc(a,"'")?c:(a.pos=b,null)},n=function(a){var b,c,d;return b=a.pos,(c=Jc(a))?(-1!==(d=c.indexOf(a.delimiters[0]))&&(c=c.substr(0,d),a.pos=b+c.length),{type:Ib,value:c}):null},m=function(a){var b,c,d;if(b=a.pos,!wc(a,'"'))return null;for(c=[],d=Gc(a)||n(a);null!==d;)c[c.length]=d,d=Gc(a)||n(a);return wc(a,'"')?c:(a.pos=b,null)}}();var Ic=function(a){var b,c;return b=a.str.length,[a.delimiters[0],a.tripleDelimiters[0],"<"].forEach(function(c){var d=a.str.indexOf(c,a.pos);-1!==d&&(b=Math.min(d,b))}),b===a.pos?null:(c=a.str.substring(a.pos,b),a.pos=b,{type:Ib,value:c})};pb=function(a){var b=Gc(a)||Hc(a)||Ic(a);return b};var Jc=function(a){var b,c,d,e,f;if(b=a.pos,c="",d=Mc(a),d&&(c+=d),e=Kc(a),e&&(c+=e),!c)return"";for(f=Jc(a);""!==f;)c+=f;return c},Kc=vc(/^[^\\"]+/),Lc=function(a){var b;return wc(a,"\\")?(b=a.str.charAt(a.pos),a.pos+=1,b):null},Mc=function(a){var b,c="";for(b=Lc(a);b;)c+=b,b=Lc(a);return c||null},Nc=function(a){var b,c,d,e,f;if(b=a.pos,c="",d=Mc(a),d&&(c+=d),e=Oc(a),e&&(c+=e),c)for(f=Nc(a);f;)c+=f,f=Nc(a);return c},Oc=vc(/^[^\\']+/);!function(){var a,b,c,d;a=/^\s*$/,b=//,c=//,e=function(c,e){var f,g,h,i;return e=e||{},b.test(c)?d(c,e):(e.sanitize===!0&&(e.sanitize={elements:"applet base basefont body frame frameset head html isindex link meta noframes noscript object param script style title".split(" "),eventAttributes:!0}),f=qb(c,e),e.preserveWhitespace||(i=f[0],i&&i.type===Ib&&a.test(i.value)&&f.shift(),i=f[f.length-1],i&&i.type===Ib&&a.test(i.value)&&f.pop()),g=ob(f,e,e.preserveWhitespace),h=g.toJSON(),"string"==typeof h?[h]:h)},d=function(a,d){var f,g,h,i,j,k;for(h={},f="",g=a;j=b.exec(g);){if(i=j[1],f+=g.substr(0,j.index),g=g.substring(j.index+j[0].length),k=c.exec(g),!k||k[1]!==i)throw new Error("Inline partials must have a closing delimiter, and cannot be nested");h[i]=e(g.substr(0,k.index),d),g=g.substring(k.index+k[0].length)}return{main:e(f,d),partials:h}}}(),qb=function(a,b){var c,d,e,f,g;for(b=b||{},c={str:sb(a),pos:0,delimiters:b.delimiters||["{{","}}"],tripleDelimiters:b.tripleDelimiters||["{{{","}}}"],remaining:function(){return c.str.substring(c.pos)}},d=[];c.pos"+g);d[d.length]=e}return tb(d),rb(d),d},b.prototype=xb,b.adaptors=yb,b.eventDefinitions=zb,b.partials={},b.easing=c,b.extend=d,b.interpolate=f,b.interpolators=g,b.parse=e,b.transitions=Ab,b.VERSION=vb,"undefined"!=typeof module&&module.exports?module.exports=b:"function"==typeof define&&define.amd?define(function(){return b}):a.Ractive=b}("undefined"!=typeof window?window:this); \ No newline at end of file diff --git a/ajax/libs/ractive.js/package.json b/ajax/libs/ractive.js/package.json index 72f25e4a1..0685dcf04 100644 --- a/ajax/libs/ractive.js/package.json +++ b/ajax/libs/ractive.js/package.json @@ -1,7 +1,7 @@ { "name": "ractive.js", "filename": "ractive.min.js", - "version": "0.3.3", + "version": "0.3.6", "description": "Next-generation DOM manipulation", "homepage": "http://www.ractivejs.org/", "keywords": [