SMAM (short for Send Me A Mail) is a free (as in freedom) contact form embedding software.

form.js 6.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. var items = {
  2. name: 'form_name',
  3. addr: 'form_addr',
  4. subj: 'form_subj',
  5. text: 'form_text',
  6. };
  7. var server = getServer();
  8. var token = "";
  9. var labels = true;
  10. var lang = {};
  11. var xhr = {
  12. lang: new XMLHttpRequest(),
  13. token: new XMLHttpRequest(),
  14. send: new XMLHttpRequest()
  15. }
  16. // XHR callbacks
  17. xhr.token.onreadystatechange = function() {
  18. if(xhr.token.readyState == XMLHttpRequest.DONE) {
  19. token = xhr.token.responseText;
  20. }
  21. };
  22. xhr.lang.onreadystatechange = function() {
  23. if(xhr.lang.readyState == XMLHttpRequest.DONE) {
  24. let response = JSON.parse(xhr.lang.responseText);
  25. lang = response.translations;
  26. labels = response.labels;
  27. }
  28. };
  29. xhr.send.onreadystatechange = function() {
  30. if(xhr.send.readyState == XMLHttpRequest.DONE) {
  31. let status = document.getElementById('form_status');
  32. status.setAttribute('class', '');
  33. if(xhr.send.status === 200) {
  34. cleanForm();
  35. status.setAttribute('class', 'success');
  36. status.innerHTML = lang.send_status_success;
  37. } else {
  38. status.setAttribute('class', 'failure');
  39. status.innerHTML = lang.send_status_failure;
  40. }
  41. }
  42. };
  43. // Returns the server's base URI based on the user's script tag
  44. // return: the SMAM server's base URI
  45. function getServer() {
  46. var scripts = document.getElementsByTagName('script');
  47. // Parsing all the <script> tags to find the URL to our file
  48. for(var i = 0; i < scripts.length; i++) {
  49. let script = scripts[i];
  50. if(script.src) {
  51. let url = script.src;
  52. // This should be our script
  53. if(url.match(/form\.js$/)) {
  54. // Port has been found
  55. return url.match(/^(https?:\/\/[^\/]+)/)[1];
  56. }
  57. }
  58. }
  59. }
  60. // Creates a form
  61. // id: HTML identifier of the document's block to create the form into
  62. // return: nothing
  63. function generateForm(id) {
  64. // Get translated strings
  65. getLangSync();
  66. var el = document.getElementById(id);
  67. // Set the form's behaviour
  68. el.setAttribute('onsubmit', 'sendForm(); return false;');
  69. // Add an empty paragraph for status
  70. var status = document.createElement('p');
  71. status.setAttribute('id', 'form_status');
  72. el.appendChild(status);
  73. var input = {
  74. name: getField(items.name, lang.form_name_label, false, 'input'),
  75. addr: getField(items.addr, lang.form_addr_label, true, 'input'),
  76. subj: getField(items.subj, lang.form_subj_label, false, 'input'),
  77. text: getField(items.text, lang.form_mesg_label, false, 'textarea')
  78. };
  79. // Adding nodes to document
  80. el.appendChild(input.name);
  81. el.appendChild(input.addr);
  82. el.appendChild(input.subj);
  83. el.appendChild(input.text);
  84. // Adding submit button
  85. el.appendChild(getSubmitButton('form_subm', lang.form_subm_label));
  86. // Retrieve the token from the server
  87. getToken();
  88. }
  89. // Returns a form field
  90. // id: field HTML identifier
  91. // placeholder: placeholder text
  92. // email: boolean: is it an email field?
  93. // type: 'input' or 'textarea'
  94. // return: a div node containing a label and an input text field
  95. function getField(id, placeholder, email, type) {
  96. var field = document.createElement('div');
  97. field.setAttribute('id', id); // TODO: configurable prefix
  98. if(labels) {
  99. field.appendChild(getLabel(id, placeholder, type));
  100. }
  101. field.appendChild(getInputField(id, placeholder, email, type));
  102. return field;
  103. }
  104. // Returns a label
  105. // id: field HTML identifier
  106. // content: label's inner content
  107. // type: 'input' or 'textarea'
  108. // return: a label node the field's description
  109. function getLabel(id, content, type) {
  110. var label = document.createElement('label');
  111. label.setAttribute('for', id + '_' + type);
  112. label.innerHTML = content;
  113. return label;
  114. }
  115. // Returns an input text field
  116. // id: field HTML identifier
  117. // placeholder: placeholder text, field description
  118. // email: boolean: is it an email field?
  119. // type: 'input' or 'textarea'
  120. // return: an input text or email field (depending on "email"'s value') with an
  121. // HTML id and a placeholder text
  122. function getInputField(id, placeholder, email, type) {
  123. var input = document.createElement(type);
  124. if(!type.localeCompare('input')) { // Set input type if input
  125. if(email) {
  126. input.setAttribute('type', 'email');
  127. } else {
  128. input.setAttribute('type', 'text');
  129. }
  130. }
  131. input.setAttribute('required', 'required');
  132. input.setAttribute('placeholder', placeholder);
  133. input.setAttribute('id', id + '_' + type);
  134. return input;
  135. }
  136. // Returns a submit button
  137. // id: button HTML identifier
  138. // text: button text
  139. // return: a div node containing the button
  140. function getSubmitButton(id, text) {
  141. var submit = document.createElement('div');
  142. submit.setAttribute('id', id);
  143. var button = document.createElement('button');
  144. button.setAttribute('type', 'submit');
  145. button.setAttribute('id', id + '_btn');
  146. button.innerHTML = text;
  147. submit.appendChild(button);
  148. return submit;
  149. }
  150. // Send form data through the XHR object
  151. // return: nothing
  152. function sendForm() {
  153. // Clear status
  154. let status = document.getElementById('form_status');
  155. status.setAttribute('class', 'sending');
  156. status.innerHTML = lang.send_status_progress;
  157. xhr.send.open('POST', server + '/send');
  158. xhr.send.setRequestHeader('Content-Type', 'application/json');
  159. xhr.send.send(JSON.stringify(getFormData()));
  160. // Get a new token
  161. getToken();
  162. }
  163. // Fetch form inputs from HTML elements
  164. // return: an object containing all the user's input
  165. function getFormData() {
  166. return {
  167. name: document.getElementById(items.name + '_input').value,
  168. addr: document.getElementById(items.addr + '_input').value,
  169. subj: document.getElementById(items.subj + '_input').value,
  170. text: document.getElementById(items.text + '_textarea').value,
  171. token: token
  172. }
  173. }
  174. // Empties the form fields
  175. // return: nothing
  176. function cleanForm() {
  177. document.getElementById(items.name + '_input').value = '';
  178. document.getElementById(items.addr + '_input').value = '';
  179. document.getElementById(items.subj + '_input').value = '';
  180. document.getElementById(items.text + '_textarea').value = '';
  181. }
  182. // Asks the server for a token
  183. // return: nothing
  184. function getToken() {
  185. xhr.token.open('GET', server + '/register');
  186. xhr.token.send();
  187. }
  188. // Asks the server for translated strings to display
  189. // return: notghing
  190. function getLangSync() {
  191. xhr.lang.open('GET', server + '/lang', false);
  192. xhr.lang.send();
  193. }