UNPKG

kdf

Version:

KD: a non-document focused UI Framework for web applications.

369 lines (246 loc) 9.42 kB
KD = require './../../core/kd.coffee' KDView = require './../../core/view.coffee' KDSplitViewPanel = require './splitpanel.coffee' KDSplitResizer = require './splitresizer.coffee' module.exports = class KDSplitView extends KDView constructor: (options = {}, data) -> options.type or= "vertical" # "vertical" or "horizontal" options.resizable ?= yes # yes or no options.sizes or= [.5, .5] # an Array of Strings such as ["50%","50%"] or ["500px","150px",null] and null for the available rest area options.minimums or= [0, 0] # an Array of Strings options.maximums or= ['100%', '100%'] # an Array of Strings options.views or= [] # an Array of KDViews options.fixed or= [] # an Array of Booleans options.duration or= 200 # a Number in miliseconds options.separator or= null # a KDView instance or null for default separator options.colored ?= no # a Boolean options.resizeHandleSize or= 2 # a Number options.type = options.type.toLowerCase() options.cssClass = KD.utils.curry "kdsplitview kdsplitview-#{options.type}", options.cssClass super options,data {@type, @resizable} = @getOptions() @panels = [] @resizer = null @sizes = [] @minimums = [] @maximums = [] @size = 0 viewAppended:-> @_calculateSizes() @_createPanels() @_putPanels() @_resizePanels() @_putViews() @_createResizer() if @resizable and @panels[1] @listenWindowResize() @parent?.on "PanelDidResize", KD.utils.debounce 10, @bound '_windowDidResize' _createPanels:-> @_createPanel 0 @_createPanel 1 if @sizes[1]? _createPanel:(index)-> {fixed, panelClass} = @getOptions() panel = new (panelClass or KDSplitViewPanel) cssClass : "kdsplitview-panel panel-#{index}" index : index type : @type size : @sizes[index] fixed : !!fixed[index] panel.on "KDObjectWillBeDestroyed", => @_panelIsBeingDestroyed panel @emit "SplitPanelCreated", panel @panels[index] = panel return panel _putPanels:-> @addSubView @panels[0] @addSubView @panels[1] if @getOptions().colored @panels[0].setCss backgroundColor : KD.utils.getRandomRGB() @panels[1].setCss backgroundColor : KD.utils.getRandomRGB() _resizePanels:-> @resizePanel @sizes[0] _panelIsBeingDestroyed:(panel)-> {views} = @getOptions() {index} = panel @panels[index] = null @sizes[index] = null @minimums[index] = null @maximums[index] = null views[index] = null _createResizer:-> {type, resizeHandleSize} = @getOptions() @resizer = @addSubView new KDSplitResizer cssClass : "kdsplitview-resizer #{type}" type : @type panel0 : @panels[0] panel1 : @panels[1] handleSize : resizeHandleSize @_repositionResizer() _repositionResizer:-> @resizer._setOffset @sizes[0] _putViews:-> {views} = @getOptions() return unless views @setView views[0], 0 if views[0] @setView views[1], 1 if views[1] _calculateSizes:-> @_setMinsAndMaxs() {sizes} = @getOptions() givenSizes = sizes splitSize = @_getSize() legitSizes = [] legitSizes[0] = @_getLegitPanelSize @_sanitizeSize(givenSizes[0]), 0 legitSizes[1] = @_getLegitPanelSize @_sanitizeSize(givenSizes[1]), 1 totalSize = legitSizes[0] + legitSizes[1] if totalSize > splitSize legitSizes[1] = splitSize - legitSizes[0] else if totalSize < splitSize if givenSizes[0] and (not givenSizes[1] or givenSizes[1] is 'auto') legitSizes[1] = splitSize - legitSizes[0] else if givenSizes[1] and (not givenSizes[0] or givenSizes[0] is 'auto') legitSizes[0] = splitSize - legitSizes[1] @size = splitSize @sizes = legitSizes _sanitizeSize: (size) -> return if "number" is typeof size if 1 > size > 0 then @_getSize() * size else size else if /px$/.test size then parseInt size, 10 else if /%$/.test size then @_getSize() / 100 * parseInt size, 10 else null _setMinsAndMaxs:-> {minimums, maximums} = @getOptions() @minimums[0] = @_sanitizeSize minimums[0] @minimums[1] = @_sanitizeSize minimums[1] @maximums[0] = @_sanitizeSize maximums[0] @maximums[1] = @_sanitizeSize maximums[1] _getSize:-> if @size then @size else if @isVertical() then @getWidth() else @getHeight() _setSize:(size)-> if @isVertical() then @setWidth size else @setHeight size _getParentSize:-> if @isVertical() if @parent and @parent.isInDom() then @parent.getWidth() else window.innerWidth else if @parent and @parent.isInDom() then @parent.getHeight() else window.innerHeight _getLegitPanelSize: (size, index) -> min = @minimums[index] or 0 max = @maximums[index] or @_getSize() return Math.min Math.max(min, size), max _windowDidResize: -> @size = null @_setSize @_getParentSize() @_calculateSizes() @_resizePanels() # find a way to do that for when parent get resized and split reachs a min-width # if @getWidth() > @_getParentSize() then @setClass "min-width-reached" else @unsetClass "min-width-reached" @_repositionResizer() if @resizable mouseUp: (event) -> @$().unbind "mousemove.resizeHandle" _panelReachedMinimum:(index)-> panel = @panels[index] panel.emit "PanelReachedMinimum" @emit "PanelReachedMinimum", {panel} _panelReachedMaximum:(index)-> panel = @panels[index] panel.emit "PanelReachedMaximum" @emit "PanelReachedMaximum", {panel} _resizeDidStart:(event)-> @emit "ResizeDidStart", event document.body.classList.add "resize-in-action" _resizeDidStop: do -> unsetResizeInAction = KD.utils.throttle 1000, (view)-> document.body.classList.remove "resize-in-action" (event)-> s1 = @sizes[0]/@_getSize() s2 = @sizes[1]/@_getSize() @setOption 'sizes', [s1, s2] @emit "ResizeDidStop", event unsetResizeInAction this isVertical:-> @type is "vertical" getPanelIndex: (panel)-> panel.index hidePanel: (index, callback = noop)-> panel = @panels[index] panel._lastSize = panel._getSize() if panel.isFloating panel.setCss "width", 0 callback { panel, index } else @resizePanel 0, index, callback.bind this, { panel, index } showPanel: (index, callback = noop) -> panel = @panels[index] newSize = panel._lastSize or @sizes[index] or 200 panel._lastSize = null if panel.isFloating panel.setCss 'width', newSize left = panel.getRelativeX() panel.setCss 'left', left - newSize if left > 0 KD.getSingleton('windowController').addLayer panel panel.once 'ReceivedClickElsewhere', => @hidePanel index callback { panel, index } else @resizePanel newSize, index, callback.bind this, { panel, index } setFloatingPanel: (index, size = 0) -> panel = @panels[index] panel.setClass 'floating' panel.isFloating = yes panel._lastSize = panel._getSize() @resizePanel size, index @emit 'PanelSetToFloating', panel unsetFloatingPanel: (index) -> panel = @panels[index] delete panel.isFloating panel.unsetClass 'floating' @showPanel index @emit 'PanelSetToNormal', panel resizePanel:(value = 0, index = 0, callback = noop, forceResize = no)-> return unless @sizes[1]? return if @beingResized @_resizeDidStart() value = @_sanitizeSize value value = @_getSize() if value > @_getSize() askedPanel = @panels[index] affectedPanel = @panels[(index + 1) % 2] if askedPanel._getSize() is value and not forceResize @_resizeDidStop() callback() return @beingResized = yes value = @_getLegitPanelSize value, index sizes = [value, @_getSize() - value] offset = if index then sizes[1] else sizes[0] askedPanel._setSize sizes[0] affectedPanel._setSize sizes[1] @panels[1]._setOffset offset @resizer._setOffset offset if @resizer @_resizeDidStop() @beingResized = no merge: -> {views} = @getOptions() @getOptions().views = [] views.forEach (view, i) => return unless view view.detach() view.unsetParent() @panels[i].subViews = [] @emit "SplitIsBeingMerged", views @destroy() removePanel:(index)-> setView: (view, index) -> return warn "view is missing at KDSplitView::setView" unless view return warn "index is missing at KDSplitView::setView" if index > @panels.length return warn "index is missing at KDSplitView::setView" unless view instanceof KDView @panels[index].addSubView view # deprecated methods deprecated = -> warn 'deprecated method invoked' _repositionPanels: deprecated _repositionResizers: deprecated _setPanelPositions: deprecated