keyboard.js 9.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. import { EventEmitter, Injectable, NgZone } from '@angular/core';
  2. import { Config } from '../config/config';
  3. import { DomController } from './dom-controller';
  4. import { isTextInput } from '../util/dom';
  5. import { KEY_TAB } from './key';
  6. import { Platform } from './platform';
  7. /**
  8. * @name Keyboard
  9. * @description
  10. * The `Keyboard` class allows you to work with the keyboard events provided
  11. * by the Ionic keyboard plugin.
  12. *
  13. * @usage
  14. * ```ts
  15. * export class MyClass {
  16. *
  17. * constructor(public keyboard: Keyboard) { }
  18. *
  19. * }
  20. * ```
  21. */
  22. var Keyboard = (function () {
  23. function Keyboard(config, _plt, _zone, _dom) {
  24. this._plt = _plt;
  25. this._zone = _zone;
  26. this._dom = _dom;
  27. this.willShow = new EventEmitter();
  28. this.willHide = new EventEmitter();
  29. this.didShow = new EventEmitter();
  30. this.didHide = new EventEmitter();
  31. this.eventsAvailable = false;
  32. this.focusOutline(config.get('focusOutline'));
  33. var win = _plt.win();
  34. if (win.Ionic && win.Ionic.keyboardPlugin) {
  35. this.listenV2(win);
  36. }
  37. else {
  38. this.listenV1(win);
  39. }
  40. }
  41. Keyboard.prototype.listenV2 = function (win) {
  42. var _this = this;
  43. var platform = this._plt;
  44. platform.registerListener(win, 'keyboardWillShow', function (ev) {
  45. _this._zone.run(function () {
  46. _this.willShow.emit(ev.keyboardHeight);
  47. });
  48. }, { zone: false, passive: true });
  49. platform.registerListener(win, 'keyboardWillHide', function () {
  50. _this._zone.run(function () {
  51. _this.willHide.emit();
  52. });
  53. }, { zone: false, passive: true });
  54. platform.registerListener(win, 'keyboardDidShow', function (ev) {
  55. _this._zone.run(function () {
  56. _this.didShow.emit(ev.keyboardHeight);
  57. });
  58. }, { zone: false, passive: true });
  59. platform.registerListener(win, 'keyboardDidHide', function () {
  60. _this._zone.run(function () {
  61. _this.didHide.emit();
  62. });
  63. }, { zone: false, passive: true });
  64. this.eventsAvailable = true;
  65. };
  66. Keyboard.prototype.listenV1 = function (win) {
  67. var _this = this;
  68. var platform = this._plt;
  69. platform.registerListener(win, 'native.keyboardhide', function () {
  70. _this.blurActiveInput(true);
  71. }, { zone: false, passive: true });
  72. platform.registerListener(win, 'native.keyboardshow', function () {
  73. _this.blurActiveInput(false);
  74. }, { zone: false, passive: true });
  75. };
  76. Keyboard.prototype.blurActiveInput = function (shouldBlur) {
  77. var _this = this;
  78. var platform = this._plt;
  79. platform.cancelTimeout(this._tmr);
  80. if (shouldBlur) {
  81. this._tmr = platform.timeout(function () {
  82. // this custom cordova plugin event fires when the keyboard will hide
  83. // useful when the virtual keyboard is closed natively
  84. // https://github.com/ionic-team/ionic-plugin-keyboard
  85. if (_this.isOpen()) {
  86. platform.focusOutActiveElement();
  87. }
  88. }, 80);
  89. }
  90. };
  91. /**
  92. * Check to see if the keyboard is open or not.
  93. *
  94. * ```ts
  95. * export class MyClass {
  96. * constructor(public keyboard: Keyboard) {
  97. *
  98. * }
  99. *
  100. * keyboardCheck() {
  101. * console.log('The keyboard is open:', this.keyboard.isOpen());
  102. * }
  103. * }
  104. * ```
  105. *
  106. * @return {boolean} returns a true or false value if the keyboard is open or not.
  107. */
  108. Keyboard.prototype.isOpen = function () {
  109. return this.hasFocusedTextInput();
  110. };
  111. /**
  112. * When the keyboard is closed, call any methods you want.
  113. *
  114. * ```ts
  115. * export class MyClass {
  116. * constructor(public keyboard: Keyboard) {
  117. * this.keyboard.onClose(this.closeCallback);
  118. * }
  119. * closeCallback() {
  120. * // call what ever functionality you want on keyboard close
  121. * console.log('Closing time');
  122. * }
  123. * }
  124. * ```
  125. *
  126. * @param {function} callback method you want to call when the keyboard has been closed.
  127. * @return {function} returns a callback that gets fired when the keyboard is closed.
  128. */
  129. Keyboard.prototype.onClose = function (callback, pollingInternval, pollingChecksMax) {
  130. if (pollingInternval === void 0) { pollingInternval = KEYBOARD_CLOSE_POLLING; }
  131. if (pollingChecksMax === void 0) { pollingChecksMax = KEYBOARD_POLLING_CHECKS_MAX; }
  132. (void 0) /* console.debug */;
  133. var self = this;
  134. var checks = 0;
  135. var promise = null;
  136. if (!callback) {
  137. // a callback wasn't provided, so let's return a promise instead
  138. promise = new Promise(function (resolve) { callback = resolve; });
  139. }
  140. function checkKeyboard() {
  141. (void 0) /* console.debug */;
  142. if (!self.isOpen() || checks > pollingChecksMax) {
  143. self._plt.timeout(function () {
  144. self._zone.run(function () {
  145. (void 0) /* console.debug */;
  146. callback();
  147. });
  148. }, 400);
  149. }
  150. else {
  151. self._plt.timeout(checkKeyboard, pollingInternval);
  152. }
  153. checks++;
  154. }
  155. self._plt.timeout(checkKeyboard, pollingInternval);
  156. return promise;
  157. };
  158. /**
  159. * Programmatically close the keyboard.
  160. */
  161. Keyboard.prototype.close = function () {
  162. var _this = this;
  163. this._dom.read(function () {
  164. if (_this.isOpen()) {
  165. // only focus out when a text input has focus
  166. (void 0) /* console.debug */;
  167. _this._dom.write(function () {
  168. _this._plt.focusOutActiveElement();
  169. });
  170. }
  171. });
  172. };
  173. /**
  174. * @hidden
  175. */
  176. Keyboard.prototype.focusOutline = function (setting) {
  177. /* Focus Outline
  178. * --------------------------------------------------
  179. * By default, when a keydown event happens from a tab key, then
  180. * the 'focus-outline' css class is added to the body element
  181. * so focusable elements have an outline. On a mousedown or
  182. * touchstart event, then the 'focus-outline' css class is removed.
  183. *
  184. * Config default overrides:
  185. * focusOutline: true - Always add the focus-outline
  186. * focusOutline: false - Do not add the focus-outline
  187. */
  188. var self = this;
  189. var platform = self._plt;
  190. var doc = platform.doc();
  191. var isKeyInputEnabled = false;
  192. var unRegMouse;
  193. var unRegTouch;
  194. var evOpts = { passive: true, zone: false };
  195. function cssClass() {
  196. self._dom.write(function () {
  197. platform.doc().body.classList[isKeyInputEnabled ? 'add' : 'remove']('focus-outline');
  198. });
  199. }
  200. if (setting === true) {
  201. isKeyInputEnabled = true;
  202. return cssClass();
  203. }
  204. else if (setting === false) {
  205. return;
  206. }
  207. // default is to add the focus-outline when the tab key is used
  208. function keyDown(ev) {
  209. if (!isKeyInputEnabled && ev.keyCode === KEY_TAB) {
  210. isKeyInputEnabled = true;
  211. enableKeyInput();
  212. }
  213. }
  214. function pointerDown() {
  215. isKeyInputEnabled = false;
  216. enableKeyInput();
  217. }
  218. function enableKeyInput() {
  219. cssClass();
  220. unRegMouse && unRegMouse();
  221. unRegTouch && unRegTouch();
  222. if (isKeyInputEnabled) {
  223. // listen for when a mousedown or touchstart event happens
  224. unRegMouse = platform.registerListener(doc, 'mousedown', pointerDown, evOpts);
  225. unRegTouch = platform.registerListener(doc, 'touchstart', pointerDown, evOpts);
  226. }
  227. }
  228. // always listen for tab keydown events
  229. platform.registerListener(platform.doc(), 'keydown', keyDown, evOpts);
  230. };
  231. Keyboard.prototype.hasFocusedTextInput = function () {
  232. var activeEle = this._plt.getActiveElement();
  233. if (isTextInput(activeEle)) {
  234. return (activeEle.parentElement.querySelector(':focus') === activeEle);
  235. }
  236. return false;
  237. };
  238. /**
  239. * Set to true to hide the additional toolbar that is on top of the keyboard.
  240. * This toolbar features the Prev, Next, and Done buttons.
  241. * @param hidden
  242. */
  243. Keyboard.prototype.hideFormAccessoryBar = function (hidden) {
  244. var win = this._plt.win();
  245. if (win && win.Keyboard && win.Keyboard.hideFormAccessoryBar) {
  246. win.Keyboard.hideFormAccessoryBar(hidden);
  247. }
  248. };
  249. Keyboard.decorators = [
  250. { type: Injectable },
  251. ];
  252. /** @nocollapse */
  253. Keyboard.ctorParameters = function () { return [
  254. { type: Config, },
  255. { type: Platform, },
  256. { type: NgZone, },
  257. { type: DomController, },
  258. ]; };
  259. return Keyboard;
  260. }());
  261. export { Keyboard };
  262. var KEYBOARD_CLOSE_POLLING = 150;
  263. var KEYBOARD_POLLING_CHECKS_MAX = 100;
  264. //# sourceMappingURL=keyboard.js.map