luda
Version:
A library helps to build cross-framework UI components.
204 lines (178 loc) • 6.88 kB
text/coffeescript
import '../kernel/index.coffee'
luda.mixin 'tabable',
# cls:
# tabable:
# active: string # required
# indicatorActive: string # required
# prev: string # optional
# next: string # optional
# data:
# tabable:
# interruption: string # required
# wrap: string # optional
# default:
# tabable:
# activeIndex: integer # optional
# wrap: boolean # optional
# evt:
# tabable:
# activate: string #required
# activated: string #required
# deactivate: string #required
# deactivated: string #required
# selector:
# tabable:
# targets: string # required
# indicators: string # required
# prevCtrl: string # optional
# nextCtrl: string # optional
tabableActiveIndex: ->
index = ?.tabable?.activeIndex or 0
.els.some (it, i) =>
return false unless luda(it).hasClass .tabable.active
index = i
true
index
tabableWrapable: ->
wrapAttr = .tabable.wrap
return false unless wrapAttr
wrapable = .data wrapAttr
return false if wrapable is false
?.tabable?.wrap
tabableActivate: (index) ->
return unless luda.isNumeric index
direction = if index < then 'prev' else 'next'
index, direction
tabableNext: ->
index = + 1
if index >= .length
return unless
index = 0
index, 'next'
tabablePrev: ->
index = - 1
if index < 0
return unless
index = .length - 1
index, 'prev'
tabableLayout: ->
.els.forEach (it, index) =>
item = luda it
return if (activeCls = .tabable.active) and item.hasClass activeCls
return if (nextCls = .tabable.next) and item.hasClass nextCls
return if (prevCls = .tabable.prev) and item.hasClass prevCls
isActive = index is
item.css('transition', 'none')
.toggleClass(activeCls, isActive)
.toggleClass(prevCls, index < )
.toggleClass(nextCls, index > )
.reflow().css('transition', '')
isActive and item.trigger .tabable.activated
tabableSlide: (index, direction) ->
return unless luda.isNumeric index
return if index is (activatedIndex = )
return if index < 0 or index >= .length
item = .eq index
activated = .eq activatedIndex
activateEvt = item.trigger( .tabable.activate, null, true)[0]
return if activateEvt.isDefaultPrevented()
deactivateEvt = activated.trigger( .tabable.deactivate, null, true)[0]
return if deactivateEvt.isDefaultPrevented()
oppsite = if direction is 'next' then 'prev' else 'next'
directionCls = .tabable[direction]
oppsiteCls = .tabable[oppsite]
activeCls = .tabable.active
item.css('transition', 'none')
.addClass(directionCls).removeClass(oppsiteCls)
.reflow().css('transition', '')
.addClass(activeCls).removeClass(directionCls)
activated.addClass(oppsiteCls).removeClass(activeCls)
= setTimeout =>
delete
item.trigger .tabable.activated
, item.transitionDuration()
= activatedIndex
= setTimeout =>
delete
delete
activated.trigger .tabable.deactivated
, activated.transitionDuration()
true
tabableTransitioning: ->
'tabableActivating' of this or 'tabableDeactivating' of this
tabableSetIndicatorsState: ->
.els.forEach (it, index) =>
activeCls = .tabable.indicatorActive
val = index is
luda(it).toggleClass activeCls, val
tabableSetDirectionCtrlsState: ->
prevCtrl =
nextCtrl =
return unless prevCtrl or nextCtrl
if .length <= 1
prevDis = nextDis = ''
else if
prevDis = nextDis = null
else
index =
minIndex = 0
maxIndex = .length - 1
prevDis = if index is minIndex then '' else null
nextDis = if index is maxIndex then '' else null
prevCtrl and prevCtrl.attr 'disabled', prevDis
nextCtrl and nextCtrl.attr 'disabled', nextDis
tabableActivateOnEvent: (e) ->
return if
index = e.detail?.tabable?.activeIndex
unless index?
index = .els.indexOf e.currentTarget
index
tabablePrevOnEvent: (e) -> unless
tabableNextOnEvent: (e) -> unless
tabableDestroy: ->
if 'tabableActivating' of this
clearTimeout
interruption = {activate: }
if 'tabableDeactivating' of this
clearTimeout
interruption ||= {}
interruption.deactivateIndex =
.data .tabable.interruption, interruption
tabableCreate: ->
dataAttr = .tabable.interruption
return unless interruption = .data dataAttr
if (activate = interruption.activated)?
.eq(activated).trigger .tabable.activated
if (deactive = interruption.deactivated)?
.eq(deactivated).trigger .tabable.deactivated
.removeData dataAttr
tabableFind: ->
conf =
tabableTargets: .tabable.targets
tabableIndicators: .tabable.indicators
conf.tabablePrevCtrl = prevCtrl if prevCtrl = .tabable.prevCtrl
conf.tabableNextCtrl = nextCtrl if nextCtrl = .tabable.nextCtrl
conf
tabableWatch: ->
attr = []
wrapAttr = .tabable.wrap
wrapAttr and attr.push [wrapAttr, ]
attr: attr
node: [
[ .tabable.targets, ]
[ .tabable.indicators, ]
]
tabableListen: ->
listeners = [
['click', .tabable.indicators, ]
]
if prevCtrl = .tabable.prevCtrl
listeners.push ['click', prevCtrl, ]
if nextCtrl = .tabable.nextCtrl
listeners.push ['click', nextCtrl, ]
listeners