UNPKG

@danielkalen/simplybind

Version:

Magically simple, framework-less one-way/two-way data binding for frontend/backend in ~5kb.

1,016 lines (1,013 loc) 35.2 kB
// Generated by CoffeeScript 1.10.0 (function() { var Bound, BoundPublic, SimplyBind, applyPlaceholders, arrayMutatorMethods, boundInstances, cache, computeProxied, errRegEx, errors, escapeRegEx, genID, genObj, getErrSource, globalOptions, handleUpdateFromEvent, isBoundInstance, maybeUpdateDep, methodNames, pholderRegEx, pholderRegExSplit, setPholderRegEx, throwError, throwErrorBadArg, throwErrorUnavail, throwWarning; arrayMutatorMethods = ['push', 'pop', 'shift', 'unshift', 'splice', 'reverse', 'sort']; genID = function() { return 'sb_' + (Math.floor((1 + Math.random()) * 1000000000000).toString(16)); }; genObj = function() { return Object.create(null); }; isBoundInstance = function(subject) { return subject instanceof BoundPublic; }; cache = { textNodes: {}, object: { set: function(B) { var prop, propsMap; prop = B.type === 'Event' ? B.property + '#' + B.eventName : B.property; if (B.object._sb_map) { return B.object._sb_map[prop] = B.ID; } else { propsMap = {}; propsMap[prop] = B.ID; return Object.defineProperty(B.object, '_sb_map', { 'configurable': true, 'value': propsMap }); } }, get: function(object, B) { var prop; prop = B.type === 'Event' ? B.property + '#' + B.eventName : B.property; if (B.object._sb_map && B.object._sb_map[prop]) { return boundInstances[B.object._sb_map[prop]]; } } }, objectFlat: { set: function(B) { return Object.defineProperty(B.object, '_sb_ID', { 'configurable': true, 'value': B.ID }); }, get: function(object) { return boundInstances[object._sb_ID]; } } }; escapeRegEx = /[.*+?^${}()|[\]\\]/g; pholderRegEx = null; pholderRegExSplit = null; setPholderRegEx = function() { var end, middle, start; start = globalOptions.placeholderStart.replace(escapeRegEx, '\\$&'); end = globalOptions.placeholderEnd.replace(escapeRegEx, '\\$&'); middle = "[^" + end + "]+"; pholderRegEx = new RegExp(start + "(" + middle + ")" + end, 'g'); return pholderRegExSplit = new RegExp("" + start + middle + end, 'g'); }; applyPlaceholders = function(contexts, values, indexMap) { var contextPart, i, index, len, output; output = ''; for (index = i = 0, len = contexts.length; i < len; index = ++i) { contextPart = contexts[index]; output += contextPart; if (indexMap[index]) { output += values[indexMap[index]]; } } return output; }; throwError = function(errorName, nonTemplate) { var err, errSource; errSource = getErrSource(); err = nonTemplate ? errorName : errors[errorName]; err += "\n\nCall Source:\n" + errSource; throw new Error('SimplyBind: ' + err); }; throwWarning = function(warningName) { var errSource, warn; if (!globalOptions.silent) { errSource = getErrSource(); warn = errors[warningName]; warn += "\n\nCall Source:\n" + errSource; return console.log('SimplyBind: ' + warn); } }; throwErrorUnavail = function(methodName) { return throwError("You can't use/invoke ." + methodName + "() at this stage", true); }; throwErrorBadArg = function(methodName, arg) { return throwError("Invalid argument/s (" + arg + ") passed to ." + methodName + "()", true); }; getErrSource = function() { return (new Error).stack.split('\n').slice(3, 10).map(function(line) { return line.replace(errRegEx, function(all, extras, source) { return "@ " + source; }); }).join('\n'); }; errRegEx = /[@(?:\wat\s)](.*)\/(.+)$/; Error.prototype.stack = '\n\n\n'; errors = { invalidParamName: "SimplyBind() and .to() only accept a function, an array, a bound object, a string, or a number.", fnOnly: "Only functions are allowed for .transform/.condition/All()", badEventArg: "Invalid argument number in .ofEvent()" }; boundInstances = {}; globalOptions = { silent: false, liveProps: true, dispatchEvents: false, updateEvenIfUndefined: false, updateEvenIfSame: false, updateOnBind: true, mutateInherited: false, trackArrayChildren: false, simpleSelector: false, promiseTransforms: false, placeholderStart: '{{', placeholderEnd: '}}' }; setPholderRegEx(); SimplyBind = function(subject, specificOptions, isBeingProxied) { if ((!subject && subject !== 0) || (typeof subject !== 'string' && typeof subject !== 'number' && typeof subject !== 'function' && !(subject instanceof Array))) { if (!isBoundInstance(subject)) { throwError('invalidParamName'); } } if (typeof subject === 'object' && !(subject instanceof Array)) { return new BoundPublic(subject._, 1, subject.placeholder); } else { return new Bound(subject, specificOptions, isBeingProxied); } }; Bound = function(subject, specificOptions, isBeingProxied) { var key, returnedObj, split, stage; if (specificOptions == null) { specificOptions = {}; } this.optionsPassed = specificOptions; this.options = {}; for (key in globalOptions) { this.options[key] = specificOptions[key] != null ? specificOptions[key] : globalOptions[key]; } this.type = null; this.ID = null; this.selector = this.property = subject; this.valueOriginal = null; this.value = null; this.deps = []; this.depsMap = { 1: genObj(), 2: genObj() }; this.depsPholders = genObj(); this.myPholders = genObj(); this.transforms = genObj(); this.conditions = genObj(); this.attachedEvents = []; this.customEventMethod = genObj(); /* ========================================================================== */ if (typeof subject === 'function') { this.setType('Func'); returnedObj = this.setObject('objectFlat', subject, isBeingProxied); if (returnedObj instanceof BoundPublic) { return returnedObj; } stage = 1; } else if (subject instanceof Array) { this.setType('Array'); returnedObj = this.setObject('objectFlat', subject); if (returnedObj instanceof BoundPublic) { return returnedObj; } stage = 1; } else { if (typeof this.selector === 'number') { this.selector = this.property = this.selector.toString(); } if (this.selector.indexOf(':') !== -1 && !this.options.simpleSelector) { split = this.property.split(':'); this.descriptor = split[0]; this.property = split[1]; } if (this.selector.indexOf('.') !== -1 && !this.options.simpleSelector) { split = this.property.split('.'); this.property = split[0]; this.placeholder = split.slice(1).join('.'); } } this.pub = new BoundPublic(this, 3); return new BoundPublic(this, stage, this.placeholder); }; BoundPublic = function(Private, stage, placeholder1, proxied, proxies, state) { var _this; this.placeholder = placeholder1; /** * Stage definitions: * * 0: Selection: Got selector, awaiting object. * 1: Indication: Got object, awaiting proxied property / function / Bound-object. * 2: Binding Selection: Got proxied selector, awaiting proxied object. * 3: Binding Complete: Complete, awaiting additional (optional) bindings/mutations. */ this.stage = stage || 0; this.proxied = proxied; this.proxies = proxies && proxies.length ? proxies : proxied ? [proxied] : []; if (state) { this.has = state; } else { this.has = { 'tf': false, 'massTf': false, 'initBind': false, 'event': false }; } if (this.placeholder) { Private.placeholder = this.placeholder; } _this = this; Object.defineProperties(this, { 'ID': { get: function() { return Private.ID; } }, 'value': { get: function() { return Private.value; } }, 'original': { get: function() { return Private.objects || Private.object; } }, 'dependents': { get: function() { return Private.deps.slice().map(function(dep) { return dep.object; }); } }, 'new': { value: function(stage, proxied, proxies) { return new BoundPublic(Private, stage, _this.placeholder, proxied || _this.proxied, proxies || _this.proxies, _this.has); } }, '_': { value: Private } }); return this; }; Bound.prototype = { setObject: function(subjectType, subject, isBeingProxied) { var arrayBinding, fromCache, key, ref, stage, subjectValue, value; stage = 1; if (isBoundInstance(subject)) { subject = subject.original; } this.object = subject; fromCache = cache[subjectType].get(this.object, this); if (fromCache) { if (this.placeholder && !fromCache.pholderValues) { fromCache.valueOriginal = fromCache.fetchDirectValue(); fromCache.scanForPholders(); } if (fromCache.type === 'ObjectProp' && !(this.property in this.object)) { fromCache.makePropertyLive(true); } ref = this.optionsPassed; for (key in ref) { value = ref[key]; fromCache.pub.setOption(key, value); } return new BoundPublic(fromCache, stage, this.placeholder); } if (this.type !== 'Event') { subjectValue = this.fetchDirectValue(null, isBeingProxied); if (typeof subjectValue === 'undefined' && subjectType === 'object') { this.object[this.property] = subjectValue = null; } this.value = this.valueOriginal = subjectValue; if (this.placeholder && !this.pholderValues && subjectType === 'object') { this.scanForPholders(); } } this.setID(); this.setType(); this.makePropertyLive(); this.attachEvents(); cache[subjectType].set(this); if (this.object instanceof Array && this.type !== 'Array') { this.arrayBinding = arrayBinding = cache.objectFlat.get(this.object); if (arrayBinding && arrayBinding.options.trackArrayChildren && arrayBinding.trackedChildren.indexOf(this.property) === -1) { arrayBinding.trackedChildren.push(this.property); SimplyBind(this.property).of(this.object).to(arrayBinding.updateSelf); } } }, setEvent: function(eventName, customInMethod, customOutMethod) { if (isNaN(parseInt(this.property))) { throwWarning('badEventArg'); } this.setType('Event'); this.isAsync = true; this.eventName = eventName; if (customInMethod) { this.customEventMethod["in"] = customInMethod; } if (customOutMethod) { return this.customEventMethod.out = customOutMethod; } }, processTransform: function(transformFn, subjects) { var i, len, prox, proxID; if (typeof transformFn !== 'function') { return throwWarning('fnOnly'); } else { for (i = 0, len = subjects.length; i < len; i++) { prox = subjects[i]; proxID = prox.ID; proxID += prox.placeholder ? '.' + prox.placeholder : ''; this.addTransform(proxID, transformFn); prox = prox._; if (this.depsMap[2][prox.ID]) { prox.addTransform(this.ID, transformFn); } if (this.options.updateOnBind || this.type === 'Func') { this.updateDep(prox); } } return true; } }, processCondition: function(conditionFn, subjects) { var i, len, prox, proxID; if (typeof conditionFn !== 'function') { return throwWarning('fnOnly'); } else { for (i = 0, len = subjects.length; i < len; i++) { prox = subjects[i]; proxID = prox.ID; proxID += prox.placeholder ? '.' + prox.placeholder : ''; this.addCondition(proxID, conditionFn); prox = prox._; if (this.depsMap[2][prox.ID]) { prox.addCondition(this.ID, conditionFn); } } return true; } }, destroy: function() { var event, i, j, len, len1, method, ref; delete boundInstances[this.ID]; if (this.type === 'ObjectProp' || this.type === 'DOMText') { Object.defineProperty(this.object, this.property, { 'value': this.value, 'writable': true }); delete this.object._sb_map; delete this.object._sb_ID; } else if (this.type === 'Event') { ref = this.attachedEvents; for (i = 0, len = ref.length; i < len; i++) { event = ref[i]; this.unRegisterEvent(event, this.customEventMethod.remove); } delete this.object._sb_map; } else if (this.type === 'Array') { delete this.object._sb_ID; for (j = 0, len1 = arrayMutatorMethods.length; j < len1; j++) { method = arrayMutatorMethods[j]; delete this.object[method]; } } else if (this.type === 'Func') { delete this.object._sb_ID; } }, setID: function() { this.ID = genID(); return boundInstances[this.ID] = this; }, setType: function(specific) { if (!this.type) { return this.type = specific || 'ObjectProp'; } }, scanForPholders: function() { var index; this.pholderValues = genObj(); this.pholderIndexMap = genObj(); this.pholderContexts = []; if (typeof this.valueOriginal === 'string') { this.pholderContexts = this.valueOriginal.split(pholderRegExSplit); index = 0; return this.value = this.valueOriginal.replace(pholderRegEx, (function(_this) { return function(e, pholder) { _this.pholderIndexMap[index++] = pholder; return _this.pholderValues[pholder] = pholder; }; })(this)); } }, attachEvents: function() { if (this.type === 'Event') { return this.registerEvent(this.eventName, this.customEventMethod["in"]); } }, fetchDirectValue: function(type, isBeingProxied) { if (type == null) { type = this.type; } switch (type) { case 'Func': if (!isBeingProxied) { return this.object(); } break; case 'Array': return this.object; default: return this.object[this.property]; } }, setValue: function(newValue, specificPlaceholder, updater, fromSelf) { var currentValue, isNewValue, isValidValue, placeholderValue, prevValue; if (updater == null) { updater = this; } currentValue = specificPlaceholder ? this.pholderValues[specificPlaceholder] : this.value; if (this.selfTransform) { newValue = this.selfTransform(newValue); } isNewValue = newValue !== currentValue || this.options.updateEvenIfSame; isValidValue = typeof newValue !== 'undefined' || this.options.updateEvenIfUndefined; if ((isNewValue && isValidValue || this.isAsync) && this.type !== 'Array') { prevValue = this.value; if (specificPlaceholder) { this.pholderValues[specificPlaceholder] = placeholderValue = newValue; this.value = newValue = applyPlaceholders(this.pholderContexts, this.pholderValues, this.pholderIndexMap); } else { this.value = newValue; } switch (this.type) { case 'ObjectProp': if (!this.isLiveProp) { this.object[this.property] = newValue; } break; case 'Func': prevValue = this.valuePassed; this.valuePassed = newValue; this.value = this.object(newValue, prevValue); break; case 'Event': if (!fromSelf) { this.emitCauser = updater; this.emitEvent(newValue); this.emitCauser = null; } } if (!(fromSelf && this.emitCauser)) { this.updateAllDeps(updater); } } }, updateAllDeps: function(updater) { var dep, i, len, ref; if (this.deps.length) { if (this.throttleRate) { if (+(new Date) - this.lastUpdate < this.throttleRate) { clearTimeout(this.throttleTimeout); return this.throttleTimeout = setTimeout(((function(_this) { return function() { return _this.updateAllDeps(updater); }; })(this)), this.throttleRate); } else { this.lastUpdate = +(new Date); } } ref = this.deps; for (i = 0, len = ref.length; i < len; i++) { dep = ref[i]; this.updateDep(dep, updater); } } }, updateDep: function(dep, updater) { var currentValue, depPlaceholder, depValue, isInfiniteLoop, isNewEventBinding, myPlaceholder, newValue; isNewEventBinding = this.value === null && this.type === 'Event'; isInfiniteLoop = updater && ((updater === dep) || (updater !== this && updater.depsMap[1][dep.ID])); if (isInfiniteLoop || isNewEventBinding) { return; } updater || (updater = this); myPlaceholder = this.myPholders[dep.ID]; currentValue = myPlaceholder ? this.pholderValues[myPlaceholder] : this.value; depPlaceholder = this.depsPholders[dep.ID]; depValue = depPlaceholder ? dep.pholderValues[depPlaceholder] : dep.value; newValue = currentValue; newValue = this.applyTransform(dep, depPlaceholder, currentValue, depValue); if (!this.checkCondition(dep, depPlaceholder, currentValue, depValue)) { return; } if (this.options.promiseTransforms && (newValue != null) && typeof newValue.then === 'function') { return newValue.then((function(_this) { return function(newValue) { return dep.setValue(newValue, depPlaceholder, updater); }; })(this)); } else { return dep.setValue(newValue, depPlaceholder, updater); } }, applyTransform: function(dep, placeholder, value, depValue) { var depID; if (!this.hasTransforms) { return value; } else { depID = dep.ID; if (placeholder) { depID += '.' + placeholder; } if (this.transforms[depID]) { return this.transforms[depID](value, depValue); } else { return value; } } }, checkCondition: function(dep, placeholder, value, depValue) { var depID; if (!this.hasConditions) { return true; } else { depID = dep.ID; if (placeholder) { depID += '.' + placeholder; } if (this.conditions[depID]) { return this.conditions[depID](value, depValue); } else { return true; } } }, makePropertyLive: function(force) { var _this, opts, origGetFn, origSetFn, propertyDescriptor, ref, ref1, shouldWriteLiveProp; if (this.options.liveProps) { _this = this; if (this.type === 'ObjectProp') { propertyDescriptor = Object.getOwnPropertyDescriptor(this.object, this.property); shouldWriteLiveProp = this.options.mutateInherited || (propertyDescriptor && propertyDescriptor.configurable); if ((shouldWriteLiveProp && !this.isLiveProp) || force) { this.isLiveProp = true; origGetFn = (propertyDescriptor != null ? (ref = propertyDescriptor.get) != null ? ref.bind(this.object) : void 0 : void 0) || function() { return _this.value; }; origSetFn = (propertyDescriptor != null ? (ref1 = propertyDescriptor.set) != null ? ref1.bind(this.object) : void 0 : void 0) || function() {}; return Object.defineProperty(this.object, this.property, { configurable: true, enumerable: propertyDescriptor != null ? propertyDescriptor.enumerable : void 0, get: function() { return origGetFn(); }, set: function(newValue) { _this.setValue(newValue); return origSetFn(newValue); } }); } } else if (this.type === 'Array') { if (!this.isLiveProp) { this.isLiveProp = true; arrayMutatorMethods.forEach(function(method) { return Object.defineProperty(_this.value, method, { configurable: true, value: function() { var result; result = Array.prototype[method].apply(_this.value, arguments); _this.updateAllDeps(); return result; } }); }); } if (this.options.trackArrayChildren && !this.trackedChildren) { this.trackedChildren = []; this.updateSelf = function() { return _this.updateAllDeps(); }; opts = { updateOnBind: false }; return this.value.forEach(function(item, index) { _this.trackedChildren.push('' + index); return SimplyBind(index, opts).of(_this.value).to(_this.updateSelf); }); } } } }, invokeEventMethod: function(eventName, eventMethod, backupMethod) { var subject; subject = this.object; if (!subject[eventMethod]) { eventMethod = backupMethod; } if (!this.eventHandler) { this.eventHandler = handleUpdateFromEvent.bind(this); } return typeof subject[eventMethod] === "function" ? subject[eventMethod](eventName, this.eventHandler) : void 0; }, emitEvent: function(extraData) { var defaultOutMethod, emitMethod, subject; subject = this.object; defaultOutMethod = 'emit'; emitMethod = this.customEventMethod.out || defaultOutMethod; if (!subject[emitMethod]) { emitMethod = defaultOutMethod; } return subject[emitMethod](this.eventName, extraData); }, addDep: function(dep, publicSelf, bothWays) { if (!this.depsMap[1][dep.ID]) { this.depsMap[1][dep.ID] = dep._; this.deps.push(dep._); } if (publicSelf.placeholder) { this.myPholders[dep.ID] = publicSelf.placeholder; } else if (this.myPholders[dep.ID]) { delete this.myPholders[dep.ID]; } if (dep.placeholder) { this.depsPholders[dep.ID] = dep.placeholder; } if (bothWays) { this.depsMap[2][dep.ID] = dep._; } else { if (dep._.depsMap[1][this.ID]) { dep._.addDep(publicSelf, dep, true); this.addDep(dep, publicSelf, true); } } return this; }, removeDep: function(dep, bothWays) { if (this.depsMap[1][dep.ID]) { this.deps.splice(this.deps.indexOf(dep), 1); delete this.depsMap[1][dep.ID]; delete this.depsPholders[dep.ID]; } if (bothWays) { dep.removeDep(this); return delete this.depsMap[2][dep.ID]; } }, removeAllDeps: function(bothWays) { var dep, i, len, ref; ref = this.deps.slice(); for (i = 0, len = ref.length; i < len; i++) { dep = ref[i]; this.removeDep(dep, bothWays); } if (bothWays || Object.keys(this.depsMap[2]).length === 0) { return this.destroy(); } }, addTransform: function(ID, transformFn) { this.hasTransforms = true; return this.transforms[ID] = transformFn; }, addCondition: function(ID, conditionFn) { this.hasConditions = true; return this.conditions[ID] = conditionFn; }, registerEvent: function(eventName, customInMethod) { var attachmentMethod, defaultInMethod; if (this.attachedEvents.indexOf(eventName) !== -1) { return; } defaultInMethod = 'on'; this.attachedEvents.push(eventName); attachmentMethod = customInMethod || defaultInMethod; return this.invokeEventMethod(eventName, attachmentMethod, defaultInMethod); }, unRegisterEvent: function(eventName, customMethod) { var defaultRemoveMethod, indexOfEvent, removalMethod; indexOfEvent = this.attachedEvents.indexOf(eventName); if (indexOfEvent === -1) { return; } defaultRemoveMethod = 'removeListener'; this.attachedEvents.splice(indexOfEvent, 1); removalMethod = customMethod || defaultRemoveMethod; return this.invokeEventMethod(eventName, removalMethod, defaultRemoveMethod); }, addPollInterval: function(time) { this.removePollInterval(); return this.pollInterval = setInterval((function(_this) { return function() { var polledValue; polledValue = _this.fetchDirectValue(); return _this.setValue(polledValue); }; })(this), time); }, removePollInterval: function() { clearInterval(this.pollInterval); return this.pollInterval = null; } }; handleUpdateFromEvent = function() { var fetchedValue; fetchedValue = this.type === 'Event' ? arguments[this.property] : this.fetchDirectValue(); return this.setValue(fetchedValue, null, this.emitCauser, true); }; BoundPublic.prototype = { of: function(object) { var proxiedIndex, returnedObj; if (this.stage !== 0 && this.stage !== 2) { throwErrorUnavail(methodNames[0]); } if (!((typeof object === 'object') || (typeof object === 'function'))) { throwErrorBadArg(methodNames[0], object); } if (this.stage === 0) { returnedObj = this._.setObject('object', object); } else { proxiedIndex = this.proxies.indexOf(this.proxied); this.proxied = this.proxied.of(object); this.proxies[proxiedIndex] = this.proxied; this.has.initBind = true; this.has.tf = false; this._.addDep(this.proxied, this); maybeUpdateDep(this._, this.proxied._); } return returnedObj || this["new"](this.stage + 1); }, ofEvent: function(eventName, customInMethod, customOutMethod) { if (this.stage !== 0 || this.has.event) { throwErrorUnavail(methodNames[1]); } else if (!eventName || typeof eventName !== 'string') { throwErrorBadArg(methodNames[1], eventName); } this._.setEvent(eventName, customInMethod, customOutMethod); this.has.event = true; return this["new"](0); }, to: function(subject, specificOptions) { var newStage; if (this.stage !== 1 || this.has.initBind) { throwErrorUnavail(methodNames[2]); } this.proxied = computeProxied(this, subject, specificOptions); if (this.proxied.stage === 0) { newStage = 2; } else { newStage = 3; this.has.initBind = true; } return this["new"](newStage); }, and: function(subject, specificOptions) { var newStage; if (this.stage !== 3 || !this.has.initBind || this.has.massTf) { throwErrorUnavail(methodNames[3]); } this.proxied = computeProxied(this, subject, specificOptions); this.proxies = this.proxies.concat(this.proxied); if (this.proxied.stage === 0) { newStage = 2; } else { newStage = 3; this.has.tf = false; } return this["new"](newStage); }, toEvent: function(eventName, customOutMethod, customInMethod, specificOptions) { if (this.stage !== 1) { throwErrorUnavail(methodNames[4]); } this.proxied = SimplyBind(0, specificOptions).ofEvent(eventName, customInMethod, customOutMethod); return this["new"](2); }, chainTo: function(subject, specificOptions) { if (this.stage !== 3) { throwErrorUnavail(methodNames[5]); } return SimplyBind(this.proxied).to(subject, specificOptions); }, set: function(newValue) { if (this.stage === 0 || this.stage === 2) { throwErrorUnavail(methodNames[6]); } this._.setValue(newValue, this.placeholder); return this; }, get: function() { if (this.stage === 0 || this.stage === 2) { throwErrorUnavail(methodNames[7]); } if (this.placeholder) { return this._.pholderValues[this.placeholder]; } else { return this._.value; } }, transformSelf: function(transformFn) { if (this.stage !== 1 || this.stage === 1 && this._.type === 'Array') { throwErrorUnavail(methodNames[8]); } if (typeof transformFn !== 'function') { throwWarning('fnOnly'); } else { this._.selfTransform = transformFn; if (this._.options.updateOnBind) { this.set(this.value); } } return this; }, transform: function(transformFn) { if (this.stage !== 3 || this.has.tf || this.has.massTf) { throwErrorUnavail(methodNames[9]); } this.has.tf = this._.processTransform(transformFn, [this.proxied]) || false; return this["new"](3); }, transformAll: function(transformFn) { if (this.stage !== 3 || this.has.tf || this.has.massTf) { throwErrorUnavail(methodNames[10]); } this.has.massTf = this._.processTransform(transformFn, this.proxies) || false; return this["new"](3); }, condition: function(conditionFn) { if (this.stage !== 3) { throwErrorUnavail(methodNames[11]); } this._.processCondition(conditionFn, [this.proxied]); return this["new"](3); }, conditionAll: function(conditionFn) { if (this.stage !== 3) { throwErrorUnavail(methodNames[12]); } this._.processCondition(conditionFn, this.proxies); return this["new"](3); }, bothWays: function(dontOrAltTransform) { var boundProxied, originCondition, originTransform, transformToUse; if (this.stage !== 3 || this.has.massTf) { throwErrorUnavail(methodNames[13]); } boundProxied = this.proxied._.addDep(this, this.proxied, true); originTransform = this._.transforms[this.proxied.ID]; originCondition = this._.conditions[this.proxied.ID]; if (originTransform || dontOrAltTransform) { transformToUse = typeof dontOrAltTransform === 'function' ? dontOrAltTransform : originTransform; if (transformToUse && dontOrAltTransform !== false) { boundProxied.addTransform(this.ID, transformToUse); } } if (originCondition) { boundProxied.addCondition(this.ID, originCondition); } this._.addDep(this.proxied, this, true); return this; }, unBind: function(bothWays) { var i, len, proxied, ref; if (this.stage !== 3) { throwErrorUnavail(methodNames[14]); } ref = this.proxies; for (i = 0, len = ref.length; i < len; i++) { proxied = ref[i]; this._.removeDep(proxied._, bothWays); } return this; }, pollEvery: function(time) { if (this.stage !== 3 || this._.type === 'Event') { throwErrorUnavail(methodNames[15]); } this._.addPollInterval(time); return this; }, stopPolling: function() { if (this.stage !== 3) { throwErrorUnavail(methodNames[16]); } this._.removePollInterval(); return this; }, updateDepsOnEvent: function(eventName, customMethod) { if (this.stage !== 3) { throwErrorUnavail(methodNames[17]); } this._.registerEvent(eventName, customMethod); return this; }, removeEvent: function(eventName, customMethod) { if (this.stage !== 3) { throwErrorUnavail(methodNames[18]); } this._.unRegisterEvent(eventName, customMethod); return this; }, throttle: function(delay) { if (this.stage !== 1 && this.stage !== 3) { throwErrorUnavail(methodNames[19]); } if (typeof delay === 'number' && delay) { this._.throttleRate = delay; } else if (delay === false) { delete this._.throttleRate; } return this; }, setOption: function(optionName, newValue) { var i, len, proxied, ref; if (globalOptions[optionName] != null) { this._.options[optionName] = newValue; this._.makePropertyLive(); ref = this.proxies; for (i = 0, len = ref.length; i < len; i++) { proxied = ref[i]; proxied._.options[optionName] = newValue; proxied._.makePropertyLive(); } } return this; } }; BoundPublic.prototype.update = BoundPublic.prototype.set; BoundPublic.prototype.twoWay = BoundPublic.prototype.bothWays; BoundPublic.prototype.pipe = BoundPublic.prototype.chainTo; methodNames = Object.keys(BoundPublic.prototype); computeProxied = function(instance, subject, specificOptions) { var proxied; if (specificOptions == null) { specificOptions = {}; } instance.proxied = proxied = SimplyBind(subject, specificOptions, true); if (proxied.stage !== 0) { instance._.addDep(proxied, instance); maybeUpdateDep(instance._, proxied._); } return proxied; }; maybeUpdateDep = function(instance, proxied) { if (instance.options.updateOnBind || instance.type === 'Func') { return instance.updateDep(proxied); } }; Object.defineProperties(SimplyBind, { 'version': { value: '1.1.2' }, 'options': { get: function() { var clonedOptions, key, value; clonedOptions = {}; for (key in globalOptions) { value = globalOptions[key]; clonedOptions[key] = value; } return clonedOptions; } } }); SimplyBind.setOption = function(option, newValue) { if (globalOptions[option] != null) { globalOptions[option] = newValue; if (option.indexOf('place') !== -1) { return setPholderRegEx(); } } }; SimplyBind.setOptions = function(newOptions) { var option, value; for (option in newOptions) { value = newOptions[option]; SimplyBind.setOption(option, value); } }; SimplyBind.unBindAll = function(object, bothWays) { var boundID, prop, propMap; if (object && ((typeof object === 'object') || (typeof object === 'function'))) { propMap = object._sb_map; if (object._sb_ID) { boundInstances[object._sb_ID].removeAllDeps(bothWays); } if (propMap) { for (prop in propMap) { boundID = propMap[prop]; boundInstances[boundID].removeAllDeps(bothWays); } } } }; return module.exports = SimplyBind; })();