UNPKG

@danielkalen/simplybind

Version:

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

157 lines (83 loc) 3.69 kB
import [browserOnly] closure-helpers-changeEvent.coffee arrayMutatorMethods = ['push','pop','shift','unshift','splice','reverse','sort'] dummyPropertyDescriptor = {} genID = ()-> 'sb_'+(Math.floor((1+Math.random()) * 1000000000000).toString(16)) genObj = ()-> Object.create(null) # ==== Checks ================================================================================= arrayIncludes = (arr, item)-> arr.indexOf(item) isnt -1 checkIf = isDefined: (subject)-> subject isnt undefined isObject: (subject)-> typeof subject is 'object' and subject # 2nd check is to test against 'null' values isString: (subject)-> typeof subject is 'string' isNumber: (subject)-> typeof subject is 'number' isFunction: (subject)-> typeof subject is 'function' isBindingInterface: (subject)-> subject instanceof BindingInterface import [browserOnly] closure-helpers-checkIf.DOM.coffee # ==== Options ================================================================================= setOptionsForBinding = (binding, newOptions)-> for option,value of newOptions binding.options[option] = value if checkIf.isDefined(globalOptions[option]) binding.makePropertyLive() return extendState = (base, stateToInherit)-> stateMapping = Object.keys(stateToInherit) base[key] = stateToInherit[key] for key in stateMapping return # ==== Binding Cache ================================================================================= cache = get: (object, isSimpleObject, selector, isMultiChoice)-> if isSimpleObject return boundInstances[object._sb_ID] else import [browserOnly] closure-helpers-cache.get.DOMChoice_group.coffee if object._sb_map and object._sb_map[selector] return boundInstances[ object._sb_map[selector] ] set: (B, isSimpleObject)-> # B ==== Binding Object if isSimpleObject Object.defineProperty B.object, '_sb_ID', {'configurable':true, 'value':B.ID} else selector = B.selector if B.object._sb_map B.object._sb_map[selector] = B.ID else propsMap = {} propsMap[selector] = B.ID Object.defineProperty B.object, '_sb_map', {'configurable':true, 'value':propsMap} return # ==== Placeholders ================================================================================= escapeRegEx = /[.*+?^${}()|[\]\\]/g pholderRegEx = pholderRegExSplit = null setPholderRegEx = ()-> start = globalOptions.placeholder[0].replace(escapeRegEx, '\\$&') end = globalOptions.placeholder[1].replace(escapeRegEx, '\\$&') middle = "[^#{end}]+" pholderRegEx = new RegExp("#{start}(#{middle})#{end}", 'g') pholderRegExSplit = new RegExp("#{start}#{middle}#{end}", 'g') return applyPlaceholders = (contexts, values, indexMap)-> output = '' for contextPart,index in contexts output += contextPart output += values[indexMap[index]] if indexMap[index] return output import [browserOnly] closure-helpers-scanTextNodesPlaceholders.coffee # ==== Errors + Warnings ================================================================================= throwError = (errorName)-> throw new Error 'SimplyBind: '+(errors[errorName] or errorName) throwWarning = (warningName, depth)-> unless globalOptions.silent errSource = getErrSource(depth) warn = errors[warningName] warn += "\n\n"+errSource console.warn('SimplyBind: '+warn) return throwErrorUnavail = (methodName)-> throwError "You can't use/invoke .#{methodName}() at this stage", true return throwErrorBadArg = (methodName, arg)-> throwError "Invalid argument/s (#{arg}) passed to .#{methodName}()", true return getErrSource = (depth)-> ((new Error).stack or '') .split('\n') .slice(depth+3) .join('\n')