coffeescript-ui
Version:
Coffeescript User Interface System
677 lines (539 loc) • 15.2 kB
text/coffeescript
###
* coffeescript-ui - Coffeescript User Interface System (CUI)
* Copyright (c) 2013 - 2016 Programmfabrik GmbH
* MIT Licence
* https://github.com/programmfabrik/coffeescript-ui, http://www.coffeescript-ui.org
###
CUI.Template.loadTemplateText(require('./DataField.html'));
class CUI.DataField extends CUI.DOMElement
: "cui-data-field-changed-marker"
:
undo_and_changed_support: false
constructor: (opts) ->
super(opts)
CUI.util.assertImplements(@, ["render"])
if
CUI.util.assertImplements(@, ["getDefaultValue"])
= undefined
CUI.Events.listen
type: "data-changed"
node:
call: (ev, info) =>
return
if
.setAttribute("cui-data-field-name", )
if and not CUI.util.isFunction()
# console.debug "setting private data: "+@,
if
if and (.text or .content)
tt_opts = CUI.util.copyObject()
tt_opts.element =
= new CUI.Tooltip(tt_opts)
= 1
?(@)
# console.debug "new: "+@
onDataChanged: (ev, info) ->
if not info?.element
console.warn("#{CUI.util.getObjectClass(@)}[DataField].listen[data-changed]: received event with element not set.", ev, info, @)
return
?(, info.element, ev, info)
initOpts: ->
super()
name:
maximize:
check: Boolean
maximize_horizontal:
check: Boolean
default: false
maximize_vertical:
check: Boolean
default: false
padded:
check: Boolean
default: false
data:
check: (v) ->
CUI.util.isFunction(v?.hasOwnProperty) or CUI.util.isFunction(v)
data_not_for_others:
default: false
check: Boolean
disabled:
default: false
check: (v) ->
CUI.util.isBoolean(v) or CUI.util.isFunction(v)
disabled_depends_on_data:
check: Function
tooltip:
check: "PlainObject"
hidden:
check: Boolean
form: {}
# set undo_support, check_changed, mark_changed all at once
undo_and_changed_support:
check: Boolean
undo_support:
default: CUI.DataField.defaults.undo_and_changed_support
check: Boolean
mark_changed:
default: CUI.DataField.defaults.undo_and_changed_support
check: Boolean
check_changed:
default: CUI.DataField.defaults.undo_and_changed_support
check: Boolean
onDataChanged:
check: Function
onDataInit:
check: Function
onInit:
check: Function
onRender:
check: Function
render_as_block:
check: Boolean
readOpts: ->
if .hasOwnProperty("undo_and_changed_support")
for k in ["undo_support", "check_changed", "mark_changed"]
if not .hasOwnProperty(k)
[k] = .undo_and_changed_support
super()
CUI.Layout::maximizeReadOpts.call(@)
maximizeAddClasses: ->
CUI.Layout::maximizeAddClasses.call(@)
getUniqueIdForLabel: ->
null
initTemplate: ->
getTemplate: ->
new CUI.Template
name: "data-field"
isResizable: ->
false
init: ->
debug: ->
console.debug "----"+@+"----", @
if
console.debug "data:",
console.debug "value:",
console.debug "init-value:",
console.debug "check-changed-value:",
toString: ->
"[#{@__cls}[#{@__uniqueId}, #{@_name or '<no name>'}]}"
reload: ->
?(@)
@
remove: ->
if not
= false
getNameOpt: ->
check: String
registerLabel: (lbl) ->
_for =
if _for
lbl.setAttribute('for', _for)
return
getLabel: ->
getMaximizeHorizontal: ->
setForm: (form) ->
CUI.util.assertImplements(form, [
"getFieldsByName"
"getFieldByIdx"
"getData"
"getFields"
])
= form
if not .getFormPath
return @
if .getMaximizeHorizontal()
if != false
#
@
# getFormDepth: ->
# parseInt(CUI.dom.getAttribute(, "cui-form-depth"))
# setFormDepth: ->
# # update depth
# path =
# CUI.dom.setAttribute(, "cui-form-depth", path.length)
#
# path.length
getFormPath: (include_self=false, path=[], call=0) ->
CUI.util.assert(call < 100, "CUI.DataField.getPath", "Recursion detected.")
if ?.getFormPath
.getFormPath(true, path, call+1)
if include_self
path.push(@)
return path
getForm: ->
# short-cut to get other field
getOtherField: (name) ->
?.getFieldsByName(name)?[0]
getRootForm: ->
if
.getRootForm()
else if @ instanceof CUI.Form
@
else
null
__initDisabled: ->
if and ( == true or .call(@, @))
return
enable: ->
@
disable: ->
@
isDisabled: ->
isHidden: ->
isShown: ->
!
updateData: (data) ->
if CUI.util.isFunction()
= .call(@, data, @)
else
= data
unsetData: ->
delete
if
return
setData: (data, init_data=true) ->
if and and not CUI.util.isFunction()
# console.debug "private data already set",
# we have private data set, ignore a setData from
# e.g. a Form, as the private data is more important
# than the Form data
return
CUI.util.assert(not , "#{@}.setData", "data is already set.", opts: , data: )
if CUI.util.isFunction()
= .call(@, data, @)
else
= data
CUI.util.assert(CUI.util.isPlainObject() or ?.hasOwnProperty?(), "#{@}.setData", "data needs to be PlainObject or have a property \"#{@getName()}\".", data: data, opts: )
# console.debug "initData", , .hasOwnProperty
if
if init_data
# console.debug "setting data", ,
@
setDataOnOthers: ->
not
hide: (trigger_event=false) ->
if trigger_event
CUI.Events.trigger
type: "form-check-row-visibility"
node:
info:
element: @
@
show: (trigger_event=false) ->
if trigger_event
CUI.Events.trigger
type: "form-check-row-visibility"
node:
info:
element: @
@
isRendered: ->
render: ->
CUI.util.assert(not , "#{@__cls}.render", "Cannot be called when already rendered.", opts: , dataField: @)
# for p of .map
# content = @["__#{p}"]
# if CUI.util.isNull(content)
# continue
#
= true
if
if
?(@)
@
displayValue: ->
CUI.util.assert(not , "#{@__cls}.displayValue", "DataField already destroyed, cannot display value.", data_field: @)
CUI.util.assert(, "#{@__cls}.displayValue", "not rendered yet, cannot display.", opts: , data: )
start: ->
CUI.util.assert(not , "#{@__cls}.start", "Cannot be called when already rendered.", opts: , dataField: @)
@
getAllDataFields: (all=false)->
getDataFields: (all=false, data_fields = [])->
if or all
data_fields.push(@)
data_fields
renderAsBlock: ->
!!
isDataField: ->
# calls method on all DataFields
# inside the "right" side
callOnOthers: (func, args...) ->
if
other_fields = .slice(0)
else
other_fields = []
for df in other_fields
if not df or not CUI.util.isFunction(df[func])
CUI.util.assert(false, "CUI.DataField.callOnOthers", "Field found in other fields has no Function \"#{func}\".", field: df, other_fields: other_fields)
return @
df[func].apply(df, args)
@
getData: ->
hasData: ->
if not CUI.util.isEmpty() and
true
else
false
hasUserData: (data) ->
and not CUI.util.isEmpty(data[])
getArrayFromOpt: (opt, event, allowDeferred=false) ->
v = @["_#{opt}"]
if CUI.util.isFunction(v)
arr = v.call(@, @, event)
CUI.util.assert(CUI.util.isArray(arr) or (CUI.util.isPromise(arr) and allowDeferred), "#{@__cls}.getArrayFromOpt", "opts.#{opt}(dataField) did not return Array or Promise.", options: arr, opts: )
else
arr = v
return arr
getName: ->
# data field needs to return the empty value
# to init data
#
getDefaultValue: ->
# get the current value of the data field
getValue: ->
[]
checkValue: ->
throw new Error("#{@__cls}.checkValue is unimplemtented.")
@
setValue: (v, flags = {}) ->
if not
if
return @
if v ==
return @
try
catch e
if e not instanceof CUI.CheckValueError
throw(e)
throw(new Error("#{@__cls}.setValue: "+v+", Error: "+e))
if flags.no_trigger not in [false, true]
flags.no_trigger = true
if
@
getInitValue: ->
undo =
if not undo
return undefined
undo.values[0]
getLastValue: ->
CUI.util.assert(, "DataField.getLastValue", "Needs opts.undo_support to be set.", opts: )
undo =
if not undo
return undefined
undo.values[undo.idx-1]
reset: ->
if undo =
[] = undo.values[0]
undo.values.splice(1)
undo.idx = 0
action: "reset"
undo_idx: 0
@
undo: ->
if undo =
if undo.idx == 0
return false
[] = undo.values[--undo.idx]
action: "undo"
undo_idx: undo.idx
return true
return null
@
redo: ->
if undo =
if undo.idx == undo.values.length - 1
return false
[] = undo.values[++undo.idx]
action: "redo"
undo_idx: undo.idx
return true
return null
@
goto: (idx) ->
if undo =
if CUI.util.isUndef(undo.values[idx])
return false
undo.idx = idx
[] = undo.values[undo.idx]
# console.debug , []
action: "goto"
undo_idx: idx
return true
return null
# data fields need to initialise the data array
initData: ->
?(@, )
# console.debug "initData", , ,
if not
return
undo =
if CUI.util.isPlainObject(undo) and CUI.util.isEmptyObject(undo)
undo.values = [ ]
undo.idx = 0
if CUI.util.isUndef()
if
@
initValue: ->
if CUI.util.isUndef([])
# console.debug "initValue", , [],
[] =
@
setCheckChangedValue: (value) ->
CUI.util.assert(, "#{@__cls}.setCheckChangedValue", "Cannot set without data.", opts: , value: value, dataField: @)
if == false
return undefined
= JSON.stringify(value)
getCheckChangedValue: ->
if == false
return undefined
CUI.util.assert(, "#{@__cls}.getCheckChangedValue", "No data set.", opts: )
getUndo: ->
if not or == false
return false
if CUI.util.isUndef(._undo)
._undo = {}
# console.debug , ._undo,
if CUI.util.isUndef(undo = ._undo[])
undo = ._undo[] = {}
undo
# stores a user changed value and
# manages old and new values
storeValue: (value, flags={}) ->
if not
return false
store_last = flags.initial_activate != true and flags.no_store != true
if store_last and (undo = )
# console.debug(".undo[#{@_name}][#{@undo.idx}]", [], ">", value)
undo.values[++undo.idx] = value
# clean evertyhing after the undo idx
undo.values.splice(undo.idx+1)
[] = value
if store_last and not flags.no_trigger
# console.debug +".storeValue: triggering data-changed: ", @
action: "store"
undo_idx: undo?.idx
@
triggerDataChanged: (info={}) ->
info.element = @
CUI.Events.trigger
type: "data-changed"
node:
info: info
isChanged: ->
if not or == false
return undefined
!= JSON.stringify()
checkChanged: ->
if == false
return
if
else
@
getChangedMarker: ->
if == false or == false
return
CUI.dom.div(CUI.DataField.changed_marker_css_class)
destroy: ->
?.destroy()
super()
: (field, delete_keys=[], default_data={}) ->
if field instanceof CUI.DataField
return field
CUI.util.assert(CUI.util.isPlainObject(field), "CUI.DataField.new", "field needs to be PlainObject.", field: field, delete_keys: delete_keys, default_data: default_data)
field_opts = {}
for k, v of field
if k == "type"
type = v
continue
if delete_keys.indexOf(k) > -1
continue
# if v instanceof CUI.Icon
# field_opts[k] = v.copy()
# continue
field_opts[k] = v
for k, v of default_data
if field_opts.hasOwnProperty(k)
continue
field_opts[k] = v
CUI.util.assert(CUI.util.isFunction(type), "CUI.DataField.new", "type is unknown: \"#{type}\".", field: field)
_field = new type(field_opts)
CUI.util.assert(_field instanceof CUI.DataField, "CUI.DataField.new", "field.type needs to be of class DataField, but is #{CUI.util.getObjectClass(_field)}.", field: field)
return _field
CUI.Events.registerEvent
type: "data-changed"
bubble: true