Posted By

dom111 on 08/13/08


Tagged

form ajax javascript forms submit mootools onsubmit


Versions (?)

Who likes this?

3 people have marked this snippet as a favorite

esquareda
stephenns
umang_nine


submitEvents - Javascript form submission handler


 / Published in: JavaScript
 

URL: http://www.dom111.co.uk/blog/coding/submitevents-javascript-form-submission-handler/20

Requires Mootools 1.2<br/> http://mootools.net/download

Based on the mootools javascript framework a re-usable class for easily implementing an array of on submit events.

  • Confirmation - Provides an Ok, Cancel input box before proceeding further
  • Submit Button - Disable and change the text on a submit button
  • Information Div - Display a div that lets the user know something is happening
  • Undo - Undo the changes (re-enable a previously disabled submit button, change the information div) that have been carried out by the class
  • AJAX - Submit the form using AJAX instead of the ‘old fashioned’ way

This work is released under the creative commons share alike license.

Requires Mootools 1.2<br/> http://mootools.net/download

  1. //
  2. // submitEvent 0.2
  3. // 19/08/2008
  4. //
  5. // Version History:
  6. //
  7. // 0.2
  8. // Slightly better fix, using .bind(this) instead of a temporary
  9. // window.submitFormData var
  10. //
  11. // 0.11
  12. // Hacky fix for IE6
  13. //
  14. // 0.1
  15. // Initial release
  16. //
  17. //
  18. // A small class for easily implementing many submit events including
  19. // displaying a confirmation dialog, disabling the submit button and
  20. // displaying an informative div so that the users stay informed.
  21. //
  22. // Please see example.html for some examples
  23. //
  24. // All the options are detailed below, and the defaults can be easily
  25. // changed to suit your needs.
  26. //
  27. // Requires mootools 1.2 (I don't think it'll work with lower) although
  28. // I may also make a prototype/scriptaculous version if required.
  29. //
  30. // This software is released under the Creative Commons Share Alike
  31. // license.
  32. //
  33. // Dom
  34. //
  35. // http://www.dom111.co.uk/
  36. //
  37. var submitEvent = new Class({
  38. Implements: [Options],
  39.  
  40. // options
  41. //
  42. // the default options
  43. // these can be overridden here if you use the same
  44. // settings often, to save yourself time
  45. //
  46. options: {
  47. // confirmation
  48. //
  49. // enabled: boolean
  50. // text: text to display on said dialog box
  51. // confirmed: used internally to make sure the
  52. // confirmation isn't displayed again if there's a
  53. // timeout
  54. confirmation: {
  55. enabled: false,
  56. text: 'Are you sure?',
  57. confirmed: false
  58. },
  59. // submitButton
  60. //
  61. // object: the object (or id as string) that is the
  62. // primary submit button for f
  63. // changeText: whether or not to change the button's
  64. // text on submit
  65. // newText: text to change the button to
  66. //
  67. submitButton: {
  68. object: null,
  69. disable: true,
  70. changeText: true,
  71. text: 'Please wait...'
  72. },
  73. // informationDiv
  74. //
  75. // display: whether or not to diplay an information
  76. // div
  77. // className: CSS class to apply to the div
  78. // centered: whether to horizontally center the div
  79. // (uses left: xxpx so class must add position absolute)
  80. // text: text (or HTML to populate the div with
  81. // inject: element to inject the div into (this.form
  82. // is used if this is left as null/false)
  83. // injectTo: position to inject element to eg. bottom,
  84. // top, before, after defaults to after
  85. //
  86. informationDiv: {
  87. enabled: true,
  88. className: '',
  89. centered: true,
  90. text: 'Loading...',
  91. inject: null,
  92. injectTo: 'after'
  93. },
  94. //
  95. // undo
  96. // enabled: boolean
  97. // timeout: in seconds to run specified undo tasks
  98. //
  99. // submitButton:
  100. // enabled: re-enable the submit button
  101. // newText: text to display on the newly enabled
  102. // submit button
  103. //
  104. // informationDiv
  105. // text: updated text to display
  106. // className: updated CSS class to apply
  107. undo: {
  108. enabled: true,
  109. timeOut: 30,
  110. submitButton: {
  111. enabled: true,
  112. newText: 'Try Again'
  113. },
  114. informationDiv: {
  115. enabled: true,
  116. text: 'Sorry, there was a problem.',
  117. className: ''
  118. }
  119. },
  120. //
  121. // ajax
  122. //
  123. // makes the form submission use ajax
  124. //
  125. // enabled: boolean
  126. // update: the dom node, or a string id of the element
  127. // to update, if not set, defaults to this.form
  128. // appendUrl: a query string to append to the ajax request
  129. // (could be used to surpress header/footer or just distinguish
  130. // between ajax/normal requests)
  131. //
  132. ajax: {
  133. enabled: false,
  134. udpate: null,
  135. appendUrl: 'ajax=1'
  136. }
  137. },
  138.  
  139. initialize: function(f, o) {
  140. // if f is a string, look for that element id...
  141. if ($type(f) == 'string') {
  142. f = $(f);
  143. }
  144.  
  145. // if f still isn't an object, give up...
  146. if ($type(f) != 'object' && $type(f) != 'element') {
  147. return true; // ... and submit the form, because we can't do anything...
  148. }
  149.  
  150. // store the form object as this.form
  151. this.form = f;
  152.  
  153. // save the old onsubmit function
  154. this.preservedOnSubmit = this.form.onsubmit || function() {};
  155.  
  156. // merge the options...
  157. this.setOptions(o || {});
  158. if (!(this.options.submitButton.object)) {
  159. this.options.submitButton.object = this.findSubmitButton(this.form);
  160. if (!(this.options.submitButton.object.id)) {
  161. this.options.submitButton.object.id = 'submitEventSubmitButton_' + new Date().getTime();
  162. }
  163. }
  164.  
  165. this.options.submitButton.oldText = this.options.submitButton.object.value;
  166.  
  167. this.informationDiv = false;
  168. this.submitButtonFunctionTimeout = false;
  169. this.informationDivFunctionTimeout = false;
  170. },
  171.  
  172. // process
  173. //
  174. // do the magic!
  175. process: function() {
  176. // carry out functions in order:
  177. //
  178. // check for a confirmation message first, as if the user
  179. // wants to cancel we could save ourselves some time
  180. if ((this.options.confirmation.enabled) && !(this.options.confirmation.confirmed)) {
  181. // if the text is blank or it's not a string
  182. if (!(this.options.confirmation.text) || $type(this.options.confirmation.text) != 'string') {
  183. // set it to some default text
  184. this.options.confirmation.text = 'Are you sure?'
  185. }
  186. // set c to true/false from the user box
  187. var c = confirm(this.options.confirmation.text);
  188.  
  189. // if it's true
  190. if (c) {
  191. // set the confirmed variable to true so the dialog isn't displayed again
  192. this.options.confirmation.confirmed = true;
  193. } else {
  194. // else stop processing anything
  195. return false;
  196. }
  197. }
  198.  
  199. // next, change the submit button if required
  200. if ((this.options.submitButton.changeText) || (this.options.submitButton.disable)) {
  201. // if the object, isn't an object, make it one
  202. if ($type(this.options.submitButton.object) == 'string') {
  203. this.options.submitButton.object = $(this.options.submitButton.object);
  204. }
  205.  
  206. // create a variable for the button, of the object
  207. var button = this.options.submitButton.object;
  208.  
  209. // make sure it's not null or false
  210. if (button) {
  211.  
  212. // if we're supposed to change the text, do...
  213. if (this.options.submitButton.changeText) {
  214. button.value = this.options.submitButton.text || 'Please wait...';
  215. }
  216.  
  217. // if we're supposed to disable it, do!
  218. if (this.options.submitButton.disable) {
  219. button.disabled = true;
  220. }
  221. }
  222. }
  223.  
  224. // information div... display if required
  225. if ((this.informationDiv) || (this.options.informationDiv.enabled)) {
  226. if ((this.options.informationDiv.text) && $type(this.options.informationDiv.text) == 'string') {
  227. // check the text is a string and nothing else
  228. if (!this.informationDiv) {
  229. // create a div element
  230. this.informationDiv = new Element('div', {
  231. 'id': 'submitEventInformationDiv_' + new Date().getTime()
  232. });
  233.  
  234. } else {
  235. if (this.options.undo.informationDiv.className) {
  236. this.informationDiv.removeClass(this.options.undo.informationDiv.className);
  237. }
  238. }
  239.  
  240. // set the innerHTML to the specified 'text', or default
  241. this.informationDiv.set('html', this.options.informationDiv.text || 'Loading...');
  242. // add the className if set
  243. this.informationDiv.addClass(this.options.informationDiv.className || '')
  244. // inject the element into the specified element, or this.form if not specified
  245. this.informationDiv.inject(this.options.informationDiv.inject || this.form, this.options.informationDiv.injectTo || 'after');
  246.  
  247. if (this.options.informationDiv.centered) {
  248. this.informationDiv.setStyle('left', this.getCenter(this.informationDiv) + 'px');
  249. }
  250. }
  251. }
  252.  
  253. // undo, the best bit...
  254. //
  255. // if we can run undo tasks and at least one is enabled...
  256. if (this.options.undo.enabled && (this.options.undo.submitButton.enabled || this.options.undo.informationDiv.enabled)) {
  257. // set the timeout variable to seconds * 1000 (milliseconds)
  258. var timeOut = (this.options.undo.timeOut || 30) * 1000;
  259.  
  260. // if we can run the undo on the button
  261. if (this.options.undo.submitButton.enabled) {
  262. // build the function to re-enable it and change the text
  263. submitButtonFunction = function() {
  264. var button = this.options.submitButton.object;
  265. button.disabled = false;
  266. button.value = this.options.undo.submitButton.newText || this.options.submitButton.oldText;
  267. }
  268. // use mootools timeout function, which allows this to be used
  269. this.submitButtonFunctionTimeout = submitButtonFunction.delay(timeOut, this);
  270. }
  271.  
  272. // if we can do the same magic with the information div...
  273. if (this.options.undo.informationDiv.enabled) {
  274.  
  275. // build a function to change the text
  276. informationDivFunction = function() {
  277. if (this.options.undo.informationDiv.text) {
  278. this.informationDiv.set('html', this.options.undo.informationDiv.text || 'Sorry, there was a problem.');
  279. }
  280.  
  281. // and add the new class
  282. if (this.options.undo.informationDiv.className) {
  283. this.informationDiv.removeClass(this.options.informationDiv.className || '');
  284. this.informationDiv.addClass(this.options.undo.informationDiv.className);
  285. }
  286.  
  287. if (this.options.informationDiv.centered) {
  288. this.informationDiv.set('styles', {
  289. 'left': this.getCenter(this.informationDiv) + 'px'
  290. })
  291. }
  292. }
  293.  
  294. // another lovely timeout function
  295. this.informationDivFunctionTimeout = informationDivFunction.delay(timeOut, this);
  296. }
  297. }
  298.  
  299. // if we're ajaxing it up...
  300. if (this.options.ajax.enabled) {
  301. // create a mootools request object
  302. this.ajaxRequest = new Request.HTML({
  303. // populate it with all the details from the HTML form
  304. method: this.form.method,
  305. url: this.appendQueryString(this.form.action),
  306. // data: this.form.toQueryString(), // fails in IE 6?
  307. data: this.formToQueryString(this.form),
  308. update: this.options.ajax.update || this.form,
  309. // add an oncomplete function to remove the additions
  310. onComplete: function() {
  311. $clear(this.submitButtonFunctionTimeout);
  312. $clear(this.informationDivFunctionTimeout);
  313. if ($(this.informationDiv.id)) {
  314. $(this.informationDiv.id).destroy();
  315. }
  316. if ($(this.options.submitButton.object.id)) {
  317. $(this.options.submitButton.object.id).value = this.options.submitButton.oldText;
  318. $(this.options.submitButton.object.id).disabled = false;
  319. }
  320. }.bind(this)
  321. }).send();
  322.  
  323. // make sure the main form isn't submitted
  324. return false;
  325. } else {
  326. return true; // post the form
  327. }
  328. },
  329.  
  330. // findSubmitButton
  331. //
  332. // returns the first submit button on a form
  333. //
  334. findSubmitButton: function(f) {
  335. // if f fails use document
  336. f = f || document;
  337. // loop through all input elements in f
  338. var i = f.getElementsByTagName('input');
  339. for (var x = i.length - 1; x >= 0; x--) {
  340. if (i[x].type == 'submit' || i[x].type == 'image') {
  341. return i[x];
  342. }
  343. }
  344. // loop through all button elements in f
  345. var i = f.getElementsByTagName('button');
  346. for (var x = i.length - 1; x >= 0; x--) {
  347. if (i[x].type == 'submit') {
  348. return i[x];
  349. }
  350. }
  351. // we didn't find anything, so return null
  352. return null;
  353. },
  354.  
  355. // getCenter
  356. //
  357. // returns the width of the screen / 2 or the width
  358. // of the screen - el.width / 2 for centering elements
  359. //
  360. getCenter: function(el) {
  361. // w contains w.x and w.y
  362. var w = window.getSize();
  363.  
  364. // if el is a string, make it an element
  365. if ($type(el) == 'string') {
  366. el = $(el);
  367. }
  368.  
  369. // if el is all working
  370. if (el) {
  371. // get the sizes of it
  372. var e = el.getSize();
  373.  
  374. // return the screen size minus the elements width / 2
  375. return (w.x - e.x) / 2;
  376.  
  377. } else {
  378. // just return the screen size / 2
  379. return w.x / 2;
  380. }
  381. },
  382.  
  383. // appendQueryString
  384. //
  385. // returns the url with the extra query string correctly
  386. // appended
  387. //
  388. appendQueryString: function(u) {
  389. if (q = this.options.ajax.appendUrl) {
  390. return (u.match(/\?/)) ? u + '&' + q : u + '?' + q;
  391. } else {
  392. return u;
  393. }
  394. },
  395.  
  396. // formToQueryString
  397. //
  398. // Ripped and modified from mooTools as form.toObject() was failing.
  399. //
  400. formToQueryString: function(form) {
  401. var obj = {};
  402.  
  403. var inputs = form.getElementsByTagName('input');
  404. var selects = form.getElementsByTagName('select');
  405. var textareas = form.getElementsByTagName('textarea');
  406.  
  407. var els = [];
  408. els[els.length] = inputs;
  409. els[els.length] = selects;
  410. els[els.length] = textareas;
  411.  
  412. for (var i = 0; i < els.length; i++) {
  413. for (var j = 0; j < els[i].length; j++) {
  414. var name = els[i][j].name;
  415. var value = els[i][j].value;
  416. if ((value !== false) && name) obj[name] = value;
  417. }
  418. }
  419.  
  420. var s = '';
  421.  
  422. $each(obj, function(value, name) {
  423. s += name + '=' + value + '&';
  424. });
  425.  
  426. return s;
  427. }
  428.  
  429. });
  430.  
  431. Examples:
  432.  
  433. <?php
  434. if (!empty($_POST)) {
  435. sleep(5);
  436. var_dump($_POST);
  437. die();
  438. }
  439. ?>
  440. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  441. "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  442. <html>
  443. <head>
  444. <title>submitEvents</title>
  445.  
  446. <script src="/js/mootools1.2.js" type="text/javascript" charset="utf-8"></script>
  447. <script src="/js/submitEvent.js" type="text/javascript" charset="utf-8"></script>
  448. </head>
  449. <body>
  450. <form action="examples.php" method="post" onsubmit="return new submitEvent(this).process();">
  451. <p>This form is using the default options</p>
  452. <p><input type="text" name="name" value="" id="name"/></p>
  453. <p><input type="text" name="email" value="" id="email"/></p>
  454. <p><input type="submit" name="submitButton" value="Submit"/></p>
  455. </form>
  456.  
  457. <form action="examples.php" method="post" onsubmit="return new submitEvent(this, { ajax: { enabled: true, update: $('test1') }, undo: { timeOut: 3 } } ).process();">
  458. <p>This form is using the default options with ajax (and a very low undo wait, to test the return to normality...)</p>
  459. <p><input type="text" name="name" value="" id="name"/></p>
  460. <p><input type="text" name="email" value="" id="email"/></p>
  461. <p><input type="submit" name="submitButton" value="Submit"/></p>
  462. </form>
  463. <div id="test1"></div>
  464.  
  465. <form action="examples.php" method="post" onsubmit="return new submitEvent(this, { confirmation: { enabled: true, text: 'Sure you\'re ready to submit?' } } ).process();">
  466. <p>This form is using the default options with a confirmation dialog</p>
  467. <p><input type="text" name="name" value="" id="name"/></p>
  468. <p><input type="text" name="email" value="" id="email"/></p>
  469. <p><input type="submit" name="submitButton" value="Submit"/></p>
  470. </form>
  471.  
  472. <form action="examples.php" method="post" onsubmit="return new submitEvent(this, { confirmation: { enabled: false }, ajax: { enabled: false }, informationDiv: { enabled: false } } ).process();">
  473. <p>This form is only going to disable the submit button</p>
  474. <p><input type="text" name="name" value="" id="name"/></p>
  475. <p><input type="text" name="email" value="" id="email"/></p>
  476. <p><input type="submit" name="submitButton" value="Submit"/></p>
  477. </form>
  478.  
  479. <form action="examples.php" method="post" id="totallyJavascriptForm">
  480. <p>This form is using the default options, but specified directly, and the event is added via javascript</p>
  481. <p><input type="text" name="name" value="" id="name"/></p>
  482. <p><input type="text" name="email" value="" id="email"/></p>
  483. <p><input type="submit" name="submitButton" value="Submit"/></p>
  484. </form>
  485.  
  486. <script type="text/javascript" charset="utf-8">
  487. $('totallyJavascriptForm').addEvent('submit', function() {
  488. return new submitEvent(this, {
  489. confirmation: {
  490. confirmation: {
  491. enabled: false,
  492. text: 'Are you sure?',
  493. confirmed: false
  494. },
  495. submitButton: {
  496. object: null,
  497. disable: true,
  498. changeText: true,
  499. text: 'Please wait...'
  500. },
  501. informationDiv: {
  502. enabled: true,
  503. className: '',
  504. centered: true,
  505. text: 'Loading...',
  506. inject: null,
  507. injectTo: 'after'
  508. },
  509. undo: {
  510. enabled: true,
  511. timeOut: 30,
  512. submitButton: {
  513. enabled: true,
  514. newText: 'Try Again'
  515. },
  516. informationDiv: {
  517. enabled: true,
  518. text: 'Sorry, there was a problem.',
  519. className: ''
  520. }
  521. },
  522. ajax: {
  523. enabled: false,
  524. udpate: null,
  525. appendUrl: 'ajax=1'
  526. }
  527. }
  528. }).process()
  529. });
  530. </script>
  531.  
  532. </body>
  533. </html>

Report this snippet  

Comments

RSS Icon Subscribe to comments
Posted By: dom111 on August 14, 2008

There were some problems in IE6 running this class, script has been updated to work properly now...

You need to login to post a comment.