UNPKG

23.7 kBJavaScriptView Raw
1/*!
2 * Copyright (c) 2017 NAVER Corp.
3 * @egjs/visible project is licensed under the MIT license
4 *
5 * @egjs/visible JavaScript library
6 * https://naver.github.io/egjs-visible/
7 *
8 * @version 2.2.0
9 */
10(function webpackUniversalModuleDefinition(root, factory) {
11 if(typeof exports === 'object' && typeof module === 'object')
12 module.exports = factory(require("@egjs/component"));
13 else if(typeof define === 'function' && define.amd)
14 define(["@egjs/component"], factory);
15 else if(typeof exports === 'object')
16 exports["Visible"] = factory(require("@egjs/component"));
17 else
18 root["eg"] = root["eg"] || {}, root["eg"]["Visible"] = factory(root["eg"]["Component"]);
19})(this, function(__WEBPACK_EXTERNAL_MODULE_2__) {
20return /******/ (function(modules) { // webpackBootstrap
21/******/ // The module cache
22/******/ var installedModules = {};
23/******/
24/******/ // The require function
25/******/ function __webpack_require__(moduleId) {
26/******/
27/******/ // Check if module is in cache
28/******/ if(installedModules[moduleId]) {
29/******/ return installedModules[moduleId].exports;
30/******/ }
31/******/ // Create a new module (and put it into the cache)
32/******/ var module = installedModules[moduleId] = {
33/******/ i: moduleId,
34/******/ l: false,
35/******/ exports: {}
36/******/ };
37/******/
38/******/ // Execute the module function
39/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
40/******/
41/******/ // Flag the module as loaded
42/******/ module.l = true;
43/******/
44/******/ // Return the exports of the module
45/******/ return module.exports;
46/******/ }
47/******/
48/******/
49/******/ // expose the modules object (__webpack_modules__)
50/******/ __webpack_require__.m = modules;
51/******/
52/******/ // expose the module cache
53/******/ __webpack_require__.c = installedModules;
54/******/
55/******/ // define getter function for harmony exports
56/******/ __webpack_require__.d = function(exports, name, getter) {
57/******/ if(!__webpack_require__.o(exports, name)) {
58/******/ Object.defineProperty(exports, name, {
59/******/ configurable: false,
60/******/ enumerable: true,
61/******/ get: getter
62/******/ });
63/******/ }
64/******/ };
65/******/
66/******/ // getDefaultExport function for compatibility with non-harmony modules
67/******/ __webpack_require__.n = function(module) {
68/******/ var getter = module && module.__esModule ?
69/******/ function getDefault() { return module['default']; } :
70/******/ function getModuleExports() { return module; };
71/******/ __webpack_require__.d(getter, 'a', getter);
72/******/ return getter;
73/******/ };
74/******/
75/******/ // Object.prototype.hasOwnProperty.call
76/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
77/******/
78/******/ // __webpack_public_path__
79/******/ __webpack_require__.p = "";
80/******/
81/******/ // Load entry module and return exports
82/******/ return __webpack_require__(__webpack_require__.s = 0);
83/******/ })
84/************************************************************************/
85/******/ ([
86/* 0 */
87/***/ (function(module, exports, __webpack_require__) {
88
89"use strict";
90
91
92var _Visible = __webpack_require__(1);
93
94var _Visible2 = _interopRequireDefault(_Visible);
95
96function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
97
98module.exports = _Visible2["default"]; /**
99 * Copyright (c) NAVER Corp.
100 * egjs-visible projects are licensed under the MIT license
101 */
102
103/***/ }),
104/* 1 */
105/***/ (function(module, exports, __webpack_require__) {
106
107"use strict";
108
109
110exports.__esModule = true;
111
112var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
113
114var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; /**
115 * Copyright (c) NAVER Corp.
116 * egjs-visible projects are licensed under the MIT license
117 */
118
119
120var _component = __webpack_require__(2);
121
122var _component2 = _interopRequireDefault(_component);
123
124var _utils = __webpack_require__(3);
125
126function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
127
128function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
129
130function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
131
132function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
133
134// IE8
135// https://stackoverflow.com/questions/43216659/babel-ie8-inherit-issue-with-object-create
136/* eslint-disable */
137if (typeof Object.create !== "function") {
138 Object.create = function (o, properties) {
139 if ((typeof o === "undefined" ? "undefined" : _typeof(o)) !== "object" && typeof o !== "function") {
140 throw new TypeError("Object prototype may only be an Object: " + o);
141 } else if (o === null) {
142 throw new Error("This browser's implementation of Object.create is a shim and doesn't support 'null' as the first argument.");
143 }
144 function F() {}
145 F.prototype = o;
146 return new F();
147 };
148}
149var SUPPORT_OBSERVER = !!window.IntersectionObserver;
150var SUPPORT_ELEMENTS_BY_CLASSNAME = function () {
151 var dummy = document.createElement("div");
152
153 if (!dummy.getElementsByClassName) {
154 return false;
155 }
156
157 var dummies = dummy.getElementsByClassName("dummy");
158
159 dummy.innerHTML = "<span class='dummy'></span>";
160 return dummies.length === 1;
161}();
162
163/* eslint-enable */
164
165/**
166 * A Class used to check whether an element is visible in the base element or viewport.
167 * @ko 엘리먼트가 기준 엘리먼트나 뷰포트 안에 보이는지 확인하는 클래스
168 * @alias eg.Visible
169 * @extends eg.Component
170 *
171 * @support {"ie": "8+", "ch" : "latest", "ff" : "latest", "sf" : "latest", "edge" : "latest", "ios" : "7+", "an" : "2.1+ (except 3.x)"}
172 */
173
174var Visible = function (_Component) {
175 _inherits(Visible, _Component);
176
177 /**
178 * @param {HTMLElement|String|jQuery} [element=document] A base element that detects if another element is visible<ko>엘리먼트가 보이는 기준 엘리먼트</ko>
179 * @param {Object} options The option object of the Visible module<ko>Visible 모듈의 옵션 객체</ko>
180 * @param {String} [options.targetClass="check_visible"] The class name of the element to be checked<ko>보이는지 확인할 엘리먼트의 클래스 이름</ko>
181 * @param {Number} [options.expandSize=0] The size of the expanded area to be checked whether an element is visible. If this value is less than zero, the size of the area is smaller than that of the base element. <ko>기준 엘리먼트의 경계를 넘어 엘리먼트가 보이는지 확인할 영역의 크기. 값이 0보다 작으면 엘리먼트가 보이는지 확인할 영역의 크기가 기준 엘리먼트보다 작아진다</ko>
182 */
183 function Visible(element, options) {
184 _classCallCheck(this, Visible);
185
186 var _this = _possibleConstructorReturn(this, _Component.call(this));
187
188 _this.options = {
189 targetClass: "check_visible",
190 expandSize: 0
191 };
192 _extends(_this.options, options);
193 _this._wrapper = (0, _utils.$)(element) || document;
194
195 // this._wrapper is Element, or may be Window
196 if (_this._wrapper.nodeType && _this._wrapper.nodeType === 1) {
197 _this._getAreaRect = _this._getWrapperRect;
198 } else {
199 _this._getAreaRect = _utils.getWindowRect;
200 }
201
202 _this._targets = [];
203 _this._timer = null;
204 _this.refresh();
205 return _this;
206 }
207 /**
208 * Updates the list of elements where the visibility property is to be checked
209 * @ko visibility 속성을 검사할 엘리먼트의 목록을 갱신한다
210 * @return {eg.Visible} An instance of a module itself<ko>모듈 자신의 인스턴스</ko>
211 *
212 * @remark
213 * If targets was added or removed from DOM tree, must call refresh method to update internal target list.
214 * <ko>확인 대상이 영역 안에 추가되거나 삭제된 경우, 모듈내부에서 사용하는 확인 대상 목록을 이 메소드를 호출하여 갱신해야한다.<ko>
215 */
216
217
218 Visible.prototype.refresh = function refresh() {
219 if (SUPPORT_ELEMENTS_BY_CLASSNAME) {
220 this._targets = this._wrapper.getElementsByClassName(this.options.targetClass);
221 this.refresh = function () {
222 this._refreshObserver();
223 return this;
224 };
225 } else {
226 this.refresh = function () {
227 var targets = this._wrapper.querySelectorAll("." + this.options.targetClass);
228
229 this._targets = [];
230 for (var i = 0; i < targets.length; i++) {
231 this._targets.push(targets[i]);
232 }
233 this._refreshObserver();
234 return this;
235 };
236 }
237 return this.refresh();
238 };
239
240 /**
241 * Checks whether the visible of the target elements has changed. It trigger that change event on a component.
242 * @ko 대상 엘리먼트의 가시성이 변경됐는지 체크한다. change 이벤트를 발생한다.
243 * @param {Number} [delay=-1] Delay time. It delay that change event trigger.<ko>지연시간. change 이벤트 발생을 지연한다.</ko>
244 * @param {Boolean} [containment=false] Whether to check only elements that are completely contained within the reference area.<ko>기준 영역 안에 완전히 포함된 엘리먼트만 체크할지 여부.</ko>
245 * @return {eg.Visible} An instance of a module itself<ko>모듈 자신의 인스턴스</ko>
246 */
247
248
249 Visible.prototype.check = function check() {
250 var _this2 = this;
251
252 var delay = arguments.length <= 0 ? undefined : arguments[0];
253 var containment = arguments.length <= 1 ? undefined : arguments[1];
254
255 if (typeof delay !== "number") {
256 containment = delay;
257 delay = -1;
258 }
259
260 if (typeof delay === "undefined") {
261 delay = -1;
262 }
263
264 if (typeof containment === "undefined") {
265 containment = false;
266 }
267
268 clearTimeout(this._timer);
269 if (delay < 0) {
270 this._check(containment);
271 this._checkAfter();
272 } else {
273 this._timer = setTimeout(function () {
274 _this2._check(containment);
275 _this2._checkAfter();
276 _this2._timer = null;
277 }, delay);
278 }
279 return this;
280 };
281
282 /**
283 * Get current visible elements.
284 * @ko 현재 보이는 엘리먼트들을 반환한다.
285 * @return {HTMLElement[]} An array of visible elements.<ko>현재 보이는 엘리먼트들의 배열</ko>
286 */
287
288
289 Visible.prototype.getVisibleElements = function getVisibleElements() {
290 var targets = this._targets;
291 var result = [];
292
293 for (var i = 0; i < targets.length; i++) {
294 var el = targets[i];
295
296 if (el && el.__VISIBLE__ === true) {
297 result.push(el);
298 }
299 }
300 return result;
301 };
302
303 Visible.prototype._getWrapperRect = function _getWrapperRect() {
304 return this._wrapper.getBoundingClientRect();
305 };
306
307 Visible.prototype._reviseElements = function _reviseElements() {
308 var _this3 = this;
309
310 if (SUPPORT_ELEMENTS_BY_CLASSNAME) {
311 this._reviseElements = function () {
312 return true;
313 };
314 } else {
315 this._reviseElements = function (target, i) {
316 if (!(0, _utils.hasClass)(target, _this3.options.targetClass)) {
317 target.__VISIBLE__ = null;
318 _this3._targets.splice(i, 1);
319 return false;
320 }
321 return true;
322 };
323 }
324 return this._reviseElements.apply(this, arguments);
325 };
326
327 Visible.prototype._check = function _check(containment) {
328 var expandSize = parseInt(this.options.expandSize, 10);
329
330 var i = void 0;
331 var target = void 0;
332 var targetArea = void 0;
333 var after = void 0;
334
335 // Error Fix: Cannot set property top of #<ClientRect> which has only a getter
336 var rect = this._getAreaRect();
337 var area = {
338 top: rect.top - expandSize,
339 left: rect.left - expandSize,
340 bottom: rect.bottom + expandSize,
341 right: rect.right + expandSize
342 };
343
344 for (i = this._targets.length - 1; target = this._targets[i]; i--) {
345 targetArea = target.getBoundingClientRect();
346
347 if (targetArea.width === 0 && targetArea.height === 0) {
348 continue;
349 }
350
351 if (!this._reviseElements(target, i)) {
352 continue;
353 }
354 if (containment) {
355 after = !(targetArea.top < area.top || targetArea.bottom > area.bottom || targetArea.right > area.right || targetArea.left < area.left);
356 } else {
357 after = !(targetArea.bottom < area.top || area.bottom < targetArea.top || targetArea.right < area.left || area.right < targetArea.left);
358 }
359 target.__AFTER__ = after;
360 }
361 };
362
363 Visible.prototype.checkObserve = function checkObserve() {
364 var _this4 = this;
365
366 var delay = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : -1;
367
368 if (this._timer) {
369 clearTimeout(this._timer);
370 this._timer = 0;
371 }
372 if (delay < 0) {
373 this._checkAfter();
374 } else {
375 this._timer = setTimeout(function () {
376 _this4._checkAfter();
377 _this4._timer = null;
378 }, delay);
379 }
380 return this;
381 };
382
383 Visible.prototype._checkAfter = function _checkAfter() {
384 var targets = this._targets;
385 var length = targets.length;
386 var visibles = [];
387 var invisibles = [];
388
389 for (var i = 0; i < length; ++i) {
390 var target = targets[i];
391 var prev = target.__VISIBLE__;
392 var after = target.__AFTER__;
393
394 if (prev === after) {
395 continue;
396 }
397 if (after) {
398 visibles.push(target);
399 } else {
400 invisibles.push(target);
401 }
402 target.__VISIBLE__ = after;
403 }
404 if (visibles.length === 0 && invisibles.length === 0) {
405 return;
406 }
407 /**
408 * This event is fired when the event is compared with the last verified one and there is an element of which the visibility property has changed.
409 * @ko 마지막으로 확인한 결과와 비교해 visibility 속성이 변경된 엘리먼트가 있을 때 발생하는 이벤트
410 * @name eg.Visible#change
411 * @event
412 * @type {obejct} The object of data to be sent when the event is fired<ko>이벤트가 발생할 때 전달되는 데이터 객체</ko>
413 * @property {Array} visible Visible elements (the element type is `HTMLElement`) <ko>보이게 된 엘리먼트들</ko>
414 * @property {Array} invisible Invisible elements (the element type is `HTMLElement`) <ko>안 보이게 된 엘리먼트들</ko>
415 * @property {Boolean} isTrusted Returns true if an event was generated by the user action, or false if it was caused by a script or API call <ko>사용자의 액션에 의해 이벤트가 발생하였으면 true, 스크립트나 API호출에 의해 발생하였을 경우에는 false를 반환한다.</ko>
416 */
417 this.trigger("change", {
418 visible: visibles,
419 invisible: invisibles,
420 isTrusted: true // This event is called by 'check' method.
421 });
422 };
423 /**
424 * Observe whether the visible of the target elements has changed. It trigger that change event on a component.
425 * @ko 대상 엘리먼트의 가시성이 변경됐는지 관찰한다. change 이벤트를 발생한다.
426 * @param {Object} [options={}] Options to observe the target elements. <ko>대상 엘리먼트를 관찰하기 위한 옵션들.</ko>
427 * @param {Number} [options.delay=-1] Delay time. It delay that change event trigger.<ko>지연시간. change 이벤트 발생을 지연한다.</ko>
428 * @param {Boolean} [options.containment=false] Whether to check only elements that are completely contained within the reference area.<ko>기준 영역 안에 완전히 포함된 엘리먼트만 체크할지 여부.</ko>
429 * @return {eg.Visible} An instance of a module itself<ko>모듈 자신의 인스턴스</ko>
430 */
431
432
433 Visible.prototype.observe = function observe() {
434 var _this5 = this;
435
436 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
437
438 if (!SUPPORT_OBSERVER) {
439 this._addObserveEvent(options);
440 return this;
441 }
442 var delay = typeof options.delay === "undefined" ? -1 : options.delay;
443 var containment = !!options.containment;
444
445 this._observeCallback = function (entries) {
446 entries.forEach(function (entry) {
447 entry.target.__AFTER__ = containment ? entry.intersectionRatio >= 1 : entry.isIntersecting;
448 });
449 _this5._checkAfter(delay);
450 };
451 if (this._observer) {
452 this.unobserve();
453 }
454 this._observer = new IntersectionObserver(this._observeCallback, {
455 root: this._wrapper.nodeType === 1 ? this._wrapper : null,
456 rootMargin: this.options.expandSize + "px",
457 threshold: containment ? [0, 1] : [0]
458 });
459 var observer = this._observer;
460 var targets = this._targets;
461 var length = targets.length;
462
463 for (var i = 0; i < length; ++i) {
464 observer.observe(targets[i]);
465 }
466 return this;
467 };
468
469 Visible.prototype.unobserve = function unobserve() {
470 if (!this._observeCallback) {
471 return this;
472 }
473 if (SUPPORT_OBSERVER) {
474 this._observer && this._observer.disconnect();
475 } else {
476 (0, _utils.removeEvent)(this._wrapper, "scroll", this._observeCallback);
477 (0, _utils.removeEvent)(this._wrapper, "resize", this._observeCallback);
478 }
479 this._observer = null;
480 this._observeCallback = null;
481 return this;
482 };
483
484 Visible.prototype._refreshObserver = function _refreshObserver() {
485 if (!this._observer) {
486 return;
487 }
488 this._observer.disconnect();
489 var targets = this._targets;
490 var length = targets.length;
491
492 for (var i = 0; i < length; ++i) {
493 this._observer.observe(targets[i]);
494 }
495 };
496
497 Visible.prototype._addObserveEvent = function _addObserveEvent() {
498 var _this6 = this;
499
500 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
501
502 if (this._observeCallback) {
503 return;
504 }
505 var delay = typeof options.delay === "undefined" ? -1 : options.delay;
506 var containment = !!options.containment;
507
508 this._observeCallback = function (e) {
509 _this6._check(containment);
510 _this6.checkObserve(delay);
511 };
512 (0, _utils.addEvent)(this._wrapper, "scroll", this._observeCallback);
513 (0, _utils.addEvent)(this._wrapper, "resize", this._observeCallback);
514
515 this._observeCallback();
516 };
517
518 Visible.prototype.destroy = function destroy() {
519 this.off();
520 this.unobserve();
521 this._targets = [];
522 this._wrapper = null;
523 this._timer = null;
524 };
525
526 return Visible;
527}(_component2["default"]);
528
529Visible.VERSION = "2.2.0";
530exports["default"] = Visible;
531module.exports = exports["default"];
532
533/***/ }),
534/* 2 */
535/***/ (function(module, exports) {
536
537module.exports = __WEBPACK_EXTERNAL_MODULE_2__;
538
539/***/ }),
540/* 3 */
541/***/ (function(module, exports, __webpack_require__) {
542
543"use strict";
544
545
546exports.__esModule = true;
547
548var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
549
550exports.toArray = toArray;
551exports.$ = $;
552exports.getWindowRect = getWindowRect;
553exports.hasClass = hasClass;
554exports.addEvent = addEvent;
555exports.removeEvent = removeEvent;
556
557var SUPPORT_ADDEVENTLISTENER = !!("addEventListener" in document);
558var SUPPORT_PASSIVE = function () {
559 var supportsPassiveOption = false;
560
561 try {
562 if (SUPPORT_ADDEVENTLISTENER && Object.defineProperty) {
563 document.addEventListener("test", null, Object.defineProperty({}, "passive", {
564 get: function get() {
565 supportsPassiveOption = true;
566 }
567 }));
568 }
569 } catch (e) {}
570 return supportsPassiveOption;
571}();
572
573function toArray(nodes) {
574 // SCRIPT5014 in IE8
575 var array = [];
576
577 if (nodes) {
578 for (var i = 0, len = nodes.length; i < len; i++) {
579 array.push(nodes[i]);
580 }
581 }
582 return array;
583}
584
585/**
586 * Select or create element
587 * @param {String|HTMLElement|jQuery} param
588 * when string given is as HTML tag, then create element
589 * otherwise it returns selected elements
590 * @param {Boolean} multi
591 * @returns {HTMLElement|HTMLElement[]|undefined}
592 */
593function $(param) {
594 var multi = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
595
596 var el = void 0;
597
598 if (param === undefined) {
599 return undefined;
600 }
601
602 if (typeof param === "string") {
603 // String (HTML, Selector)
604 // check if string is HTML tag format
605 var match = param.match(/^<([a-z]+)\s*([^>]*)>/);
606
607 // creating element
608 if (match) {
609 // HTML
610 var dummy = document.createElement("div");
611
612 dummy.innerHTML = param;
613 el = toArray(dummy.childNodes);
614 } else {
615 // Selector
616 el = toArray(document.querySelectorAll(param));
617 }
618 if (!multi) {
619 el = el.length >= 1 ? el[0] : undefined;
620 }
621 } else if (param === window) {
622 // window
623 el = param;
624 } else if (param.nodeName && (param.nodeType === 1 || param.nodeType === 9)) {
625 // HTMLElement, Document
626 el = param;
627 } else if ("jQuery" in window && param instanceof jQuery || param.constructor.prototype.jquery) {
628 // jQuery
629 el = multi ? param.toArray() : param.get(0);
630 } else if (Array.isArray(param)) {
631 el = param.map(function (v) {
632 return $(v);
633 });
634 if (!multi) {
635 el = el.length >= 1 ? el[0] : undefined;
636 }
637 }
638 return el;
639}
640function getWindowRect() {
641 // [IE7] document.documentElement.clientHeight has always value 0 (bug)
642 return {
643 top: 0,
644 left: 0,
645 bottom: window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight,
646 right: window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth
647 };
648}
649function hasClass(el, className) {
650 if (el.classList) {
651 return el.classList.contains(className);
652 } else {
653 return new RegExp("(^| )" + className + "( |$)", "gi").test(el.className);
654 }
655}
656function addEvent(element, type, handler, eventListenerOptions) {
657 if (SUPPORT_ADDEVENTLISTENER) {
658 var options = eventListenerOptions || false;
659
660 if ((typeof eventListenerOptions === "undefined" ? "undefined" : _typeof(eventListenerOptions)) === "object") {
661 options = SUPPORT_PASSIVE ? eventListenerOptions : false;
662 }
663 element.addEventListener(type, handler, options);
664 } else if (element.attachEvent) {
665 element.attachEvent("on" + type, handler);
666 } else {
667 element["on" + type] = handler;
668 }
669}
670function removeEvent(element, type, handler) {
671 if (element.removeEventListener) {
672 element.removeEventListener(type, handler, false);
673 } else if (element.detachEvent) {
674 element.detachEvent("on" + type, handler);
675 } else {
676 element["on" + type] = null;
677 }
678}
679
680/***/ })
681/******/ ]);
682});
\No newline at end of file