@egjs/rotate
Version:
Tiny custom rotate event binder
430 lines (375 loc) • 12.2 kB
JavaScript
/*!
* Copyright (c) 2017 NAVER Corp.
* @egjs/rotate project is licensed under the MIT <https://naver.github.io/egjs/license.txt> license
*
* @egjs/rotate JavaScript library
* https://github.com/naver/egjs-rotate
*
* @version 2.1.0
*/
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define("rotate", [], factory);
else if(typeof exports === 'object')
exports["rotate"] = factory();
else
root["eg"] = root["eg"] || {}, root["eg"]["rotate"] = factory();
})(window, function() {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var _rotate = __webpack_require__(1);
var _rotate2 = _interopRequireDefault(_rotate);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
/**
* Version info string
* @ko 버전정보 문자열
* @name VERSION
* @static
* @type {String}
* @example
* eg.rotate.VERSION; // ex) 2.2.0
* @memberof eg.rotate
*/
_rotate2["default"].VERSION = "2.1.0"; /**
* Copyright (c) 2015 NAVER Corp.
* egjs projects are licensed under the MIT license
*/
module.exports = _rotate2["default"];
/***/ }),
/* 1 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
exports.__esModule = true;
var _browser = __webpack_require__(2);
exports["default"] = function () {
var beforeScreenWidth = -1;
var beforeVertical = null;
var USER_LISTENERS = []; // user's event listener
var agent = function () {
var ua = _browser.window.navigator.userAgent;
var match = ua.match(/(iPhone OS|CPU OS|Android)\s([^\s;-]+)/); // fetch Android & iOS env only
var res = {
os: "",
version: "",
ua: ua
};
if (match) {
res.os = match[1].replace(/(?:CPU|iPhone)\sOS/, "ios").toLowerCase();
res.version = match[2].replace(/\D/g, ".");
}
return res;
}();
var isMobile = /android|ios/.test(agent.os) || /Mobi/.test(agent.ua);
// for non-mobile, will return an empty function methods
if (!isMobile) {
var fn = function fn() {
return false;
};
return {
on: fn,
off: fn,
isVertical: fn
};
}
/**
* Return event name string for orientationChange according browser support
*/
var ORIENTATION_CHANGE_EVENT = function () {
var type = void 0;
/**
* Some platform/broswer returns previous widht/height state value. For workaround, give some delays.
*
* Android bug:
* - Andorid 2.3 - Has orientationchange with bug. Needs 500ms delay.
*
* Note: Samsung's branded Android 2.3
* When check orientationchange using resize event, could cause browser crash if user binds resize event on window
*
* - Android 2.2 - orientationchange fires twice(at first time width/height are not updated, but second returns well)
* - Lower than 2.2 - use resize event
*
* InApp bug:
* - Set 200ms delay
*/
if (agent.os === "android" && agent.version === "2.1") {
type = "resize";
} else {
type = "onorientationchange" in _browser.window ? "orientationchange" : "resize";
}
return type;
}();
/**
* When viewport orientation is portrait, return true otherwise false
*/
function isVertical() {
var screenWidth = void 0;
var degree = void 0;
var vertical = void 0;
if (ORIENTATION_CHANGE_EVENT === "resize") {
screenWidth = _browser.document.documentElement.clientWidth;
if (beforeScreenWidth === -1) {
// first call isVertical
vertical = screenWidth < _browser.document.documentElement.clientHeight;
} else {
if (screenWidth < beforeScreenWidth) {
vertical = true;
} else if (screenWidth === beforeScreenWidth) {
vertical = beforeVertical;
} else {
vertical = false;
}
}
} else {
degree = _browser.window.orientation;
if (degree === 0 || degree === 180) {
vertical = true;
} else if (degree === 90 || degree === -90) {
vertical = false;
}
}
return vertical;
}
/**
* Trigger rotate event
*/
function triggerRotate(e) {
var currentVertical = isVertical();
if (isMobile) {
if (beforeVertical !== currentVertical) {
beforeVertical = currentVertical;
beforeScreenWidth = _browser.document.documentElement.clientWidth;
USER_LISTENERS.forEach(function (v) {
return v(e, {
isVertical: beforeVertical
});
});
}
}
}
/**
* Trigger event handler
*/
function handler(e) {
var rotateTimer = null;
if (ORIENTATION_CHANGE_EVENT === "resize") {
_browser.window.setTimeout(function () {
return triggerRotate(e);
}, 0);
} else {
if (agent.os === "android") {
var screenWidth = _browser.document.documentElement.clientWidth;
if (e.type === "orientationchange" && screenWidth === beforeScreenWidth) {
_browser.window.setTimeout(function () {
return handler(e);
}, 500);
// When width value wasn't changed after firing orientationchange, then call handler again after 300ms.
return false;
}
}
rotateTimer && _browser.window.clearTimeout(rotateTimer);
rotateTimer = _browser.window.setTimeout(function () {
return triggerRotate(e);
}, 300);
}
return undefined;
}
/**
* Tiny custom rotate event binder.
* > **NOTE:**
* > - It works for mobile environment only.
* > - For non-mobile environment, every methods will return 'false'.
*
* > **참고:**
* > - 모바일 환경에서만 동작 합니다.
* > - 비모바일 환경에서는 모든 메서드들은 'false'를 반환합니다.
* @ko 기기 회전에 따른 rotate 커스텀 이벤트 바인더
* @namespace eg.rotate
* @param {Event} e Native event object<ko>네이티브 이벤트 객체</ko>
* @param {Object} info The object of data to be sent when the event is fired<ko>이벤트가 발생할 때 전달되는 데이터 객체</ko>
* @param {Boolean} info.isVertical The orientation of the device (true: portrait, false: landscape) <ko>기기의 화면 방향(true: 수직 방향, false: 수평 방향)</ko>
* @support { "ios" : "7+", "an" : "2.1+ (except 3.x)"}
* @example
* var handler = function(e, info){
* info.isVertical;
* }
* // bind
* eg.rotate.on(handler);
*
* // unbind
* eg.rotate.off(handler);
*
* // unbind all event attached (call without listener param)
* eg.rotate.off();
*/
return {
/**
* Bind rotate event
* @ko rotate 이벤트 바인딩
* @memberof eg.rotate
* @static
* @param {Function} listener listener function <ko>이벤트 핸들러 함수</ko>
*/
on: function on(listener) {
if (typeof listener !== "function") {
return;
}
beforeVertical = isVertical();
beforeScreenWidth = _browser.document.documentElement.clientWidth;
USER_LISTENERS.push(listener);
// only attach once
USER_LISTENERS.length === 1 && _browser.window.addEventListener(ORIENTATION_CHANGE_EVENT, handler);
},
/**
* Unbind rotate event
* Without param, will unbind all binded listeners
* @ko rotate 이벤트 바인딩 해제. 파라미터 없이 호출되는 경우, 바인딩된 모든 이벤트를 해제한다.
* @memberof eg.rotate
* @static
* @param {Function} [listener] listener function <ko>이벤트 핸들러 함수</ko>
*/
off: function off(listener) {
if (typeof listener === "function") {
// remove given listener from list
for (var i = 0, el; el = USER_LISTENERS[i]; i++) {
if (el === listener) {
USER_LISTENERS.splice(i, 1);
break;
}
}
}
// detach when the condition is met
if (!listener || USER_LISTENERS.length === 0) {
USER_LISTENERS.splice(0);
_browser.window.removeEventListener(ORIENTATION_CHANGE_EVENT, handler);
}
},
/**
* Native event name used to detect rotate
* @ko roate 이벤트를 위해 사용된 네이티브 이벤트 명
* @memberof eg.rotate
* @property {String} event event name <ko>이벤 명</ko>
* @private
*/
orientationChange: ORIENTATION_CHANGE_EVENT,
/**
* Get device is in vertical mode
* @ko 화면이 수직 방향인지 여부
* @memberof eg.rotate
* @static
* @method
* @return {Boolean} The orientation of the device (true: portrait, false: landscape) <ko>기기의 화면 방향(true: 수직 방향, false: 수평 방향)</ko>
* @example
* eg.rotate.isVertical(); // Check if device is in portrait mode
*/
isVertical: isVertical,
/**
* Trigger rotate event
* @memberof eg.rotate
* @private
*/
triggerRotate: triggerRotate,
/**
* Event handler function
* @memberof eg.rotate
* @private
*/
handler: handler
};
}(); /**
* Copyright (c) 2015 NAVER Corp.
* egjs projects are licensed under the MIT license
*/
module.exports = exports["default"];
/***/ }),
/* 2 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
exports.__esModule = true;
/**
* Copyright (c) 2015 NAVER Corp.
* egjs projects are licensed under the MIT license
*/
/* eslint-disable no-new-func, no-nested-ternary */
var win = typeof window !== "undefined" && window.Math === Math ? window : typeof self !== "undefined" && self.Math === Math ? self : Function("return this")();
/* eslint-enable no-new-func, no-nested-ternary */
var document = win.document;
exports.window = win;
exports.document = document;
/***/ })
/******/ ]);
});