kdf
Version:
192 lines (150 loc) • 5.5 kB
text/coffeescript
KDContentEditableView = require './contenteditableview.coffee'
KDContextMenu = require './../contextmenu/contextmenu.coffee'
module.exports = class KDTokenizedInput extends KDContentEditableView
constructor: (options = {}, data) ->
options.cssClass = KD.utils.curry 'kdtokenizedinputview', options.cssClass
options.bind = KD.utils.curry 'keyup', options.bind
options.rules or= {}
options.layer or= {}
super options, data
= {}
getValue: (options = {}) ->
value = ""
for node in .childNodes
value += "\n" if node.tagName?.toLowerCase() is "div"
nodeValue = node
value += nodeValue if nodeValue isnt "\n"
if value is Encoder.htmlDecode( .placeholder) then return ""
else return value
getValueOfNode: (node) ->
value = ""
switch node.nodeType
when Node.TEXT_NODE
value += node.textContent if node.textContent isnt ""
when Node.ELEMENT_NODE
value += node
return value
getValueOfElement: (element) ->
key = element.dataset?.key
value = key if key
return value if value
tagName = element.tagName.toLowerCase()
switch tagName
when "br" then return "\n"
else
value = ""
value += child for child in element.childNodes
return value or ""
getValueOfTokenElement: (key) ->
view = key
return view.encodeValue() if key and view
getTokens: ->
return
findTokensInElement: (element) ->
tokens = []
for child in element.childNodes
switch child.nodeType
when Node.ELEMENT_NODE
if key = child.dataset?.key
view = key
{type} = view.getOptions()
data = view.getData()
tokens.push {type, data}
else
tokens = tokens.concat child
return tokens
getTokenView: (key) ->
return [key]
matchPrefix: ->
return if
return unless range = .getSelectionRange()
node = range.commonAncestorContainer
if node.children?.length is 1
return node.textContent is node.children[0].textContent
start = range.startOffset - 1
char = node.textContent[start]
for name, rule of .rules
if char is rule.prefix
= rule
= document.createElement "span"
.textContent = rule.prefix
.replaceRange node, , start, start + rule.prefix.length
.selectText , rule.prefix.length
matchToken: ->
return unless .parentNode
token = .textContent.substring .prefix.length
return if /\s/.test token
return if token is
= token
if token.trim()
{dataSource} =
dataSource token, 'showMenu'
else if token.length isnt 0
sanitizeInput: ->
showMenu:(options = {}, data)->
?.destroy()
= null
return unless and data.length
pos = .getBoundingClientRect()
options.x ?= pos.left
options.y ?= pos.top + parseInt window.getComputedStyle( ).lineHeight, 10
= new KDContextMenu options, data
.on 'ContextMenuItemReceivedClick', 'menuItemClicked'
hideMenu: ->
?.destroy()
= null
= null
= null
menuItemClicked: (item, tokenViewClass) ->
item.data, tokenViewClass
addToken: (item, tokenViewClass = .tokenViewClass) ->
{type, prefix, pistachio} =
tokenView = new tokenViewClass {type, prefix, pistachio}, item
tokenElement = tokenView.getElement()
tokenKey = "#{tokenView.getId()}-#{tokenView.getKey()}"
[tokenKey] = tokenView
tokenView.setAttributes "data-key": tokenKey
.parentElement.insertBefore tokenElement,
tokenView.emit "viewAppended"
.nextSibling.textContent = "\u00a0"
.selectText .nextSibling, 1
.remove()
"TokenAdded", type, item
keyDown: (event) ->
switch event.which
when 9, 13, 27, 38, 40 # enter, tab, escape, up, down
if
.treeController.keyEventHappened event
KD.utils.stopDOMEvent event
else
super event
switch event.which
when 27 then if
keyUp: (event) ->
super
switch event.which
when 9, 13, 27, 38, 40 # enter, tab, escape, up, down
else
return if event.altKey or event.ctrlKey or event.metaKey
if then
else
cancel: ->
if .parentNode
text = document.createTextNode .textContent
.parentElement.insertBefore text,
.nextSibling.remove()
.remove()
.selectEnd text
reset: ->
for own id, view of
view.destroy()
delete [id]
viewAppended: ->
super
on