scrollreveal
Version:
Easy scroll animations for web and mobile browsers.
1,108 lines (914 loc) • 28.6 kB
JavaScript
var ScrollReveal = (function () {
;
var defaults = {
origin: 'bottom',
distance: '0',
duration: 600,
delay: 0,
rotate: {
x: 0,
y: 0,
z: 0,
},
opacity: 0,
scale: 1,
easing: 'cubic-bezier(0.6, 0.2, 0.1, 1)',
container: document.documentElement,
desktop: true,
mobile: true,
reset: false,
useDelay: 'always',
viewFactor: 0.0,
viewOffset: {
top: 0,
right: 0,
bottom: 0,
left: 0,
},
beforeReveal: function beforeReveal () {},
beforeReset: function beforeReset () {},
afterReveal: function afterReveal () {},
afterReset: function afterReset () {},
};
var noop = {
destroy: function destroy () {},
reveal: function reveal () {},
sync: function sync () {},
get noop () { return true },
};
function deepAssign (target) {
var sources = [], len = arguments.length - 1;
while ( len-- > 0 ) sources[ len ] = arguments[ len + 1 ];
if (isObject(target)) {
each(sources, function (source) {
each(source, function (data, key) {
if (isObject(data)) {
if (!target[key] || !isObject(target[key])) {
target[key] = {};
}
deepAssign(target[key], data);
} else {
target[key] = data;
}
});
});
return target
} else {
throw new TypeError('Expected an object literal.')
}
}
function isObject (object) {
return object !== null && typeof object === 'object'
&& (object.constructor === Object || Object.prototype.toString.call(object) === '[object Object]')
}
function each (collection, callback) {
if (isObject(collection)) {
var keys = Object.keys(collection);
for (var i = 0; i < keys.length; i++) {
callback(collection[ keys[i] ], keys[i], collection);
}
} else if (Array.isArray(collection)) {
for (var i$1 = 0; i$1 < collection.length; i$1++) {
callback(collection[i$1], i$1, collection);
}
} else {
throw new TypeError('Expected either an array or object literal.')
}
}
var nextUniqueId = (function () {
var uid = 0;
return function () { return uid++; }
})();
function destroy () {
var this$1 = this;
/**
* Remove all generated styles and element ids
*/
each(this.store.elements, function (element) {
element.node.setAttribute('style', element.styles.inline);
element.node.removeAttribute('data-sr-id');
});
/**
* Remove all event listeners.
*/
each(this.store.containers, function (container) {
if (container.node === document.documentElement) {
window.removeEventListener('scroll', this$1.delegate);
window.removeEventListener('resize', this$1.delegate);
} else {
container.node.removeEventListener('scroll', this$1.delegate);
container.node.removeEventListener('resize', this$1.delegate);
}
});
/**
* Clear all data from the store
*/
this.store = {
containers: {},
elements: {},
history: [],
sequences: {},
};
}
/**
* Transformation matrices in the browser come in two flavors:
*
* - Long (3D) transformation matrix with 16 values
* - Short (2D) transformation matrix with 6 values
*
* This utility follows this conversion Guide: https://goo.gl/EJlUQ1
* to expand short form matrices to their equivalent long form.
*
* @param {array} source
* @return {array}
*/
function format (source) {
if (source.constructor !== Array) { throw new TypeError('Expected array.') }
if (source.length === 16) { return source }
if (source.length === 6) {
var matrix = identity();
matrix[0] = source[0];
matrix[1] = source[1];
matrix[4] = source[2];
matrix[5] = source[3];
matrix[12] = source[4];
matrix[13] = source[5];
return matrix
}
throw new RangeError('Expected array with either 6 or 16 values.')
}
function identity () {
var matrix = [];
for (var i = 0; i < 16; i++) {
i % 5 == 0 ? matrix.push(1) : matrix.push(0);
}
return matrix
}
function multiply (m, x) {
if (m.length !== 16 || x.length !== 16) {
throw new RangeError('Expected arrays with 16 values.')
}
var sum = [];
for (var i = 0; i < 4; i++) {
var row = [m[i], m[i + 4], m[i + 8], m[i + 12]];
for (var j = 0; j < 4; j++) {
var k = j * 4;
var col = [x[k], x[k + 1], x[k + 2], x[k + 3]];
var result = row[0] * col[0] + row[1] * col[1] + row[2] * col[2] + row[3] * col[3];
sum[i + k] = parseFloat(result.toPrecision(6));
}
}
return sum
}
function rotateX (theta) {
var angle = Math.PI / 180 * theta;
var matrix = identity();
matrix[5] = matrix[10] = Math.cos(angle);
matrix[6] = matrix[9] = Math.sin(angle);
matrix[9] *= -1;
return matrix
}
function rotateY (theta) {
var angle = Math.PI / 180 * theta;
var matrix = identity();
matrix[0] = matrix[10] = Math.cos(angle);
matrix[2] = matrix[8] = Math.sin(angle);
matrix[2] *= -1;
return matrix
}
function rotateZ (theta) {
var angle = Math.PI / 180 * theta;
var matrix = identity();
matrix[0] = matrix[5] = Math.cos(angle);
matrix[1] = matrix[4] = Math.sin(angle);
matrix[4] *= -1;
return matrix
}
function scale (scalar) {
var matrix = identity();
matrix[0] = matrix[5] = scalar;
return matrix
}
function translateX (distance) {
var matrix = identity();
matrix[12] = distance;
return matrix
}
function translateY (distance) {
var matrix = identity();
matrix[13] = distance;
return matrix
}
var matrix = Object.freeze({
format: format,
identity: identity,
multiply: multiply,
rotateX: rotateX,
rotateY: rotateY,
rotateZ: rotateZ,
scale: scale,
translateX: translateX,
translateY: translateY
});
var getPrefixedStyleProperty = (function () {
var properties = {};
var style = document.documentElement.style;
function getPrefixedStyleProperty (name, source) {
if ( source === void 0 ) source = style;
if (name && typeof name === 'string') {
if (properties[name]) {
return properties[name]
}
if (typeof source[name] === 'string') {
return properties[name] = name
}
if (typeof source[("-webkit-" + name)] === 'string') {
return properties[name] = "-webkit-" + name
}
throw new RangeError(("Unable to find \"" + name + "\" style property."))
}
throw new TypeError('Expected a string.')
}
getPrefixedStyleProperty.clearCache = function () { return properties = {}; };
return getPrefixedStyleProperty
})();
function isMobile (agent) {
if ( agent === void 0 ) agent = navigator.userAgent;
return /Android|iPhone|iPad|iPod/i.test(agent)
}
function isNode (target) {
return typeof window.Node === 'object'
? target instanceof window.Node
: target !== null
&& typeof target === 'object'
&& typeof target.nodeType === 'number'
&& typeof target.nodeName === 'string'
}
function isNodeList (target) {
var prototypeToString = Object.prototype.toString.call(target);
var regex = /^\[object (HTMLCollection|NodeList|Object)\]$/;
return typeof window.NodeList === 'object'
? target instanceof window.NodeList
: typeof target === 'object'
&& typeof target.length === 'number'
&& regex.test(prototypeToString)
&& (target.length === 0 || isNode(target[0]))
}
function transformSupported () {
var style = document.documentElement.style;
return 'transform' in style || 'WebkitTransform' in style
}
function transitionSupported () {
var style = document.documentElement.style;
return 'transition' in style || 'WebkitTransition' in style
}
function style (element) {
var computed = window.getComputedStyle(element.node);
var position = computed.position;
var config = element.config;
/**
* Generate inline styles
*/
var inlineRegex = /.+[^;]/g;
var inlineStyle = element.node.getAttribute('style') || '';
var inlineMatch = inlineRegex.exec(inlineStyle);
var inline = (inlineMatch) ? ((inlineMatch[0]) + ";") : '';
if (inline.indexOf('visibility: visible') === -1) {
inline += (inline.length) ? ' ' : '';
inline += 'visibility: visible;';
}
/**
* Generate opacity styles
*/
var computedOpacity = parseFloat(computed.opacity);
var configOpacity = !isNaN(parseFloat(config.opacity))
? parseFloat(config.opacity)
: parseFloat(computed.opacity);
var opacity = {
computed: (computedOpacity !== configOpacity) ? ("opacity: " + computedOpacity + ";") : '',
generated: (computedOpacity !== configOpacity) ? ("opacity: " + configOpacity + ";") : '',
};
/**
* Generate transformation styles
*/
var transformations = [];
if (parseFloat(config.distance)) {
var axis = (config.origin === 'top' || config.origin === 'bottom') ? 'Y' : 'X';
/**
* Let’s make sure our our pixel distances are negative for top and left.
* e.g. { origin: 'top', distance: '25px' } starts at `top: -25px` in CSS.
*/
var distance = config.distance;
if (config.origin === 'top' || config.origin === 'left') {
distance = /^-/.test(distance)
? distance.substr(1)
: ("-" + distance);
}
var ref = distance.match(/(^-?\d+\.?\d?)|(em$|px$|\%$)/g);
var value = ref[0];
var unit = ref[1];
switch (unit) {
case 'em':
distance = parseInt(computed.fontSize) * value;
break
case 'px':
distance = value;
break
case '%':
distance = (axis === 'Y')
? element.node.getBoundingClientRect().height * value / 100
: element.node.getBoundingClientRect().width * value / 100;
break
default:
throw new RangeError('Unrecognized or missing distance unit.')
}
transformations.push(matrix[("translate" + axis)](distance));
}
if (config.rotate.x) { transformations.push(rotateX(config.rotate.x)); }
if (config.rotate.y) { transformations.push(rotateY(config.rotate.y)); }
if (config.rotate.z) { transformations.push(rotateZ(config.rotate.z)); }
if (config.scale !== 1) { transformations.push(scale(config.scale)); }
var transform = {};
if (transformations.length) {
var transformProperty = getPrefixedStyleProperty('transform');
transform.property = transformProperty;
transform.computed = {
raw: computed[transformProperty],
};
/**
* The default computed transform value should be one of:
* undefined || 'none' || 'matrix()' || 'matrix3d()'
*/
if (transform.computed.raw === 'none') {
transform.computed.matrix = identity();
} else {
var match = transform.computed.raw.match(/\(([^)]+)\)/);
if (match) {
var values = match[1].split(', ').map(function (value) { return parseFloat(value); });
transform.computed.matrix = format(values);
} else {
throw new RangeError('Unrecognized computed transform property value.')
}
}
transformations.unshift(transform.computed.matrix);
var product = transformations.reduce(function (m, x) { return multiply(m, x); });
transform.generated = {
initial: ((transform.property) + ": matrix3d(" + (product.join(', ')) + ");"),
final: ((transform.property) + ": matrix3d(" + (transform.computed.matrix.join(', ')) + ");"),
};
} else {
transform.generated = {
initial: '',
final: '',
};
}
/**
* Generate transition styles
*/
var transition;
if (opacity.generated || transform.generated.initial) {
var transitionProperty = getPrefixedStyleProperty('transition');
transition = {
computed: computed[transitionProperty],
fragments: [],
property: transitionProperty,
};
var delay = config.delay;
var duration = config.duration;
var easing = config.easing;
if (opacity.generated) {
transition.fragments.push({
delayed: ("opacity " + (duration / 1000) + "s " + easing + " " + (delay / 1000) + "s"),
instant: ("opacity " + (duration / 1000) + "s " + easing + " 0s"),
});
}
if (transform.generated.initial) {
transition.fragments.push({
delayed: ((transform.property) + " " + (duration / 1000) + "s " + easing + " " + (delay / 1000) + "s"),
instant: ((transform.property) + " " + (duration / 1000) + "s " + easing + " 0s"),
});
}
/**
* The default computed transition property should be one of:
* undefined || '' || 'all 0s ease 0s' || 'all 0s 0s cubic-bezier()'
*/
if (transition.computed && !transition.computed.match(/all 0s/)) {
transition.fragments.unshift({
delayed: transition.computed,
instant: transition.computed,
});
}
var composed = transition.fragments.reduce(function (composition, fragment, i) {
composition.delayed += (i === 0) ? fragment.delayed : (", " + (fragment.delayed));
composition.instant += (i === 0) ? fragment.instant : (", " + (fragment.instant));
return composition
}, {
delayed: '',
instant: '',
});
transition.generated = {
delayed: ((transition.property) + ": " + (composed.delayed) + ";"),
instant: ((transition.property) + ": " + (composed.instant) + ";"),
};
}
return {
inline: inline,
opacity: opacity,
position: position,
transform: transform,
transition: transition,
}
}
function initialize () {
var this$1 = this;
var activeContainerIds = [];
var activeSequenceIds = [];
each(this.store.elements, function (element) {
if (activeContainerIds.indexOf(element.containerId) === -1) {
activeContainerIds.push(element.containerId);
}
if (element.sequence && activeSequenceIds.indexOf(element.sequence.id) === -1) {
activeSequenceIds.push(element.sequence.id);
}
var styles = [element.styles.inline];
if (element.visible) {
styles.push(element.styles.opacity.computed);
styles.push(element.styles.transform.generated.final);
} else {
styles.push(element.styles.opacity.generated);
styles.push(element.styles.transform.generated.initial);
}
element.node.setAttribute('style', styles.join(' '));
});
/**
* Remove unused sequences.
*/
each(this.store.sequences, function (sequence) {
if (activeSequenceIds.indexOf(sequence.id) === -1) {
delete this$1.store.sequences[sequence.id];
}
});
each(this.store.containers, function (container) {
/**
* Remove unused containers.
*/
if (activeContainerIds.indexOf(container.id) === -1) {
container.node.removeEventListener('scroll', this$1.delegate);
container.node.removeEventListener('resize', this$1.delegate);
delete this$1.store.containers[container.id];
/**
* Bind event listeners
*/
} else if (container.node === document.documentElement) {
window.addEventListener('scroll', this$1.delegate);
window.addEventListener('resize', this$1.delegate);
} else {
container.node.addEventListener('scroll', this$1.delegate);
container.node.addEventListener('resize', this$1.delegate);
}
});
/**
* Manually invoke delegate once to capture
* element and container dimensions, container
* scroll position, and trigger any valid reveals
*/
this.delegate();
this.initTimeout = null;
}
function isElementVisible (element) {
var container = this.store.containers[element.containerId];
var viewFactor = element.config.viewFactor;
var viewOffset = element.config.viewOffset;
var elementBounds = {
top: element.geometry.bounds.top + element.geometry.height * viewFactor,
right: element.geometry.bounds.right - element.geometry.width * viewFactor,
bottom: element.geometry.bounds.bottom - element.geometry.height * viewFactor,
left: element.geometry.bounds.left + element.geometry.width * viewFactor,
};
var containerBounds = {
top: container.geometry.bounds.top + container.scroll.top + viewOffset.top,
right: container.geometry.bounds.right + container.scroll.left + viewOffset.right,
bottom: container.geometry.bounds.bottom + container.scroll.top + viewOffset.bottom,
left: container.geometry.bounds.left + container.scroll.left + viewOffset.left,
};
return elementBounds.top < containerBounds.bottom
&& elementBounds.right > containerBounds.left
&& elementBounds.bottom > containerBounds.top
&& elementBounds.left < containerBounds.right
|| element.styles.position === 'fixed'
}
function getGeometry (target, isContainer) {
/**
* We want to ignore padding and scrollbars for container elements.
* More information here: https://goo.gl/vOZpbz
*/
var height = (isContainer) ? target.node.clientHeight : target.node.offsetHeight;
var width = (isContainer) ? target.node.clientWidth : target.node.offsetWidth;
var offsetTop = 0;
var offsetLeft = 0;
var node = target.node;
do {
if (!isNaN(node.offsetTop)) {
offsetTop += node.offsetTop;
}
if (!isNaN(node.offsetLeft)) {
offsetLeft += node.offsetLeft;
}
node = node.offsetParent;
} while (node)
return {
bounds: {
top: offsetTop,
right: offsetLeft + width,
bottom: offsetTop + height,
left: offsetLeft,
},
height: height,
width: width,
}
}
function getNode (target, container) {
if ( container === void 0 ) container = document;
var node = null;
if (typeof target === 'string') {
try {
node = container.querySelector(target);
if (!node) { logger(("Querying the selector \"" + target + "\" returned nothing.")); }
} catch (err) {
logger(("\"" + target + "\" is not a valid selector."));
}
}
return isNode(target) ? target : node
}
function getNodes (target, container) {
if ( container === void 0 ) container = document;
if (isNode(target)) { return [target] }
if (isNodeList(target)) { return Array.prototype.slice.call(target) }
if (typeof target === 'string') {
try {
var query = container.querySelectorAll(target);
var nodes = Array.prototype.slice.call(query);
if (nodes.length) { return nodes }
logger(("Querying the selector \"" + target + "\" returned nothing."));
} catch (error) {
logger(("\"" + target + "\" is not a valid selector."));
}
}
return []
}
function getScrolled (container) {
return (container.node === document.documentElement)
? {
top: window.pageYOffset,
left: window.pageXOffset,
} : {
top: container.node.scrollTop,
left: container.node.scrollLeft,
}
}
function logger (message) {
var details = [], len = arguments.length - 1;
while ( len-- > 0 ) details[ len ] = arguments[ len + 1 ];
if (console) {
var report = "ScrollReveal: " + message;
details.forEach(function (detail) { return report += "\n - " + detail; });
console.log(report); // eslint-disable-line no-console
}
}
function reveal (target, options, interval, sync) {
var this$1 = this;
/**
* The reveal method has an optional 2nd parameter,
* so here we just shuffle things around to accept
* the interval being passed as the 2nd argument.
*/
if (typeof options === 'number') {
interval = Math.abs(parseInt(options));
options = {};
} else {
interval = Math.abs(parseInt(interval));
options = options || {};
}
var config = deepAssign({}, this.defaults, options);
var containers = this.store.containers;
var container = getNode(config.container);
var targets = getNodes(target, container);
if (!targets.length) {
logger('Reveal aborted.', 'Reveal cannot be performed on 0 elements.');
return
}
/**
* Verify our platform matches our platform configuration.
*/
if (!config.mobile && isMobile() || !config.desktop && !isMobile()) {
logger('Reveal aborted.', 'This platform has been disabled.');
return
}
/**
* Sequence intervals must be at least 16ms (60fps).
*/
var sequence;
if (interval) {
if (interval >= 16) {
var sequenceId = nextUniqueId();
sequence = {
elementIds: [],
head: { index: null, blocked: false },
tail: { index: null, blocked: false },
id: sequenceId,
interval: Math.abs(interval),
};
} else {
logger('Reveal failed.', 'Sequence intervals must be at least 16 milliseconds.');
return
}
}
var containerId;
each(containers, function (storedContainer) {
if (!containerId && storedContainer.node === container) {
containerId = storedContainer.id;
}
});
if (isNaN(containerId)) {
containerId = nextUniqueId();
}
try {
var elements = targets.map(function (node) {
var element = {};
var existingId = node.getAttribute('data-sr-id');
if (existingId) {
deepAssign(element, this$1.store.elements[existingId]);
/**
* In order to prevent previously generated styles
* from throwing off the new styles, the style tag
* has to be reverted to it's pre-reveal state.
*/
element.node.setAttribute('style', element.styles.inline);
} else {
element.id = nextUniqueId();
element.node = node;
element.seen = false;
element.visible = false;
}
element.config = config;
element.containerId = containerId;
element.styles = style(element);
if (sequence) {
element.sequence = {
id: sequence.id,
index: sequence.elementIds.length,
};
sequence.elementIds.push(element.id);
}
return element
});
/**
* 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, function (element) {
this$1.store.elements[element.id] = element;
element.node.setAttribute('data-sr-id', element.id);
});
} catch (error) {
logger('Reveal failed.', error.message);
return
}
containers[containerId] = containers[containerId] || {
id: containerId,
node: container,
};
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 (!sync) {
this.store.history.push({ target: target, options: options, interval: interval });
/**
* Push initialization to the event queue, giving
* multiple reveal calls time to be interpretted.
*/
if (this.initTimeout) {
window.clearTimeout(this.initTimeout);
}
this.initTimeout = window.setTimeout(initialize.bind(this), 0);
}
}
function sync () {
var this$1 = this;
each(this.store.history, function (record) {
reveal.call(this$1, record.target, record.options, record.interval, true);
});
initialize.call(this);
}
function animate (element) {
var this$1 = this;
var isDelayed = element.config.useDelay === 'always'
|| element.config.useDelay === 'onload' && this.pristine
|| element.config.useDelay === 'once' && !element.seen;
var sequence = (element.sequence) ? this.store.sequences[element.sequence.id] : null;
var styles = [element.styles.inline];
if (isElementVisible.call(this, element) && !element.visible) {
if (sequence) {
if (sequence.head.index === null && sequence.tail.index === null) {
sequence.head.index = sequence.tail.index = element.sequence.index;
sequence.head.blocked = sequence.tail.blocked = true;
} else if (sequence.head.index - 1 === element.sequence.index && !sequence.head.blocked) {
sequence.head.index--;
sequence.head.blocked = true;
} else if (sequence.tail.index + 1 === element.sequence.index && !sequence.tail.blocked) {
sequence.tail.index++;
sequence.tail.blocked = true;
} else { return }
window.setTimeout(function () {
sequence.head.blocked = sequence.tail.blocked = false;
this$1.delegate();
}, sequence.interval);
}
styles.push(element.styles.opacity.computed);
styles.push(element.styles.transform.generated.final);
if (isDelayed) {
styles.push(element.styles.transition.generated.delayed);
} else {
styles.push(element.styles.transition.generated.instant);
}
element.seen = true;
element.visible = true;
registerCallbacks(element, isDelayed);
element.node.setAttribute('style', styles.join(' '));
} else {
if (!isElementVisible.call(this, element) && element.visible && element.config.reset) {
if (sequence) {
if (sequence.head.index === element.sequence.index) {
sequence.head.index++;
} else if (sequence.tail.index === element.sequence.index) {
sequence.tail.index--;
} else { return }
}
styles.push(element.styles.opacity.generated);
styles.push(element.styles.transform.generated.initial);
styles.push(element.styles.transition.generated.instant);
element.visible = false;
registerCallbacks(element);
element.node.setAttribute('style', styles.join(' '));
}
}
}
function registerCallbacks (element, isDelayed) {
var duration = (isDelayed)
? element.config.duration + element.config.delay
: element.config.duration;
var afterCallback;
if (element.visible) {
element.config.beforeReveal(element.node);
afterCallback = element.config.afterReveal;
} else {
element.config.beforeReset(element.node);
afterCallback = element.config.afterReset;
}
var elapsed = 0;
if (element.callbackTimer) {
elapsed = Date.now() - element.callbackTimer.start;
window.clearTimeout(element.callbackTimer.clock);
}
element.callbackTimer = {
start: Date.now(),
clock: window.setTimeout(function () {
afterCallback(element.node);
if (element.visible && !element.config.reset) {
element.node.setAttribute('style', element.styles.inline);
element.node.removeAttribute('data-sr-id');
}
element.callbackTimer = null;
}, duration - elapsed),
};
}
var polyfill = (function () {
var clock = Date.now();
return function (callback) {
var currentTime = Date.now();
if (currentTime - clock > 16) {
clock = currentTime;
callback(currentTime);
} else {
setTimeout(function () { return polyfill(callback); }, 0);
}
}
})();
var requestAnimationFrame = window.requestAnimationFrame
|| window.webkitRequestAnimationFrame
|| window.mozRequestAnimationFrame
|| polyfill;
function delegate (event) {
var this$1 = this;
if ( event === void 0 ) event = {};
requestAnimationFrame(function () {
var containers = this$1.store.containers;
var elements = this$1.store.elements;
switch (event.type) {
case 'scroll':
each(containers, function (container) { return container.scroll = getScrolled.call(this$1, container); });
each(elements, function (element) { return animate.call(this$1, element); });
break
case 'resize':
default:
each(containers, function (container) {
container.geometry = getGeometry.call(this$1, container, /* isContainer: */ true);
container.scroll = getScrolled.call(this$1, container);
});
each(elements, function (element) {
element.geometry = getGeometry.call(this$1, element);
animate.call(this$1, element);
});
}
this$1.pristine = false;
});
}
var version = "4.0.0-beta.1";
function ScrollReveal (options) {
if ( options === void 0 ) options = {};
/**
* Support instantiation without the `new` keyword.
*/
if (typeof this === 'undefined' || Object.getPrototypeOf(this) !== ScrollReveal.prototype) {
return new ScrollReveal(options)
}
if (!ScrollReveal.isSupported()) {
logger('Instantiation aborted.', 'This browser is not supported.');
return noop
}
try {
Object.defineProperty(this, 'defaults', {
get: (function () {
var config = {};
deepAssign(config, defaults, options);
return function () { return config; }
})(),
});
} catch (error) {
logger('Instantiation failed.', 'Invalid configuration provided.', error.message);
return noop
}
var container = getNode(this.defaults.container);
if (!container) {
logger('Instantiation failed.', 'Invalid or missing container.');
return noop
}
if (this.defaults.mobile === isMobile() || this.defaults.desktop === !isMobile()) {
document.documentElement.classList.add('sr');
}
this.store = {
containers: {},
elements: {},
history: [],
sequences: {},
};
this.pristine = true;
this.delegate = delegate.bind(this);
Object.defineProperty(this, 'version', {
get: function () { return version; },
});
Object.defineProperty(this, 'noop', {
get: function () { return false; },
});
}
ScrollReveal.isSupported = function () { return transformSupported() && transitionSupported(); };
ScrollReveal.prototype.destroy = destroy;
ScrollReveal.prototype.reveal = reveal;
ScrollReveal.prototype.sync = sync;
///// ///// ///// /////
///// ///// ///// /////
///// ///// ///// /////
///// ///// ///// /////
///// ///// /////
///// ///// /////
///// ///// ///// /////
///// ///// ///// /////
///// /////
///// /////
///// ///// ///// /////
///// ///// ///// /////
///// ///// ///// /////
///// ///// ///// /////
/*!
* ScrollReveal
* ------------
* Website : https://scrollreveal.com
* Support : https://github.com/jlmakes/scrollreveal/issues
* Author : https://twitter.com/jlmakes
*
* Licensed under the GNU General Public License 3.0 for
* compatible open source projects and non-commercial use.
*
* For commercial sites, themes, projects, and applications,
* keep your source code proprietary and please purchase a
* commercial license from https://scrollreveal.com
*
* Copyright (c) 2014–2017 Julian Lloyd. All rights reserved.
*/
return ScrollReveal;
}());