{"version":3,"file":"ractive.min.js","sources":["../src/view/Fragment.js","../src/Ractive/prototype/reset.js","../src/Ractive/prototype/reverse.js","../src/Ractive/prototype/shift.js","../src/Ractive/prototype/sort.js","../src/Ractive/prototype/splice.js","../src/Ractive/prototype/unshift.js","../src/Ractive/prototype.js","../src/Ractive/static/styles.js","../src/extend/_extend.js","../src/Ractive.js","../src/view/items/element/specials/Option.js","../src/view/items/Partial.js","../src/model/specials/KeyModel.js","../src/view/RepeatedFragment.js","../src/view/items/Section.js","../src/view/items/element/specials/Select.js","../src/view/items/element/specials/Textarea.js","../src/view/items/Text.js","../src/config/visibility.js","../src/view/items/element/transitions/prefix.js","../src/view/items/element/transitions/createTransitions.js","../src/view/items/element/transitions/hyphenate.js","../src/view/items/element/Transition.js","../src/view/items/triple/insertHtml.js","../src/view/items/Triple.js","../src/view/items/createItem.js","../src/view/resolvers/ExpressionProxy.js","../src/view/items/element/Decorator.js","../src/view/items/Doctype.js","../src/view/items/element/binding/Binding.js","../src/view/items/element/binding/CheckboxBinding.js","../src/view/items/element/binding/getBindingGroup.js","../src/view/items/element/binding/CheckboxNameBinding.js","../src/view/items/element/binding/ContentEditableBinding.js","../src/view/items/element/binding/GenericBinding.js","../src/view/items/element/binding/FileBinding.js","../src/view/items/element/binding/MultipleSelectBinding.js","../src/view/items/element/binding/NumericBinding.js","../src/view/items/element/binding/RadioBinding.js","../src/view/items/element/binding/RadioNameBinding.js","../src/view/items/element/binding/SingleSelectBinding.js","../src/view/items/Element.js","../src/view/items/element/specials/Form.js","../src/view/items/element/ElementEvents.js","../src/view/items/component/RactiveEvent.js","../src/view/items/shared/EventDirective.js","../src/view/resolvers/ReferenceExpressionProxy.js","../src/view/items/shared/Mustache.js","../src/view/items/Interpolator.js","../src/view/items/element/specials/Input.js","../src/utils/parseJSON.js","../src/view/items/component/Mapping.js","../src/shared/Context.js","../src/Ractive/static/getContext.js","../src/utils/dom.js","../src/config/namespaces.js","../src/Ractive/prototype/observe/Observer.js","../src/Ractive/prototype/observe/Pattern.js","../src/Ractive/prototype/observe/Array.js","../src/Ractive/prototype/observeOnce.js","../src/Ractive/prototype/shared/trim.js","../src/Ractive/prototype/shared/notEmptyString.js","../src/Ractive/prototype/pop.js","../src/Ractive/prototype/push.js","../src/global/css.js","../src/Ractive/config/custom/adapt.js","../src/utils/cleanCss.js","../src/Ractive/config/custom/css/transform.js","../src/model/specials/CSSModel.js","../src/Ractive/config/custom/css/css.js","../src/Ractive/config/custom/data.js","../src/Ractive/config/custom/template.js","../src/Ractive/config/registries.js","../src/Ractive/config/config.js","../src/view/items/shared/Item.js","../src/view/helpers/specialAttrs.js","../src/view/items/element/attribute/getUpdateDelegate.js","../src/view/items/element/attribute/propertyNames.js","../src/view/items/element/ConditionalAttribute.js","../src/view/items/element/Attribute.js","../src/view/items/element/BindingFlag.js","../src/view/items/Comment.js","../src/model/specials/RactiveModel.js","../src/model/RootModel.js","../src/Ractive/construct.js","../src/view/items/Component.js","../src/model/ComputationChild.js","../src/model/Computation.js","../src/Ractive/static/interpolators.js","../src/shared/keypaths.js","../src/utils/bind.js","../src/model/ModelBase.js","../src/global/capture.js","../src/model/LinkModel.js","../src/shared/getFunction.js","../src/config/template.js","../src/parse/Parser.js","../src/config/types.js","../src/parse/converters/expressions/readTypeof.js","../src/parse/converters/mustache/readDelimiterChange.js","../src/parse/converters/expressions/primary/literal/readRegexpLiteral.js","../src/utils/escapeRegExp.js","../src/parse/converters/utils/getLowestIndex.js","../src/utils/html.js","../src/parse/converters/expressions/shared/errors.js","../src/parse/converters/expressions/primary/literal/readNumberLiteral.js","../src/parse/converters/expressions/primary/literal/stringLiteral/makeQuotedStringMatcher.js","../src/parse/converters/expressions/primary/literal/readStringLiteral.js","../src/parse/converters/expressions/primary/literal/readTemplateStringLiteral.js","../src/parse/converters/expressions/shared/patterns.js","../src/parse/converters/expressions/shared/readKey.js","../src/parse/converters/expressions/primary/readReference.js","../src/parse/converters/expressions/readLogicalOr.js","../src/parse/converters/element/readAttribute.js","../src/parse/converters/readMustache.js","../src/parse/converters/mustache/readAliases.js","../src/parse/converters/mustache/section/readInlineBlock.js","../src/parse/converters/mustache/handlebarsBlockCodes.js","../src/parse/converters/mustache/readSection.js","../src/parse/converters/readHtmlComment.js","../src/parse/utils/stripStandalones.js","../src/parse/utils/cleanup.js","../src/parse/converters/element/readClosingTag.js","../src/parse/converters/readElement.js","../src/parse/converters/readPartialDefinitionSection.js","../src/Ractive/shared.js","../src/parse/_parse.js","../src/Ractive/config/runtime-parser.js","../src/global/TransitionManager.js","../src/global/runloop.js","../src/shared/Ticker.js","../src/model/helpers/getPrefixer.js","../src/model/Model.js","../src/model/specials/SharedModel.js","../src/shared/getRactiveContext.js","../src/shared/set.js","../src/Ractive/prototype/shared/add.js","../src/Ractive/prototype/animate.js","../src/events/fireEvent.js","../src/events/Hook.js","../src/Ractive/prototype/shared/makeArrayMethod.js","../src/Ractive/prototype/teardown.js","../src/Ractive/helpers/subscribe.js","../src/view/items/shared/directiveArgs.js","../src/view/items/element/binding/handleDomEvent.js","../src/utils/getSelectedOptions.js","../src/view/items/element/binding/selectBinding.js","../src/view/items/shared/progressiveText.js","../src/view/resolvers/resolve.js","../src/view/items/partial/getPartialTemplate.js","../src/view/items/component/getComponentConstructor.js","../src/view/items/asyncProxy.js","../src/view/items/Await.js","../src/view/helpers/processItems.js","../src/Ractive/initialise.js","../src/Ractive/render.js","../src/Ractive/prototype/render.js","../src/Ractive/prototype/resetPartial.js","../src/Ractive/prototype/resetTemplate.js","../src/Ractive/prototype/set.js","../src/Ractive/prototype/subtract.js","../src/Ractive/prototype/toggle.js","../src/Ractive/prototype/toCSS.js","../src/Ractive/prototype/toHTML.js","../src/Ractive/prototype/toText.js","../src/Ractive/prototype/transition.js","../src/Ractive/prototype/unlink.js","../src/Ractive/prototype/unrender.js","../src/Ractive/prototype/updateModel.js","../src/Ractive/prototype/use.js","../src/Ractive/static/isInstance.js","../src/Ractive/static/styleGet.js","../src/Ractive/static/sharedSet.js","../src/Ractive/static/sharedGet.js","../src/Ractive/static/use.js","../src/extend/_macro.js","../src/Ractive/static/findPlugin.js","../src/polyfills/Object.assign.js","../src/utils/object.js","../src/utils/is.js","../src/polyfills/performance.now.js","../src/polyfills/array.find.js","../src/polyfills/node.contains.js","../src/config/environment.js","../src/polyfills/Promise.js","../src/polyfills/requestAnimationFrame.js","../src/Ractive/config/defaults.js","../src/utils/log.js","../src/Ractive/static/easing.js","../src/config/errors.js","../src/view/resolvers/resolveReference.js","../src/Ractive/prototype/add.js","../src/events/eventStack.js","../src/shared/anchors.js","../src/Ractive/prototype/attachChild.js","../src/Ractive/prototype/compute.js","../src/Ractive/prototype/detach.js","../src/Ractive/prototype/detachChild.js","../src/Ractive/prototype/find.js","../src/Ractive/prototype/findAll.js","../src/Ractive/prototype/findAllComponents.js","../src/Ractive/prototype/findComponent.js","../src/Ractive/prototype/findContainer.js","../src/Ractive/prototype/findParent.js","../src/view/items/shared/findElement.js","../src/shared/getNewIndices.js","../src/Ractive/prototype/update.js","../src/Ractive/prototype/fire.js","../src/Ractive/prototype/get.js","../src/Ractive/prototype/getLocalContext.js","../src/Ractive/prototype/getContext.js","../src/Ractive/prototype/insert.js","../src/Ractive/prototype/link.js","../src/Ractive/static/keypaths.js","../src/Ractive/prototype/observe.js","../src/Ractive/prototype/off.js","../src/Ractive/prototype/on.js","../src/Ractive/prototype/once.js","../src/Ractive/prototype/readLink.js","../src/utils/id.js","../src/Ractive/static/styleSet.js","../src/Ractive/config/wrapPrototypeMethod.js","../src/Ractive/config/deprecate.js","../src/utils/noop.js","../src/shared/registry.js","../src/shared/interpolate.js","../src/utils/array.js","../src/shared/methodCallers.js","../src/shared/rebind.js","../src/parse/utils/createFunction.js","../src/parse/converters/expressions/primary/literal/readBooleanLiteral.js","../src/parse/converters/expressions/primary/literal/objectLiteral/keyValuePair.js","../src/parse/converters/expressions/primary/literal/objectLiteral/keyValuePairs.js","../src/parse/converters/expressions/primary/literal/readObjectLiteral.js","../src/parse/converters/expressions/primary/literal/readArrayLiteral.js","../src/parse/converters/expressions/primary/readLiteral.js","../src/parse/converters/expressions/primary/readBracketedExpression.js","../src/parse/converters/expressions/readPrimary.js","../src/parse/converters/expressions/shared/readRefinement.js","../src/parse/converters/expressions/readMemberOrInvocation.js","../src/parse/converters/expressions/readConditional.js","../src/parse/converters/readExpression.js","../src/parse/converters/expressions/shared/readExpressionList.js","../src/parse/converters/readExpressionOrReference.js","../src/parse/utils/flattenExpression.js","../src/parse/utils/refineExpression.js","../src/parse/converters/mustache/readTriple.js","../src/parse/converters/mustache/readUnescaped.js","../src/parse/converters/mustache/readPartial.js","../src/parse/converters/mustache/readMustacheComment.js","../src/parse/converters/mustache/readInterpolator.js","../src/parse/converters/mustache/section/readClosing.js","../src/parse/utils/trimWhitespace.js","../src/utils/hyphenateCamel.js","../src/parse/converters/readText.js","../src/parse/converters/readTemplate.js","../src/parse/utils/insertExpressions.js","../src/Ractive/helpers/getComputationSignature.js"],"sourcesContent":["import { ELEMENT, YIELDER } from 'config/types';\nimport runloop from 'src/global/runloop';\nimport { findMap } from 'utils/array';\nimport { getContext, findParentWithContext } from 'shared/getRactiveContext';\nimport { shuffled, toEscapedString, toString } from 'shared/methodCallers';\nimport createItem from './items/createItem';\nimport processItems from './helpers/processItems';\nimport parseJSON from 'utils/parseJSON';\nimport { createDocumentFragment } from 'utils/dom';\nimport KeyModel from 'src/model/specials/KeyModel';\nimport resolve from './resolvers/resolve';\n\nfunction resolveAliases(aliases, fragment, dest = {}) {\n for (let i = 0; i < aliases.length; i++) {\n if (!dest[aliases[i].n]) {\n const m = resolve(fragment, aliases[i].x);\n dest[aliases[i].n] = m;\n m.reference();\n }\n }\n\n return dest;\n}\n\nexport default class Fragment {\n constructor(options) {\n this.owner = options.owner; // The item that owns this fragment - an element, section, partial, or attribute\n\n this.isRoot = !options.owner.up;\n this.parent = this.isRoot ? null : this.owner.up;\n this.ractive = options.ractive || (this.isRoot ? options.owner : this.parent.ractive);\n\n this.componentParent =\n this.isRoot && this.ractive.component\n ? this.ractive.component.up\n : this.owner.containerFragment || null;\n if (!this.isRoot || this.ractive.delegate) {\n this.delegate = this.owner.containerFragment\n ? this.owner.containerFragment && this.owner.containerFragment.delegate\n : (this.componentParent && this.componentParent.delegate) ||\n (this.parent && this.parent.delegate);\n } else {\n this.delegate = false;\n }\n\n this.context = null;\n this.rendered = false;\n\n // encapsulated styles should be inherited until they get applied by an element\n if ('cssIds' in options) {\n this.cssIds = options.cssIds && options.cssIds.length && options.cssIds;\n } else {\n this.cssIds = this.parent ? this.parent.cssIds : null;\n }\n\n this.dirty = false;\n this.dirtyValue = true; // used for attribute values\n\n this.template = options.template || [];\n this.createItems();\n }\n\n bind(context) {\n this.context = context;\n\n if (this.owner.template.z) {\n this.aliases = resolveAliases(\n this.owner.template.z,\n this.owner.containerFragment || this.parent\n );\n }\n\n const len = this.items.length;\n for (let i = 0; i < len; i++) this.items[i].bind();\n this.bound = true;\n\n // in rare cases, a forced resolution (or similar) will cause the\n // fragment to be dirty before it's even finished binding. In those\n // cases we update immediately\n if (this.dirty) this.update();\n\n return this;\n }\n\n bubble() {\n this.dirtyValue = true;\n\n if (!this.dirty) {\n this.dirty = true;\n\n if (this.isRoot) {\n // TODO encapsulate 'is component root, but not overall root' check?\n if (this.ractive.component) {\n this.ractive.component.bubble();\n } else if (this.bound) {\n runloop.addFragment(this);\n }\n } else {\n this.owner.bubble(this.index);\n }\n }\n }\n\n createItems() {\n // this is a hot code path\n const max = this.template.length;\n this.items = [];\n for (let i = 0; i < max; i++) {\n this.items[i] = createItem({\n up: this,\n template: this.template[i],\n index: i\n });\n }\n }\n\n destroyed() {\n const len = this.items.length;\n for (let i = 0; i < len; i++) this.items[i].destroyed();\n if (this.pathModel) this.pathModel.destroyed();\n if (this.rootModel) this.rootModel.destroyed();\n }\n\n detach() {\n const docFrag = createDocumentFragment();\n const xs = this.items;\n const len = xs.length;\n for (let i = 0; i < len; i++) {\n docFrag.appendChild(xs[i].detach());\n }\n return docFrag;\n }\n\n find(selector, options) {\n return findMap(this.items, i => i.find(selector, options));\n }\n\n findAll(selector, options) {\n if (this.items) {\n this.items.forEach(i => i.findAll && i.findAll(selector, options));\n }\n }\n\n findComponent(name, options) {\n return findMap(this.items, i => i.findComponent(name, options));\n }\n\n findAllComponents(name, options) {\n if (this.items) {\n this.items.forEach(i => i.findAllComponents && i.findAllComponents(name, options));\n }\n }\n\n findContext() {\n const base = findParentWithContext(this);\n if (!base || !base.context) return this.ractive.viewmodel;\n else return base.context;\n }\n\n findNextNode(item) {\n // search for the next node going forward\n if (item) {\n let it;\n for (let i = item.index + 1; i < this.items.length; i++) {\n it = this.items[i];\n if (!it || !it.firstNode) continue;\n\n const node = it.firstNode(true);\n if (node) return node;\n }\n }\n\n // if this is the root fragment, and there are no more items,\n // it means we're at the end...\n if (this.isRoot) {\n if (this.ractive.component) {\n return this.ractive.component.up.findNextNode(this.ractive.component);\n }\n\n // TODO possible edge case with other content\n // appended to this.ractive.el?\n return null;\n }\n\n if (this.parent) return this.owner.findNextNode(this); // the argument is in case the parent is a RepeatedFragment\n }\n\n findParentNode() {\n let fragment = this;\n\n do {\n if (fragment.owner.type === ELEMENT) {\n return fragment.owner.node;\n }\n\n if (fragment.isRoot && !fragment.ractive.component) {\n // TODO encapsulate check\n return fragment.ractive.el;\n }\n\n if (fragment.owner.type === YIELDER) {\n fragment = fragment.owner.containerFragment;\n } else {\n fragment = fragment.componentParent || fragment.parent; // TODO ugh\n }\n } while (fragment);\n\n throw new Error('Could not find parent node'); // TODO link to issue tracker\n }\n\n firstNode(skipParent) {\n const node = findMap(this.items, i => i.firstNode(true));\n if (node) return node;\n if (skipParent) return null;\n\n return this.parent.findNextNode(this.owner);\n }\n\n getKey() {\n return this.keyModel || (this.keyModel = new KeyModel(this.key));\n }\n\n getIndex() {\n return this.idxModel || (this.idxModel = new KeyModel(this.index));\n }\n\n rebind(next) {\n this.context = next;\n if (this.rootModel) this.rootModel.context = this.context;\n if (this.pathModel) this.pathModel.context = this.context;\n }\n\n rebound(update) {\n if (this.owner.template.z) {\n const aliases = this.aliases;\n for (const k in aliases) {\n if (aliases[k].rebound) aliases[k].rebound(update);\n else {\n aliases[k].unreference();\n aliases[k] = 0;\n }\n }\n\n resolveAliases(this.owner.template.z, this.owner.containerFragment || this.parent, aliases);\n }\n\n this.items.forEach(x => x.rebound(update));\n if (update) {\n if (this.rootModel) this.rootModel.applyValue(this.context.getKeypath(this.ractive.root));\n if (this.pathModel) this.pathModel.applyValue(this.context.getKeypath());\n }\n }\n\n render(target, occupants) {\n if (this.rendered) throw new Error('Fragment is already rendered!');\n this.rendered = true;\n\n const xs = this.items;\n const len = xs.length;\n for (let i = 0; i < len; i++) {\n xs[i].render(target, occupants);\n }\n }\n\n resetTemplate(template) {\n const wasBound = this.bound;\n const wasRendered = this.rendered;\n\n // TODO ensure transitions are disabled globally during reset\n\n if (wasBound) {\n if (wasRendered) this.unrender(true);\n this.unbind();\n }\n\n this.template = template;\n this.createItems();\n\n if (wasBound) {\n this.bind(this.context);\n\n if (wasRendered) {\n const parentNode = this.findParentNode();\n const anchor = this.findNextNode();\n\n if (anchor) {\n const docFrag = createDocumentFragment();\n this.render(docFrag);\n parentNode.insertBefore(docFrag, anchor);\n } else {\n this.render(parentNode);\n }\n }\n }\n }\n\n shuffled() {\n this.items.forEach(shuffled);\n if (this.rootModel) this.rootModel.applyValue(this.context.getKeypath(this.ractive.root));\n if (this.pathModel) this.pathModel.applyValue(this.context.getKeypath());\n }\n\n toString(escape) {\n return this.items.map(escape ? toEscapedString : toString).join('');\n }\n\n unbind(view) {\n if (this.owner.template.z && !this.owner.yielder) {\n for (const k in this.aliases) {\n this.aliases[k].unreference();\n }\n\n this.aliases = {};\n }\n\n this.context = null;\n const len = this.items.length;\n for (let i = 0; i < len; i++) this.items[i].unbind(view);\n this.bound = false;\n\n return this;\n }\n\n unrender(shouldDestroy) {\n const len = this.items.length;\n for (let i = 0; i < len; i++) this.items[i].unrender(shouldDestroy);\n this.rendered = false;\n }\n\n update() {\n if (this.dirty) {\n if (!this.updating) {\n this.dirty = false;\n this.updating = true;\n const len = this.items.length;\n for (let i = 0; i < len; i++) this.items[i].update();\n this.updating = false;\n } else if (this.isRoot) {\n runloop.addFragmentToRoot(this);\n }\n }\n }\n\n valueOf() {\n if (this.items.length === 1) {\n return this.items[0].valueOf();\n }\n\n if (this.dirtyValue) {\n const values = {};\n const source = processItems(this.items, values, this.ractive._guid);\n const parsed = parseJSON(source, values);\n\n this.value = parsed ? parsed.value : this.toString();\n\n this.dirtyValue = false;\n }\n\n return this.value;\n }\n}\nFragment.prototype.getContext = getContext;\nFragment.prototype.getKeypath = getKeypath;\n\nexport function getKeypath(root) {\n const base = findParentWithContext(this);\n let model;\n if (root) {\n if (!this.rootModel) {\n this.rootModel = new KeyModel(\n this.context.getKeypath(this.ractive.root),\n this.context,\n this.ractive.root\n );\n model = this.rootModel;\n } else return this.rootModel;\n } else {\n if (!this.pathModel) {\n this.pathModel = new KeyModel(this.context.getKeypath(), this.context);\n model = this.pathModel;\n } else return this.pathModel;\n }\n\n if (base && base.context) base.getKeypath(root).registerChild(model);\n\n return model;\n}\n","import runloop from 'src/global/runloop';\nimport config from '../config/config';\nimport hooks from '../../events/Hook';\nimport dataConfigurator from '../config/custom/data';\nimport { isObjectType } from 'utils/is';\n\nconst shouldRerender = ['template', 'partials', 'components', 'decorators', 'events'];\n\nexport default function Ractive$reset(data) {\n data = data || {};\n\n if (!isObjectType(data)) {\n throw new Error('The reset method takes either no arguments, or an object containing new data');\n }\n\n // TEMP need to tidy this up\n data = dataConfigurator.init(this.constructor, this, { data });\n\n const promise = runloop.start();\n\n // If the root object is wrapped, try and use the wrapper's reset value\n const wrapper = this.viewmodel.wrapper;\n if (wrapper && wrapper.reset) {\n if (wrapper.reset(data) === false) {\n // reset was rejected, we need to replace the object\n this.viewmodel.set(data);\n }\n } else {\n this.viewmodel.set(data);\n }\n\n // reset config items and track if need to rerender\n const changes = config.reset(this);\n let rerender;\n\n let i = changes.length;\n while (i--) {\n if (shouldRerender.indexOf(changes[i]) > -1) {\n rerender = true;\n break;\n }\n }\n\n if (rerender) {\n hooks.unrender.fire(this);\n this.fragment.resetTemplate(this.template);\n hooks.render.fire(this);\n hooks.complete.fire(this);\n }\n\n runloop.end();\n\n hooks.reset.fire(this, data);\n\n return promise;\n}\n","import makeArrayMethod from './shared/makeArrayMethod';\nexport default makeArrayMethod('reverse').path;\n","import makeArrayMethod from './shared/makeArrayMethod';\nexport default makeArrayMethod('shift').path;\n","import makeArrayMethod from './shared/makeArrayMethod';\nexport default makeArrayMethod('sort').path;\n","import makeArrayMethod from './shared/makeArrayMethod';\nexport default makeArrayMethod('splice').path;\n","import makeArrayMethod from './shared/makeArrayMethod';\nexport default makeArrayMethod('unshift').path;\n","import add from './prototype/add';\nimport animate from './prototype/animate';\nimport attachChild from './prototype/attachChild';\nimport compute from './prototype/compute';\nimport detach from './prototype/detach';\nimport detachChild from './prototype/detachChild';\nimport find from './prototype/find';\nimport findAll from './prototype/findAll';\nimport findAllComponents from './prototype/findAllComponents';\nimport findComponent from './prototype/findComponent';\nimport findContainer from './prototype/findContainer';\nimport findParent from './prototype/findParent';\nimport fire from './prototype/fire';\nimport get from './prototype/get';\nimport getLocalContext from './prototype/getLocalContext';\nimport getContext from './prototype/getContext';\nimport insert from './prototype/insert';\nimport link from './prototype/link';\nimport observe from './prototype/observe';\nimport observeOnce from './prototype/observeOnce';\nimport off from './prototype/off';\nimport on from './prototype/on';\nimport once from './prototype/once';\nimport pop from './prototype/pop';\nimport push from './prototype/push';\nimport readLink from './prototype/readLink';\nimport render from './prototype/render';\nimport reset from './prototype/reset';\nimport resetPartial from './prototype/resetPartial';\nimport resetTemplate from './prototype/resetTemplate';\nimport reverse from './prototype/reverse';\nimport set from './prototype/set';\nimport shift from './prototype/shift';\nimport sort from './prototype/sort';\nimport splice from './prototype/splice';\nimport subtract from './prototype/subtract';\nimport teardown from './prototype/teardown';\nimport toggle from './prototype/toggle';\nimport toCSS from './prototype/toCSS';\nimport toHTML from './prototype/toHTML';\nimport toText from './prototype/toText';\nimport transition from './prototype/transition';\nimport unlink from './prototype/unlink';\nimport unrender from './prototype/unrender';\nimport unshift from './prototype/unshift';\nimport update from './prototype/update';\nimport updateModel from './prototype/updateModel';\nimport use from './prototype/use';\n\nconst proto = {\n add,\n animate,\n attachChild,\n compute,\n detach,\n detachChild,\n find,\n findAll,\n findAllComponents,\n findComponent,\n findContainer,\n findParent,\n fire,\n get,\n getLocalContext,\n getContext,\n insert,\n link,\n observe,\n observeOnce,\n off,\n on,\n once,\n pop,\n push,\n readLink,\n render,\n reset,\n resetPartial,\n resetTemplate,\n reverse,\n set,\n shift,\n sort,\n splice,\n subtract,\n teardown,\n toggle,\n toCSS,\n toCss: toCSS,\n toHTML,\n toHtml: toHTML,\n toText,\n transition,\n unlink,\n unrender,\n unshift,\n update,\n updateModel,\n use\n};\n\nexport default proto;\n","import { isFunction } from 'utils/is';\nimport { addCSS, applyCSS } from 'src/global/css';\nimport { recomputeCSS } from './styleSet';\n\nconst styles = [];\n\nexport function addStyle(id, css) {\n if (styles.find(s => s.id === id))\n throw new Error(`Extra styles with the id '${id}' have already been added.`);\n styles.push({ id, css });\n\n if (!this.css) {\n Object.defineProperty(this, 'css', { configurable: false, writable: false, value: buildCSS });\n }\n\n if (!this._cssDef) {\n Object.defineProperty(this, '_cssDef', {\n configurable: true,\n writable: false,\n value: {\n transform: false,\n id: 'Ractive.addStyle'\n }\n });\n\n addCSS(this._cssDef);\n }\n\n recomputeCSS(this);\n applyCSS(true);\n}\n\nfunction buildCSS(data) {\n return styles\n .map(s => `\\n/* ---- extra style ${s.id} */\\n` + (isFunction(s.css) ? s.css(data) : s.css))\n .join('');\n}\n\nexport function hasStyle(id) {\n return !!styles.find(s => s.id === id);\n}\n","import config from '../Ractive/config/config';\nimport dataConfigurator from '../Ractive/config/custom/data';\nimport construct from '../Ractive/construct';\nimport initialise from '../Ractive/initialise';\nimport Ractive from '../Ractive';\nimport isInstance from '../Ractive/static/isInstance';\nimport styleSet from '../Ractive/static/styleSet';\nimport styleGet from '../Ractive/static/styleGet';\nimport { addStyle, hasStyle } from '../Ractive/static/styles';\nimport sharedSet from '../Ractive/static/sharedSet';\nimport sharedGet from '../Ractive/static/sharedGet';\nimport use from '../Ractive/static/use';\nimport { create, defineProperties, toPairs, defineProperty } from 'utils/object';\nimport { isArray, isFunction } from 'utils/is';\n\nconst callsSuper = /super\\s*\\(|\\.call\\s*\\(\\s*this/;\n\nexport function extend(...options) {\n if (!options.length) {\n return extendOne(this);\n } else {\n return options.reduce(extendOne, this);\n }\n}\n\nexport function extendWith(Class, options = {}) {\n return extendOne(this, options, Class);\n}\n\nfunction extendOne(Parent, options = {}, Target) {\n let proto;\n let Child = isFunction(Target) && Target;\n\n if (options.prototype instanceof Ractive) {\n throw new Error(`Ractive no longer supports multiple inheritance.`);\n }\n\n if (Child) {\n if (!(Child.prototype instanceof Parent)) {\n throw new Error(\n `Only classes that inherit the appropriate prototype may be used with extend`\n );\n }\n if (!callsSuper.test(Child.toString())) {\n throw new Error(`Only classes that call super in their constructor may be used with extend`);\n }\n\n proto = Child.prototype;\n } else {\n Child = function(options) {\n if (!(this instanceof Child)) return new Child(options);\n\n construct(this, options || {});\n initialise(this, options || {}, {});\n };\n\n proto = create(Parent.prototype);\n proto.constructor = Child;\n\n Child.prototype = proto;\n }\n\n // Static properties\n defineProperties(Child, {\n // alias prototype as defaults\n defaults: { value: proto },\n\n extend: { value: extend, writable: true, configurable: true },\n extendWith: { value: extendWith, writable: true, configurable: true },\n extensions: { value: [] },\n use: { value: use },\n\n isInstance: { value: isInstance },\n\n Parent: { value: Parent },\n Ractive: { value: Ractive },\n\n styleGet: { value: styleGet.bind(Child), configurable: true },\n styleSet: { value: styleSet.bind(Child), configurable: true }\n });\n\n // extend configuration\n config.extend(Parent, proto, options, Child);\n\n // store event and observer registries on the constructor when extending\n Child._on = (Parent._on || []).concat(toPairs(options.on));\n Child._observe = (Parent._observe || []).concat(toPairs(options.observe));\n\n Parent.extensions.push(Child);\n\n // attribute defs are not inherited, but they need to be stored\n if (options.attributes) {\n let attrs;\n\n // allow an array of optional props or an object with arrays for optional and required props\n if (isArray(options.attributes)) {\n attrs = { optional: options.attributes, required: [] };\n } else {\n attrs = options.attributes;\n }\n\n // make sure the requisite keys actually store arrays\n if (!isArray(attrs.required)) attrs.required = [];\n if (!isArray(attrs.optional)) attrs.optional = [];\n\n Child.attributes = attrs;\n }\n\n dataConfigurator.extend(Parent, proto, options, Child);\n\n defineProperty(Child, 'helpers', { writable: true, value: proto.helpers });\n\n if (isArray(options.use)) Child.use.apply(Child, options.use);\n\n return Child;\n}\n\ndefineProperties(Ractive, {\n sharedGet: { value: sharedGet },\n sharedSet: { value: sharedSet },\n styleGet: { configurable: true, value: styleGet.bind(Ractive) },\n styleSet: { configurable: true, value: styleSet.bind(Ractive) },\n addCSS: { configurable: false, value: addStyle.bind(Ractive) },\n hasCSS: { configurable: false, value: hasStyle.bind(Ractive) }\n});\n","import './polyfills/Object.assign';\nimport './polyfills/array.find';\nimport './polyfills/node.contains';\nimport './polyfills/performance.now';\nimport './polyfills/Promise';\nimport './polyfills/requestAnimationFrame';\n\nimport defaults from './Ractive/config/defaults';\nimport easing from './Ractive/static/easing';\nimport interpolators from './Ractive/static/interpolators';\nimport { svg, win } from './config/environment';\nimport proto from './Ractive/prototype';\nimport { extend, extendWith } from './extend/_extend';\nimport macro from './extend/_macro';\nimport parse from './parse/_parse';\nimport getContext from './Ractive/static/getContext';\nimport isInstance from './Ractive/static/isInstance';\nimport use from './Ractive/static/use';\nimport construct from './Ractive/construct';\nimport initialise from './Ractive/initialise';\nimport { getCSS, splitTag } from './global/css';\nimport { escapeKey, unescapeKey, normalise } from './shared/keypaths';\nimport { joinKeys, splitKeypath } from './Ractive/static/keypaths';\nimport shared from './Ractive/shared';\nimport { findPlugin } from './Ractive/static/findPlugin';\nimport parseJSON from './utils/parseJSON';\nimport CSSModel from './model/specials/CSSModel';\nimport { data as sharedData } from './model/specials/SharedModel';\nimport { extern } from './shared/getRactiveContext';\nimport { warn } from 'utils/log';\n\nimport { batch } from './global/runloop';\n\nimport { assign, defineProperty, defineProperties } from 'utils/object';\n\nexport default function Ractive(options) {\n if (!(this instanceof Ractive)) return new Ractive(options);\n\n construct(this, options || {});\n initialise(this, options || {}, {});\n}\n\n// check to see if we're being asked to force Ractive as a global for some weird environments\nif (win && !win.Ractive) {\n let opts = '';\n const script =\n document.currentScript ||\n /* istanbul ignore next */ document.querySelector('script[data-ractive-options]');\n\n if (script) opts = script.getAttribute('data-ractive-options') || '';\n\n /* istanbul ignore next */\n if (~opts.indexOf('ForceGlobal')) win.Ractive = Ractive;\n} else if (win) {\n warn(`Ractive already appears to be loaded while loading BUILD_PLACEHOLDER_VERSION.`);\n}\n\nassign(Ractive.prototype, proto, defaults);\nRactive.prototype.constructor = Ractive;\n\n// alias prototype as `defaults`\nRactive.defaults = Ractive.prototype;\n\n// share defaults with the parser\nshared.defaults = Ractive.defaults;\nshared.Ractive = Ractive;\n\n// static properties\ndefineProperties(Ractive, {\n // debug flag\n DEBUG: { writable: true, value: true },\n DEBUG_PROMISES: { writable: true, value: true },\n\n // static methods:\n extend: { value: extend },\n extendWith: { value: extendWith },\n escapeKey: { value: escapeKey },\n evalObjectString: { value: parseJSON },\n findPlugin: { value: findPlugin },\n getContext: { value: getContext },\n getCSS: { value: getCSS },\n isInstance: { value: isInstance },\n joinKeys: { value: joinKeys },\n macro: { value: macro },\n normaliseKeypath: { value: normalise },\n parse: { value: parse },\n splitKeypath: { value: splitKeypath },\n // sharedSet and styleSet are in _extend because circular refs\n unescapeKey: { value: unescapeKey },\n use: { value: use },\n\n // support\n enhance: { writable: true, value: false },\n svg: { value: svg },\n tick: {\n get() {\n return batch && batch.promise;\n }\n },\n\n // version\n VERSION: { value: 'BUILD_PLACEHOLDER_VERSION' },\n\n // plugins\n adaptors: { writable: true, value: {} },\n components: { writable: true, value: {} },\n decorators: { writable: true, value: {} },\n easing: { writable: true, value: easing },\n events: { writable: true, value: {} },\n extensions: { value: [] },\n helpers: { writable: true, value: defaults.helpers },\n interpolators: { writable: true, value: interpolators },\n partials: { writable: true, value: {} },\n transitions: { writable: true, value: {} },\n\n // CSS variables\n cssData: { configurable: true, value: {} },\n perComponentStyleElements: { get: splitTag, set: splitTag },\n\n // access to @shared without an instance\n sharedData: { value: sharedData },\n\n // for getting the source Ractive lib from a constructor\n Ractive: { value: Ractive },\n\n // to allow extending contexts\n Context: { value: extern.Context.prototype }\n});\n\n// cssData must already be in place\ndefineProperty(Ractive, '_cssModel', {\n configurable: true,\n value: new CSSModel(Ractive)\n});\n\ndefineProperty(Ractive.prototype, 'rendered', {\n get() {\n return this.fragment && this.fragment.rendered;\n }\n});\n","import { removeFromArray } from 'utils/array';\nimport Element from '../../Element';\nimport findElement from '../../shared/findElement';\nimport { isArray, isUndefined } from 'utils/is';\n\nexport default class Option extends Element {\n constructor(options) {\n const template = options.template;\n if (!template.a) template.a = {};\n\n // If the value attribute is missing, use the element's content,\n // as long as it isn't disabled\n if (isUndefined(template.a.value) && !('disabled' in template.a)) {\n template.a.value = template.f || '';\n }\n\n super(options);\n\n this.select = findElement(this.parent || this.up, false, 'select');\n }\n\n bind() {\n if (!this.select) {\n super.bind();\n return;\n }\n\n // If the select has a value, it overrides the `selected` attribute on\n // this option - so we delete the attribute\n const selectedAttribute = this.attributeByName.selected;\n if (selectedAttribute && this.select.getAttribute('value') !== undefined) {\n const index = this.attributes.indexOf(selectedAttribute);\n this.attributes.splice(index, 1);\n delete this.attributeByName.selected;\n }\n\n super.bind();\n this.select.options.push(this);\n }\n\n bubble() {\n // if we're using content as value, may need to update here\n const value = this.getAttribute('value');\n if (this.node && this.node.value !== value) {\n this.node._ractive.value = value;\n }\n super.bubble();\n }\n\n getAttribute(name) {\n const attribute = this.attributeByName[name];\n return attribute\n ? attribute.getValue()\n : name === 'value' && this.fragment\n ? this.fragment.valueOf()\n : undefined;\n }\n\n isSelected() {\n const optionValue = this.getAttribute('value');\n\n if (isUndefined(optionValue) || !this.select) {\n return false;\n }\n\n const selectValue = this.select.getAttribute('value');\n\n if (this.select.compare(selectValue, optionValue)) {\n return true;\n }\n\n if (this.select.getAttribute('multiple') && isArray(selectValue)) {\n let i = selectValue.length;\n while (i--) {\n if (this.select.compare(selectValue[i], optionValue)) {\n return true;\n }\n }\n }\n }\n\n render(target, occupants) {\n super.render(target, occupants);\n\n if (!this.attributeByName.value) {\n this.node._ractive.value = this.getAttribute('value');\n }\n }\n\n unbind(view) {\n super.unbind(view);\n\n if (this.select) {\n removeFromArray(this.select.options, this);\n }\n }\n}\n","import { ELEMENT, PARTIAL, SECTION, SECTION_WITH, YIELDER } from 'config/types';\nimport { assign, create, hasOwn, keys } from 'utils/object';\nimport { isArray, isFunction, isObjectType, isString } from 'utils/is';\nimport noop from 'utils/noop';\nimport { MustacheContainer } from './shared/Mustache';\nimport Fragment from '../Fragment';\nimport getPartialTemplate from './partial/getPartialTemplate';\nimport { warnOnceIfDebug, warnIfDebug } from 'utils/log';\nimport parser from 'src/Ractive/config/runtime-parser';\nimport runloop from 'src/global/runloop';\nimport { applyCSS } from 'src/global/css';\nimport { splitKeypath } from 'shared/keypaths';\n\nexport default function Partial(options) {\n MustacheContainer.call(this, options);\n\n const tpl = options.template;\n\n // yielder is a special form of partial that will later require special handling\n if (tpl.t === YIELDER) {\n this.yielder = 1;\n } else if (tpl.t === ELEMENT) {\n // this is a macro partial, complete with macro constructor\n // leaving this as an element will confuse up-template searches\n this.type = PARTIAL;\n this.macro = options.macro;\n }\n}\n\nconst proto = (Partial.prototype = create(MustacheContainer.prototype));\n\nassign(proto, {\n constructor: Partial,\n\n bind() {\n const template = this.template;\n\n if (this.yielder) {\n // the container is the instance that owns this node\n this.container = this.up.ractive;\n this.component = this.container.component;\n this.containerFragment = this.up;\n\n // normal component\n if (this.component) {\n // yields skip the owning instance and go straight to the surrounding context\n this.up = this.component.up;\n\n // {{yield}} is equivalent to {{yield content}}\n if (!template.r && !template.x && !template.rx) this.refName = 'content';\n } else {\n // plain-ish instance that may be attached to a parent later\n this.fragment = new Fragment({\n owner: this,\n template: []\n });\n this.fragment.bind();\n return;\n }\n }\n\n // this is a macro/super partial\n if (this.macro) {\n this.fn = this.macro;\n } else {\n // this is a plain partial or yielder\n if (!this.refName) this.refName = template.r;\n\n // if the refName exists as a partial, this is a plain old partial reference where no model binding will happen\n if (this.refName) {\n partialFromValue(this, this.refName);\n }\n\n // this is a dynamic/inline partial\n if (!this.partial && !this.fn) {\n MustacheContainer.prototype.bind.call(this);\n if (this.model) partialFromValue(this, this.model.get());\n }\n }\n\n if (!this.partial && !this.fn) {\n warnOnceIfDebug(`Could not find template for partial '${this.name}'`);\n }\n\n createFragment(this, this.partial || []);\n\n // macro/super partial\n if (this.fn) initMacro(this);\n\n this.fragment.bind();\n },\n\n bubble() {\n if (!this.dirty) {\n this.dirty = true;\n\n if (this.yielder) {\n this.containerFragment.bubble();\n } else {\n this.up.bubble();\n }\n }\n },\n\n findNextNode() {\n return (this.containerFragment || this.up).findNextNode(this);\n },\n\n handleChange() {\n this.dirtyTemplate = true;\n this.externalChange = true;\n this.bubble();\n },\n\n rebound(update) {\n if (this._attrs) {\n keys(this._attrs).forEach(k => this._attrs[k].rebound(update));\n }\n MustacheContainer.prototype.rebound.call(this, update);\n },\n\n refreshAttrs() {\n keys(this._attrs).forEach(k => {\n this.handle.attributes[k] = !this._attrs[k].items.length || this._attrs[k].valueOf();\n });\n },\n\n resetTemplate() {\n if (this.fn && this.proxy) {\n this.last = 0;\n if (this.externalChange) {\n if (isFunction(this.proxy.teardown)) this.proxy.teardown();\n this.fn = this.proxy = null;\n } else {\n this.partial = this.fnTemplate;\n return true;\n }\n }\n\n this.partial = null;\n\n if (this.refName) {\n this.partial = getPartialTemplate(this.ractive, this.refName, this.up);\n }\n\n if (!this.partial && this.model) {\n partialFromValue(this, this.model.get());\n }\n\n if (!this.fn) {\n if (this.last && this.partial === this.last) return false;\n else if (this.partial) {\n this.last = this.partial;\n contextifyTemplate(this);\n }\n }\n\n this.unbindAttrs();\n\n if (this.fn) {\n initMacro(this);\n if (isFunction(this.proxy.render)) runloop.scheduleTask(() => this.proxy.render());\n } else if (!this.partial) {\n warnOnceIfDebug(`Could not find template for partial '${this.name}'`);\n }\n\n return true;\n },\n\n render(target, occupants) {\n if (this.fn && this.fn._cssDef && !this.fn._cssDef.applied) applyCSS();\n\n this.fragment.render(target, occupants);\n\n if (this.proxy && isFunction(this.proxy.render)) this.proxy.render();\n },\n\n unbind(view) {\n this.fragment.unbind(view);\n\n this.unbindAttrs(view);\n\n MustacheContainer.prototype.unbind.call(this, view);\n },\n\n unbindAttrs(view) {\n if (this._attrs) {\n keys(this._attrs).forEach(k => {\n this._attrs[k].unbind(view);\n });\n }\n },\n\n unrender(shouldDestroy) {\n if (this.proxy && isFunction(this.proxy.teardown)) this.proxy.teardown();\n\n this.fragment.unrender(shouldDestroy);\n },\n\n update() {\n const proxy = this.proxy;\n this.updating = 1;\n\n if (this.dirtyAttrs) {\n this.dirtyAttrs = false;\n keys(this._attrs).forEach(k => this._attrs[k].update());\n this.refreshAttrs();\n if (isFunction(proxy.update)) proxy.update(this.handle.attributes);\n }\n\n if (this.dirtyTemplate) {\n this.dirtyTemplate = false;\n this.resetTemplate() && this.fragment.resetTemplate(this.partial || []);\n }\n\n if (this.dirty) {\n this.dirty = false;\n if (proxy && isFunction(proxy.invalidate)) proxy.invalidate();\n this.fragment.update();\n }\n\n this.externalChange = false;\n this.updating = 0;\n }\n});\n\nfunction createFragment(self, partial) {\n self.partial = self.last = partial;\n contextifyTemplate(self);\n\n const options = {\n owner: self,\n template: self.partial\n };\n\n if (self.yielder) options.ractive = self.container.parent;\n\n if (self.fn) options.cssIds = self.fn._cssIds;\n\n self.fragment = new Fragment(options);\n}\n\nfunction contextifyTemplate(self) {\n if (self.template.c) {\n self.partial = [{ t: SECTION, n: SECTION_WITH, f: self.partial }];\n assign(self.partial[0], self.template.c);\n if (self.yielder) self.partial[0].y = self;\n else self.partial[0].z = self.template.z;\n }\n}\n\nfunction partialFromValue(self, value, okToParse) {\n let tpl = value;\n\n if (isArray(tpl)) {\n self.partial = tpl;\n } else if (tpl && isObjectType(tpl)) {\n if (isArray(tpl.t)) self.partial = tpl.t;\n else if (isString(tpl.template))\n self.partial = parsePartial(tpl.template, tpl.template, self.ractive).t;\n } else if (isFunction(tpl) && tpl.styleSet) {\n self.fn = tpl;\n if (self.fragment) self.fragment.cssIds = tpl._cssIds;\n } else if (tpl != null) {\n tpl = getPartialTemplate(self.ractive, '' + tpl, self.containerFragment || self.up);\n if (tpl) {\n self.name = value;\n if (tpl.styleSet) {\n self.fn = tpl;\n if (self.fragment) self.fragment.cssIds = tpl._cssIds;\n } else self.partial = tpl;\n } else if (okToParse) {\n self.partial = parsePartial('' + value, '' + value, self.ractive).t;\n } else {\n self.name = value;\n }\n }\n\n return self.partial;\n}\n\nfunction setTemplate(template) {\n partialFromValue(this, template, true);\n\n if (!this.initing) {\n this.dirtyTemplate = true;\n this.fnTemplate = this.partial;\n\n if (this.updating) {\n this.bubble();\n runloop.promise();\n } else {\n const promise = runloop.start();\n\n this.bubble();\n runloop.end();\n\n return promise;\n }\n }\n}\n\nfunction aliasLocal(ref, name) {\n const aliases = this.fragment.aliases || (this.fragment.aliases = {});\n if (!name) {\n aliases[ref] = this._data;\n } else {\n aliases[name] = this._data.joinAll(splitKeypath(ref));\n }\n}\n\nconst extras = 'extra-attributes';\n\nfunction initMacro(self) {\n const fn = self.fn;\n const fragment = self.fragment;\n\n // defensively copy the template in case it changes\n const template = (self.template = assign({}, self.template));\n const handle = (self.handle = fragment.getContext({\n proxy: self,\n aliasLocal,\n name: self.template.e || self.name,\n attributes: {},\n setTemplate: setTemplate.bind(self),\n template,\n macro: fn\n }));\n\n if (!template.p) template.p = {};\n template.p = handle.partials = assign({}, template.p);\n if (!hasOwn(template.p, 'content')) template.p.content = template.f || [];\n\n if (isArray(fn.attributes)) {\n self._attrs = {};\n\n const invalidate = function() {\n this.dirty = true;\n self.dirtyAttrs = true;\n self.bubble();\n };\n\n if (isArray(template.m)) {\n const attrs = template.m;\n template.p[extras] = template.m = attrs.filter(a => !~fn.attributes.indexOf(a.n));\n attrs\n .filter(a => ~fn.attributes.indexOf(a.n))\n .forEach(a => {\n const fragment = new Fragment({\n template: a.f,\n owner: self\n });\n fragment.bubble = invalidate;\n fragment.findFirstNode = noop;\n self._attrs[a.n] = fragment;\n });\n } else {\n template.p[extras] = [];\n }\n } else {\n template.p[extras] = template.m;\n }\n\n if (self._attrs) {\n keys(self._attrs).forEach(k => {\n self._attrs[k].bind();\n });\n self.refreshAttrs();\n }\n\n self.initing = 1;\n self.proxy = fn.call(self.ractive, handle, handle.attributes) || {};\n if (!self.partial) self.partial = [];\n self.fnTemplate = self.partial;\n self.initing = 0;\n\n contextifyTemplate(self);\n fragment.resetTemplate(self.partial);\n}\n\nfunction parsePartial(name, partial, ractive) {\n let parsed;\n\n try {\n parsed = parser.parse(partial, parser.getParseOptions(ractive));\n } catch (e) {\n warnIfDebug(`Could not parse partial from expression '${name}'\\n${e.message}`);\n }\n\n return parsed || { t: [] };\n}\n","import { addToArray, removeFromArray } from 'utils/array';\nimport { unescapeKey } from 'shared/keypaths';\nimport { capture } from 'src/global/capture';\nimport { handleChange } from 'src/shared/methodCallers';\nimport noop from 'utils/noop';\n\nexport default class KeyModel {\n constructor(value, context, instance) {\n this.value = this.key = value;\n this.context = context;\n this.isReadonly = this.isKey = true;\n this.deps = [];\n this.links = [];\n this.children = [];\n this.instance = instance;\n }\n\n applyValue(value) {\n if (value !== this.value) {\n this.value = this.key = value;\n this.deps.forEach(handleChange);\n this.links.forEach(handleChange);\n this.children.forEach(c => {\n c.applyValue(c.context.getKeypath(c.instance));\n });\n }\n }\n\n destroyed() {\n if (this.upstream) this.upstream.unregisterChild(this);\n }\n\n get(shouldCapture) {\n if (shouldCapture) capture(this);\n return unescapeKey(this.value);\n }\n\n getKeypath() {\n return unescapeKey(this.value);\n }\n\n has() {\n return false;\n }\n\n rebind(next, previous) {\n let i = this.deps.length;\n while (i--) this.deps[i].rebind(next, previous, false);\n\n i = this.links.length;\n while (i--) this.links[i].relinking(next, false);\n }\n\n register(dependant) {\n this.deps.push(dependant);\n }\n\n registerChild(child) {\n addToArray(this.children, child);\n child.upstream = this;\n }\n\n registerLink(link) {\n addToArray(this.links, link);\n }\n\n unregister(dependant) {\n removeFromArray(this.deps, dependant);\n }\n\n unregisterChild(child) {\n removeFromArray(this.children, child);\n }\n\n unregisterLink(link) {\n removeFromArray(this.links, link);\n }\n}\n\nKeyModel.prototype.reference = noop;\nKeyModel.prototype.unreference = noop;\n","import { createDocumentFragment } from 'utils/dom';\nimport { isArray, isObject, isObjectType, isUndefined } from 'utils/is';\nimport { findMap, buildNewIndices } from 'utils/array';\nimport { toEscapedString, toString, shuffled, update } from 'shared/methodCallers';\nimport Fragment, { getKeypath } from './Fragment';\nimport { ELEMENT } from 'config/types';\nimport { getContext } from 'shared/getRactiveContext';\nimport { keys } from 'utils/object';\nimport KeyModel from 'src/model/specials/KeyModel';\nimport { splitKeypath } from '../shared/keypaths';\nimport resolve from './resolvers/resolve';\n\nconst keypathString = /^\"(\\\\\"|[^\"])+\"$/;\n\nexport default class RepeatedFragment {\n constructor(options) {\n this.parent = options.owner.up;\n\n // bit of a hack, so reference resolution works without another\n // layer of indirection\n this.up = this;\n this.owner = options.owner;\n this.ractive = this.parent.ractive;\n this.delegate =\n this.ractive.delegate !== false && (this.parent.delegate || findDelegate(this.parent));\n // delegation disabled by directive\n if (this.delegate && this.delegate.delegate === false) this.delegate = false;\n // let the element know it's a delegate handler\n if (this.delegate) this.delegate.delegate = this.delegate;\n\n // encapsulated styles should be inherited until they get applied by an element\n this.cssIds = 'cssIds' in options ? options.cssIds : this.parent ? this.parent.cssIds : null;\n\n this.context = null;\n this.rendered = false;\n this.iterations = [];\n\n this.template = options.template;\n\n this.indexRef = options.indexRef;\n this.keyRef = options.keyRef;\n\n this.pendingNewIndices = null;\n this.previousIterations = null;\n\n // track array versus object so updates of type rest\n this.isArray = false;\n }\n\n bind(context) {\n this.context = context;\n this.bound = true;\n const value = context.get();\n\n const aliases = (this.aliases = this.owner.template.z && this.owner.template.z.slice());\n\n const shuffler = aliases && aliases.find(a => a.n === 'shuffle');\n if (shuffler && shuffler.x && shuffler.x.x) {\n if (shuffler.x.x.s === 'true') this.shuffler = true;\n else if (keypathString.test(shuffler.x.x.s))\n this.shuffler = splitKeypath(shuffler.x.x.s.slice(1, -1));\n }\n\n if (this.shuffler) this.values = shuffleValues(this, this.shuffler);\n\n if (this.source) this.source.model.unbind(this.source);\n const source = context.isComputed && aliases && aliases.find(a => a.n === 'source');\n if (source && source.x && source.x.r) {\n const model = resolve(this, source.x);\n this.source = {\n handleChange() {},\n rebind(next) {\n this.model.unregister(this);\n this.model = next;\n next.register(this);\n }\n };\n this.source.model = model;\n model.register(this.source);\n }\n\n // {{#each array}}...\n if ((this.isArray = isArray(value))) {\n // we can't use map, because of sparse arrays\n this.iterations = [];\n const max = (this.length = value.length);\n for (let i = 0; i < max; i += 1) {\n this.iterations[i] = this.createIteration(i, i);\n }\n } else if (isObject(value)) {\n // {{#each object}}...\n this.isArray = false;\n\n // TODO this is a dreadful hack. There must be a neater way\n if (this.indexRef) {\n const refs = this.indexRef.split(',');\n this.keyRef = refs[0];\n this.indexRef = refs[1];\n }\n\n const ks = keys(value);\n this.length = ks.length;\n\n this.iterations = ks.map((key, index) => {\n return this.createIteration(key, index);\n });\n }\n\n return this;\n }\n\n bubble(index) {\n if (!this.bubbled) this.bubbled = [];\n this.bubbled.push(index);\n\n if (!this.rebounding) this.owner.bubble();\n }\n\n createIteration(key, index) {\n const fragment = new Fragment({\n owner: this,\n template: this.template\n });\n\n fragment.isIteration = true;\n fragment.delegate = this.delegate;\n\n if (this.aliases) fragment.aliases = {};\n swizzleFragment(this, fragment, key, index);\n\n return fragment.bind(fragment.context);\n }\n\n destroyed() {\n const len = this.iterations.length;\n for (let i = 0; i < len; i++) this.iterations[i].destroyed();\n if (this.pathModel) this.pathModel.destroyed();\n if (this.rootModel) this.rootModel.destroyed();\n }\n\n detach() {\n const docFrag = createDocumentFragment();\n this.iterations.forEach(fragment => docFrag.appendChild(fragment.detach()));\n return docFrag;\n }\n\n find(selector, options) {\n return findMap(this.iterations, i => i.find(selector, options));\n }\n\n findAll(selector, options) {\n return this.iterations.forEach(i => i.findAll(selector, options));\n }\n\n findAllComponents(name, options) {\n return this.iterations.forEach(i => i.findAllComponents(name, options));\n }\n\n findComponent(name, options) {\n return findMap(this.iterations, i => i.findComponent(name, options));\n }\n\n findContext() {\n return this.context;\n }\n\n findNextNode(iteration) {\n if (iteration.index < this.iterations.length - 1) {\n for (let i = iteration.index + 1; i < this.iterations.length; i++) {\n const node = this.iterations[i].firstNode(true);\n if (node) return node;\n }\n }\n\n return this.owner.findNextNode();\n }\n\n firstNode(skipParent) {\n return this.iterations[0] ? this.iterations[0].firstNode(skipParent) : null;\n }\n\n getLast() {\n return this.lastModel || (this.lastModel = new KeyModel(this.length - 1));\n }\n\n rebind(next) {\n this.context = next;\n if (this.source) return;\n if (next) {\n this.iterations.forEach(fragment => {\n swizzleFragment(this, fragment, fragment.key, fragment.index);\n });\n }\n }\n\n rebound(update) {\n this.context = this.owner.model;\n this.iterations.forEach((f, i) => {\n f.context = contextFor(this, f, i);\n f.rebound(update);\n });\n }\n\n render(target, occupants) {\n const xs = this.iterations;\n if (xs) {\n const len = xs.length;\n for (let i = 0; i < len; i++) {\n xs[i].render(target, occupants);\n }\n }\n\n this.rendered = true;\n }\n\n shuffle(newIndices, merge) {\n if (!this.pendingNewIndices) this.previousIterations = this.iterations.slice();\n\n if (!this.pendingNewIndices) this.pendingNewIndices = [];\n\n this.pendingNewIndices.push(newIndices);\n\n const iterations = [];\n\n newIndices.forEach((newIndex, oldIndex) => {\n if (newIndex === -1) return;\n\n const fragment = this.iterations[oldIndex];\n iterations[newIndex] = fragment;\n\n if (newIndex !== oldIndex && fragment) {\n fragment.dirty = true;\n if (merge) fragment.shouldRebind = 1;\n }\n });\n\n this.iterations = iterations;\n\n // if merging, we're in the midst of an update already\n if (!merge) this.bubble();\n }\n\n shuffled() {\n this.iterations.forEach(shuffled);\n }\n\n toString(escape) {\n return this.iterations ? this.iterations.map(escape ? toEscapedString : toString).join('') : '';\n }\n\n unbind(view) {\n this.bound = false;\n if (this.source) this.source.model.unregister(this.source);\n const iterations = this.pendingNewIndices ? this.previousIterations : this.iterations;\n const len = iterations.length;\n for (let i = 0; i < len; i++) iterations[i].unbind(view);\n return this;\n }\n\n unrender(shouldDestroy) {\n let len = this.iterations.length;\n for (let i = 0; i < len; i++) this.iterations[i].unrender(shouldDestroy);\n if (this.pendingNewIndices && this.previousIterations) {\n len = this.previousIterations.length;\n for (let i = 0; i < len; i++) this.previousIterations[i].unrender(shouldDestroy);\n }\n this.rendered = false;\n }\n\n update() {\n if (this.pendingNewIndices) {\n this.bubbled.length = 0;\n this.updatePostShuffle();\n return;\n }\n\n if (this.updating) return;\n this.updating = true;\n\n if (this.shuffler) {\n const values = shuffleValues(this, this.shuffler);\n const newIndices = buildNewIndices(this.values, values);\n if (!newIndices.same) {\n this.shuffle(newIndices, true);\n this.updatePostShuffle();\n } else {\n this.iterations.forEach(update);\n }\n } else {\n let len = this.iterations.length;\n for (let i = 0; i < len; i++) {\n const f = this.iterations[i];\n f && f.idxModel && f.idxModel.applyValue(i);\n }\n\n const value = this.context.get();\n const wasArray = this.isArray;\n\n let toRemove;\n let oldKeys;\n let reset = true;\n let i;\n\n if ((this.isArray = isArray(value))) {\n // if there's a source to map back to, make sure everything stays bound correctly\n if (this.source) {\n this.rebounding = 1;\n const source = this.source.model.get();\n this.iterations.forEach((f, c) => {\n if (c < value.length && f.lastValue !== value[c] && ~(i = source.indexOf(value[c]))) {\n swizzleFragment(this, f, c, c);\n f.rebound(true);\n }\n });\n this.rebounding = 0;\n }\n\n if (wasArray) {\n reset = false;\n if (this.iterations.length > value.length) {\n toRemove = this.iterations.splice(value.length);\n }\n }\n } else if (isObject(value) && !wasArray) {\n reset = false;\n toRemove = [];\n oldKeys = {};\n i = this.iterations.length;\n\n while (i--) {\n const fragment = this.iterations[i];\n if (fragment.key in value) {\n oldKeys[fragment.key] = true;\n } else {\n this.iterations.splice(i, 1);\n toRemove.push(fragment);\n }\n }\n }\n\n const newLength = isArray(value) ? value.length : isObject(value) ? keys(value).length : 0;\n this.length = newLength;\n this.updateLast();\n\n if (reset) {\n toRemove = this.iterations;\n this.iterations = [];\n }\n\n if (toRemove) {\n len = toRemove.length;\n for (let i = 0; i < len; i++) toRemove[i].unbind().unrender(true);\n }\n\n // update the remaining ones\n if (!reset && this.isArray && this.bubbled && this.bubbled.length) {\n const bubbled = this.bubbled;\n this.bubbled = [];\n len = bubbled.length;\n for (let i = 0; i < len; i++)\n this.iterations[bubbled[i]] && this.iterations[bubbled[i]].update();\n } else {\n len = this.iterations.length;\n for (let i = 0; i < len; i++) this.iterations[i].update();\n }\n\n // add new iterations\n let docFrag;\n let fragment;\n\n if (newLength > this.iterations.length) {\n docFrag = this.rendered ? createDocumentFragment() : null;\n i = this.iterations.length;\n\n if (isArray(value)) {\n while (i < value.length) {\n fragment = this.createIteration(i, i);\n\n this.iterations.push(fragment);\n if (this.rendered) fragment.render(docFrag);\n\n i += 1;\n }\n } else if (isObject(value)) {\n // TODO this is a dreadful hack. There must be a neater way\n if (this.indexRef && !this.keyRef) {\n const refs = this.indexRef.split(',');\n this.keyRef = refs[0];\n this.indexRef = refs[1];\n }\n\n keys(value).forEach(key => {\n if (!oldKeys || !(key in oldKeys)) {\n fragment = this.createIteration(key, i);\n\n this.iterations.push(fragment);\n if (this.rendered) fragment.render(docFrag);\n\n i += 1;\n }\n });\n }\n\n if (this.rendered) {\n const parentNode = this.parent.findParentNode();\n const anchor = this.parent.findNextNode(this.owner);\n\n parentNode.insertBefore(docFrag, anchor);\n }\n }\n }\n\n this.updating = false;\n }\n\n updateLast() {\n if (this.lastModel) this.lastModel.applyValue(this.length - 1);\n }\n\n updatePostShuffle() {\n const newIndices = this.pendingNewIndices[0];\n const parentNode = this.rendered ? this.parent.findParentNode() : null;\n const nextNode = parentNode && this.owner.findNextNode();\n const docFrag = parentNode ? createDocumentFragment() : null;\n\n // map first shuffle through\n this.pendingNewIndices.slice(1).forEach(indices => {\n newIndices.forEach((newIndex, oldIndex) => {\n newIndices[oldIndex] = indices[newIndex];\n });\n });\n\n const len = (this.length = this.context.get().length);\n const prev = this.previousIterations;\n const iters = this.iterations;\n const value = this.context.get();\n const stash = {};\n let idx, dest, pos, next, anchor, rebound;\n\n const map = new Array(newIndices.length);\n newIndices.forEach((e, i) => (map[e] = i));\n\n this.updateLast();\n\n idx = pos = 0;\n while (idx < len) {\n // if there's not an existing thing to shuffle, handle that\n if (isUndefined(map[idx])) {\n next = iters[idx] = this.createIteration(idx, idx);\n if (parentNode) {\n anchor = prev[pos];\n anchor = (anchor && parentNode && anchor.firstNode()) || nextNode;\n\n next.render(docFrag);\n parentNode.insertBefore(docFrag, anchor);\n }\n\n idx++;\n } else {\n dest = newIndices[pos];\n\n if (dest === -1) {\n // if it needs to be dropped, drop it\n prev[pos] && prev[pos].unbind().unrender(true);\n prev[pos++] = 0;\n } else if (dest > idx) {\n // if it needs to move down, stash it\n stash[dest] = prev[pos];\n prev[pos++] = null;\n } else {\n // get the fragment that goes for this idx\n iters[idx] = next = iters[idx] || stash[idx] || this.createIteration(idx, idx);\n\n // if it's an existing fragment, swizzle\n if (stash[idx] || pos !== idx) {\n rebound = this.source && next.lastValue !== value[idx];\n swizzleFragment(this, next, idx, idx);\n }\n\n // does next need to be moved?\n if (parentNode && (stash[idx] || !prev[pos])) {\n anchor = prev[pos + 1];\n anchor = (anchor && parentNode && anchor.firstNode()) || nextNode;\n\n if (stash[idx]) {\n parentNode.insertBefore(next.detach(), anchor);\n } else {\n next.render(docFrag);\n parentNode.insertBefore(docFrag, anchor);\n }\n }\n\n prev[pos++] = 0;\n idx++;\n }\n\n if (next && isObjectType(next)) {\n if (next.shouldRebind || rebound) {\n next.rebound(rebound);\n next.shouldRebind = 0;\n }\n next.update();\n next.shuffled();\n }\n }\n }\n\n // clean up any stragglers\n const plen = prev.length;\n for (let i = 0; i < plen; i++) prev[i] && prev[i].unbind().unrender(true);\n\n if (this.shuffler) this.values = shuffleValues(this, this.shuffler);\n\n this.pendingNewIndices = null;\n this.previousIterations = null;\n }\n}\n\nRepeatedFragment.prototype.getContext = getContext;\nRepeatedFragment.prototype.getKeypath = getKeypath;\n\n// find the topmost delegate\nfunction findDelegate(start) {\n let frag = start;\n let delegate, el;\n\n out: while (frag) {\n // find next element\n el = 0;\n while (!el && frag) {\n if (frag.owner.type === ELEMENT) el = frag.owner;\n if (frag.owner.ractive && frag.owner.ractive.delegate === false) break out;\n frag = frag.parent || frag.componentParent;\n }\n\n if (el.delegate === false) break out;\n delegate = el.delegate || el;\n\n // find next repeated fragment\n while (frag) {\n if (frag.iterations) break;\n if (frag.owner.ractive && frag.owner.ractive.delegate === false) break out;\n frag = frag.parent || frag.componentParent;\n }\n }\n\n return delegate;\n}\n\nfunction swizzleFragment(section, fragment, key, idx) {\n const model = section.context ? contextFor(section, fragment, key) : undefined;\n\n fragment.key = key;\n fragment.index = idx;\n fragment.context = model;\n if (section.source) fragment.lastValue = model && model.get();\n\n if (fragment.idxModel) fragment.idxModel.applyValue(idx);\n if (fragment.keyModel) fragment.keyModel.applyValue(key);\n if (fragment.pathModel) {\n fragment.pathModel.context = model;\n fragment.pathModel.applyValue(model.getKeypath());\n }\n if (fragment.rootModel) {\n fragment.rootModel.context = model;\n fragment.rootModel.applyValue(model.getKeypath(fragment.ractive.root));\n }\n\n // handle any aliases\n const aliases = fragment.aliases;\n section.aliases &&\n section.aliases.forEach(a => {\n if (a.x.r === '.') aliases[a.n] = model;\n else if (a.x.r === '@index') aliases[a.n] = fragment.getIndex();\n else if (a.x.r === '@key') aliases[a.n] = fragment.getKey();\n else if (a.x.r === '@keypath') aliases[a.n] = fragment.getKeypath();\n else if (a.x.r === '@rootpath') aliases[a.n] = fragment.getKeypath(true);\n });\n}\n\nfunction shuffleValues(section, shuffler) {\n const array = section.context.get() || [];\n if (shuffler === true) {\n return array.slice();\n } else {\n return array.map(v => shuffler.reduce((a, c) => a && a[c], v));\n }\n}\n\nfunction contextFor(section, fragment, key) {\n if (section.source) {\n let idx;\n const source = section.source.model.get();\n if (source.indexOf && ~(idx = source.indexOf(section.context.joinKey(key).get())))\n return section.source.model.joinKey(idx);\n }\n\n return section.context.joinKey(key);\n}\n","import {\n ALIAS,\n SECTION_EACH,\n SECTION_IF,\n SECTION_IF_WITH,\n SECTION_UNLESS,\n SECTION_WITH\n} from 'config/types';\nimport { createDocumentFragment } from 'utils/dom';\nimport { isArray, isObject, isObjectLike, isUndefined } from 'utils/is';\nimport { keep } from 'shared/set';\nimport runloop from 'src/global/runloop';\nimport Fragment from '../Fragment';\nimport RepeatedFragment from '../RepeatedFragment';\nimport { MustacheContainer } from './shared/Mustache';\nimport { keys } from 'utils/object';\nimport Context from 'src/shared/Context';\n\nfunction isEmpty(value) {\n return (\n !value ||\n (isArray(value) && value.length === 0) ||\n (isObject(value) && keys(value).length === 0)\n );\n}\n\nfunction getType(value, hasIndexRef) {\n if (hasIndexRef || isArray(value)) return SECTION_EACH;\n if (isObjectLike(value)) return SECTION_IF_WITH;\n if (isUndefined(value)) return null;\n return SECTION_IF;\n}\n\nexport default class Section extends MustacheContainer {\n constructor(options) {\n super(options);\n\n this.isAlias = options.template.t === ALIAS;\n this.sectionType = options.template.n || (this.isAlias && SECTION_WITH) || null;\n this.templateSectionType = this.sectionType;\n this.subordinate = options.template.l === 1;\n this.fragment = null;\n }\n\n bind() {\n super.bind();\n\n if (this.subordinate) {\n this.sibling = this.up.items[this.up.items.indexOf(this) - 1];\n this.sibling.nextSibling = this;\n }\n\n // if we managed to bind, we need to create children\n if (this.model || this.isAlias) {\n this.dirty = true;\n this.update();\n } else if (\n this.sectionType &&\n this.sectionType === SECTION_UNLESS &&\n (!this.sibling || !this.sibling.isTruthy())\n ) {\n this.fragment = new Fragment({\n owner: this,\n template: this.template.f\n }).bind();\n }\n }\n\n bubble() {\n if (!this.dirty && this.yield) {\n this.dirty = true;\n this.containerFragment.bubble();\n } else super.bubble();\n }\n\n detach() {\n const frag = this.fragment || this.detached;\n return frag ? frag.detach() : super.detach();\n }\n\n findNextNode() {\n return (this.containerFragment || this.up).findNextNode(this);\n }\n\n isTruthy() {\n if (this.subordinate && this.sibling.isTruthy()) return true;\n const value = !this.model ? undefined : this.model.isRoot ? this.model.value : this.model.get();\n return !!value && (this.templateSectionType === SECTION_IF_WITH || !isEmpty(value));\n }\n\n rebind(next, previous, safe) {\n if (super.rebind(next, previous, safe)) {\n if (this.fragment && this.sectionType !== SECTION_IF && this.sectionType !== SECTION_UNLESS) {\n this.fragment.rebind(next);\n }\n }\n }\n\n rebound(update) {\n if (this.model) {\n if (this.model.rebound) this.model.rebound(update);\n else {\n super.unbind();\n super.bind();\n if (\n this.sectionType === SECTION_WITH ||\n this.sectionType === SECTION_IF_WITH ||\n this.sectionType === SECTION_EACH\n ) {\n if (this.fragment) this.fragment.rebind(this.model);\n }\n\n if (update) this.bubble();\n }\n }\n if (this.fragment) this.fragment.rebound(update);\n }\n\n render(target, occupants) {\n this.rendered = true;\n if (this.fragment) this.fragment.render(target, occupants);\n }\n\n shuffle(newIndices) {\n if (this.fragment && this.sectionType === SECTION_EACH) {\n this.fragment.shuffle(newIndices);\n }\n }\n\n unbind(view) {\n super.unbind(view);\n if (this.fragment) this.fragment.unbind(view);\n }\n\n unrender(shouldDestroy) {\n if (this.rendered && this.fragment) this.fragment.unrender(shouldDestroy);\n this.rendered = false;\n }\n\n update() {\n if (!this.dirty) return;\n\n if (this.fragment && this.sectionType !== SECTION_IF && this.sectionType !== SECTION_UNLESS) {\n this.fragment.context = this.model;\n }\n\n if (!this.model && this.sectionType !== SECTION_UNLESS && !this.isAlias) return;\n\n this.dirty = false;\n\n const value = !this.model ? undefined : this.model.isRoot ? this.model.value : this.model.get();\n const siblingFalsey = !this.subordinate || !this.sibling.isTruthy();\n const lastType = this.sectionType;\n\n if (this.yield && this.yield !== value) {\n this.up = this.containerFragment;\n this.container = null;\n this.yield = null;\n if (this.rendered) this.fragment.unbind().unrender(true);\n this.fragment = null;\n } else if (this.rendered && !this.yield && value instanceof Context) {\n if (this.rendered && this.fragment) this.fragment.unbind().unrender(true);\n this.fragment = null;\n }\n\n // watch for switching section types\n if (this.sectionType === null || this.templateSectionType === null)\n this.sectionType = getType(value, this.template.i);\n if (lastType && lastType !== this.sectionType && this.fragment) {\n if (this.rendered) {\n this.fragment.unbind().unrender(true);\n }\n\n this.fragment = null;\n }\n\n let newFragment;\n\n const fragmentShouldExist =\n this.sectionType === SECTION_EACH || // each always gets a fragment, which may have no iterations\n this.sectionType === SECTION_WITH || // with (partial context) always gets a fragment\n (siblingFalsey &&\n (this.sectionType === SECTION_UNLESS ? !this.isTruthy() : this.isTruthy())) || // if, unless, and if-with depend on siblings and the condition\n this.isAlias;\n\n if (fragmentShouldExist) {\n if (!this.fragment) this.fragment = this.detached;\n\n if (this.fragment) {\n // check for detached fragment\n if (this.detached) {\n attach(this, this.fragment);\n this.detached = false;\n this.rendered = true;\n }\n\n if (!this.fragment.bound) this.fragment.bind(this.model);\n this.fragment.update();\n } else {\n if (this.sectionType === SECTION_EACH) {\n newFragment = new RepeatedFragment({\n owner: this,\n template: this.template.f,\n indexRef: this.template.i\n }).bind(this.model);\n } else {\n // only with and if-with provide context - if and unless do not\n let context =\n this.sectionType !== SECTION_IF && this.sectionType !== SECTION_UNLESS\n ? this.model\n : null;\n\n if (value instanceof Context) {\n this.yield = value;\n this.containerFragment = this.up;\n this.up = value.fragment;\n this.container = value.ractive;\n context = undefined;\n }\n\n newFragment = new Fragment({\n owner: this,\n template: this.template.f\n }).bind(context);\n }\n }\n } else {\n if (this.fragment && this.rendered) {\n if (keep !== true) {\n this.fragment.unbind().unrender(true);\n } else {\n this.unrender(false);\n this.detached = this.fragment;\n runloop.promise().then(() => {\n if (this.detached) this.detach();\n });\n }\n } else if (this.fragment) {\n this.fragment.unbind();\n }\n\n this.fragment = null;\n }\n\n if (newFragment) {\n if (this.rendered) {\n attach(this, newFragment);\n }\n\n this.fragment = newFragment;\n }\n\n if (this.nextSibling) {\n this.nextSibling.dirty = true;\n this.nextSibling.update();\n }\n }\n}\n\nfunction attach(section, fragment) {\n const anchor = (section.containerFragment || section.up).findNextNode(section);\n\n if (anchor) {\n const docFrag = createDocumentFragment();\n fragment.render(docFrag);\n\n anchor.parentNode.insertBefore(docFrag, anchor);\n } else {\n fragment.render(section.up.findParentNode());\n }\n}\n","import { toArray } from 'utils/array';\nimport getSelectedOptions from 'utils/getSelectedOptions';\nimport Element from '../../Element';\nimport { isArray, isFunction } from 'utils/is';\n\nexport default class Select extends Element {\n constructor(options) {\n super(options);\n this.options = [];\n }\n\n foundNode(node) {\n if (this.binding) {\n const selectedOptions = getSelectedOptions(node);\n\n if (selectedOptions.length > 0) {\n this.selectedOptions = selectedOptions;\n }\n }\n }\n\n render(target, occupants) {\n super.render(target, occupants);\n this.sync();\n\n const node = this.node;\n\n let i = node.options.length;\n while (i--) {\n node.options[i].defaultSelected = node.options[i].selected;\n }\n\n this.rendered = true;\n }\n\n sync() {\n const selectNode = this.node;\n\n if (!selectNode) return;\n\n const options = toArray(selectNode.options);\n\n if (this.selectedOptions) {\n options.forEach(o => {\n if (this.selectedOptions.indexOf(o) >= 0) o.selected = true;\n else o.selected = false;\n });\n this.binding.setFromNode(selectNode);\n delete this.selectedOptions;\n return;\n }\n\n const selectValue = this.getAttribute('value');\n const isMultiple = this.getAttribute('multiple');\n const array = isMultiple && isArray(selectValue);\n\n // If the ', '']\n };\n}\n\nexport default function(html, node) {\n const nodes = [];\n\n // render 0 and false\n if (html == null || html === '') return nodes;\n\n let container;\n let wrapper;\n let selectedOption;\n\n /* istanbul ignore if */\n if (ieBug && (wrapper = ieBlacklist[node.tagName])) {\n container = element('DIV');\n container.innerHTML = wrapper[0] + html + wrapper[1];\n container = container.querySelector('.x');\n\n if (container.tagName === 'SELECT') {\n selectedOption = container.options[container.selectedIndex];\n }\n } else if (node.namespaceURI === svg) {\n container = element('DIV');\n container.innerHTML = '' + html + '';\n container = container.querySelector('.x');\n } else if (node.tagName === 'TEXTAREA') {\n container = createElement('div');\n\n if (typeof container.textContent !== 'undefined') {\n container.textContent = html;\n } else {\n container.innerHTML = html;\n }\n } else {\n container = element(node.tagName);\n container.innerHTML = html;\n\n if (container.tagName === 'SELECT') {\n selectedOption = container.options[container.selectedIndex];\n }\n }\n\n let child;\n while ((child = container.firstChild)) {\n nodes.push(child);\n container.removeChild(child);\n }\n\n // This is really annoying. Extracting