UNPKG

ractive

Version:

Next-generation DOM manipulation

1,273 lines (1,231 loc) 261 kB
/* Ractive - v0.3.8 - 2013-12-21 ============================================================== Next-generation DOM manipulation - http://ractivejs.org Follow @RactiveJS for updates -------------------------------------------------------------- Copyright 2013 2013 Rich Harris and contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ (function ( global ) { var utils_create = function () { var create; try { Object.create(null); create = Object.create; } catch (err) { create = function () { var F = function () { }; return function (proto, props) { var obj; if (proto === null) { return {}; } F.prototype = proto; obj = new F(); if (props) { Object.defineProperties(obj, props); } return obj; }; }(); } return create; }(); var config_isClient = function () { if (typeof document === 'object') { return true; } return false; }(); var utils_defineProperty = function (isClient) { try { Object.defineProperty({}, 'test', { value: 0 }); if (isClient) { Object.defineProperty(document.createElement('div'), 'test', { value: 0 }); } return Object.defineProperty; } catch (err) { return function (obj, prop, desc) { obj[prop] = desc.value; }; } }(config_isClient); var utils_defineProperties = function (defineProperty, isClient) { try { try { Object.defineProperties({}, { test: { value: 0 } }); } catch (err) { throw err; } if (isClient) { Object.defineProperties(document.createElement('div'), { test: { value: 0 } }); } return Object.defineProperties; } catch (err) { return function (obj, props) { var prop; for (prop in props) { if (props.hasOwnProperty(prop)) { defineProperty(obj, prop, props[prop]); } } }; } }(utils_defineProperty, config_isClient); var utils_normaliseKeypath = function () { var regex = /\[\s*(\*|[0-9]|[1-9][0-9]+)\s*\]/g; return function (keypath) { return keypath.replace(regex, '.$1'); }; }(); var registries_adaptors = {}; var config_types = { 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 }; var utils_isArray = function () { var toString = Object.prototype.toString; return function (thing) { return toString.call(thing) === '[object Array]'; }; }(); var shared_clearCache = function () { return function clearCache(ractive, keypath) { var cacheMap, wrappedProperty; if (wrappedProperty = ractive._wrapped[keypath]) { if (wrappedProperty.teardown() !== false) { ractive._wrapped[keypath] = null; } } ractive._cache[keypath] = undefined; if (cacheMap = ractive._cacheMap[keypath]) { while (cacheMap.length) { clearCache(ractive, cacheMap.pop()); } } }; }(); var shared_getValueFromCheckboxes = function () { return function (ractive, keypath) { var value, checkboxes, checkbox, len, i, rootEl; value = []; rootEl = ractive.rendered ? ractive.el : ractive.fragment.docFrag; checkboxes = rootEl.querySelectorAll('input[type="checkbox"][name="{{' + keypath + '}}"]'); len = checkboxes.length; for (i = 0; i < len; i += 1) { checkbox = checkboxes[i]; if (checkbox.hasAttribute('checked') || checkbox.checked) { value[value.length] = checkbox._ractive.value; } } return value; }; }(); var shared_preDomUpdate = function (getValueFromCheckboxes) { return function (ractive) { var deferred, evaluator, selectValue, attribute, keypath, radio; deferred = ractive._deferred; while (evaluator = deferred.evals.pop()) { evaluator.update().deferred = false; } while (selectValue = deferred.selectValues.pop()) { selectValue.deferredUpdate(); } while (attribute = deferred.attrs.pop()) { attribute.update().deferred = false; } while (keypath = deferred.checkboxes.pop()) { ractive.set(keypath, getValueFromCheckboxes(ractive, keypath)); } while (radio = deferred.radios.pop()) { radio.update(); } }; }(shared_getValueFromCheckboxes); var shared_postDomUpdate = function () { return function (ractive) { var deferred, focusable, query, decorator, transition, observer; deferred = ractive._deferred; if (focusable = deferred.focusable) { focusable.focus(); deferred.focusable = null; } while (query = deferred.liveQueries.pop()) { query._sort(); } while (decorator = deferred.decorators.pop()) { decorator.init(); } while (transition = deferred.transitions.pop()) { transition.init(); } while (observer = deferred.observers.pop()) { observer.update(); } }; }(); var shared_makeTransitionManager = function () { var makeTransitionManager = function (root, callback) { var transitionManager, elementsToDetach, detachNodes, nodeHasNoTransitioningChildren; elementsToDetach = []; detachNodes = function () { var i, element; i = elementsToDetach.length; while (i--) { element = elementsToDetach[i]; if (nodeHasNoTransitioningChildren(element.node)) { element.detach(); elementsToDetach.splice(i, 1); } } }; nodeHasNoTransitioningChildren = function (node) { var i, candidate; i = transitionManager.active.length; while (i--) { candidate = transitionManager.active[i]; if (node.contains(candidate)) { return false; } } return true; }; transitionManager = { active: [], push: function (node) { transitionManager.active[transitionManager.active.length] = node; }, pop: function (node) { var index; index = transitionManager.active.indexOf(node); if (index === -1) { return; } transitionManager.active.splice(index, 1); detachNodes(); if (!transitionManager.active.length && transitionManager._ready) { transitionManager.complete(); } }, complete: function () { if (callback) { callback.call(root); } }, ready: function () { detachNodes(); transitionManager._ready = true; if (!transitionManager.active.length) { transitionManager.complete(); } }, detachWhenReady: function (element) { elementsToDetach[elementsToDetach.length] = element; } }; return transitionManager; }; return makeTransitionManager; }(); var shared_notifyDependants = function () { var notifyDependants, lastKey, starMaps = {}; lastKey = /[^\.]+$/; notifyDependants = function (ractive, keypath, onlyDirect) { var i; if (ractive._patternObservers.length) { notifyPatternObservers(ractive, keypath, keypath, onlyDirect, true); } for (i = 0; i < ractive._deps.length; i += 1) { notifyDependantsAtPriority(ractive, keypath, i, onlyDirect); } }; notifyDependants.multiple = function (ractive, keypaths, onlyDirect) { var i, j, len; len = keypaths.length; if (ractive._patternObservers.length) { i = len; while (i--) { notifyPatternObservers(ractive, keypaths[i], keypaths[i], onlyDirect, true); } } for (i = 0; i < ractive._deps.length; i += 1) { if (ractive._deps[i]) { j = len; while (j--) { notifyDependantsAtPriority(ractive, keypaths[j], i, onlyDirect); } } } }; return notifyDependants; function notifyDependantsAtPriority(ractive, keypath, priority, onlyDirect) { var depsByKeypath = ractive._deps[priority]; if (!depsByKeypath) { return; } updateAll(depsByKeypath[keypath]); if (onlyDirect) { return; } cascade(ractive._depsMap[keypath], ractive, priority); } function updateAll(deps) { var i, len; if (deps) { len = deps.length; for (i = 0; i < len; i += 1) { deps[i].update(); } } } function cascade(childDeps, ractive, priority, onlyDirect) { var i; if (childDeps) { i = childDeps.length; while (i--) { notifyDependantsAtPriority(ractive, childDeps[i], priority, onlyDirect); } } } function notifyPatternObservers(ractive, registeredKeypath, actualKeypath, isParentOfChangedKeypath, isTopLevelCall) { var i, patternObserver, children, child, key, childActualKeypath, potentialWildcardMatches, cascade; i = ractive._patternObservers.length; while (i--) { patternObserver = ractive._patternObservers[i]; if (patternObserver.regex.test(actualKeypath)) { patternObserver.update(actualKeypath); } } if (isParentOfChangedKeypath) { return; } cascade = function (keypath) { if (children = ractive._depsMap[keypath]) { i = children.length; while (i--) { child = children[i]; key = lastKey.exec(child)[0]; childActualKeypath = actualKeypath + '.' + key; notifyPatternObservers(ractive, child, childActualKeypath); } } }; if (isTopLevelCall) { potentialWildcardMatches = getPotentialWildcardMatches(actualKeypath); potentialWildcardMatches.forEach(cascade); } else { cascade(registeredKeypath); } } function getPotentialWildcardMatches(keypath) { var keys, starMap, mapper, i, result, wildcardKeypath; keys = keypath.split('.'); starMap = getStarMap(keys.length); result = []; mapper = function (star, i) { return star ? '*' : keys[i]; }; i = starMap.length; while (i--) { wildcardKeypath = starMap[i].map(mapper).join('.'); if (!result[wildcardKeypath]) { result[result.length] = wildcardKeypath; result[wildcardKeypath] = true; } } return result; } function getStarMap(num) { var ones = '', max, binary, starMap, mapper, i; if (!starMaps[num]) { starMap = []; while (ones.length < num) { ones += 1; } max = parseInt(ones, 2); mapper = function (digit) { return digit === '1'; }; for (i = 0; i <= max; i += 1) { binary = i.toString(2); while (binary.length < num) { binary = '0' + binary; } starMap[i] = Array.prototype.map.call(binary, mapper); } starMaps[num] = starMap; } return starMaps[num]; } }(); var Ractive_prototype_get_arrayAdaptor = function (types, defineProperty, isArray, clearCache, preDomUpdate, postDomUpdate, makeTransitionManager, notifyDependants) { var arrayAdaptor, notifyArrayDependants, ArrayWrapper, patchArrayMethods, unpatchArrayMethods, patchedArrayProto, testObj, mutatorMethods, noop, errorMessage; arrayAdaptor = { filter: function (ractive, object, keypath) { return keypath.charAt(0) !== '(' && isArray(object) && (!object._ractive || !object._ractive.setting); }, wrap: function (ractive, array, keypath) { return new ArrayWrapper(ractive, array, keypath); } }; ArrayWrapper = function (ractive, array, keypath) { this.root = ractive; this.value = array; this.keypath = keypath; if (!array._ractive) { defineProperty(array, '_ractive', { value: { wrappers: [], instances: [], setting: false }, configurable: true }); patchArrayMethods(array); } if (!array._ractive.instances[ractive._guid]) { array._ractive.instances[ractive._guid] = 0; array._ractive.instances.push(ractive); } array._ractive.instances[ractive._guid] += 1; array._ractive.wrappers.push(this); }; ArrayWrapper.prototype = { get: function () { return this.value; }, teardown: function () { var array, storage, wrappers, instances, index; array = this.value; storage = array._ractive; wrappers = storage.wrappers; instances = storage.instances; if (storage.setting) { return false; } index = wrappers.indexOf(this); if (index === -1) { throw new Error(errorMessage); } wrappers.splice(index, 1); if (!wrappers.length) { delete array._ractive; unpatchArrayMethods(this.value); } else { instances[this.root._guid] -= 1; if (!instances[this.root._guid]) { index = instances.indexOf(this.root); if (index === -1) { throw new Error(errorMessage); } instances.splice(index, 1); } } } }; notifyArrayDependants = function (array, methodName, args) { var notifyKeypathDependants, queueDependants, wrappers, wrapper, i; notifyKeypathDependants = function (root, keypath) { var depsByKeypath, deps, keys, upstreamQueue, smartUpdateQueue, dumbUpdateQueue, i, changed, start, end, childKeypath, lengthUnchanged; if (methodName === 'sort' || methodName === 'reverse') { root.set(keypath, array); return; } clearCache(root, keypath); smartUpdateQueue = []; dumbUpdateQueue = []; for (i = 0; i < root._deps.length; i += 1) { depsByKeypath = root._deps[i]; if (!depsByKeypath) { continue; } deps = depsByKeypath[keypath]; if (deps) { queueDependants(keypath, deps, smartUpdateQueue, dumbUpdateQueue); preDomUpdate(root); while (smartUpdateQueue.length) { smartUpdateQueue.pop().smartUpdate(methodName, args); } while (dumbUpdateQueue.length) { dumbUpdateQueue.pop().update(); } } } if (methodName === 'splice' && args.length > 2 && args[1]) { changed = Math.min(args[1], args.length - 2); start = args[0]; end = start + changed; if (args[1] === args.length - 2) { lengthUnchanged = true; } for (i = start; i < end; i += 1) { childKeypath = keypath + '.' + i; notifyDependants(root, childKeypath); } } preDomUpdate(root); upstreamQueue = []; keys = keypath.split('.'); while (keys.length) { keys.pop(); upstreamQueue[upstreamQueue.length] = keys.join('.'); } notifyDependants.multiple(root, upstreamQueue, true); if (!lengthUnchanged) { notifyDependants(root, keypath + '.length', true); } }; queueDependants = function (keypath, deps, smartUpdateQueue, dumbUpdateQueue) { var k, dependant; k = deps.length; while (k--) { dependant = deps[k]; if (dependant.type === types.REFERENCE) { dependant.update(); } else if (dependant.keypath === keypath && dependant.type === types.SECTION && !dependant.inverted && dependant.pNode) { smartUpdateQueue[smartUpdateQueue.length] = dependant; } else { dumbUpdateQueue[dumbUpdateQueue.length] = dependant; } } }; wrappers = array._ractive.wrappers; i = wrappers.length; while (i--) { wrapper = wrappers[i]; notifyKeypathDependants(wrapper.root, wrapper.keypath); } }; patchedArrayProto = []; mutatorMethods = [ 'pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift' ]; noop = function () { }; mutatorMethods.forEach(function (methodName) { var method = function () { var result, instances, instance, i, previousTransitionManagers = {}, transitionManagers = {}; result = Array.prototype[methodName].apply(this, arguments); instances = this._ractive.instances; i = instances.length; while (i--) { instance = instances[i]; previousTransitionManagers[instance._guid] = instance._transitionManager; instance._transitionManager = transitionManagers[instance._guid] = makeTransitionManager(instance, noop); } this._ractive.setting = true; notifyArrayDependants(this, methodName, arguments); this._ractive.setting = false; i = instances.length; while (i--) { instance = instances[i]; instance._transitionManager = previousTransitionManagers[instance._guid]; transitionManagers[instance._guid].ready(); preDomUpdate(instance); postDomUpdate(instance); } return result; }; defineProperty(patchedArrayProto, methodName, { value: method }); }); testObj = {}; if (testObj.__proto__) { patchArrayMethods = function (array) { array.__proto__ = patchedArrayProto; }; unpatchArrayMethods = function (array) { array.__proto__ = Array.prototype; }; } else { patchArrayMethods = function (array) { var i, methodName; i = mutatorMethods.length; while (i--) { methodName = mutatorMethods[i]; defineProperty(array, methodName, { value: patchedArrayProto[methodName], configurable: true }); } }; unpatchArrayMethods = function (array) { var i; i = mutatorMethods.length; while (i--) { delete array[mutatorMethods[i]]; } }; } errorMessage = 'Something went wrong in a rather interesting way'; return arrayAdaptor; }(config_types, utils_defineProperty, utils_isArray, shared_clearCache, shared_preDomUpdate, shared_postDomUpdate, shared_makeTransitionManager, shared_notifyDependants); var Ractive_prototype_get_magicAdaptor = function () { var magicAdaptor, MagicWrapper; try { Object.defineProperty({}, 'test', { value: 0 }); } catch (err) { return false; } magicAdaptor = { wrap: function (ractive, object, keypath) { return new MagicWrapper(ractive, object, keypath); } }; MagicWrapper = function (ractive, object, keypath) { var wrapper = this, keys, prop, objKeypath, descriptor, wrappers, oldGet, oldSet, get, set; this.ractive = ractive; this.keypath = keypath; keys = keypath.split('.'); this.prop = keys.pop(); objKeypath = keys.join('.'); this.obj = ractive.get(objKeypath); descriptor = this.originalDescriptor = Object.getOwnPropertyDescriptor(this.obj, this.prop); if (descriptor && descriptor.set && (wrappers = descriptor.set._ractiveWrappers)) { if (wrappers.indexOf(this) === -1) { wrappers[wrappers.length] = this; } return; } if (descriptor && !descriptor.configurable) { throw new Error('Cannot use magic mode with property "' + prop + '" - object is not configurable'); } if (descriptor) { this.value = descriptor.value; oldGet = descriptor.get; oldSet = descriptor.set; } get = oldGet || function () { return wrapper.value; }; set = function (value) { var wrappers, wrapper, i; if (oldSet) { oldSet(value); } wrappers = set._ractiveWrappers; i = wrappers.length; while (i--) { wrapper = wrappers[i]; if (!wrapper.resetting) { wrapper.ractive.set(wrapper.keypath, value); } } }; set._ractiveWrappers = [this]; Object.defineProperty(this.obj, this.prop, { get: get, set: set, enumerable: true, configurable: true }); }; MagicWrapper.prototype = { get: function () { return this.value; }, reset: function (value) { this.resetting = true; this.value = value; this.obj[this.prop] = value; this.resetting = false; }, teardown: function () { var descriptor, set, value, wrappers; descriptor = Object.getOwnPropertyDescriptor(this.obj, this.prop); set = descriptor.set; wrappers = set._ractiveWrappers; wrappers.splice(wrappers.indexOf(this), 1); if (!wrappers.length) { value = this.obj[this.prop]; Object.defineProperty(this.obj, this.prop, this.originalDescriptor); this.obj[this.prop] = value; } } }; return magicAdaptor; }(); var Ractive_prototype_get__get = function (normaliseKeypath, adaptorRegistry, arrayAdaptor, magicAdaptor) { var get, _get, retrieve, prefix, getPrefixer, prefixers = {}, adaptIfNecessary; get = function (keypath) { return _get(this, keypath); }; _get = function (ractive, keypath) { var cache, cached, value, wrapped, evaluator; keypath = normaliseKeypath(keypath || ''); cache = ractive._cache; if ((cached = cache[keypath]) !== undefined) { return cached; } if (wrapped = ractive._wrapped[keypath]) { value = wrapped.value; } else if (!keypath) { adaptIfNecessary(ractive, '', ractive.data); value = ractive.data; } else if (evaluator = ractive._evaluators[keypath]) { value = evaluator.value; } else { value = retrieve(ractive, keypath); } cache[keypath] = value; return value; }; retrieve = function (ractive, keypath) { var keys, key, parentKeypath, parentValue, cacheMap, value, wrapped; keys = keypath.split('.'); key = keys.pop(); parentKeypath = keys.join('.'); parentValue = _get(ractive, parentKeypath); if (wrapped = ractive._wrapped[parentKeypath]) { parentValue = wrapped.get(); } if (parentValue === null || parentValue === undefined) { return; } if (!(cacheMap = ractive._cacheMap[parentKeypath])) { ractive._cacheMap[parentKeypath] = [keypath]; } else { if (cacheMap.indexOf(keypath) === -1) { cacheMap[cacheMap.length] = keypath; } } value = parentValue[key]; if (adaptIfNecessary(ractive, keypath, value)) { return value; } if (ractive.magic) { ractive._wrapped[keypath] = magicAdaptor.wrap(ractive, value, keypath); } if (ractive.modifyArrays) { if (arrayAdaptor.filter(ractive, value, keypath)) { ractive._wrapped[keypath] = arrayAdaptor.wrap(ractive, value, keypath); } } ractive._cache[keypath] = value; return value; }; prefix = function (obj, prefix) { var prefixed = {}, key; if (!prefix) { return obj; } prefix += '.'; for (key in obj) { if (obj.hasOwnProperty(key)) { prefixed[prefix + key] = obj[key]; } } return prefixed; }; getPrefixer = function (rootKeypath) { var rootDot; if (!prefixers[rootKeypath]) { rootDot = rootKeypath ? rootKeypath + '.' : ''; prefixers[rootKeypath] = function (relativeKeypath, value) { var obj; if (typeof relativeKeypath === 'string') { obj = {}; obj[rootDot + relativeKeypath] = value; return obj; } if (typeof relativeKeypath === 'object') { return rootDot ? prefix(relativeKeypath, rootKeypath) : relativeKeypath; } }; } return prefixers[rootKeypath]; }; adaptIfNecessary = function (ractive, keypath, value) { var i, adaptor, wrapped; i = ractive.adaptors.length; while (i--) { adaptor = ractive.adaptors[i]; if (typeof adaptor === 'string') { if (!adaptorRegistry[adaptor]) { throw new Error('Missing adaptor "' + adaptor + '"'); } adaptor = ractive.adaptors[i] = adaptorRegistry[adaptor]; } if (adaptor.filter(value, keypath, ractive)) { wrapped = ractive._wrapped[keypath] = adaptor.wrap(ractive, value, keypath, getPrefixer(keypath)); ractive._cache[keypath] = value; return true; } } }; return get; }(utils_normaliseKeypath, registries_adaptors, Ractive_prototype_get_arrayAdaptor, Ractive_prototype_get_magicAdaptor); var utils_isObject = function () { var toString = Object.prototype.toString; return function (thing) { return typeof thing === 'object' && toString.call(thing) === '[object Object]'; }; }(); var utils_isEqual = function () { return function (a, b) { if (a === null && b === null) { return true; } if (typeof a === 'object' || typeof b === 'object') { return false; } return a === b; }; }(); var shared_resolveRef = function () { var resolveRef; resolveRef = function (ractive, ref, contextStack) { var keys, lastKey, contextKeys, innerMostContext, postfix, parentKeypath, parentValue, wrapped, keypath, context, ancestorErrorMessage; ancestorErrorMessage = 'Could not resolve reference - too many "../" prefixes'; if (ref === '.') { if (!contextStack.length) { return ''; } return contextStack[contextStack.length - 1]; } if (ref.charAt(0) === '.') { context = contextStack[contextStack.length - 1]; contextKeys = context ? context.split('.') : []; if (ref.substr(0, 3) === '../') { while (ref.substr(0, 3) === '../') { if (!contextKeys.length) { throw new Error(ancestorErrorMessage); } contextKeys.pop(); ref = ref.substring(3); } contextKeys.push(ref); return contextKeys.join('.'); } if (!context) { return ref.substring(1); } return context + ref; } keys = ref.split('.'); lastKey = keys.pop(); postfix = keys.length ? '.' + keys.join('.') : ''; contextStack = contextStack.concat(); while (contextStack.length) { innerMostContext = contextStack.pop(); parentKeypath = innerMostContext + postfix; parentValue = ractive.get(parentKeypath); if (wrapped = ractive._wrapped[parentKeypath]) { parentValue = wrapped.get(); } if (typeof parentValue === 'object' && parentValue !== null && parentValue.hasOwnProperty(lastKey)) { keypath = innerMostContext + '.' + ref; break; } } if (!keypath && ractive.get(ref) !== undefined) { keypath = ref; } return keypath; }; return resolveRef; }(); var shared_attemptKeypathResolution = function (resolveRef) { var push = Array.prototype.push; return function (ractive) { var unresolved, keypath, leftover; while (unresolved = ractive._pendingResolution.pop()) { keypath = resolveRef(ractive, unresolved.ref, unresolved.contextStack); if (keypath !== undefined) { unresolved.resolve(keypath); } else { (leftover || (leftover = [])).push(unresolved); } } if (leftover) { push.apply(ractive._pendingResolution, leftover); } }; }(shared_resolveRef); var shared_processDeferredUpdates = function (preDomUpdate, postDomUpdate) { return function (ractive) { preDomUpdate(ractive); postDomUpdate(ractive); }; }(shared_preDomUpdate, shared_postDomUpdate); var Ractive_prototype_shared_replaceData = function () { return function (ractive, keypath, value) { var keys, accumulated, wrapped, obj, key, currentKeypath, keypathToClear; keys = keypath.split('.'); accumulated = []; if (wrapped = ractive._wrapped['']) { if (wrapped.set) { wrapped.set(keys.join('.'), value); } obj = wrapped.get(); } else { obj = ractive.data; } while (keys.length > 1) { key = accumulated[accumulated.length] = keys.shift(); currentKeypath = accumulated.join('.'); if (wrapped = ractive._wrapped[currentKeypath]) { if (wrapped.set) { wrapped.set(keys.join('.'), value); } obj = wrapped.get(); } else { if (!obj[key]) { if (!keypathToClear) { keypathToClear = currentKeypath; } obj[key] = /^\s*[0-9]+\s*$/.test(keys[0]) ? [] : {}; } obj = obj[key]; } } key = keys[0]; obj[key] = value; return keypathToClear; }; }(); var Ractive_prototype_set = function (isObject, isEqual, normaliseKeypath, clearCache, notifyDependants, attemptKeypathResolution, makeTransitionManager, processDeferredUpdates, replaceData) { var set, updateModel, getUpstreamChanges, resetWrapped; set = function (keypath, value, complete) { var map, changes, upstreamChanges, previousTransitionManager, transitionManager, i, changeHash; changes = []; if (isObject(keypath)) { map = keypath; complete = value; } if (map) { for (keypath in map) { if (map.hasOwnProperty(keypath)) { value = map[keypath]; keypath = normaliseKeypath(keypath); updateModel(this, keypath, value, changes); } } } else { keypath = normaliseKeypath(keypath); updateModel(this, keypath, value, changes); } if (!changes.length) { return; } previousTransitionManager = this._transitionManager; this._transitionManager = transitionManager = makeTransitionManager(this, complete); upstreamChanges = getUpstreamChanges(changes); if (upstreamChanges.length) { notifyDependants.multiple(this, upstreamChanges, true); } notifyDependants.multiple(this, changes); if (this._pendingResolution.length) { attemptKeypathResolution(this); } processDeferredUpdates(this); this._transitionManager = previousTransitionManager; transitionManager.ready(); if (!this.firingChangeEvent) { this.firingChangeEvent = true; changeHash = {}; i = changes.length; while (i--) { changeHash[changes[i]] = this.get(changes[i]); } this.fire('change', changeHash); this.firingChangeEvent = false; } return this; }; updateModel = function (ractive, keypath, value, changes) { var cached, previous, wrapped, keypathToClear; if ((wrapped = ractive._wrapped[keypath]) && wrapped.reset) { if (resetWrapped(ractive, keypath, value, wrapped, changes) !== false) { return; } } cached = ractive._cache[keypath]; previous = ractive.get(keypath); if (previous !== value) { keypathToClear = replaceData(ractive, keypath, value); } else { if (value === cached && typeof value !== 'object') { return; } } clearCache(ractive, keypathToClear || keypath); changes[changes.length] = keypath; }; getUpstreamChanges = function (changes) { var upstreamChanges = [''], i, keypath, keys, upstreamKeypath; i = changes.length; while (i--) { keypath = changes[i]; keys = keypath.split('.'); while (keys.length > 1) { keys.pop(); upstreamKeypath = keys.join('.'); if (!upstreamChanges[upstreamKeypath]) { upstreamChanges[upstreamChanges.length] = upstreamKeypath; upstreamChanges[upstreamKeypath] = true; } } } return upstreamChanges; }; resetWrapped = function (ractive, keypath, value, wrapped, changes) { var previous, cached, cacheMap, i; previous = wrapped.get(); if (!isEqual(previous, value)) { if (wrapped.reset(value) === false) { return false; } } value = wrapped.get(); cached = ractive._cache[keypath]; if (!isEqual(cached, value)) { ractive._cache[keypath] = value; cacheMap = ractive._cacheMap[keypath]; if (cacheMap) { i = cacheMap.length; while (i--) { clearCache(ractive, cacheMap[i]); } } changes[changes.length] = keypath; } }; return set; }(utils_isObject, utils_isEqual, utils_normaliseKeypath, shared_clearCache, shared_notifyDependants, shared_attemptKeypathResolution, shared_makeTransitionManager, shared_processDeferredUpdates, Ractive_prototype_shared_replaceData); var Ractive_prototype_update = function (makeTransitionManager, attemptKeypathResolution, clearCache, notifyDependants, processDeferredUpdates) { return function (keypath, complete) { var transitionManager, previousTransitionManager; if (typeof keypath === 'function') { complete = keypath; keypath = ''; } previousTransitionManager = this._transitionManager; this._transitionManager = transitionManager = makeTransitionManager(this, complete); attemptKeypathResolution(this); clearCache(this, keypath || ''); notifyDependants(this, keypath || ''); processDeferredUpdates(this); this._transitionManager = previousTransitionManager; transitionManager.ready(); if (typeof keypath === 'string') { this.fire('update', keypath); } else { this.fire('update'); } return this; }; }(shared_makeTransitionManager, shared_attemptKeypathResolution, shared_clearCache, shared_notifyDependants, shared_processDeferredUpdates); var utils_arrayContentsMatch = function (isArray) { return function (a, b) { var i; if (!isArray(a) || !isArray(b)) { return false; } if (a.length !== b.length) { return false; } i = a.length; while (i--) { if (a[i] !== b[i]) { return false; } } return true; }; }(utils_isArray); var Ractive_prototype_updateModel = function (getValueFromCheckboxes, arrayContentsMatch, isEqual) { return function (keypath, cascade) { var values, deferredCheckboxes, i; if (typeof keypath !== 'string') { keypath = ''; cascade = true; } consolidateChangedValues(this, keypath, values = {}, deferredCheckboxes = [], cascade); if (i = deferredCheckboxes.length) { while (i--) { keypath = deferredCheckboxes[i]; values[keypath] = getValueFromCheckboxes(this, keypath); } } this.set(values); }; function consolidateChangedValues(ractive, keypath, values, deferredCheckboxes, cascade) { var bindings, childDeps, i, binding, oldValue, newValue; bindings = ractive._twowayBindings[keypath]; if (bindings) { i = bindings.length; while (i--) { binding = bindings[i]; if (binding.radioName && !binding.node.checked) { continue; } if (binding.checkboxName) { if (binding.changed() && !deferredCheckboxes[keypath]) { deferredCheckboxes[keypath] = true; deferredCheckboxes[deferredCheckboxes.length] = keypath; } continue; } oldValue = binding.attr.value; newValue = binding.value(); if (arrayContentsMatch(oldValue, newValue)) { continue; } if (!isEqual(oldValue, newValue)) { values[keypath] = newValue; } } } if (!cascade) { return; } childDeps = ractive._depsMap[keypath]; if (childDeps) { i = childDeps.length; while (i--) { consolidateChangedValues(ractive, childDeps[i], values, deferredCheckboxes, cascade); } } } }(shared_getValueFromCheckboxes, utils_arrayContentsMatch, utils_isEqual); var Ractive_prototype_animate_requestAnimationFrame = function () { if (typeof window === 'undefined') { return; } (function (vendors, lastTime, window) { var x, setTimeout; if (window.requestAnimationFrame) { return; } for (x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame']; } if (!window.requestAnimationFrame) { setTimeout = window.setTimeout; window.requestAnimationFrame = function (callback) { var currTime, timeToCall, id; currTime = Date.now(); timeToCall = Math.max(0, 16 - (currTime - lastTime)); id = setTimeout(function () { callback(currTime + timeToCall); }, timeToCall); lastTime = currTime + timeToCall; return id; }; } }([ 'ms', 'moz', 'webkit', 'o' ], 0, window)); return window.requestAnimationFrame; }(); var Ractive_prototype_animate_animations = function (rAF) { var queue = []; var animations = { tick: function () { var i, animation; for (i = 0; i < queue.length; i += 1) { animation = queue[i]; if (!animation.tick()) { queue.splice(i--, 1); } } if (queue.length) { rAF(animations.tick); } else { animations.running = false; } }, add: function (animation) { queue[queue.length] = animation; if (!animations.running) { animations.running = true; animations.tick(); } }, abort: function (keypath, root) { var i = queue.length, animation; while (i--) { animation = queue[i]; if (animation.root === root && animation.keypath === keypath) { animation.stop(); } } } }; return animations; }(Ractive_prototype_animate_requestAnimationFrame); var utils_warn = function () { if (typeof console !== 'undefined' && typeof console.warn === 'function' && typeof console.warn.apply === 'function') { return function () { console.warn.apply(console, arguments); }; } return function () { }; }(); var utils_isNumeric = function () { return function (thing) { return !isNaN(parseFloat(thing)) && isFinite(thing); }; }(); var shared_interpolate = function (isArray, isObject, isNumeric) { var interpolate = function (from, to) { if (isNumeric(from) && isNumeric(to)) { return makeNumberInterpolator(+from, +to); } if (isArray(from) && isArray(to)) { return