jquery.placeholder.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /*! http://mths.be/placeholder v2.0.9 by @mathias */
  2. (function(factory) {
  3. if (typeof define === 'function' && define.amd) {
  4. // AMD
  5. define(['jquery'], factory);
  6. } else {
  7. // Browser globals
  8. factory(jQuery);
  9. }
  10. }(function($) {
  11. // Opera Mini v7 doesn’t support placeholder although its DOM seems to indicate so
  12. var isOperaMini = Object.prototype.toString.call(window.operamini) == '[object OperaMini]';
  13. var isInputSupported = 'placeholder' in document.createElement('input') && !isOperaMini;
  14. var isTextareaSupported = 'placeholder' in document.createElement('textarea') && !isOperaMini;
  15. var valHooks = $.valHooks;
  16. var propHooks = $.propHooks;
  17. var hooks;
  18. var placeholder;
  19. if (isInputSupported && isTextareaSupported) {
  20. placeholder = $.fn.placeholder = function() {
  21. return this;
  22. };
  23. placeholder.input = placeholder.textarea = true;
  24. } else {
  25. placeholder = $.fn.placeholder = function() {
  26. var $this = this;
  27. $this
  28. .filter((isInputSupported ? 'textarea' : ':input') + '[placeholder]')
  29. .not('.placeholder')
  30. .bind({
  31. 'focus.placeholder': clearPlaceholder,
  32. 'blur.placeholder': setPlaceholder
  33. })
  34. .data('placeholder-enabled', true)
  35. .trigger('blur.placeholder');
  36. return $this;
  37. };
  38. placeholder.input = isInputSupported;
  39. placeholder.textarea = isTextareaSupported;
  40. hooks = {
  41. 'get': function(element) {
  42. var $element = $(element);
  43. var $passwordInput = $element.data('placeholder-password');
  44. if ($passwordInput) {
  45. return $passwordInput[0].value;
  46. }
  47. return $element.data('placeholder-enabled') && $element.hasClass('placeholder') ? '' : element.value;
  48. },
  49. 'set': function(element, value) {
  50. var $element = $(element);
  51. var $passwordInput = $element.data('placeholder-password');
  52. if ($passwordInput) {
  53. return $passwordInput[0].value = value;
  54. }
  55. if (!$element.data('placeholder-enabled')) {
  56. return element.value = value;
  57. }
  58. if (value === '') {
  59. element.value = value;
  60. // Issue #56: Setting the placeholder causes problems if the element continues to have focus.
  61. if (element != safeActiveElement()) {
  62. // We can't use `triggerHandler` here because of dummy text/password inputs :(
  63. setPlaceholder.call(element);
  64. }
  65. } else if ($element.hasClass('placeholder')) {
  66. clearPlaceholder.call(element, true, value) || (element.value = value);
  67. } else {
  68. element.value = value;
  69. }
  70. // `set` can not return `undefined`; see http://jsapi.info/jquery/1.7.1/val#L2363
  71. return $element;
  72. }
  73. };
  74. if (!isInputSupported) {
  75. valHooks.input = hooks;
  76. propHooks.value = hooks;
  77. }
  78. if (!isTextareaSupported) {
  79. valHooks.textarea = hooks;
  80. propHooks.value = hooks;
  81. }
  82. $(function() {
  83. // Look for forms
  84. $(document).delegate('form', 'submit.placeholder', function() {
  85. // Clear the placeholder values so they don't get submitted
  86. var $inputs = $('.placeholder', this).each(clearPlaceholder);
  87. setTimeout(function() {
  88. $inputs.each(setPlaceholder);
  89. }, 10);
  90. });
  91. });
  92. // Clear placeholder values upon page reload
  93. $(window).bind('beforeunload.placeholder', function() {
  94. $('.placeholder').each(function() {
  95. this.value = '';
  96. });
  97. });
  98. }
  99. function args(elem) {
  100. // Return an object of element attributes
  101. var newAttrs = {};
  102. var rinlinejQuery = /^jQuery\d+$/;
  103. $.each(elem.attributes, function(i, attr) {
  104. if (attr.specified && !rinlinejQuery.test(attr.name)) {
  105. newAttrs[attr.name] = attr.value;
  106. }
  107. });
  108. return newAttrs;
  109. }
  110. function clearPlaceholder(event, value) {
  111. var input = this;
  112. var $input = $(input);
  113. if (input.value == $input.attr('placeholder') && $input.hasClass('placeholder')) {
  114. if ($input.data('placeholder-password')) {
  115. $input = $input.hide().nextAll('input[type="password"]:first').show().attr('id', $input.removeAttr('id').data('placeholder-id'));
  116. // If `clearPlaceholder` was called from `$.valHooks.input.set`
  117. if (event === true) {
  118. return $input[0].value = value;
  119. }
  120. $input.focus();
  121. } else {
  122. input.value = '';
  123. $input.removeClass('placeholder');
  124. input == safeActiveElement() && input.select();
  125. }
  126. }
  127. }
  128. function setPlaceholder() {
  129. var $replacement;
  130. var input = this;
  131. var $input = $(input);
  132. var id = this.id;
  133. if (input.value === '') {
  134. if (input.type === 'password') {
  135. if (!$input.data('placeholder-textinput')) {
  136. try {
  137. $replacement = $input.clone().attr({ 'type': 'text' });
  138. } catch(e) {
  139. $replacement = $('<input>').attr($.extend(args(this), { 'type': 'text' }));
  140. }
  141. $replacement
  142. .removeAttr('name')
  143. .data({
  144. 'placeholder-password': $input,
  145. 'placeholder-id': id
  146. })
  147. .bind('focus.placeholder', clearPlaceholder);
  148. $input
  149. .data({
  150. 'placeholder-textinput': $replacement,
  151. 'placeholder-id': id
  152. })
  153. .before($replacement);
  154. }
  155. $input = $input.removeAttr('id').hide().prevAll('input[type="text"]:first').attr('id', id).show();
  156. // Note: `$input[0] != input` now!
  157. }
  158. $input.addClass('placeholder');
  159. $input[0].value = $input.attr('placeholder');
  160. } else {
  161. $input.removeClass('placeholder');
  162. }
  163. }
  164. function safeActiveElement() {
  165. // Avoid IE9 `document.activeElement` of death
  166. // https://github.com/mathiasbynens/jquery-placeholder/pull/99
  167. try {
  168. return document.activeElement;
  169. } catch (exception) {}
  170. }
  171. }));