Form result:
28 |├── js ├── .jshintrc ├── jquery.placeholder-enhanced.min.js └── jquery.placeholder-enhanced.js ├── Makefile ├── css ├── placeholder-enhanced.css └── demo.css ├── package.json ├── LICENSE.txt ├── demo.html └── README.md /js/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "camelcase": true, 3 | "curly": true, 4 | "eqeqeq": true, 5 | "forin": true, 6 | "immed": true, 7 | "latedef": true, 8 | "noarg": true, 9 | "noempty": true, 10 | "quotmark": "single", 11 | "undef": true, 12 | "unused": true, 13 | "strict": true, 14 | "trailing": true, 15 | "browser": true, 16 | "jquery": true 17 | } 18 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # vim: ts=4 sw=4 noexpandtab 2 | SHELL := /bin/bash 3 | LICENSE_SHORT := "/*! jQuery Placeholder Enhanced 1.6.9 | @tdecs | under the MIT license */" 4 | BIN := ./node_modules/.bin 5 | INPUT := ./js/jquery.placeholder-enhanced.js 6 | OUTPUT := ./js/jquery.placeholder-enhanced.min.js 7 | 8 | build: 9 | @rm ${OUTPUT} 10 | @echo ${LICENSE_SHORT} > ${OUTPUT} 11 | @node ${BIN}/uglifyjs ${INPUT} -c -m --comments >> ${OUTPUT} 12 | 13 | lint: 14 | @node ${BIN}/jshint ${INPUT} 15 | 16 | .PHONY: lint 17 | -------------------------------------------------------------------------------- /css/placeholder-enhanced.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * jQuery Placeholder Enhanced 1.6.9 3 | * Copyright (c) 2013-2015 Denis Ciccale (@tdecs) 4 | * Released under MIT license 5 | * https://raw.github.com/dciccale/placeholder-enhanced/master/LICENSE.txt 6 | */ 7 | 8 | /* 9 | * You may change the name of the class 10 | * (remember changing it in the js file too) 11 | */ 12 | 13 | /* All browsers */ 14 | .placeholder { 15 | color: #aaa; 16 | } 17 | 18 | /* WebKit */ 19 | ::-webkit-input-placeholder { 20 | color: #aaa; 21 | } 22 | 23 | /* Firefox 4 to 18 */ 24 | :-moz-placeholder { 25 | color: #aaa; 26 | } 27 | 28 | /* Firefox 19+ */ 29 | ::-moz-placeholder { 30 | color: #aaa; 31 | } 32 | 33 | /* Internet Explorer 10+ */ 34 | :-ms-input-placeholder { 35 | color: #aaa; 36 | } 37 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "placeholder-enhanced", 3 | "version": "1.6.9", 4 | "description": "This jQuery Placeholder plugin is an enhanced polyfill for the HTML5 placeholder attribute.", 5 | "keywords": ["placeholder", "enhanced", "html5", "polyfill"], 6 | "homepage": "https://github.com/dciccale/placeholder-enhanced", 7 | "author": { 8 | "name": "Denis Ciccale", 9 | "email": "dciccale@gmail.com", 10 | "url": "http://twitter.com/tdecs" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git://github.com/dciccale/placeholder-enhanced.git" 15 | }, 16 | "bugs": { 17 | "url": "https://github.com/dciccale/placeholder-enhanced/issues" 18 | }, 19 | "licenses": [ 20 | { 21 | "type": "MIT", 22 | "url": "https://github.com/dciccale/placeholder-enhanced/blob/master/LICENSE.txt" 23 | } 24 | ], 25 | "devDependencies": { 26 | "jshint": "^2.8.0", 27 | "uglify-js": "^2.4.23" 28 | }, 29 | "dependencies": { 30 | "jquery": ">=1.4.4" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Denis Ciccale (@tdecs) 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without limitation 7 | the rights to use, copy, modify, merge, publish, 8 | distribute, sublicense, and/or sell copies of the 9 | Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice 13 | shall be included in all copies or substantial portions of 14 | the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY 17 | KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 18 | WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 19 | PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS 20 | OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 22 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /css/demo.css: -------------------------------------------------------------------------------- 1 | *{margin:0;padding:0;outline:0;font-size:1em;font-weight:normal;font-style:normal;border:0;text-decoration:none;list-style-type:none} 2 | 3 | body { 4 | padding:30px; 5 | font-family:verdana; 6 | background-color:#ebebeb; 7 | font-size:1em; 8 | } 9 | 10 | h1, h2 { 11 | font-family:'Trebuchet MS'; 12 | font-weight:bold; 13 | } 14 | 15 | h1 { 16 | font-size:22px; 17 | margin-bottom:20px; 18 | } 19 | 20 | h2 { 21 | font-size:18px; 22 | margin-bottom:10px; 23 | } 24 | 25 | a { 26 | color:#00F; 27 | text-decoration:underline; 28 | } 29 | 30 | a:hover { 31 | color:#000; 32 | } 33 | 34 | #content { 35 | background-color:#fff; 36 | border:3px solid #ccc; 37 | padding:20px; 38 | } 39 | 40 | p { 41 | margin:10px 0; 42 | } 43 | 44 | label { 45 | cursor:pointer; 46 | font-size:14px; 47 | } 48 | 49 | strong { 50 | font-weight:bold; 51 | } 52 | 53 | .separator { 54 | overflow:hidden; 55 | height:25px; 56 | margin-bottom:25px; 57 | border-bottom:1px solid #999; 58 | clear:left; 59 | } 60 | 61 | #submit { 62 | margin:0; 63 | } 64 | 65 | .btn { 66 | padding:5px 15px; 67 | border:2px solid gray; 68 | font-size:14px; 69 | cursor:pointer; 70 | background-color:#ccc; 71 | color:#333; 72 | font-weight:bold; 73 | } 74 | 75 | input, textarea { 76 | font-family:verdana; 77 | font-size:.85em; 78 | border:1px solid #ccc; 79 | padding:3px; 80 | } 81 | -------------------------------------------------------------------------------- /js/jquery.placeholder-enhanced.min.js: -------------------------------------------------------------------------------- 1 | /*! jQuery Placeholder Enhanced 1.6.9 | @tdecs | under the MIT license */ 2 | !function(e,a){"use strict";var l="placeholderEnhanced",s=a.createElement("input"),t=a.createElement("textarea"),n="placeholder"in s&&"placeholder"in t,r={FOCUS:"focus.placeholder",BLUR:"blur.placeholder"},o={cssClass:"placeholder",normalize:!0},c=e.fn.val,i=function(a){return e.nodeName(a,"input")||e.nodeName(a,"textarea")},d=function(a){for(var l,s=["placeholder","name","id"],t={},n=0,r=a.attributes.length;r>n;n++)l=a.attributes[n],l.specified&&e.inArray(l.name,s)<0&&(t[l.name]=l.value);return t},u=function(e){e.css({position:"",left:""})},p=function(e){e.css({position:"absolute",left:"-9999em"})};(!n||o.normalize)&&(n?n&&o.normalize&&(e.fn.val=function(){var a=arguments,s=this[0];return s?a.length?this.each(function(s,t){var n=e(t),r=e.data(t,l),o=t._placeholder;r&&o&&i(t)&&(a[0]||t.value===o?a[0]&&n.hasClass(r.cssClass)&&n.removeClass(r.cssClass):n.addClass(r.cssClass).attr("placeholder",o)),c.apply(n,a)}):c.apply(this,a):void 0}):e.fn.val=function(){var a,s=arguments,t=this[0];return t?s.length?this.each(function(a,t){var n=e(t),r=e.data(t,l),o=n.attr("placeholder");r&&o&&i(t)?s[0]||t.value===o?s[0]&&(n.hasClass(r.cssClass)&&n.removeClass(r.cssClass),c.apply(n,s)):t.value=n.addClass(r.cssClass).attr("placeholder"):c.apply(n,s)}):(a=e(t).attr("placeholder"),a&&i(t)?t.value===a?"":t.value:c.apply(this,s)):void 0},e.fn[l]=function(a){var s=e.extend(o,a);if(this.length&&(!n||s.normalize))return"destroy"===a?this.filter(function(a,s){return e.data(s,l)}).removeClass(s.cssClass).each(function(a,s){var t=e(s).unbind(".placeholder"),r="password"===s.type,o=t.attr("placeholder");n?delete s._placeholder:(s.value===o&&(s.value=""),r&&(u(t),t.prev().unbind(".placeholder").remove())),e.fn.val=c,e.removeData(s,l)}):this.each(function(a,t){if(!e.data(t,l)){e.data(t,l,s);var o=e(t),c="password"===t.type,i=o.attr("placeholder"),h=null,v=null,f=null;n?n&&s.normalize&&(t._placeholder=o.attr("placeholder"),v=function(){t.value||o.addClass(s.cssClass).attr("placeholder",i)},f=function(){o.removeAttr("placeholder").removeClass(s.cssClass)}):(v=function(){o.val()?o.val()&&c&&f():c?(u(h),p(o)):o.val(i).addClass(s.cssClass)},c?(f=function(){u(o),p(h)},h=e("",e.extend(d(t),{type:"text",value:i,tabindex:-1})).addClass(s.cssClass).bind(r.FOCUS,function(){o.trigger(r.FOCUS)}).insertBefore(o)):f=function(){o.hasClass(s.cssClass)&&(t.value="",o.removeClass(s.cssClass))}),o.bind(r.BLUR,v).bind(r.FOCUS,f).trigger(r.BLUR)}})},e(function(){e("input[placeholder], textarea[placeholder]")[l]()}))}(jQuery,document); 3 | -------------------------------------------------------------------------------- /demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
Form result:
28 |Set/Empty value to the first input programatically using jQuery's .val() function
32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 68 | 69 |
70 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Placeholder Enhanced 1.6.9
2 |
3 | ### This jQuery Placeholder plugin is an enhanced polyfill for the HTML5 placeholder attribute.
4 |
5 | ## Features
6 |
7 | - Cross-browser & Cross-styling
8 | - Support for all input types, password, textarea, text, email, search, url, etc...
9 | - Robust: it heavely behave as the HTML5 placeholder defined in the specs
10 | - Normalize placeholder behaviour in modern browsers (optional). This means the placeholder will
11 | hide on input focus.
12 | - Fix jQuery.val() function to work as expected to set/get the value of inputs with placeholder
13 | - Lightweight: **970 bytes** minified & gzipped
14 |
15 | *Requires jQuery 1.4.4 or higher*
16 |
17 | ## Installation
18 |
19 | ```
20 | bower install placeholder-enhanced
21 | ```
22 |
23 | or download this repo
24 |
25 | ## Usage
26 |
27 | Just include the js file after jQuery on your HTML page and the plugin will be automatically initialized
28 |
29 | ```html
30 |
31 |
32 | ```
33 |
34 | If you want to initialize the plugin yourself after the first auto-initialize (for example after ajax content being
35 | loaded), just call the plugin like this:
36 |
37 | ```javascript
38 | $('input[placeholder], textarea[placeholder]').placeholderEnhanced();
39 | ```
40 |
41 | ### Example:
42 |
43 | Initialize the plugin after loading an HTML page via AJAX, call the plugin after the content is loaded.
44 |
45 | ```javascript
46 | $(function () {
47 | $.get('file.html', function (html) {
48 | $('#container')
49 | // append the html
50 | .append(html)
51 | // find any inputs or textareas with placeholder and initialize the plugin
52 | .find('input[placeholder], textarea[placeholder]').placeholderEnhanced();
53 | });
54 | })
55 | ```
56 |
57 | ### Destroy
58 |
59 | If you want to destroy the plugin call:
60 |
61 | ```javascript
62 | $('input[placeholder], textarea[placeholder]').placeholderEnhanced('destroy');
63 | ```
64 |
65 | It will automatically clean all what the plugin first created as if it was never initialized, only for the selected elements.
66 |
67 | ## CSS
68 |
69 | Customize the style of the placeholder with CSS in a cross-browser manner:
70 |
71 | See [placeholder-enhanced.css](https://github.com/dciccale/placeholder-enhanced/blob/master/css/placeholder-enhanced.css)
72 |
73 | ## Demo
74 |
75 | For a demo see [demo.html](https://github.com/dciccale/placeholder-enhanced/blob/master/demo.html) **[online](http://dciccale.github.com/placeholder-enhanced/)**
76 |
77 | ## Build
78 |
79 | If you want to work on the plugin there is a Makefile with two targets:
80 |
81 | To lint with jshint
82 |
83 | ```sh
84 | $ make lint
85 | ```
86 |
87 | Minify the js file
88 |
89 | ```sh
90 | $ make build
91 | ```
92 |
93 | ## TODO
94 |
95 | These are not major tasks, but nice to have:
96 |
97 | - Create a [kimbo.js](http://kimbojs.com) plugin version.
98 | - Create a plain JavaScript version?
99 | - Create two separate versions.
100 | - Version 1.x to give *full* cross-browser support and normalization. (current version)
101 | - Version 2.x only to normalize *modern browsers* placeholder behaviour.
102 |
103 | ## License
104 |
105 | See [LICENSE.txt](https://raw.github.com/dciccale/placeholder-enhanced/master/LICENSE.txt)
106 |
--------------------------------------------------------------------------------
/js/jquery.placeholder-enhanced.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * jQuery Placeholder Enhanced 1.6.9
3 | * Copyright (c) 2013-2015 Denis Ciccale (@tdecs)
4 | * Released under MIT license
5 | * https://raw.github.com/dciccale/placeholder-enhanced/master/LICENSE.txt
6 | */
7 |
8 | /* jshint jquery: true */
9 | (function ($, doc) {
10 | 'use strict';
11 |
12 | var PLUGIN_NAME = 'placeholderEnhanced';
13 |
14 | var input = doc.createElement('input');
15 | var textarea = doc.createElement('textarea');
16 |
17 | // Check for support
18 | var HAS_NATIVE_SUPPORT = 'placeholder' in input && 'placeholder' in textarea;
19 |
20 | // Event namespaces
21 | var EVENT = {
22 | FOCUS: 'focus.placeholder',
23 | BLUR: 'blur.placeholder'
24 | };
25 |
26 | /*
27 | * Define defaults here as some options are needed before initialization
28 | * it also merges with an options object when you call the plugin
29 | */
30 | var DEFAULTS = {
31 | cssClass: 'placeholder',
32 |
33 | /*
34 | * Normalize behaviour & style across browsers
35 | * (remove placeholder on focus, show on blur)
36 | * if false, each browser wil handle behaviour & style natively
37 | * i.e. in case of Chrome placeholder is still visible on focus
38 | */
39 | normalize: true
40 | };
41 |
42 | // Save original jQuery .val() function
43 | var $val = $.fn.val;
44 |
45 | // Checks if the node is valid to use with the fixed jQuery .val() function
46 | var isValidNode = function (el) {
47 | return ($.nodeName(el, 'input') || $.nodeName(el, 'textarea'));
48 | };
49 |
50 | // Copy attributes from a DOM node to a plain object to use later
51 | var copyAttrs = function (el) {
52 | var exclude = ['placeholder', 'name', 'id'];
53 | var attrs = {};
54 | var attr;
55 |
56 | for (var i = 0, l = el.attributes.length; i < l; i++) {
57 | attr = el.attributes[i];
58 | if (attr.specified && $.inArray(attr.name, exclude) < 0) {
59 | attrs[attr.name] = attr.value;
60 | }
61 | }
62 |
63 | return attrs;
64 | };
65 |
66 | // Shows specified password input
67 | var showInput = function ($input) {
68 | $input.css({position: '', left: ''});
69 | };
70 |
71 | // Hides specified password input
72 | var hideInput = function ($input) {
73 | $input.css({position: 'absolute', left: '-9999em'});
74 | };
75 |
76 | // Don't do anything if there is native placeholder support and normalize mode is off by default
77 | if (HAS_NATIVE_SUPPORT && !DEFAULTS.normalize) {
78 | return;
79 | }
80 |
81 | /*
82 | * Handle the use of jQuery .val(), if placeholder is not supported, the .val() function
83 | * returns the placeholder value, wrap the val function to fix this, also useful when
84 | * using .serialize() or any other jQuery method that uses .val()
85 | */
86 |
87 | // Fix .val() function for unsupported browsers
88 | if (!HAS_NATIVE_SUPPORT) {
89 | $.fn.val = function () {
90 | var args = arguments;
91 | var el = this[0];
92 | var placeholderTxt;
93 |
94 | if (!el) {
95 | return;
96 | }
97 |
98 | // Handle .val()
99 | if (!args.length) {
100 | placeholderTxt = $(el).attr('placeholder');
101 |
102 | // Handle get if the node has a placeholder
103 | if (placeholderTxt && isValidNode(el)) {
104 | return (el.value === placeholderTxt ? '' : el.value);
105 |
106 | // No placeholder, call native
107 | } else {
108 | return $val.apply(this, args);
109 | }
110 | }
111 |
112 | // Handle .val(...)
113 | return this.each(function (i, el) {
114 | var $el = $(el);
115 | var settings = $.data(el, PLUGIN_NAME);
116 | var placeholderTxt = $el.attr('placeholder');
117 |
118 | if (settings && placeholderTxt && isValidNode(el)) {
119 |
120 | // Handle .val(''), .val(null), .val(undefined)
121 | if (!args[0] && el.value !== placeholderTxt) {
122 | el.value = $el.addClass(settings.cssClass).attr('placeholder');
123 |
124 | // Handle .val('value')
125 | } else if (args[0]) {
126 | if ($el.hasClass(settings.cssClass)) {
127 | $el.removeClass(settings.cssClass);
128 | }
129 | $val.apply($el, args);
130 | }
131 |
132 | } else {
133 | $val.apply($el, args);
134 | }
135 | });
136 | };
137 |
138 | // Fix .val() function for modern browsers when normalize mode is on
139 | } else if (HAS_NATIVE_SUPPORT && DEFAULTS.normalize) {
140 | $.fn.val = function () {
141 | var args = arguments;
142 | var el = this[0];
143 |
144 | if (!el) {
145 | return;
146 | }
147 |
148 | // Handle .val()
149 | if (!args.length) {
150 | return $val.apply(this, args);
151 | }
152 |
153 | // Handle .val(...)
154 | return this.each(function (i, el) {
155 | var $el = $(el);
156 | var settings = $.data(el, PLUGIN_NAME);
157 | var placeholderTxt = el._placeholder;
158 |
159 | if (settings && placeholderTxt && isValidNode(el)) {
160 |
161 | // Handle .val(''), .val(null), .val(undefined)
162 | if (!args[0] && el.value !== placeholderTxt) {
163 |
164 | // Restore the placeholder
165 | $el.addClass(settings.cssClass).attr('placeholder', placeholderTxt);
166 |
167 | // Handle .val('value')
168 | } else if (args[0]) {
169 | if ($el.hasClass(settings.cssClass)) {
170 | $el.removeClass(settings.cssClass);
171 | }
172 | }
173 | }
174 |
175 | $val.apply($el, args);
176 | });
177 | };
178 | }
179 |
180 | // Placeholder Enhanced plugin
181 | $.fn[PLUGIN_NAME] = function (options) {
182 |
183 | // Merge passed options with defaults
184 | var settings = $.extend(DEFAULTS, options);
185 |
186 | // Don't do anything if empty set or if placeholder is supported but
187 | // don't want to normalize modern browsers
188 | if (!this.length || (HAS_NATIVE_SUPPORT && !settings.normalize)) {
189 | return;
190 | }
191 |
192 | // Check if options param is destroy method
193 | if (options === 'destroy') {
194 |
195 | // Completely destroy the plugin
196 | return this
197 |
198 | // Get the elements where the plugin was initialized
199 | .filter(function (i, el) {
200 | return $.data(el, PLUGIN_NAME);
201 | })
202 |
203 | // Remove class
204 | .removeClass(settings.cssClass)
205 |
206 | // Clean other stuff
207 | .each(function (i, el) {
208 | var $el = $(el).unbind('.placeholder');
209 | var isPassword = (el.type === 'password');
210 | var placeholderTxt = $el.attr('placeholder');
211 |
212 | // Do all this only for unsupported browsers
213 | if (!HAS_NATIVE_SUPPORT) {
214 | if (el.value === placeholderTxt) {
215 | el.value = '';
216 | }
217 |
218 | // Remove fake password input
219 | if (isPassword) {
220 | showInput($el);
221 | $el.prev().unbind('.placeholder').remove();
222 | }
223 |
224 | // Delete backup prop
225 | } else {
226 | delete el._placeholder;
227 | }
228 |
229 | // Restore original jQuery .val() function
230 | $.fn.val = $val;
231 |
232 | // Plugin off
233 | $.removeData(el, PLUGIN_NAME);
234 | });
235 | }
236 |
237 | return this.each(function (i, el) {
238 |
239 | // Check if the plugin was already initialized for this element
240 | if ($.data(el, PLUGIN_NAME)) {
241 | return;
242 | }
243 |
244 | // Mark plugin as initialized for the current element at the begining to
245 | // prevent multiple calls of the plugin for the same set of elements
246 | $.data(el, PLUGIN_NAME, settings);
247 |
248 | // jQuery object
249 | var $el = $(el);
250 |
251 | // Passwords have different treatment
252 | var isPassword = (el.type === 'password');
253 |
254 | // Current placeholder text
255 | var placeholderTxt = $el.attr('placeholder');
256 |
257 | // A fake input will be created for passwords
258 | var fakePassw = null;
259 |
260 | var setPlaceholder = null;
261 | var removePlaceholder = null;
262 |
263 | // Placeholder support for unsupported browsers
264 | if (!HAS_NATIVE_SUPPORT) {
265 |
266 | setPlaceholder = function () {
267 |
268 | // If there is no initial value or initial value is equal to the
269 | // placeholder (done in the $.fn.val wrapper) show the placeholder
270 | if (!$el.val()) {
271 | if (isPassword) {
272 | showInput(fakePassw);
273 | hideInput($el);
274 | } else {
275 | $el.val(placeholderTxt).addClass(settings.cssClass);
276 | }
277 | } else if ($el.val() && isPassword) {
278 |
279 | // If there is a value already, we want to remove the fake
280 | // placeholder. Otherwise, we'll have both the fake placeholder
281 | // and the actual input visible
282 | removePlaceholder();
283 | }
284 | };
285 |
286 | // Remove function for inputs and textareas
287 | if (!isPassword) {
288 |
289 | removePlaceholder = function () {
290 | if ($el.hasClass(settings.cssClass)) {
291 | el.value = '';
292 | $el.removeClass(settings.cssClass);
293 | }
294 | };
295 |
296 | // And for password inputs
297 | } else {
298 |
299 | removePlaceholder = function () {
300 | showInput($el);
301 | hideInput(fakePassw);
302 | };
303 |
304 | // Create a fake password input
305 | fakePassw = $('', $.extend(copyAttrs(el), {
306 | 'type': 'text',
307 | value: placeholderTxt,
308 | tabindex: -1 // Skip tabbing
309 | }))
310 | .addClass(settings.cssClass)
311 |
312 | // When focus, trigger real input focus
313 | .bind(EVENT.FOCUS, function () {
314 | $el.trigger(EVENT.FOCUS);
315 | })
316 |
317 | // Insert the fake input
318 | .insertBefore($el);
319 | }
320 |
321 | // Normalize placeholder behaviour and style in modern browsers if normalize mode is on
322 | } else if (HAS_NATIVE_SUPPORT && settings.normalize) {
323 |
324 | // Save the placeholder to restore it when needed
325 | el._placeholder = $el.attr('placeholder');
326 |
327 | setPlaceholder = function () {
328 | if (!el.value) {
329 | $el.addClass(settings.cssClass).attr('placeholder', placeholderTxt);
330 | }
331 | };
332 |
333 | removePlaceholder = function () {
334 | $el.removeAttr('placeholder').removeClass(settings.cssClass);
335 | };
336 |
337 | }
338 |
339 | // Bind events and trigger blur the first time
340 | $el
341 | .bind(EVENT.BLUR, setPlaceholder)
342 | .bind(EVENT.FOCUS, removePlaceholder)
343 | .trigger(EVENT.BLUR);
344 | });
345 | };
346 |
347 | // Auto-initialize the plugin
348 | $(function () {
349 | $('input[placeholder], textarea[placeholder]')[PLUGIN_NAME]();
350 | });
351 |
352 | }(jQuery, document));
353 |
--------------------------------------------------------------------------------