Source: customEvent/rotate.js

  1. /**
  2. * Copyright (c) 2015 NAVER Corp.
  3. * egjs projects are licensed under the MIT license
  4. */
  5. // jscs:disable maximumLineLength
  6. eg.module("rotate", ["jQuery", eg, window, document], function($, ns, global, doc) {
  7. "use strict";
  8. // jscs:enable maximumLineLength
  9. /**
  10. * @namespace jQuery
  11. * @group jQuery Extension
  12. */
  13. /**
  14. * This jQuery custom event is fired when device rotates.
  15. *
  16. * @ko 기기가 회전할 때 발생하는 jQuery 커스텀 이벤트
  17. * @name jQuery#rotate
  18. * @event
  19. * @param {Event} e The Event object in jQuery<ko>jQuery의 Event 객체</ko>
  20. * @param {Object} info The object of data to be sent when the event is fired<ko>이벤트가 발생할 때 전달되는 데이터 객체</ko>
  21. * @param {Boolean} info.isVertical The orientation of the device (true: portrait, false: landscape) <ko>기기의 화면 방향(true: 수직 방향, false: 수평 방향)</ko>
  22. * @support { "ios" : "7+", "an" : "2.1+ (except 3.x)"}
  23. * @example
  24. * $(window).on("rotate",function(e, info){
  25. * info.isVertical;
  26. * });
  27. *
  28. */
  29. var beforeScreenWidth = -1;
  30. var beforeVertical = null;
  31. var rotateTimer = null;
  32. var agent = (function() {
  33. var ua = global.navigator.userAgent;
  34. var match = ua.match(/(iPhone OS|CPU OS|Android)\s([^\s;-]+)/); // fetch Android & iOS env only
  35. var res = {
  36. os: "",
  37. version: ""
  38. };
  39. if (match) {
  40. res.os = match[1].replace(/(?:CPU|iPhone)\sOS/, "ios").toLowerCase();
  41. res.version = match[2].replace(/\D/g, ".");
  42. }
  43. return res;
  44. })();
  45. var isMobile = /android|ios/.test(agent.os);
  46. if (!isMobile) {
  47. ns.isPortrait = function() {
  48. return false;
  49. };
  50. return;
  51. }
  52. /**
  53. * Return event name string for orientationChange according browser support
  54. */
  55. var orientationChange = function() {
  56. var type;
  57. /**
  58. * Some platform/broswer returns previous widht/height state value. For workaround, give some delays.
  59. *
  60. * Android bug:
  61. * - Andorid 2.3 - Has orientationchange with bug. Needs 500ms delay.
  62. *
  63. * Note: Samsung's branded Android 2.3
  64. * When check orientationchange using resize event, could cause browser crash if user binds resize event on window
  65. *
  66. * - Android 2.2 - orientationchange fires twice(at first time width/height are not updated, but second returns well)
  67. * - Lower than 2.2 - use resize event
  68. *
  69. * InApp bug:
  70. * - Set 200ms delay
  71. */
  72. if ((agent.os === "android" && agent.version === "2.1")) {//|| htInfo.galaxyTab2)
  73. type = "resize";
  74. } else {
  75. type = "onorientationchange" in global ? "orientationchange" : "resize";
  76. }
  77. orientationChange = function() {
  78. return type;
  79. };
  80. return type;
  81. };
  82. /**
  83. * When viewport orientation is portrait, return true otherwise false
  84. */
  85. function isVertical() {
  86. var eventName = orientationChange();
  87. var screenWidth;
  88. var degree;
  89. var vertical;
  90. if (eventName === "resize") {
  91. screenWidth = doc.documentElement.clientWidth;
  92. if (beforeScreenWidth === -1) { //first call isVertical
  93. vertical = screenWidth < doc.documentElement.clientHeight;
  94. } else {
  95. if (screenWidth < beforeScreenWidth) {
  96. vertical = true;
  97. } else if (screenWidth === beforeScreenWidth) {
  98. vertical = beforeVertical;
  99. } else {
  100. vertical = false;
  101. }
  102. }
  103. } else {
  104. degree = global.orientation;
  105. if (degree === 0 || degree === 180) {
  106. vertical = true;
  107. } else if (degree === 90 || degree === -90) {
  108. vertical = false;
  109. }
  110. }
  111. return vertical;
  112. }
  113. /**
  114. * Trigger rotate event
  115. */
  116. function triggerRotate() {
  117. var currentVertical = isVertical();
  118. if (isMobile) {
  119. if (beforeVertical !== currentVertical) {
  120. beforeVertical = currentVertical;
  121. beforeScreenWidth = doc.documentElement.clientWidth;
  122. $(global).trigger("rotate", {
  123. isVertical: beforeVertical
  124. });
  125. }
  126. }
  127. }
  128. /**
  129. * Trigger event handler
  130. */
  131. function handler(e) {
  132. var eventName = orientationChange();
  133. var delay;
  134. var screenWidth;
  135. if (eventName === "resize") {
  136. global.setTimeout(function() {
  137. triggerRotate();
  138. }, 0);
  139. } else {
  140. delay = 300;
  141. if (agent.os === "android") {
  142. screenWidth = doc.documentElement.clientWidth;
  143. if (e.type === "orientationchange" && screenWidth === beforeScreenWidth) {
  144. global.setTimeout(function() {
  145. handler(e);
  146. }, 500);
  147. // When width value wasn't changed after firing orientationchange, then call handler again after 300ms.
  148. return false;
  149. }
  150. }
  151. global.clearTimeout(rotateTimer);
  152. rotateTimer = global.setTimeout(function() {
  153. triggerRotate();
  154. }, delay);
  155. }
  156. }
  157. $.event.special.rotate = {
  158. setup: function() {
  159. beforeVertical = isVertical();
  160. beforeScreenWidth = doc.documentElement.clientWidth;
  161. $(global).on(orientationChange(), handler);
  162. },
  163. teardown: function() {
  164. $(global).off(orientationChange(), handler);
  165. },
  166. trigger: function(e) {
  167. e.isVertical = beforeVertical;
  168. }
  169. };
  170. /**
  171. * Checks whether the current orientation of the device is portrait.
  172. * @ko 기기의 화면이 수직 방향인지 확인한다
  173. * @method eg#isPortrait
  174. * @return {Boolean} The orientation of the device (true: portrait, false: landscape) <ko>기기의 화면 방향(true: 수직 방향, false: 수평 방향)</ko>
  175. * @example
  176. eg.isPortrait(); // Check if device is in portrait mode
  177. */
  178. ns.isPortrait = isVertical;
  179. return {
  180. "orientationChange": orientationChange,
  181. "isVertical": isVertical,
  182. "triggerRotate": triggerRotate,
  183. "handler": handler
  184. };
  185. });
comments powered by Disqus