UNPKG

@danielkalen/simplybind

Version:

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

81 lines (60 loc) 5.09 kB
Binding = (object, type, state)-> extendState(@, state) @optionsDefault = if @saveOptions then @options else defaultOptions @type = type # ObjectProp | Array | Func | Proxy | Event | Pholder | DOMAttr | DOMValue | DOMCheckbox | DOMRadio @object = object # The subject object of this binding, i.e. function, array, {}, DOM el, etc. @ID = genID() # Assigned only after passing a valid object to .of() @subs = [] # Subscribers array listing all of the objects that will be updated upon value update @subsMeta = genObj() # Map subscribers' ID to their metadata (i.e. options, transform, condition, one-time-binding, etc.) @pubsMap = genObj() # Map publishers (bindings that update this binding) by their ID @attachedEvents = [] # Array listing all of the events currently listened on @object @setValue = noop if @type is 'Array' or @type is 'Proxy' # ==== Properties declared later or inherited from binding interface ================================================================================= # @options = options # @value = undefined # Will represent the actual current value of the binding/object # @property = property # The property name or array index or event callback argument # @selector = selector # The property name or array index or event callback argument # @origFn = Function # The original proxied function passed to Proxy bindings # @customEventMethod = {} # Names of the event emitter/trigger methods (if applicable) # @pholderContexts = {} # Placeholder surroundings (original binding value split by the placeholder regEx) # @pholderIndexMap = {} # Placeholder occurence mapping, i.e. the placeholder name for each placeholder occurence # @placeholder = "" # The last specified placeholder to bind the value to # @descriptor = "" # Describes the type of property, i.e. 'attr:data-name' to indicate a DOMAttr type binding # @isLiveProp = Boolean # Indicates whether or not the Object/Object's propety have been modified to be a live property # @isDom = Boolean # Indicates whether or not the binding's object is a DOM object # @pollInterval = ID # The interval ID of the timer that manually polls the object's value at a set interval # @arrayBinding = Binding # Reference to the parent array binding (if exists) for an index-of-array binding (i.e. SimplyBind(array)) # @trackedChildren = [] # For Array type bindings - indicates which indicies of the array are tracked for changes (applicable when @options.trackArrayChildren) is true # @eventName = "" # The name of the event this binding is listening to (for Event type bindings) # @isEmitter = Boolean # Tracker to let us know we shouldn't handle the event update we received as it is the event this binding just emitted # @eventHandler = Function # The callback that gets triggered upon an event emittance (for Even type bindings) # @eventObject = Event # The dispatched event object (for Event type bindings) # @selfTransform = Function # The transform function that new values being set to this binding are being passed through during @setValue (if applicable) # @throttleRate = milliseconds # The rate in which the binding's subscribers will be updated only once in # @throttleTimeout = ID # The timeout ID of the delay timer to update a throttled binding # @lastUpdate = epoch timestamp # Last time the subs have been updated; used for throttle functions # @isAsync = Boolean # Indicates if this is an async binding (currently only used for Event bindings) ### ========================================================================== ### import [browserOnly] -DOMChoice_group.coffee unless @type is 'Event' or (@type is 'Func' and @parentInterface) # the second condition will prevent function subscribers from being invoked on this binding creation if @type is 'Pholder' import [browserOnly] -Pholder-parentProperty-browser.coffee import [nodeOnly] -Pholder-parentProperty-node.coffee parentBinding = @parentBinding = SimplyBind(parentProperty).of(object)._ parentBinding.scanForPholders() @value = parentBinding.pholderValues[@pholder] import [browserOnly] -Pholder-textNodes_definition.coffee else @value = subjectValue = @fetchDirectValue() if @type is 'ObjectProp' and not checkIf.isDefined(subjectValue) @object[@property] = subjectValue # Define the prop on the object if it non-existent @convertToLive() @attachEvents() # IF this is a binding to a specific index of an array then we must make this binding update the array on change if the array binding is tracking its children if @object instanceof Array and @type isnt 'Array' @arrayBinding = arrayBinding = cache.get(@object, true) if arrayBinding and arrayBinding.trackedChildren and not targetIncludes(arrayBinding.trackedChildren, @property) arrayBinding.trackedChildren.push(@property) SimplyBind(@property).of(@object).to arrayBinding.updateSelf return boundInstances[@ID] = @ import prototype.coffee