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

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