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