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

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