@egjs/rotate
Version:
Tiny custom rotate event binder
413 lines (325 loc) • 11.8 kB
HTML
<html>
<head>
<meta charset="utf-8">
<title>Source: rotate.js | egjs::rotate - API</title>
<meta name="description" content="Tiny custom rotate event binder" />
<meta property="og:title" content=""/>
<meta property="og:type" content="website"/>
<meta property="og:image" content=""/>
<meta property="og:url" content=""/>
<script src="scripts/prettify/prettify.js"></script>
<script src="scripts/prettify/lang-css.js"></script>
<script src="scripts/jquery.min.js"></script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link rel="canonical" href="http://naver.github.io/egjs-rotate/release/latest/doc/"/>
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/bootstrap.min.css">
<link type="text/css" rel="stylesheet" href="styles/jaguar.css">
<script>
var config = {"monospaceLinks":true,"cleverLinks":true,"default":{"outputSourceFiles":true},"applicationName":"eg.Rotate","disqus":"egjs","googleAnalytics":"UA-70842526-22","openGraph":{"title":"","type":"website","image":"","site_name":"","url":""},"meta":{"title":"egjs::rotate - API","description":"Tiny custom rotate event binder","keyword":""},"linenums":true,"link":{"canonical":"http://naver.github.io/egjs-rotate/release/latest/doc/"}};
</script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', config.googleAnalytics]);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</head>
<body>
<div id="wrap" class="clearfix">
<div class="navigation">
<h3 class="applicationName">
<a href="//naver.github.io/egjs/"><img style="width:40px; height:20px;" src="img/type_white.svg"/></a>
<!-- Homepage link (prefer link.home than applicationName) -->
<a href="//naver.github.io/egjs-rotate/">Rotate</a>
</h3>
<div class="search">
<input id="search" type="text" class="form-control input-sm" placeholder="Search Documentations">
</div>
<ul class="list">
<li class="item">
<span class="title">
<a href="index.html">README</a>
</span>
</li>
<!-- Non Grouping Version -->
<li class="item" data-name="eg.rotate">
<span class="title">
<a href="eg.rotate.html">eg.rotate</a>
<span class="static">static</span>
</span>
<ul class="members itemMembers expends">
<span class="subtitle">Members</span>
<li data-name="eg.rotate.VERSION"><a href="eg.rotate.html#.VERSION">VERSION</a></li>
</ul>
<ul class="typedefs itemMembers expends">
</ul>
<ul class="methods itemMembers expends">
<span class="subtitle">Methods</span>
<li data-name="eg.rotate.isVertical"><a href="eg.rotate.html#.isVertical">isVertical</a></li>
<li data-name="eg.rotate.off"><a href="eg.rotate.html#.off">off</a></li>
<li data-name="eg.rotate.on"><a href="eg.rotate.html#.on">on</a></li>
</ul>
<ul class="events itemMembers expends">
</ul>
</li>
</ul>
</div>
<div class="main">
<h1 class="page-title" data-filename="rotate.js.html">Source: rotate.js</h1>
<section>
<article>
<pre class="prettyprint source linenums"><code>/**
* Copyright (c) 2015 NAVER Corp.
* egjs projects are licensed under the MIT license
*/
import {window, document} from "./browser";
export default (() => {
let beforeScreenWidth = -1;
let beforeVertical = null;
const USER_LISTENERS = []; // user's event listener
const agent = (() => {
const ua = window.navigator.userAgent;
const match = ua.match(/(iPhone OS|CPU OS|Android)\s([^\s;-]+)/); // fetch Android & iOS env only
const res = {
os: "",
version: "",
ua
};
if (match) {
res.os = match[1].replace(/(?:CPU|iPhone)\sOS/, "ios").toLowerCase();
res.version = match[2].replace(/\D/g, ".");
}
return res;
})();
const isMobile = /android|ios/.test(agent.os) || /Mobi/.test(agent.ua);
// for non-mobile, will return an empty function methods
if (!isMobile) {
const fn = () => false;
return {
on: fn,
off: fn,
isVertical: fn
};
}
/**
* Return event name string for orientationChange according browser support
*/
const ORIENTATION_CHANGE_EVENT = (() => {
let type;
/**
* 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 window ? "orientationchange" : "resize";
}
return type;
})();
/**
* When viewport orientation is portrait, return true otherwise false
*/
function isVertical() {
let screenWidth;
let degree;
let vertical;
if (ORIENTATION_CHANGE_EVENT === "resize") {
screenWidth = document.documentElement.clientWidth;
if (beforeScreenWidth === -1) { // first call isVertical
vertical = screenWidth < document.documentElement.clientHeight;
} else {
if (screenWidth < beforeScreenWidth) {
vertical = true;
} else if (screenWidth === beforeScreenWidth) {
vertical = beforeVertical;
} else {
vertical = false;
}
}
} else {
degree = 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) {
const currentVertical = isVertical();
if (isMobile) {
if (beforeVertical !== currentVertical) {
beforeVertical = currentVertical;
beforeScreenWidth = document.documentElement.clientWidth;
USER_LISTENERS.forEach(v => v(e, {
isVertical: beforeVertical
}));
}
}
}
/**
* Trigger event handler
*/
function handler(e) {
let rotateTimer = null;
if (ORIENTATION_CHANGE_EVENT === "resize") {
window.setTimeout(() => triggerRotate(e), 0);
} else {
if (agent.os === "android") {
const screenWidth = document.documentElement.clientWidth;
if (e.type === "orientationchange" && screenWidth === beforeScreenWidth) {
window.setTimeout(() => handler(e), 500);
// When width value wasn't changed after firing orientationchange, then call handler again after 300ms.
return false;
}
}
rotateTimer && window.clearTimeout(rotateTimer);
rotateTimer = window.setTimeout(() => 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(listener) {
if (typeof(listener) !== "function") {
return;
}
beforeVertical = isVertical();
beforeScreenWidth = document.documentElement.clientWidth;
USER_LISTENERS.push(listener);
// only attach once
USER_LISTENERS.length === 1 &&
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(listener) {
if (typeof(listener) === "function") {
// remove given listener from list
for (let 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);
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,
/**
* Trigger rotate event
* @memberof eg.rotate
* @private
*/
triggerRotate,
/**
* Event handler function
* @memberof eg.rotate
* @private
*/
handler
};
})();
</code></pre>
</article>
</section>
<!-- disqus code -->
<div id="disqus_thread"></div>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="//disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>
<!-- // disqus code -->
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Fri May 04 2018 17:35:19 GMT+0900 (대한민국 표준시)
</footer>
</div>
</div>
<script>prettyPrint();</script>
<script src="scripts/main.js"></script>
</body>
</html>