Source: fxa/js/screens/fxam_enter_email.js

  1. /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
  2. /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
  3. /* global FxaModuleStates, FxaModuleUI, FxaModule, FxaModuleNavigation,
  4. FxModuleServerRequest, FxaModuleOverlay, FxaModuleManager, EntrySheet,
  5. BrowserFrame */
  6. /* exported FxaModuleEnterEmail */
  7. 'use strict';
  8. /**
  9. * This module checks the validity of an email address, and if valid,
  10. * determines which screen to go next.
  11. */
  12. var FxaModuleEnterEmail = (function() {
  13. var _ = null;
  14. var termsUrl = 'https://accounts.firefox.com/legal/terms';
  15. var privacyUrl = 'https://accounts.firefox.com/legal/privacy';
  16. function _isEmailValid(emailEl) {
  17. return emailEl && emailEl.value && emailEl.validity.valid;
  18. }
  19. function _loadSignIn(done) {
  20. done(FxaModuleStates.ENTER_PASSWORD);
  21. }
  22. function _loadSignUp(done) {
  23. done(FxaModuleStates.SET_PASSWORD);
  24. }
  25. function _loadCoppa(done) {
  26. done(FxaModuleStates.COPPA);
  27. }
  28. function _enableNext(emailEl) {
  29. if (_isEmailValid(emailEl)) {
  30. FxaModuleUI.enableNextButton();
  31. } else {
  32. FxaModuleUI.disableNextButton();
  33. }
  34. }
  35. var Module = Object.create(FxaModule);
  36. Module.init = function init(options) {
  37. _ = navigator.mozL10n.get;
  38. // Cache static HTML elements
  39. this.importElements(
  40. 'fxa-email-input',
  41. 'fxa-logo',
  42. 'fxa-notice'
  43. );
  44. // Blocks the navigation until check the condition
  45. _enableNext(this.fxaEmailInput);
  46. if (this.initialized) {
  47. return;
  48. }
  49. // dynamically construct and localize ToS/PN notice
  50. // XXX This relies on the current l10n fallback mechanism which will change
  51. // in the future; a real solution involves DOM overlays:
  52. // https://bugzil.la/994357
  53. var noticeText = _('fxa-notice');
  54. var tosReplaced = noticeText.replace(
  55. /{{\s*tos\s*}}/,
  56. '<a id="fxa-terms" href="' + termsUrl + '">Terms of Service</a>'
  57. );
  58. var tosPnReplaced = tosReplaced.replace(
  59. /{{\s*pn\s*}}/,
  60. '<a id="fxa-privacy" href="' + privacyUrl + '">Privacy Notice</a>'
  61. );
  62. this.fxaNotice.innerHTML = tosPnReplaced;
  63. // manually import a few elements after innerHTMLing
  64. this.fxaPrivacy = document.getElementById('fxa-privacy');
  65. this.fxaPrivacy.setAttribute('data-l10n-id', 'fxa-pn');
  66. this.fxaTerms = document.getElementById('fxa-terms');
  67. this.fxaTerms.setAttribute('data-l10n-id', 'fxa-tos');
  68. this.isFTU = !!(options && options.isftu);
  69. // Add listeners
  70. this.fxaEmailInput.addEventListener(
  71. 'input',
  72. function onInput(event) {
  73. _enableNext(event.target);
  74. }
  75. );
  76. this.fxaEmailInput.addEventListener(
  77. 'focus',
  78. function onFocus() {
  79. this.fxaLogo.setAttribute('hidden', true);
  80. }.bind(this)
  81. );
  82. this.fxaEmailInput.addEventListener(
  83. 'blur',
  84. function onBlur() {
  85. this.fxaLogo.removeAttribute('hidden');
  86. }.bind(this)
  87. );
  88. this.fxaTerms.addEventListener('click', onExternalLinkClick.bind(this));
  89. this.fxaPrivacy.addEventListener('click', onExternalLinkClick.bind(this));
  90. function onExternalLinkClick(e) {
  91. /*jshint validthis:true */
  92. e.stopPropagation();
  93. e.preventDefault();
  94. if (!navigator.onLine) {
  95. return this.showErrorResponse({error: 'OFFLINE'});
  96. }
  97. var url = e.target.href;
  98. if (this.entrySheet) {
  99. this.entrySheet.close();
  100. this.entrySheet = null;
  101. }
  102. this.entrySheet = new EntrySheet(
  103. window.top.document.getElementById('screen'),
  104. // Prefix url with LRM character
  105. // This ensures truncation occurs correctly in an RTL document
  106. // We can remove this when bug 1154438 is fixed.
  107. '\u200E' + url,
  108. new BrowserFrame({
  109. url: url,
  110. oop: true
  111. })
  112. );
  113. this.entrySheet.open();
  114. }
  115. document.addEventListener(
  116. 'visibilitychange',
  117. onVisibilityChange.bind(this)
  118. );
  119. function onVisibilityChange() {
  120. /*jshint validthis:true */
  121. if (document.hidden) {
  122. document.removeEventListener('visibilitychange', onVisibilityChange);
  123. if (this.entrySheet) {
  124. this.entrySheet.close();
  125. this.entrySheet = null;
  126. }
  127. }
  128. }
  129. window.addEventListener('holdhome', hideEntrySheet.bind(this));
  130. window.addEventListener('home', hideEntrySheet.bind(this));
  131. window.addEventListener('activityrequesting', hideEntrySheet.bind(this));
  132. function hideEntrySheet() {
  133. /*jshint validthis:true */
  134. if (this.entrySheet) {
  135. this.entrySheet.close();
  136. this.entrySheet = null;
  137. }
  138. window.removeEventListener('holdhome', hideEntrySheet);
  139. window.removeEventListener('home', hideEntrySheet);
  140. window.removeEventListener('activityrequesting', hideEntrySheet);
  141. }
  142. // Ensure that pressing 'ENTER' (keycode 13) we send the form
  143. // as expected
  144. this.fxaEmailInput.addEventListener(
  145. 'keypress',
  146. function onKeypress(event) {
  147. if (_isEmailValid(this.fxaEmailInput) && event.keyCode === 13) {
  148. document.activeElement.blur();
  149. FxaModuleNavigation.next();
  150. }
  151. }.bind(this)
  152. );
  153. // Avoid to add listener twice
  154. this.initialized = true;
  155. };
  156. Module.onNext = function onNext(gotoNextStepCallback) {
  157. FxaModuleOverlay.show('fxa-connecting');
  158. var email = this.fxaEmailInput.value;
  159. FxModuleServerRequest.checkEmail(
  160. email,
  161. function onSuccess(response) {
  162. FxaModuleOverlay.hide();
  163. FxaModuleManager.setParam('email', email);
  164. if (response && response.registered) {
  165. _loadSignIn(gotoNextStepCallback);
  166. } else if (this.isFTU) {
  167. // XXX Skip COPPA verification during FTU: if a child has a mobile
  168. // device, we assume a parent/guardian has given it to them, which
  169. // implies parental consent. So, we skip to the next step in the
  170. // signup flow, the set-password screen. See also bug 1010598.
  171. _loadSignUp(gotoNextStepCallback);
  172. } else {
  173. _loadCoppa(gotoNextStepCallback);
  174. }
  175. }.bind(this),
  176. this.showErrorResponse);
  177. };
  178. Module.onBack = function onBack() {
  179. FxaModuleUI.enableNextButton();
  180. };
  181. return Module;
  182. }());