UNPKG

@egjs/rotate

Version:

Tiny custom rotate event binder

413 lines (325 loc) 11.8 kB
<!DOCTYPE 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 &amp; 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" &amp;&amp; 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 &lt; document.documentElement.clientHeight; } else { if (screenWidth &lt; 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" &amp;&amp; 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 &amp;&amp; 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&lt;ko>네이티브 이벤트 객체&lt;/ko> * @param {Object} info The object of data to be sent when the event is fired&lt;ko>이벤트가 발생할 때 전달되는 데이터 객체&lt;/ko> * @param {Boolean} info.isVertical The orientation of the device (true: portrait, false: landscape) &lt;ko>기기의 화면 방향(true: 수직 방향, false: 수평 방향)&lt;/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 &lt;ko>이벤트 핸들러 함수&lt;/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 &amp;&amp; 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 &lt;ko>이벤트 핸들러 함수&lt;/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 &lt;ko>이벤 명&lt;/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) &lt;ko>기기의 화면 방향(true: 수직 방향, false: 수평 방향)&lt;/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>