2 * jQuery Migrate - v1.2.1 - 2013-05-08
3 * https://github.com/jquery/jquery-migrate
4 * Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors; Licensed MIT
6 (function( jQuery
, window
, undefined ) {
7 // See http://bugs.jquery.com/ticket/13335
13 // List of warnings already given; public read only
14 jQuery
.migrateWarnings
= [];
16 // Set to true to prevent console output; migrateWarnings still maintained
17 // jQuery.migrateMute = false;
19 // Show a message on the console so devs know we're active
20 if ( !jQuery
.migrateMute
&& window
.console
&& window
.console
.log
) {
21 window
.console
.log("JQMIGRATE: Logging is active");
24 // Set to false to disable traces that appear with warnings
25 if ( jQuery
.migrateTrace
=== undefined ) {
26 jQuery
.migrateTrace
= true;
29 // Forget any warnings we've already given; public
30 jQuery
.migrateReset = function() {
32 jQuery
.migrateWarnings
.length
= 0;
35 function migrateWarn( msg
) {
36 var console
= window
.console
;
37 if ( !warnedAbout
[ msg
] ) {
38 warnedAbout
[ msg
] = true;
39 jQuery
.migrateWarnings
.push( msg
);
40 if ( console
&& console
.warn
&& !jQuery
.migrateMute
) {
41 console
.warn( "JQMIGRATE: " + msg
);
42 if ( jQuery
.migrateTrace
&& console
.trace
) {
49 function migrateWarnProp( obj
, prop
, value
, msg
) {
50 if ( Object
.defineProperty
) {
51 // On ES5 browsers (non-oldIE), warn if the code tries to get prop;
52 // allow property to be overwritten in case some other plugin wants it
54 Object
.defineProperty( obj
, prop
, {
61 set: function( newValue
) {
68 // IE8 is a dope about Object.defineProperty, can't warn there
72 // Non-ES5 (or broken) browser; just set the property
73 jQuery
._definePropertyBroken
= true;
77 if ( document
.compatMode
=== "BackCompat" ) {
78 // jQuery has never supported or tested Quirks Mode
79 migrateWarn( "jQuery is not compatible with Quirks Mode" );
83 var attrFn
= jQuery( "<input/>", { size
: 1 } ).attr("size") && jQuery
.attrFn
,
84 oldAttr
= jQuery
.attr
,
85 valueAttrGet
= jQuery
.attrHooks
.value
&& jQuery
.attrHooks
.value
.get ||
86 function() { return null; },
87 valueAttrSet
= jQuery
.attrHooks
.value
&& jQuery
.attrHooks
.value
.set ||
88 function() { return undefined; },
89 rnoType
= /^(?:input|button)$/i,
90 rnoAttrNodeType
= /^[238]$/,
91 rboolean
= /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
92 ruseDefault
= /^(?:checked|selected)$/i;
95 migrateWarnProp( jQuery
, "attrFn", attrFn
|| {}, "jQuery.attrFn is deprecated" );
97 jQuery
.attr = function( elem
, name
, value
, pass
) {
98 var lowerName
= name
.toLowerCase(),
99 nType
= elem
&& elem
.nodeType
;
102 // Since pass is used internally, we only warn for new jQuery
103 // versions where there isn't a pass arg in the formal params
104 if ( oldAttr
.length
< 4 ) {
105 migrateWarn("jQuery.fn.attr( props, pass ) is deprecated");
107 if ( elem
&& !rnoAttrNodeType
.test( nType
) &&
108 (attrFn
? name
in attrFn
: jQuery
.isFunction(jQuery
.fn
[name
])) ) {
109 return jQuery( elem
)[ name
]( value
);
113 // Warn if user tries to set `type`, since it breaks on IE 6/7/8; by checking
114 // for disconnected elements we don't warn on $( "<button>", { type: "button" } ).
115 if ( name
=== "type" && value
!== undefined && rnoType
.test( elem
.nodeName
) && elem
.parentNode
) {
116 migrateWarn("Can't change the 'type' of an input or button in IE 6/7/8");
119 // Restore boolHook for boolean property/attribute synchronization
120 if ( !jQuery
.attrHooks
[ lowerName
] && rboolean
.test( lowerName
) ) {
121 jQuery
.attrHooks
[ lowerName
] = {
122 get: function( elem
, name
) {
123 // Align boolean attributes with corresponding properties
124 // Fall back to attribute presence where some booleans are not supported
126 property
= jQuery
.prop( elem
, name
);
127 return property
=== true || typeof property
!== "boolean" &&
128 ( attrNode
= elem
.getAttributeNode(name
) ) && attrNode
.nodeValue
!== false ?
133 set: function( elem
, value
, name
) {
135 if ( value
=== false ) {
136 // Remove boolean attributes when set to false
137 jQuery
.removeAttr( elem
, name
);
139 // value is true since we know at this point it's type boolean and not false
140 // Set boolean attributes to the same name and set the DOM property
141 propName
= jQuery
.propFix
[ name
] || name
;
142 if ( propName
in elem
) {
143 // Only set the IDL specifically if it already exists on the element
144 elem
[ propName
] = true;
147 elem
.setAttribute( name
, name
.toLowerCase() );
153 // Warn only for attributes that can remain distinct from their properties post-1.9
154 if ( ruseDefault
.test( lowerName
) ) {
155 migrateWarn( "jQuery.fn.attr('" + lowerName
+ "') may use property instead of attribute" );
159 return oldAttr
.call( jQuery
, elem
, name
, value
);
163 jQuery
.attrHooks
.value
= {
164 get: function( elem
, name
) {
165 var nodeName
= ( elem
.nodeName
|| "" ).toLowerCase();
166 if ( nodeName
=== "button" ) {
167 return valueAttrGet
.apply( this, arguments
);
169 if ( nodeName
!== "input" && nodeName
!== "option" ) {
170 migrateWarn("jQuery.fn.attr('value') no longer gets properties");
172 return name
in elem
?
176 set: function( elem
, value
) {
177 var nodeName
= ( elem
.nodeName
|| "" ).toLowerCase();
178 if ( nodeName
=== "button" ) {
179 return valueAttrSet
.apply( this, arguments
);
181 if ( nodeName
!== "input" && nodeName
!== "option" ) {
182 migrateWarn("jQuery.fn.attr('value', val) no longer sets properties");
184 // Does not return so that setAttribute is also used
190 var matched
, browser
,
191 oldInit
= jQuery
.fn
.init
,
192 oldParseJSON
= jQuery
.parseJSON
,
193 // Note: XSS check is done below after string is trimmed
194 rquickExpr
= /^([^<]*)(<[\w\W]+>)([^>]*)$/;
196 // $(html) "looks like html" rule change
197 jQuery
.fn
.init = function( selector
, context
, rootjQuery
) {
200 if ( selector
&& typeof selector
=== "string" && !jQuery
.isPlainObject( context
) &&
201 (match
= rquickExpr
.exec( jQuery
.trim( selector
) )) && match
[ 0 ] ) {
202 // This is an HTML string according to the "old" rules; is it still?
203 if ( selector
.charAt( 0 ) !== "<" ) {
204 migrateWarn("$(html) HTML strings must start with '<' character");
207 migrateWarn("$(html) HTML text after last tag is ignored");
209 // Consistently reject any HTML-like string starting with a hash (#9521)
210 // Note that this may break jQuery 1.6.x code that otherwise would work.
211 if ( match
[ 0 ].charAt( 0 ) === "#" ) {
212 migrateWarn("HTML string cannot start with a '#' character");
213 jQuery
.error("JQMIGRATE: Invalid selector string (XSS)");
215 // Now process using loose rules; let pre-1.8 play too
216 if ( context
&& context
.context
) {
217 // jQuery object as context; parseHTML expects a DOM object
218 context
= context
.context
;
220 if ( jQuery
.parseHTML
) {
221 return oldInit
.call( this, jQuery
.parseHTML( match
[ 2 ], context
, true ),
222 context
, rootjQuery
);
225 return oldInit
.apply( this, arguments
);
227 jQuery
.fn
.init
.prototype = jQuery
.fn
;
229 // Let $.parseJSON(falsy_value) return null
230 jQuery
.parseJSON = function( json
) {
231 if ( !json
&& json
!== null ) {
232 migrateWarn("jQuery.parseJSON requires a valid JSON string");
235 return oldParseJSON
.apply( this, arguments
);
238 jQuery
.uaMatch = function( ua
) {
239 ua
= ua
.toLowerCase();
241 var match
= /(chrome)[ \/]([\w.]+)/.exec( ua
) ||
242 /(webkit)[ \/]([\w.]+)/.exec( ua
) ||
243 /(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua
) ||
244 /(msie) ([\w.]+)/.exec( ua
) ||
245 ua
.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua
) ||
249 browser
: match
[ 1 ] || "",
250 version
: match
[ 2 ] || "0"
254 // Don't clobber any existing jQuery.browser in case it's different
255 if ( !jQuery
.browser
) {
256 matched
= jQuery
.uaMatch( navigator
.userAgent
);
259 if ( matched
.browser
) {
260 browser
[ matched
.browser
] = true;
261 browser
.version
= matched
.version
;
264 // Chrome is Webkit, but Webkit is also Safari.
265 if ( browser
.chrome
) {
266 browser
.webkit
= true;
267 } else if ( browser
.webkit
) {
268 browser
.safari
= true;
271 jQuery
.browser
= browser
;
274 // Warn if the code tries to get jQuery.browser
275 migrateWarnProp( jQuery
, "browser", jQuery
.browser
, "jQuery.browser is deprecated" );
277 jQuery
.sub = function() {
278 function jQuerySub( selector
, context
) {
279 return new jQuerySub
.fn
.init( selector
, context
);
281 jQuery
.extend( true, jQuerySub
, this );
282 jQuerySub
.superclass
= this;
283 jQuerySub
.fn
= jQuerySub
.prototype = this();
284 jQuerySub
.fn
.constructor = jQuerySub
;
285 jQuerySub
.sub
= this.sub
;
286 jQuerySub
.fn
.init
= function init( selector
, context
) {
287 if ( context
&& context
instanceof jQuery
&& !(context
instanceof jQuerySub
) ) {
288 context
= jQuerySub( context
);
291 return jQuery
.fn
.init
.call( this, selector
, context
, rootjQuerySub
);
293 jQuerySub
.fn
.init
.prototype = jQuerySub
.fn
;
294 var rootjQuerySub
= jQuerySub(document
);
295 migrateWarn( "jQuery.sub() is deprecated" );
300 // Ensure that $.ajax gets the new parseJSON defined in core.js
303 "text json": jQuery
.parseJSON
308 var oldFnData
= jQuery
.fn
.data
;
310 jQuery
.fn
.data = function( name
) {
314 // Handles 1.7 which has this behavior and 1.8 which doesn't
315 if ( elem
&& name
=== "events" && arguments
.length
=== 1 ) {
316 ret
= jQuery
.data( elem
, name
);
317 evt
= jQuery
._data( elem
, name
);
318 if ( ( ret
=== undefined || ret
=== evt
) && evt
!== undefined ) {
319 migrateWarn("Use of jQuery.fn.data('events') is deprecated");
323 return oldFnData
.apply( this, arguments
);
327 var rscriptType
= /\/(java|ecma)script/i,
328 oldSelf
= jQuery
.fn
.andSelf
|| jQuery
.fn
.addBack
;
330 jQuery
.fn
.andSelf = function() {
331 migrateWarn("jQuery.fn.andSelf() replaced by jQuery.fn.addBack()");
332 return oldSelf
.apply( this, arguments
);
335 // Since jQuery.clean is used internally on older versions, we only shim if it's missing
336 if ( !jQuery
.clean
) {
337 jQuery
.clean = function( elems
, context
, fragment
, scripts
) {
338 // Set context per 1.8 logic
339 context
= context
|| document
;
340 context
= !context
.nodeType
&& context
[0] || context
;
341 context
= context
.ownerDocument
|| context
;
343 migrateWarn("jQuery.clean() is deprecated");
345 var i
, elem
, handleScript
, jsTags
,
348 jQuery
.merge( ret
, jQuery
.buildFragment( elems
, context
).childNodes
);
350 // Complex logic lifted directly from jQuery 1.8
352 // Special handling of each script element
353 handleScript = function( elem
) {
354 // Check if we consider it executable
355 if ( !elem
.type
|| rscriptType
.test( elem
.type
) ) {
356 // Detach the script and store it in the scripts array (if provided) or the fragment
357 // Return truthy to indicate that it has been handled
359 scripts
.push( elem
.parentNode
? elem
.parentNode
.removeChild( elem
) : elem
) :
360 fragment
.appendChild( elem
);
364 for ( i
= 0; (elem
= ret
[i
]) != null; i
++ ) {
365 // Check if we're done after handling an executable script
366 if ( !( jQuery
.nodeName( elem
, "script" ) && handleScript( elem
) ) ) {
367 // Append to fragment and handle embedded scripts
368 fragment
.appendChild( elem
);
369 if ( typeof elem
.getElementsByTagName
!== "undefined" ) {
370 // handleScript alters the DOM, so use jQuery.merge to ensure snapshot iteration
371 jsTags
= jQuery
.grep( jQuery
.merge( [], elem
.getElementsByTagName("script") ), handleScript
);
373 // Splice the scripts into ret after their former ancestor and advance our index beyond them
374 ret
.splice
.apply( ret
, [i
+ 1, 0].concat( jsTags
) );
385 var eventAdd
= jQuery
.event
.add
,
386 eventRemove
= jQuery
.event
.remove
,
387 eventTrigger
= jQuery
.event
.trigger
,
388 oldToggle
= jQuery
.fn
.toggle
,
389 oldLive
= jQuery
.fn
.live
,
390 oldDie
= jQuery
.fn
.die
,
391 ajaxEvents
= "ajaxStart|ajaxStop|ajaxSend|ajaxComplete|ajaxError|ajaxSuccess",
392 rajaxEvent
= new RegExp( "\\b(?:" + ajaxEvents
+ ")\\b" ),
393 rhoverHack
= /(?:^|\s)hover(\.\S+|)\b/,
394 hoverHack = function( events
) {
395 if ( typeof( events
) !== "string" || jQuery
.event
.special
.hover
) {
398 if ( rhoverHack
.test( events
) ) {
399 migrateWarn("'hover' pseudo-event is deprecated, use 'mouseenter mouseleave'");
401 return events
&& events
.replace( rhoverHack
, "mouseenter$1 mouseleave$1" );
404 // Event props removed in 1.9, put them back if needed; no practical way to warn them
405 if ( jQuery
.event
.props
&& jQuery
.event
.props
[ 0 ] !== "attrChange" ) {
406 jQuery
.event
.props
.unshift( "attrChange", "attrName", "relatedNode", "srcElement" );
409 // Undocumented jQuery.event.handle was "deprecated" in jQuery 1.7
410 if ( jQuery
.event
.dispatch
) {
411 migrateWarnProp( jQuery
.event
, "handle", jQuery
.event
.dispatch
, "jQuery.event.handle is undocumented and deprecated" );
414 // Support for 'hover' pseudo-event and ajax event warnings
415 jQuery
.event
.add = function( elem
, types
, handler
, data
, selector
){
416 if ( elem
!== document
&& rajaxEvent
.test( types
) ) {
417 migrateWarn( "AJAX events should be attached to document: " + types
);
419 eventAdd
.call( this, elem
, hoverHack( types
|| "" ), handler
, data
, selector
);
421 jQuery
.event
.remove = function( elem
, types
, handler
, selector
, mappedTypes
){
422 eventRemove
.call( this, elem
, hoverHack( types
) || "", handler
, selector
, mappedTypes
);
425 jQuery
.fn
.error = function() {
426 var args
= Array
.prototype.slice
.call( arguments
, 0);
427 migrateWarn("jQuery.fn.error() is deprecated");
428 args
.splice( 0, 0, "error" );
429 if ( arguments
.length
) {
430 return this.bind
.apply( this, args
);
432 // error event should not bubble to window, although it does pre-1.7
433 this.triggerHandler
.apply( this, args
);
437 jQuery
.fn
.toggle = function( fn
, fn2
) {
439 // Don't mess with animation or css toggles
440 if ( !jQuery
.isFunction( fn
) || !jQuery
.isFunction( fn2
) ) {
441 return oldToggle
.apply( this, arguments
);
443 migrateWarn("jQuery.fn.toggle(handler, handler...) is deprecated");
445 // Save reference to arguments for access in closure
446 var args
= arguments
,
447 guid
= fn
.guid
|| jQuery
.guid
++,
449 toggler = function( event
) {
450 // Figure out which function to execute
451 var lastToggle
= ( jQuery
._data( this, "lastToggle" + fn
.guid
) || 0 ) % i
;
452 jQuery
._data( this, "lastToggle" + fn
.guid
, lastToggle
+ 1 );
454 // Make sure that clicks stop
455 event
.preventDefault();
457 // and execute the function
458 return args
[ lastToggle
].apply( this, arguments
) || false;
461 // link all the functions, so any of them can unbind this click handler
463 while ( i
< args
.length
) {
464 args
[ i
++ ].guid
= guid
;
467 return this.click( toggler
);
470 jQuery
.fn
.live = function( types
, data
, fn
) {
471 migrateWarn("jQuery.fn.live() is deprecated");
473 return oldLive
.apply( this, arguments
);
475 jQuery( this.context
).on( types
, this.selector
, data
, fn
);
479 jQuery
.fn
.die = function( types
, fn
) {
480 migrateWarn("jQuery.fn.die() is deprecated");
482 return oldDie
.apply( this, arguments
);
484 jQuery( this.context
).off( types
, this.selector
|| "**", fn
);
488 // Turn global events into document-triggered events
489 jQuery
.event
.trigger = function( event
, data
, elem
, onlyHandlers
){
490 if ( !elem
&& !rajaxEvent
.test( event
) ) {
491 migrateWarn( "Global events are undocumented and deprecated" );
493 return eventTrigger
.call( this, event
, data
, elem
|| document
, onlyHandlers
);
495 jQuery
.each( ajaxEvents
.split("|"),
496 function( _
, name
) {
497 jQuery
.event
.special
[ name
] = {
501 // The document needs no shimming; must be !== for oldIE
502 if ( elem
!== document
) {
503 jQuery
.event
.add( document
, name
+ "." + jQuery
.guid
, function() {
504 jQuery
.event
.trigger( name
, null, elem
, true );
506 jQuery
._data( this, name
, jQuery
.guid
++ );
510 teardown: function() {
511 if ( this !== document
) {
512 jQuery
.event
.remove( document
, name
+ "." + jQuery
._data( this, name
) );
521 })( jQuery
, window
);