jquery.realperson.js 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /* http://keith-wood.name/realPerson.html
  2. Real Person Form Submission for jQuery v1.0.1.
  3. Written by Keith Wood (kwood{at}iinet.com.au) June 2009.
  4. Dual licensed under the GPL (http://dev.jquery.com/browser/trunk/jquery/GPL-LICENSE.txt) and
  5. MIT (http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt) licenses.
  6. Please attribute the author if you use it. */
  7. (function($) { // Hide scope, no $ conflict
  8. var PROP_NAME = 'realPerson';
  9. /* Real person manager. */
  10. function RealPerson() {
  11. this._defaults = {
  12. length: 6, // Number of characters to use
  13. includeNumbers: false, // True to use numbers as well as letters
  14. regenerate: 'Click to change', // Instruction text to regenerate
  15. hashName: '{n}Hash' // Name of the hash value field to compare with,
  16. // use {n} to substitute with the original field name
  17. };
  18. }
  19. var CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
  20. var DOTS = [
  21. [' * ', ' * * ', ' * * ', ' * * ', ' ***** ', '* *', '* *'],
  22. ['****** ', '* *', '* *', '****** ', '* *', '* *', '****** '],
  23. [' ***** ', '* *', '* ', '* ', '* ', '* *', ' ***** '],
  24. ['****** ', '* *', '* *', '* *', '* *', '* *', '****** '],
  25. ['*******', '* ', '* ', '**** ', '* ', '* ', '*******'],
  26. ['*******', '* ', '* ', '**** ', '* ', '* ', '* '],
  27. [' ***** ', '* *', '* ', '* ', '* ***', '* *', ' ***** '],
  28. ['* *', '* *', '* *', '*******', '* *', '* *', '* *'],
  29. ['*******', ' * ', ' * ', ' * ', ' * ', ' * ', '*******'],
  30. [' *', ' *', ' *', ' *', ' *', '* *', ' ***** '],
  31. ['* *', '* ** ', '* ** ', '** ', '* ** ', '* ** ', '* *'],
  32. ['* ', '* ', '* ', '* ', '* ', '* ', '*******'],
  33. ['* *', '** **', '* * * *', '* * *', '* *', '* *', '* *'],
  34. ['* *', '** *', '* * *', '* * *', '* * *', '* **', '* *'],
  35. [' ***** ', '* *', '* *', '* *', '* *', '* *', ' ***** '],
  36. ['****** ', '* *', '* *', '****** ', '* ', '* ', '* '],
  37. [' ***** ', '* *', '* *', '* *', '* * *', '* * ', ' **** *'],
  38. ['****** ', '* *', '* *', '****** ', '* * ', '* * ', '* *'],
  39. [' ***** ', '* *', '* ', ' ***** ', ' *', '* *', ' ***** '],
  40. ['*******', ' * ', ' * ', ' * ', ' * ', ' * ', ' * '],
  41. ['* *', '* *', '* *', '* *', '* *', '* *', ' ***** '],
  42. ['* *', '* *', ' * * ', ' * * ', ' * * ', ' * * ', ' * '],
  43. ['* *', '* *', '* *', '* * *', '* * * *', '** **', '* *'],
  44. ['* *', ' * * ', ' * * ', ' * ', ' * * ', ' * * ', '* *'],
  45. ['* *', ' * * ', ' * * ', ' * ', ' * ', ' * ', ' * '],
  46. ['*******', ' * ', ' * ', ' * ', ' * ', ' * ', '*******'],
  47. [' *** ', ' * * ', '* *', '* *', '* *', ' * * ', ' *** '],
  48. [' * ', ' ** ', ' * * ', ' * ', ' * ', ' * ', '*******'],
  49. [' ***** ', '* *', ' *', ' * ', ' ** ', ' ** ', '*******'],
  50. [' ***** ', '* *', ' *', ' ** ', ' *', '* *', ' ***** '],
  51. [' * ', ' ** ', ' * * ', ' * * ', '*******', ' * ', ' * '],
  52. ['*******', '* ', '****** ', ' *', ' *', '* *', ' ***** '],
  53. [' **** ', ' * ', '* ', '****** ', '* *', '* *', ' ***** '],
  54. ['*******', ' * ', ' * ', ' * ', ' * ', ' * ', '* '],
  55. [' ***** ', '* *', '* *', ' ***** ', '* *', '* *', ' ***** '],
  56. [' ***** ', '* *', '* *', ' ******', ' *', ' * ', ' **** ']];
  57. $.extend(RealPerson.prototype, {
  58. /* Class name added to elements to indicate already configured with real person. */
  59. markerClassName: 'hasRealPerson',
  60. /* Override the default settings for all real person instances.
  61. @param settings (object) the new settings to use as defaults
  62. @return (RealPerson) this object */
  63. setDefaults: function(settings) {
  64. $.extend(this._defaults, settings || {});
  65. return this;
  66. },
  67. /* Attach the real person functionality to an input field.
  68. @param target (element) the control to affect
  69. @param settings (object) the custom options for this instance */
  70. _attachRealPerson: function(target, settings) {
  71. target = $(target);
  72. if (target.hasClass(this.markerClassName)) {
  73. return;
  74. }
  75. target.addClass(this.markerClassName);
  76. var inst = {settings: $.extend({}, this._defaults)};
  77. $.data(target[0], PROP_NAME, inst);
  78. this._changeRealPerson(target, settings);
  79. },
  80. /* Reconfigure the settings for a real person control.
  81. @param target (element) the control to affect
  82. @param settings (object) the new options for this instance or
  83. (string) an individual property name
  84. @param value (any) the individual property value (omit if settings is an object) */
  85. _changeRealPerson: function(target, settings, value) {
  86. target = $(target);
  87. if (!target.hasClass(this.markerClassName)) {
  88. return;
  89. }
  90. settings = settings || {};
  91. if (typeof settings == 'string') {
  92. var name = settings;
  93. settings = {};
  94. settings[name] = value;
  95. }
  96. var inst = $.data(target[0], PROP_NAME);
  97. $.extend(inst.settings, settings);
  98. target.prevAll('.realperson-challenge,.realperson-hash').remove().end().
  99. before(this._generateHTML(target, inst));
  100. },
  101. /* Generate the additional content for this control.
  102. @param target (jQuery) the input field
  103. @param inst (object) the current instance settings
  104. @return (string) the additional content */
  105. _generateHTML: function(target, inst) {
  106. var text = '';
  107. for (var i = 0; i < inst.settings.length; i++) {
  108. text += CHARS.charAt(Math.floor(Math.random() *
  109. (inst.settings.includeNumbers ? 36 : 26)));
  110. }
  111. var html = '<div class="realperson-challenge"><div class="realperson-text">';
  112. for (var i = 0; i < DOTS[0].length; i++) {
  113. for (var j = 0; j < text.length; j++) {
  114. html += DOTS[CHARS.indexOf(text.charAt(j))][i].replace(/ /g, '&nbsp;') +
  115. '&nbsp;&nbsp;';
  116. }
  117. html += '<br>';
  118. }
  119. html += '</div><div class="realperson-regen">' + inst.settings.regenerate +
  120. '</div></div><input type="hidden" class="realperson-hash" name="' +
  121. inst.settings.hashName.replace(/\{n\}/, target.attr('name')) +
  122. '" value="' + this._hash(text) + '">';
  123. return html;
  124. },
  125. /* Remove the real person functionality from a control.
  126. @param target (element) the control to affect */
  127. _destroyRealPerson: function(target) {
  128. target = $(target);
  129. if (!target.hasClass(this.markerClassName)) {
  130. return;
  131. }
  132. target.removeClass(this.markerClassName).
  133. prevAll('.realperson-challenge,.realperson-hash').remove();
  134. $.removeData(target[0], PROP_NAME);
  135. },
  136. /* Compute a hash value for the given text.
  137. @param value (string) the text to hash
  138. @return the corresponding hash value */
  139. _hash: function(value) {
  140. var hash = 5381;
  141. for (var i = 0; i < value.length; i++) {
  142. hash = ((hash << 5) + hash) + value.charCodeAt(i);
  143. }
  144. return hash;
  145. }
  146. });
  147. /* Attach the real person functionality to a jQuery selection.
  148. @param command (string) the command to run (optional, default 'attach')
  149. @param options (object) the new settings to use for these instances (optional)
  150. @return (jQuery) for chaining further calls */
  151. $.fn.realperson = function(options) {
  152. var otherArgs = Array.prototype.slice.call(arguments, 1);
  153. return this.each(function() {
  154. if (typeof options == 'string') {
  155. $.realperson['_' + options + 'RealPerson'].
  156. apply($.realperson, [this].concat(otherArgs));
  157. }
  158. else {
  159. $.realperson._attachRealPerson(this, options || {});
  160. }
  161. });
  162. };
  163. /* Initialise the real person functionality. */
  164. $.realperson = new RealPerson(); // singleton instance
  165. $('.realperson-challenge').live('click', function() {
  166. $(this).next().next().realperson('change');
  167. });
  168. })(jQuery);