-
Notifications
You must be signed in to change notification settings - Fork 5
/
transitions.coffee
129 lines (102 loc) · 3.78 KB
/
transitions.coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
ENDTRANSITION = 'transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd transitionEnd msTransitionEnd animationend webkitAnimationEnd oAnimationEnd MSAnimationEnd animationEnd msAnimationEnd'
class Transitions
constructor: (options) ->
defaults =
onScreenClass: ''
offScreenClass: ''
hiddenClass: 'out'
animateClass: "animated"
@opt = _.defaults options, defaults
@opt.insertTimeout = @getInsertTimeout()
@opt.removeTimeout = @getRemoveTimeout()
@opt.parentNode._uihooks = @createHooks()
self = @
@setupStyles()
# This for when the page first loads
_.each $(@opt.parentNode).find('.animated.out'), (item) ->
self.insertElement(item, null)
setupStyles: ->
if @opt.inDuration or @opt.outDuration
# For durations to be changed we need to inject CSS
randName = @opt.onScreenClass + _.random(0, 1000)
styleInjection = $("<style></style>")
$(@opt.parentNode).addClass(randName)
if @opt.inDuration
styleInjection.append(".#{randName} .animated.#{@opt.onScreenClass} {-webkit-animation-duration: #{@opt.inDuration}ms;animation-duration: #{@opt.inDuration}ms;}")
if @opt.outDuration
styleInjection.append(".#{randName} .animated.#{@opt.offScreenClass} {-webkit-animation-duration: #{@opt.outDuration}ms;animation-duration: #{@opt.outDuration}ms;}")
$(@opt.parentNode).append(styleInjection)
getInsertTimeout: ->
return parseInt(@opt.inDuration) if @opt.inDuration
switch @opt.onScreenClass
when 'hinge' then 2000
when 'bounceIn' then 750
else 1000
getRemoveTimeout: ->
return parseInt(@opt.outDuration) if @opt.outDuration
switch @opt.offScreenClass
when 'hinge' then 2000
when 'bounceOut' then 750
when 'flipOutX' then 750
when 'flipOutY' then 750
else 1000
insertElement: (node, next) ->
self = @
$node = $(node)
$parent = $(self.opt.parentNode)
$node.addClass("#{self.opt.animateClass} #{self.opt.hiddenClass}")
$node.attr('hidden', true)
$(next).before($node)
finish = (e) ->
$node.removeClass(self.opt.onScreenClass)
node.setAttribute('inserting', false)
insert = ->
$node.width()
$node.attr('hidden', false)
$node.removeClass(self.opt.hiddenClass)
$node.addClass(self.opt.onScreenClass)
$node.one ENDTRANSITION, finish
if self.removing
Meteor.setTimeout insert, self.opt.removeTimeout
else
insert()
removeElement: (node) ->
$node = $(node)
self = @
$node.addClass(self.opt.animateClass)
remove = (e) ->
self.removing = false
$node.remove()
if self.opt.offScreenClass
$node.addClass(self.opt.offScreenClass)
self.removing = true
$node.one ENDTRANSITION, remove
else
remove()
createHooks: ->
opt: @opt
insertElement: @insertElement
removeElement: @removeElement
Template.transition.onRendered ->
transitionIn = @data?.in?.match(/^(.*)\:/)?[1] || @data?.in
transitionOut = @data?.out?.match(/^(.*)\:/)?[1] || @data?.out
# Duration can be passed in like this:
# in="bounceIn:500"
# 500 means 500 milliseconds
inDuration = @data?.in?.match(/\:(\d*)/)?[1]
outDuration = @data?.out?.match(/\:(\d*)/)?[1]
# If "wrap=true" is provided, then div.transition-wrapper will
# be the parent. Else just whatever is the parent above this template.
if @$('>').first().hasClass('transition-wrapper')
parentNode = @$('>').first()[0]
else
parentNode = @firstNode?.parentNode
params =
onScreenClass: transitionIn
offScreenClass: transitionOut
inDuration: inDuration
outDuration: outDuration
parentNode: parentNode
transitions = new Transitions(params)
Template.transition.onDestroyed ->
@firstNode?.parentNode?._uihooks = null