jquery.placeholder.js 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. /*!
  2. * jQuery Placeholder Plugin v2.3.1
  3. * https://github.com/mathiasbynens/jquery-placeholder
  4. *
  5. * Copyright 2011, 2015 Mathias Bynens
  6. * Released under the MIT license
  7. */
  8. (function(factory) {
  9. if (typeof define === 'function' && define.amd) {
  10. // AMD
  11. define(['jquery'], factory);
  12. } else if (typeof module === 'object' && module.exports) {
  13. factory(require('jquery'));
  14. } else {
  15. // Browser globals
  16. factory(jQuery);
  17. }
  18. }(function($) {
  19. /****
  20. * Allows plugin behavior simulation in modern browsers for easier debugging.
  21. * When setting to true, use attribute "placeholder-x" rather than the usual "placeholder" in your inputs/textareas
  22. * i.e. <input type="text" placeholder-x="my placeholder text" />
  23. */
  24. var debugMode = false;
  25. // Opera Mini v7 doesn't support placeholder although its DOM seems to indicate so
  26. var isOperaMini = Object.prototype.toString.call(window.operamini) === '[object OperaMini]';
  27. var isInputSupported = 'placeholder' in document.createElement('input') && !isOperaMini && !debugMode;
  28. var isTextareaSupported = 'placeholder' in document.createElement('textarea') && !isOperaMini && !debugMode;
  29. var valHooks = $.valHooks;
  30. var propHooks = $.propHooks;
  31. var hooks;
  32. var placeholder;
  33. var settings = {};
  34. if (isInputSupported && isTextareaSupported) {
  35. placeholder = $.fn.placeholder = function() {
  36. return this;
  37. };
  38. placeholder.input = true;
  39. placeholder.textarea = true;
  40. } else {
  41. placeholder = $.fn.placeholder = function(options) {
  42. var defaults = {customClass: 'placeholder'};
  43. settings = $.extend({}, defaults, options);
  44. return this.filter((isInputSupported ? 'textarea' : ':input') + '[' + (debugMode ? 'placeholder-x' : 'placeholder') + ']')
  45. .not('.'+settings.customClass)
  46. .not(':radio, :checkbox, [type=hidden]')
  47. .bind({
  48. 'focus.placeholder': clearPlaceholder,
  49. 'blur.placeholder': setPlaceholder
  50. })
  51. .data('placeholder-enabled', true)
  52. .trigger('blur.placeholder');
  53. };
  54. placeholder.input = isInputSupported;
  55. placeholder.textarea = isTextareaSupported;
  56. hooks = {
  57. 'get': function(element) {
  58. var $element = $(element);
  59. var $passwordInput = $element.data('placeholder-password');
  60. if ($passwordInput) {
  61. return $passwordInput[0].value;
  62. }
  63. return $element.data('placeholder-enabled') && $element.hasClass(settings.customClass) ? '' : element.value;
  64. },
  65. 'set': function(element, value) {
  66. var $element = $(element);
  67. var $replacement;
  68. var $passwordInput;
  69. if (value !== '') {
  70. $replacement = $element.data('placeholder-textinput');
  71. $passwordInput = $element.data('placeholder-password');
  72. if ($replacement) {
  73. clearPlaceholder.call($replacement[0], true, value) || (element.value = value);
  74. $replacement[0].value = value;
  75. } else if ($passwordInput) {
  76. clearPlaceholder.call(element, true, value) || ($passwordInput[0].value = value);
  77. element.value = value;
  78. }
  79. }
  80. if (!$element.data('placeholder-enabled')) {
  81. element.value = value;
  82. return $element;
  83. }
  84. if (value === '') {
  85. element.value = value;
  86. // Setting the placeholder causes problems if the element continues to have focus.
  87. if (element != safeActiveElement()) {
  88. // We can't use `triggerHandler` here because of dummy text/password inputs :(
  89. setPlaceholder.call(element);
  90. }
  91. } else {
  92. if ($element.hasClass(settings.customClass)) {
  93. clearPlaceholder.call(element);
  94. }
  95. element.value = value;
  96. }
  97. // `set` can not return `undefined`; see http://jsapi.info/jquery/1.7.1/val#L2363
  98. return $element;
  99. }
  100. };
  101. if (!isInputSupported) {
  102. valHooks.input = hooks;
  103. propHooks.value = hooks;
  104. }
  105. if (!isTextareaSupported) {
  106. valHooks.textarea = hooks;
  107. propHooks.value = hooks;
  108. }
  109. $(function() {
  110. // Look for forms
  111. $(document).delegate('form', 'submit.placeholder', function() {
  112. // Clear the placeholder values so they don't get submitted
  113. var $inputs = $('.'+settings.customClass, this).each(function() {
  114. clearPlaceholder.call(this, true, '');
  115. });
  116. setTimeout(function() {
  117. $inputs.each(setPlaceholder);
  118. }, 10);
  119. });
  120. });
  121. // Clear placeholder values upon page reload
  122. $(window).bind('beforeunload.placeholder', function() {
  123. var clearPlaceholders = true;
  124. try {
  125. // Prevent IE javascript:void(0) anchors from causing cleared values
  126. if (document.activeElement.toString() === 'javascript:void(0)') {
  127. clearPlaceholders = false;
  128. }
  129. } catch (exception) { }
  130. if (clearPlaceholders) {
  131. $('.'+settings.customClass).each(function() {
  132. this.value = '';
  133. });
  134. }
  135. });
  136. }
  137. function args(elem) {
  138. // Return an object of element attributes
  139. var newAttrs = {};
  140. var rinlinejQuery = /^jQuery\d+$/;
  141. $.each(elem.attributes, function(i, attr) {
  142. if (attr.specified && !rinlinejQuery.test(attr.name)) {
  143. newAttrs[attr.name] = attr.value;
  144. }
  145. });
  146. return newAttrs;
  147. }
  148. function clearPlaceholder(event, value) {
  149. var input = this;
  150. var $input = $(this);
  151. if (input.value === $input.attr((debugMode ? 'placeholder-x' : 'placeholder')) && $input.hasClass(settings.customClass)) {
  152. input.value = '';
  153. $input.removeClass(settings.customClass);
  154. if ($input.data('placeholder-password')) {
  155. $input = $input.hide().nextAll('input[type="password"]:first').show().attr('id', $input.removeAttr('id').data('placeholder-id'));
  156. // If `clearPlaceholder` was called from `$.valHooks.input.set`
  157. if (event === true) {
  158. $input[0].value = value;
  159. return value;
  160. }
  161. $input.focus();
  162. } else {
  163. input == safeActiveElement() && input.select();
  164. }
  165. }
  166. }
  167. function setPlaceholder(event) {
  168. var $replacement;
  169. var input = this;
  170. var $input = $(this);
  171. var id = input.id;
  172. // If the placeholder is activated, triggering blur event (`$input.trigger('blur')`) should do nothing.
  173. if (event && event.type === 'blur' && $input.hasClass(settings.customClass)) {
  174. return;
  175. }
  176. if (input.value === '') {
  177. if (input.type === 'password') {
  178. if (!$input.data('placeholder-textinput')) {
  179. try {
  180. $replacement = $input.clone().prop({ 'type': 'text' });
  181. } catch(e) {
  182. $replacement = $('<input>').attr($.extend(args(this), { 'type': 'text' }));
  183. }
  184. $replacement
  185. .removeAttr('name')
  186. .data({
  187. 'placeholder-enabled': true,
  188. 'placeholder-password': $input,
  189. 'placeholder-id': id
  190. })
  191. .bind('focus.placeholder', clearPlaceholder);
  192. $input
  193. .data({
  194. 'placeholder-textinput': $replacement,
  195. 'placeholder-id': id
  196. })
  197. .before($replacement);
  198. }
  199. input.value = '';
  200. $input = $input.removeAttr('id').hide().prevAll('input[type="text"]:first').attr('id', $input.data('placeholder-id')).show();
  201. } else {
  202. var $passwordInput = $input.data('placeholder-password');
  203. if ($passwordInput) {
  204. $passwordInput[0].value = '';
  205. $input.attr('id', $input.data('placeholder-id')).show().nextAll('input[type="password"]:last').hide().removeAttr('id');
  206. }
  207. }
  208. $input.addClass(settings.customClass);
  209. $input[0].value = $input.attr((debugMode ? 'placeholder-x' : 'placeholder'));
  210. } else {
  211. $input.removeClass(settings.customClass);
  212. }
  213. }
  214. function safeActiveElement() {
  215. // Avoid IE9 `document.activeElement` of death
  216. try {
  217. return document.activeElement;
  218. } catch (exception) {}
  219. }
  220. }));