forked from jlmakes/scrollreveal
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathreveal.js
More file actions
150 lines (132 loc) · 3.88 KB
/
reveal.js
File metadata and controls
150 lines (132 loc) · 3.88 KB
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
import tealight from 'tealight'
import deepAssign from '../../utils/deep-assign'
import each from '../../utils/each'
import isMobile from '../../utils/is-mobile'
import logger from '../../utils/logger'
import nextUniqueId from '../../utils/next-unique-id'
import defaults from '../defaults'
import initialize from '../functions/initialize'
import { Sequence } from '../functions/sequence'
import style, { applyStyle } from '../functions/style'
import clean from '../methods/clean'
export default function reveal(target, options = {}, syncing = false) {
const containerBuffer = []
let sequence
let interval = options.interval || defaults.interval
try {
if (interval) {
sequence = new Sequence(interval)
}
const nodes = tealight(target)
if (!nodes.length) {
throw new Error('Invalid reveal target.')
}
const elements = nodes.reduce((elementBuffer, elementNode) => {
const element = {}
const existingId = elementNode.getAttribute('data-sr-id')
if (existingId) {
deepAssign(element, this.store.elements[existingId])
/**
* In order to prevent previously generated styles
* from throwing off the new styles, the style tag
* has to be reverted to its pre-reveal state.
*/
applyStyle(element.node, element.styles.inline.computed)
} else {
element.id = nextUniqueId()
element.node = elementNode
element.seen = false
element.revealed = false
element.visible = false
}
const config = deepAssign({}, element.config || this.defaults, options)
if ((!config.mobile && isMobile()) || (!config.desktop && !isMobile())) {
if (existingId) {
clean.call(this, element)
}
return elementBuffer // skip elements that are disabled
}
const containerNode = tealight(config.container)[0]
if (!containerNode) {
throw new Error('Invalid container.')
}
if (!containerNode.contains(elementNode)) {
return elementBuffer // skip elements found outside the container
}
let containerId
{
containerId = getContainerId(
containerNode,
containerBuffer,
this.store.containers
)
if (containerId === null) {
containerId = nextUniqueId()
containerBuffer.push({ id: containerId, node: containerNode })
}
}
element.config = config
element.containerId = containerId
element.styles = style(element)
if (sequence) {
element.sequence = {
id: sequence.id,
index: sequence.members.length
}
sequence.members.push(element.id)
}
elementBuffer.push(element)
return elementBuffer
}, [])
/**
* Modifying the DOM via setAttribute needs to be handled
* separately from reading computed styles in the map above
* for the browser to batch DOM changes (limiting reflows)
*/
each(elements, element => {
this.store.elements[element.id] = element
element.node.setAttribute('data-sr-id', element.id)
})
} catch (e) {
return logger.call(this, 'Reveal failed.', e.message)
}
/**
* Now that element set-up is complete...
* Let’s commit any container and sequence data we have to the store.
*/
each(containerBuffer, container => {
this.store.containers[container.id] = {
id: container.id,
node: container.node
}
})
if (sequence) {
this.store.sequences[sequence.id] = sequence
}
/**
* If reveal wasn't invoked by sync, we want to
* make sure to add this call to the history.
*/
if (syncing !== true) {
this.store.history.push({ target, options })
/**
* Push initialization to the event queue, giving
* multiple reveal calls time to be interpreted.
*/
if (this.initTimeout) {
window.clearTimeout(this.initTimeout)
}
this.initTimeout = window.setTimeout(initialize.bind(this), 0)
}
}
function getContainerId(node, ...collections) {
let id = null
each(collections, collection => {
each(collection, container => {
if (id === null && container.node === node) {
id = container.id
}
})
})
return id
}