$sum and $val also supports bind.
This commit is contained in:
parent
37c11bfcb2
commit
084ba95b6a
@ -22,12 +22,41 @@ $watch = (collection, {
|
||||
if: cond
|
||||
|
||||
bind
|
||||
|
||||
# Initial value.
|
||||
init
|
||||
}, fn) ->
|
||||
# The default value is simply the value of the item.
|
||||
val ?= -> @val
|
||||
|
||||
watcher = {
|
||||
# Method allowing the cleanup when the helper is no longer used.
|
||||
cleanUp: -> # TODO: noop for now.
|
||||
|
||||
# Keys of items using the current helper.
|
||||
consumers: Object.create null
|
||||
|
||||
generator: ->
|
||||
{key} = this
|
||||
|
||||
# Register this item has a consumer.
|
||||
watcher.consumers[@key] = true
|
||||
|
||||
# Returns the value for this item if any or the common value.
|
||||
values = watcher.values
|
||||
if key of values
|
||||
values["$#{key}"]
|
||||
else
|
||||
values.common
|
||||
|
||||
# Current values.
|
||||
values: Object.create null
|
||||
}
|
||||
watcher.values.common = init
|
||||
|
||||
process = (event, items) ->
|
||||
values = []
|
||||
# Values are grouped by namespace.
|
||||
valuesByNamespace = Object.create null
|
||||
|
||||
$_.each items, (item) ->
|
||||
return unless not cond? or cond.call item
|
||||
@ -40,10 +69,29 @@ $watch = (collection, {
|
||||
else
|
||||
'common'
|
||||
|
||||
values.push [event, value, namespace]
|
||||
(valuesByNamespace[namespace] ?= []).push value
|
||||
|
||||
# If something has been processed, call `fn`.
|
||||
fn values unless $_.isEmpty values
|
||||
# For each namespace.
|
||||
for namespace, values of valuesByNamespace
|
||||
|
||||
# Updates the value.
|
||||
value = watcher.values[namespace]
|
||||
ctx = {
|
||||
value: if value is undefined then init else value
|
||||
}
|
||||
changed = if event is 'enter'
|
||||
fn.call ctx, values, []
|
||||
else
|
||||
fn.call ctx, [], values
|
||||
|
||||
# Notifies watchers unless it is known the value has not
|
||||
# changed.
|
||||
unless changed is false
|
||||
watcher.values[namespace] = ctx.value
|
||||
if namespace is 'common'
|
||||
collection.touch watcher.consumers
|
||||
else
|
||||
collection.touch (namespace.substr 1)
|
||||
|
||||
processOne = (event, item) ->
|
||||
process event, [item]
|
||||
@ -70,6 +118,9 @@ $watch = (collection, {
|
||||
|
||||
collection.on 'any', updateMultiple
|
||||
|
||||
# Returns the watcher object.
|
||||
watcher
|
||||
|
||||
#=====================================================================
|
||||
|
||||
# Creates a set of value from various items.
|
||||
@ -77,104 +128,67 @@ $set = (options) ->
|
||||
# Contrary to other helpers, the default value is the key.
|
||||
options.val ?= -> @key
|
||||
|
||||
# Keys of items using this value.
|
||||
users = Object.create null
|
||||
options.init = []
|
||||
|
||||
#
|
||||
sets = {
|
||||
common: []
|
||||
}
|
||||
watcher = $watch this, options, (entered, exited) ->
|
||||
changed = false
|
||||
|
||||
$watch this, options, (values) =>
|
||||
# Marks changed namespaces to avoid unnecessary updates.
|
||||
changed = {}
|
||||
for value in entered
|
||||
if @value.indexOf value is -1
|
||||
@value.push value
|
||||
changed = true
|
||||
|
||||
$_.each values, ([event, value, namespace]) ->
|
||||
set = (sets[namespace] ?= [])
|
||||
if event is 'enter'
|
||||
return unless set.indexOf value is -1
|
||||
set.push value
|
||||
changed[namespace] = true
|
||||
else
|
||||
changed[namespace] = true if $removeValue set, value
|
||||
for value in exited
|
||||
changed = true if $removeValue @value, value
|
||||
|
||||
if changed.common
|
||||
@touch users
|
||||
delete changed.common
|
||||
for key in changed
|
||||
@touch (key.substr 1) # Remove the leading “$”.
|
||||
changed
|
||||
|
||||
# This function both allows users to register to this set and gives
|
||||
# them the current value.
|
||||
->
|
||||
# Registers this item as a consumer.
|
||||
users[@key] = true
|
||||
|
||||
# Returns its dedicated value or the common one.
|
||||
sets["$#{@key}"] ? sets.common
|
||||
watcher.generator
|
||||
|
||||
#---------------------------------------------------------------------
|
||||
|
||||
$sum = (options) ->
|
||||
# Keys of items using this value.
|
||||
users = Object.create null
|
||||
options.init ?= 0
|
||||
|
||||
# The current sum.
|
||||
if options.init
|
||||
sum = options.init
|
||||
delete options.init
|
||||
else
|
||||
sum = 0
|
||||
watcher = $watch this, options, (entered, exited) ->
|
||||
prev = @value
|
||||
|
||||
$watch this, options, (values) =>
|
||||
prev = sum
|
||||
@value += value for value in entered
|
||||
@value -= value for value in exited
|
||||
|
||||
$_.each values, ([event, value]) ->
|
||||
sum += if event is 'enter' then value else -value
|
||||
@value isnt prev
|
||||
|
||||
@touch users if sum isnt prev
|
||||
|
||||
# This function both allows users to register to this sum and gives
|
||||
# them the current value.
|
||||
->
|
||||
users[@key] = true
|
||||
sum
|
||||
watcher.generator
|
||||
|
||||
#---------------------------------------------------------------------
|
||||
|
||||
# Uses a value from another item.
|
||||
#
|
||||
# Important note: This helper is badly specified when binding to
|
||||
# multiple items.
|
||||
# Important note: Behavior is not specified when binding to multiple
|
||||
# items.
|
||||
$val = (options) ->
|
||||
# Keys of items using this value.
|
||||
users = Object.create null
|
||||
|
||||
# The default value.
|
||||
def = options.default
|
||||
delete options.default
|
||||
|
||||
options.init ?= def
|
||||
|
||||
# Should the last value be kept instead of returning to the default
|
||||
# value when no items are available!
|
||||
keepLast = !!options.keepLast
|
||||
delete options.keepLast
|
||||
|
||||
# The current value.
|
||||
value = def
|
||||
watcher = $watch this, options, (entered, exited) ->
|
||||
prev = @value
|
||||
|
||||
$watch this, options, (values) =>
|
||||
prev = value
|
||||
if not $_.isEmpty entered
|
||||
@value = entered[0]
|
||||
else
|
||||
@value = def unless keepLast
|
||||
|
||||
for [event, value] in values
|
||||
break if event is 'enter'
|
||||
@value isnt prev
|
||||
|
||||
value = def unless keepLast
|
||||
|
||||
@touch users if value isnt prev
|
||||
|
||||
->
|
||||
users[@key] = true
|
||||
value
|
||||
watcher.generator
|
||||
|
||||
#=====================================================================
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user