neft
Version:
Universal Platform
181 lines (146 loc) • 4.78 kB
text/coffeescript
'use strict'
utils = require 'src/utils'
assert = require 'src/assert'
log = require 'src/log'
signal = require 'src/signal'
Dict = require 'src/dict'
List = require 'src/list'
Binding = require 'src/binding'
assert = assert.scope 'View.Input'
log = log.scope 'View', 'Input'
class DocumentBinding extends Binding
@New = (binding, ctx, target) ->
target ?= new DocumentBinding binding, ctx
Binding.New binding, ctx, target
constructor: (binding, ctx) ->
super binding, ctx
@args = ctx.file.inputArgs
`//<development>`
@failed = false
@failCheckPending = false
`//</development>`
getItemById: (item) ->
if item is 'this'
@ctx
else if item is 'refs'
@args[0]
else if item is 'props'
@args[1]
else if item is 'state'
@args[2]
`//<development>`
failCheckQueue = []
failCheckQueuePending = false
checkFails = ->
while binding = failCheckQueue.pop()
err = failCheckQueue.pop()
if binding.failed
log.error "Error in '#{binding.ctx.text}', file '#{binding.ctx.file.path}':\n#{err}"
binding.failCheckPending = false
failCheckQueuePending = false
return
onError: (err) ->
@failed = true
unless @failCheckPending
@failCheckPending = true
failCheckQueue.push err, @
unless failCheckQueuePending
failCheckQueuePending = true
setImmediate checkFails
return
`//</development>`
update: ->
# disable updates for reverted files
unless @ctx.file.isRendered
@ctx.isDirty = true
return
`//<development>`
@failed = false
`//</development>`
super()
getValue: ->
@ctx.getValue()
setValue: (val) ->
@ctx.setValue val
module.exports = (File) -> class Input extends signal.Emitter
{Element} = File
{Tag} = Element
@__name__ = 'Input'
@__path__ = 'File.Input'
JSON_CTOR_ID = @JSON_CTOR_ID = File.JSON_CTORS.push(Input) - 1
i = 1
JSON_NODE = @JSON_NODE = i++
JSON_TEXT = @JSON_TEXT = i++
JSON_BINDING = @JSON_BINDING = i++
JSON_ARGS_LENGTH = @JSON_ARGS_LENGTH = i
@_fromJSON = (file, arr, obj) ->
unless obj
node = file.node.getChildByAccessPath arr[JSON_NODE]
obj = new Input file, node, arr[JSON_TEXT], arr[JSON_BINDING]
obj
RE = @RE = new RegExp '([^$]*)\\${([^}]*)}([^$]*)', 'gm'
@test = (str) ->
RE.lastIndex = 0
RE.test str
if utils.isServer
@parse = require('./input/parser').parse
initBindingConfig = (cfg) ->
cfg.func ?= new Function 'refs', 'props', 'state', cfg.body
cfg.tree ?= [cfg.func, cfg.connections]
return
constructor: (@file, @node, @text, @bindingConfig) ->
assert.instanceOf @file, File
assert.instanceOf @node, File.Element
assert.isString @text
assert.isObject @bindingConfig
super()
@target = null
@context = null
@isDirty = false
@binding = null
initBindingConfig @bindingConfig
`//<development>`
if @constructor is Input
Object.seal @
`//</development>`
signal.Emitter.createSignal @, 'onTargetChange'
signal.Emitter.createSignal @, 'onContextChange'
registerBinding: ->
assert.isNotDefined @binding
@binding = DocumentBinding.New @bindingConfig.tree, @
if @bindingConfig.updateOnCreate
@isDirty = true
return
render: ->
oldTarget = @target
oldContext = @context
@target = @file.scope
@context = @file.context
if oldTarget isnt @target
@onTargetChange.emit()
if oldContext isnt @context
@onContextChange.emit()
return
onRender: ->
if @isDirty
@isDirty = false
@binding.update()
return
revert: ->
return
clone: (original, file) ->
node = original.node.getCopiedElement @node, file.node
new Input file, node, @text, @bindingConfig
toJSON: (key, arr) ->
unless arr
arr = new Array JSON_ARGS_LENGTH
arr[0] = JSON_CTOR_ID
arr[JSON_NODE] = @node.getAccessPath @file.node
arr[JSON_TEXT] = @text
arr[JSON_BINDING] =
body: @bindingConfig.body
connections: @bindingConfig.connections
updateOnCreate: @bindingConfig.updateOnCreate
arr
@Text = require('./input/text.coffee') File, @
@Prop = require('./input/prop.coffee') File, @