Merge "Add tests for WikiMap and WikiReference"
[lhc/web/wiklou.git] / resources / src / jquery / jquery.placeholder.js
1 /**
2 * HTML5 placeholder emulation for jQuery plugin
3 *
4 * This will automatically use the HTML5 placeholder attribute if supported, or emulate this behavior if not.
5 *
6 * This is a fork from Mathias Bynens' jquery.placeholder as of this commit
7 * https://github.com/mathiasbynens/jquery-placeholder/blob/47f05d400e2dd16b59d144141a2cf54a9a77c502/jquery.placeholder.js
8 *
9 * @author Mathias Bynens <http://mathiasbynens.be/>
10 * @author Trevor Parscal <tparscal@wikimedia.org>, 2012
11 * @author Krinkle <krinklemail@gmail.com>, 2012
12 * @author Alex Ivanov <alexivanov97@gmail.com>, 2013
13 * @version 2.1.0
14 * @license MIT
15 */
16 ( function ( $ ) {
17
18 var isInputSupported = 'placeholder' in document.createElement( 'input' ),
19 isTextareaSupported = 'placeholder' in document.createElement( 'textarea' ),
20 prototype = $.fn,
21 valHooks = $.valHooks,
22 propHooks = $.propHooks,
23 hooks,
24 placeholder;
25
26 function safeActiveElement() {
27 // Avoid IE9 `document.activeElement` of death
28 // https://github.com/mathiasbynens/jquery-placeholder/pull/99
29 try {
30 return document.activeElement;
31 } catch ( err ) {}
32 }
33
34 function args( elem ) {
35 // Return an object of element attributes
36 var newAttrs = {},
37 rinlinejQuery = /^jQuery\d+$/;
38 $.each( elem.attributes, function ( i, attr ) {
39 if ( attr.specified && !rinlinejQuery.test( attr.name ) ) {
40 newAttrs[ attr.name ] = attr.value;
41 }
42 } );
43 return newAttrs;
44 }
45
46 function clearPlaceholder( event, value ) {
47 var input = this,
48 $input = $( input );
49 if ( input.value === $input.attr( 'placeholder' ) && $input.hasClass( 'placeholder' ) ) {
50 if ( $input.data( 'placeholder-password' ) ) {
51 $input = $input.hide().next().show().attr( 'id', $input.removeAttr( 'id' ).data( 'placeholder-id' ) );
52 // If `clearPlaceholder` was called from `$.valHooks.input.set`
53 if ( event === true ) {
54 $input[ 0 ].value = value;
55 return value;
56 }
57 $input.focus();
58 } else {
59 input.value = '';
60 $input.removeClass( 'placeholder' );
61 if ( input === safeActiveElement() ) {
62 input.select();
63 }
64 }
65 }
66 }
67
68 function setPlaceholder() {
69 var $replacement,
70 input = this,
71 $input = $( input ),
72 id = this.id;
73 if ( !input.value ) {
74 if ( input.type === 'password' ) {
75 if ( !$input.data( 'placeholder-textinput' ) ) {
76 try {
77 $replacement = $input.clone().attr( { type: 'text' } );
78 } catch ( e ) {
79 $replacement = $( '<input>' ).attr( $.extend( args( this ), { type: 'text' } ) );
80 }
81 $replacement
82 .removeAttr( 'name' )
83 .data( {
84 'placeholder-password': $input,
85 'placeholder-id': id
86 } )
87 .bind( 'focus.placeholder drop.placeholder', clearPlaceholder );
88 $input
89 .data( {
90 'placeholder-textinput': $replacement,
91 'placeholder-id': id
92 } )
93 .before( $replacement );
94 }
95 $input = $input.removeAttr( 'id' ).hide().prev().attr( 'id', id ).show();
96 // Note: `$input[0] != input` now!
97 }
98 $input.addClass( 'placeholder' );
99 $input[ 0 ].value = $input.attr( 'placeholder' );
100 } else {
101 $input.removeClass( 'placeholder' );
102 }
103 }
104
105 function changePlaceholder( text ) {
106 var hasArgs = arguments.length,
107 $input = this;
108 if ( hasArgs ) {
109 if ( $input.attr( 'placeholder' ) !== text ) {
110 $input.prop( 'placeholder', text );
111 if ( $input.hasClass( 'placeholder' ) ) {
112 $input[ 0 ].value = text;
113 }
114 }
115 }
116 }
117
118 if ( isInputSupported && isTextareaSupported ) {
119
120 placeholder = prototype.placeholder = function ( text ) {
121 var hasArgs = arguments.length;
122
123 if ( hasArgs ) {
124 changePlaceholder.call( this, text );
125 }
126
127 return this;
128 };
129
130 placeholder.input = placeholder.textarea = true;
131
132 } else {
133
134 placeholder = prototype.placeholder = function ( text ) {
135 var $this = this,
136 hasArgs = arguments.length;
137
138 if ( hasArgs ) {
139 changePlaceholder.call( this, text );
140 }
141
142 $this
143 .filter( ( isInputSupported ? 'textarea' : ':input' ) + '[placeholder]' )
144 .filter( function () {
145 return !$( this ).data( 'placeholder-enabled' );
146 } )
147 .bind( {
148 'focus.placeholder drop.placeholder': clearPlaceholder,
149 'blur.placeholder': setPlaceholder
150 } )
151 .data( 'placeholder-enabled', true )
152 .trigger( 'blur.placeholder' );
153 return $this;
154 };
155
156 placeholder.input = isInputSupported;
157 placeholder.textarea = isTextareaSupported;
158
159 hooks = {
160 get: function ( element ) {
161 var $element = $( element ),
162 $passwordInput = $element.data( 'placeholder-password' );
163 if ( $passwordInput ) {
164 return $passwordInput[ 0 ].value;
165 }
166
167 return $element.data( 'placeholder-enabled' ) && $element.hasClass( 'placeholder' ) ? '' : element.value;
168 },
169 set: function ( element, value ) {
170 var $element = $( element ),
171 $passwordInput = $element.data( 'placeholder-password' );
172 if ( $passwordInput ) {
173 $passwordInput[ 0 ].value = value;
174 return value;
175 }
176
177 if ( !$element.data( 'placeholder-enabled' ) ) {
178 element.value = value;
179 return value;
180 }
181 if ( !value ) {
182 element.value = value;
183 // Issue #56: Setting the placeholder causes problems if the element continues to have focus.
184 if ( element !== safeActiveElement() ) {
185 // We can't use `triggerHandler` here because of dummy text/password inputs :(
186 setPlaceholder.call( element );
187 }
188 } else if ( $element.hasClass( 'placeholder' ) ) {
189 if ( !clearPlaceholder.call( element, true, value ) ) {
190 element.value = value;
191 }
192 } else {
193 element.value = value;
194 }
195 // `set` can not return `undefined`; see http://jsapi.info/jquery/1.7.1/val#L2363
196 return $element;
197 }
198 };
199
200 if ( !isInputSupported ) {
201 valHooks.input = hooks;
202 propHooks.value = hooks;
203 }
204 if ( !isTextareaSupported ) {
205 valHooks.textarea = hooks;
206 propHooks.value = hooks;
207 }
208
209 $( function () {
210 // Look for forms
211 $( document ).delegate( 'form', 'submit.placeholder', function () {
212 // Clear the placeholder values so they don't get submitted
213 var $inputs = $( '.placeholder', this ).each( clearPlaceholder );
214 setTimeout( function () {
215 $inputs.each( setPlaceholder );
216 }, 10 );
217 } );
218 } );
219
220 // Clear placeholder values upon page reload
221 $( window ).bind( 'beforeunload.placeholder', function () {
222 $( '.placeholder' ).each( function () {
223 this.value = '';
224 } );
225 } );
226
227 }
228 }( jQuery ) );