kd-contextmenu
Version:
contextmenu module for kd
156 lines (116 loc) • 4.36 kB
text/coffeescript
KDView = require 'core/View'
KDCustomHTMLView = require 'core/CustomHTMLView'
JContextMenuTreeViewController = require './JContextMenuTreeViewController'
module.exports = class KDContextMenu extends KDView
constructor:(options = {}, data)->
options.cssClass = .curry "kdcontextmenu", options.cssClass
options.menuMaxWidth or= "auto"
options.menuMinWidth or= "auto"
options.menuWidth or= 172
options.offset or= {}
options.offset.left or= 0
options.offset.top or= 0
options.arrow ?= no
options.sticky ?= no
super options, data
= 0
= 0
o =
= o.sticky
KD.getSingleton("windowController").addLayer @
'ReceivedClickElsewhere', => unless
if data
= new JContextMenuTreeViewController
type : o.type
view : o.view
delegate : @
treeItemClass : o.treeItemClass
listViewClass : o.listViewClass
itemChildClass : o.itemChildClass
itemChildOptions : o.itemChildOptions
addListsCollapsed : o.addListsCollapsed
putDepthInfo : o.putDepthInfo
lazyLoad : o.lazyLoad ? no
, data
.getView()
.getView().on 'ReceivedClickElsewhere', => unless
.on "NodeExpanded", "positionSubMenu"
if options.arrow
"viewAppended", "addArrow"
changeStickyState: (state)-> = state
childAppended:->
super
if "deferPositioning"
KD.utils.defer =>
else
addArrow:->
o = .arrow
o.placement or= "top"
o.margin ?= 0
if o.placement in ['top', 'bottom']
o.margin +=
else
o.margin +=
= new KDCustomHTMLView
tagName : "span"
cssClass : "arrow #{o.placement}"
.$().css switch o.placement
when "top"
rule = {}
if o.margin > 0 then rule.left = o.margin else rule.right = -(o.margin)
rule
when "bottom"
rule = {}
if o.margin > 0 then rule.left = o.margin else rule.right = -(o.margin)
rule
when "right"
rule = {}
if o.margin > 0 then rule.top = o.margin else rule.bottom = -(o.margin)
rule
when "left"
rule = {}
if o.margin > 0 then rule.top = o.margin else rule.bottom = -(o.margin)
rule
else {}
positionContextMenu: KD.utils.debounce 10, ->
options =
event = options.event or {}
mainView = KD.getSingleton 'mainView'
mainHeight = mainView.getHeight()
mainWidth = mainView.getWidth()
{ menuWidth, menuHeight, menuMaxWidth, menuMinWidth } = options
menuHeight ?=
menuWidth ?=
top = (options.y or event.pageY or 0) + options.offset.top
left = (options.x or event.pageX or 0) + options.offset.left
expectedTop = top
expectedLeft = left
if top + menuHeight > mainHeight
top = mainHeight - menuHeight + options.offset.top
if left + menuWidth > mainWidth
left = mainWidth - menuWidth + options.offset.left
= expectedTop - top
= expectedLeft - left
style =
width : "#{menuWidth}px"
top : top
left : left
if menuMaxWidth
style.maxWidth = "#{menuMaxWidth}px"
style.minWidth = "#{menuMinWidth}px" if menuMinWidth
.css style
positionSubMenu: (nodeView)->
{children, id} = nodeView.getData()
if children
expandView = .listControllers[id].getView()
fullViewHeight = expandView.getY() + expandView.getHeight()
if fullViewHeight > window.innerHeight
expandView.$().css "bottom", 0
fullViewWidth = expandView.getX() + expandView.getWidth()
if fullViewWidth > window.innerWidth
expandView.$().css "left", - expandView.getWidth()
expandView.setClass "left-aligned"