/*
Copyright (c) 2017 NAVER Corp.
@egjs/infinitegrid project is licensed under the MIT license
@egjs/infinitegrid JavaScript library
https://github.com/naver/egjs-infinitegrid
@version 3.5.2
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.eg = global.eg || {}, global.eg.Parallax = factory());
}(this, (function () { 'use strict';
var win;
if (typeof window === "undefined") {
// window is undefined in node.js
win = {
document: {},
navigator: {
userAgent: ""
}
};
} else {
win = window;
}
var document$1 = win.document;
var ua = win.navigator.userAgent;
var SUPPORT_ADDEVENTLISTENER = !!("addEventListener" in document$1);
var SUPPORT_PASSIVE = function () {
var supportsPassiveOption = false;
try {
if (SUPPORT_ADDEVENTLISTENER && Object.defineProperty) {
document$1.addEventListener("test", null, Object.defineProperty({}, "passive", {
get: function () {
supportsPassiveOption = true;
}
}));
}
} catch (e) {//
}
return supportsPassiveOption;
}();
var IS_IE = /MSIE|Trident|Windows Phone|Edge/.test(ua);
var IS_IOS = /iPhone|iPad/.test(ua);
var IS_ANDROID2 = /Android 2\./.test(ua);
var agent = ua.toLowerCase();
var isMobile = /mobi|ios|android/.test(agent);
var ALIGN = {
START: "start",
CENTER: "center",
END: "end",
JUSTIFY: "justify"
};
var webkit = /applewebkit\/([\d|.]*)/g.exec(agent);
var WEBKIT_VERSION = webkit && parseInt(webkit[1], 10) || 0;
var TRANSFORM = (_a = function () {
var properties = {
transitionend: "",
webkitTransitionEnd: "-webkit-",
MSTransitionEnd: "-ms-",
oTransitionEnd: "-o-",
mozTransitionEnd: "-moz-"
};
for (var property in properties) {
var prefix = properties[property];
if ("on" + property.toLowerCase() in win) {
return [prefix + "transform", prefix + "transition", property];
}
}
return [];
}(), _a[0]),
TRANSITION = _a[1],
TRANSITION_END = _a[2];
var _a;
function toArray(nodes) {
// SCRIPT5014 in IE8
var array = [];
if (nodes) {
for (var i = 0, len = nodes.length; i < len; i++) {
array.push(nodes[i]);
}
}
return array;
}
function matchHTML(html) {
return html.match(/^<([A-z]+)\s*([^>]*)>/);
}
function $(param, multi) {
if (multi === void 0) {
multi = false;
}
var el;
if (typeof param === "string") {
// String (HTML, Selector)
// check if string is HTML tag format
var match = matchHTML(param); // creating element
if (match) {
// HTML
var dummy = document$1.createElement("div");
dummy.innerHTML = param;
el = dummy.childNodes;
} else {
// Selector
el = document$1.querySelectorAll(param);
}
if (multi) {
return toArray(el);
} else {
return el && el[0];
}
} else if (isWindow(param)) {
// window
el = param;
} else if (isJQuery(param)) {
// jQuery
el = multi ? $(param.toArray(), true) : $(param.get(0), false);
} else if (Array.isArray(param)) {
el = param.map(function (v) {
return $(v);
});
if (!multi) {
el = el.length >= 1 ? el[0] : undefined;
}
} else if (param.nodeName && (param.nodeType === 1 || param.nodeType === 9)) {
// HTMLElement, Document
el = param;
}
return el;
}
function assign(target) {
var sources = [];
for (var _i = 1; _i < arguments.length; _i++) {
sources[_i - 1] = arguments[_i];
}
sources.forEach(function (source) {
for (var key in source) {
target[key] = source[key];
}
});
return target;
}
function isJQuery(el) {
return typeof win.jQuery === "function" && el instanceof win.jQuery || el.constructor.prototype.jquery && el.toArray;
}
function isWindow(el) {
return el === win;
}
var style = {
vertical: {
position: "top",
size: "height",
cammelSize: "Height",
coordinate: "Y"
},
horizontal: {
position: "left",
size: "width",
cammelSize: "Width",
coordinate: "X"
}
};
var START = ALIGN.START,
CENTER = ALIGN.CENTER;
/**
* @classdesc Parallax is a displacement or difference in the apparent position of an object viewed along two different lines of sight. You can apply parallax by scrolling the image and speed of the item.
* @ko Parallax는 서로 다른 두 개의 시선에서 바라본 물체의 외관상 위치의 변위 또는 차이입니다. 스크롤에 따라 이미지와 아이템의 속도를 차이를 줌으로써 parallax을 적용할 수 있습니다.
* @class eg.Parallax
* @param {Element|String} [root=window] Scrolling target. If you scroll in the body, set window. 스크롤하는 대상. 만약 body에서 스크롤하면 window로 설정한다.
* @param {Object} [options] The option object of eg.Parallax module eg.Parallax 모듈의 옵션 객체
* @param {Boolean} [options.horizontal=false] Direction of the scroll movement (false: vertical, true: horizontal) 스크롤 이동 방향 (false: 세로방향, true: 가로방향)
* @param {Element|String} [options.container=null] Container wrapping items. If root and container have no gaps, do not set option. 아이템들을 감싸고 있는 컨테이너. 만약 root와 container간의 차이가 없으면, 옵션을 설정하지 않아도 된다.
* @param {String} [options.selector="img"] The selector of the image to apply the parallax in the item 아이템안에 있는 parallax를 적용할 이미지의 selector
* @param {Boolean} [options.strength=1] Dimensions that indicate the sensitivity of parallax. The higher the strength, the faster.
* @param {Boolean} [options.center=0] The middle point of parallax. The top is 1 and the bottom is -1. parallax가 가운데로 오는 점. 상단이 1이고 하단이 -1이다.
* @param {Boolean} [options.range=[-1, 1]] Range to apply the parallax. The top is 1 and the bottom is -1. parallax가 적용되는 범위, 상단이 1이고 하단이 -1이다.
* @param {Boolean} [options.align="start"] The alignment of the image in the item. ("start" : top or left, "center": middle) 아이템안의 이미지의 정렬
* @example
```
```
**/
var Parallax =
/*#__PURE__*/
function () {
function Parallax(root, options) {
if (root === void 0) {
root = window;
}
if (options === void 0) {
options = {};
}
this.options = assign({
container: null,
selector: "img",
strength: 1,
center: 0,
range: [-1, 1],
align: START,
horizontal: false
}, options);
this._root = $(root);
this._container = this.options.container && $(this.options.container);
this._rootSize = 0;
this._containerPosition = 0;
this._style = style[this.options.horizontal ? "horizontal" : "vertical"];
this.resize();
}
/**
* As the browser is resized, the gaps between the root and the container and the size of the items are updated.
* @ko 브라우저의 크기가 변경됨으로 써 root와 container의 간격과 아이템들의 크기를 갱신한다.
* @method eg.Parallax#resize
* @param {Array} [items = []] Items to apply parallax. It does not apply if it is not in visible range. parallax를 적용할 아이템들. 가시거리에 존재하지 않으면 적용이 안된다.
* @return {eg.Parallax} An instance of a module itself모듈 자신의 인스턴스
* @example
```js
window.addEventListener("resize", function (e) {
parallax.resize(items);
});
```
*/
var __proto = Parallax.prototype;
__proto.resize = function (items) {
var _this = this;
if (items === void 0) {
items = [];
}
var root = this._root;
var container = this._container;
var positionName = this._style.position;
var sizeName = this._style.cammelSize;
if (!container || root === container) {
this._containerPosition = 0;
} else {
var rootRect = (isWindow(root) ? document.body : root).getBoundingClientRect();
var containertRect = container.getBoundingClientRect();
this._containerPosition = containertRect[positionName] - rootRect[positionName];
}
this._rootSize = isWindow(root) ? window["inner" + sizeName] || document.documentElement["client" + sizeName] : root["client" + sizeName];
if (isMobile && isWindow(root)) {
var bodyWidth = document.body.offsetWidth || document.documentElement.offsetWidth;
var windowWidth = window.innerWidth;
this._rootSize = this._rootSize / (bodyWidth / windowWidth);
}
items.forEach(function (item) {
_this._checkParallaxItem(item.el);
});
return this;
};
/**
* Scrolls the image in the item by a parallax.
* @ko 스크롤하면 아이템안의 이미지를 시차적용시킨다.
* @method eg.Parallax#refresh
* @param {Array} [items = []] Items to apply parallax. It does not apply if it is not in visible range. parallax를 적용할 아이템들. 가시거리에 존재하지 않으면 적용이 안된다.
* @param {Number} [scrollPositionStart = 0] The scroll position.
* @return {eg.Parallax} An instance of a module itself모듈 자신의 인스턴스
* @example
```js
document.body.addEventListener("scroll", function (e) {
parallax.refresh(items, e.scrollTop);
});
```
*/
__proto.refresh = function (items, scrollPositionStart) {
var _this = this;
if (items === void 0) {
items = [];
}
if (scrollPositionStart === void 0) {
scrollPositionStart = 0;
}
var styleNames = this._style;
var positionName = styleNames.position;
var coordinateName = styleNames.coordinate;
var sizeName = styleNames.size;
var options = this.options;
var strength = options.strength,
center = options.center,
range = options.range,
align = options.align;
var rootSize = this._rootSize;
var scrollPositionEnd = scrollPositionStart + rootSize;
var containerPosition = this._containerPosition;
items.forEach(function (item) {
if (!item.rect || !item.size || !item.el) {
return;
}
var position = containerPosition + item.rect[positionName];
var itemSize = item.rect[sizeName] || item.size[sizeName]; // check item is in container.
if (scrollPositionStart > position + itemSize || scrollPositionEnd < position) {
return;
}
var el = item.el;
if (!el.__IMAGE__) {
_this._checkParallaxItem(el);
}
if (el.__IMAGE__ === -1) {
return;
}
var imageElement = el.__IMAGE__;
var boxElement = el.__BOX__;
var boxSize = boxElement.__SIZE__;
var imageSize = imageElement.__SIZE__; // no parallax
if (boxSize >= imageSize) {
// remove transform style
imageElement.style[TRANSFORM] = "";
return;
} // if area's position is center, ratio is 0.
// if area is hidden at the top, ratio is 1.
// if area is hidden at the bottom, ratio is -1.
var imagePosition = position + boxSize / 2;
var ratio = (scrollPositionStart + rootSize / 2 - (rootSize + boxSize) / 2 * center - imagePosition) / (rootSize + boxSize) * 2 * strength; // if ratio is out of the range of -1 and 1, show empty space.
ratio = Math.max(Math.min(ratio, range[1]), range[0]); // dist is the position when thumnail's image is centered.
var dist = (boxSize - imageSize) / 2;
var translate = dist * (1 - ratio);
if (align === CENTER) {
translate -= dist;
}
imageElement.__TRANSLATE__ = translate;
imageElement.__RATIO__ = ratio;
imageElement.style[TRANSFORM] = "translate" + coordinateName + "(" + translate + "px)";
});
return this;
};
__proto._checkParallaxItem = function (element) {
if (!element) {
return;
}
var selector = this.options.selector;
if (!element.__IMAGE__) {
var img = element.querySelector(selector);
element.__IMAGE__ = img || -1;
if (element.__IMAGE__ === -1) {
return;
}
element.__BOX__ = img.parentNode;
}
if (element.__IMAGE__ === -1) {
return;
}
var sizeName = this._style.cammelSize;
element.__IMAGE__.__SIZE__ = element.__IMAGE__["offset" + sizeName];
element.__BOX__.__SIZE__ = element.__BOX__["offset" + sizeName];
};
return Parallax;
}();
return Parallax;
})));
//# sourceMappingURL=parallax.js.map