UNPKG

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