Set background to none on our mock body and remove its contents to avoid a crash...
[jquery.git] / src / css.js
blob318cd597955acca88772a798a627dc87dbdb22a3
1 (function( jQuery ) {
3 var ralpha = /alpha\([^)]*\)/i,
4         ropacity = /opacity=([^)]*)/,
5         rdashAlpha = /-([a-z])/ig,
6         // fixed for IE9, see #8346
7         rupper = /([A-Z]|^ms)/g,
8         rnumpx = /^-?\d+(?:px)?$/i,
9         rnum = /^-?\d/,
10         rrelNum = /^[+\-]=/,
11         rrelNumFilter = /[^+\-\.\de]+/g,
13         cssShow = { position: "absolute", visibility: "hidden", display: "block" },
14         cssWidth = [ "Left", "Right" ],
15         cssHeight = [ "Top", "Bottom" ],
16         curCSS,
18         getComputedStyle,
19         currentStyle,
21         fcamelCase = function( all, letter ) {
22                 return letter.toUpperCase();
23         };
25 jQuery.fn.css = function( name, value ) {
26         // Setting 'undefined' is a no-op
27         if ( arguments.length === 2 && value === undefined ) {
28                 return this;
29         }
31         return jQuery.access( this, name, value, true, function( elem, name, value ) {
32                 return value !== undefined ?
33                         jQuery.style( elem, name, value ) :
34                         jQuery.css( elem, name );
35         });
38 jQuery.extend({
39         // Add in style property hooks for overriding the default
40         // behavior of getting and setting a style property
41         cssHooks: {
42                 opacity: {
43                         get: function( elem, computed ) {
44                                 if ( computed ) {
45                                         // We should always get a number back from opacity
46                                         var ret = curCSS( elem, "opacity", "opacity" );
47                                         return ret === "" ? "1" : ret;
49                                 } else {
50                                         return elem.style.opacity;
51                                 }
52                         }
53                 }
54         },
56         // Exclude the following css properties to add px
57         cssNumber: {
58                 "zIndex": true,
59                 "fontWeight": true,
60                 "opacity": true,
61                 "zoom": true,
62                 "lineHeight": true,
63                 "widows": true,
64                 "orphans": true
65         },
67         // Add in properties whose names you wish to fix before
68         // setting or getting the value
69         cssProps: {
70                 // normalize float css property
71                 "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
72         },
74         // Get and set the style property on a DOM Node
75         style: function( elem, name, value, extra ) {
76                 // Don't set styles on text and comment nodes
77                 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
78                         return;
79                 }
81                 // Make sure that we're working with the right name
82                 var ret, type, origName = jQuery.camelCase( name ),
83                         style = elem.style, hooks = jQuery.cssHooks[ origName ];
85                 name = jQuery.cssProps[ origName ] || origName;
87                 // Check if we're setting a value
88                 if ( value !== undefined ) {
89                         type = typeof value;
91                         // Make sure that NaN and null values aren't set. See: #7116
92                         if ( type === "number" && isNaN( value ) || value == null ) {
93                                 return;
94                         }
96                         // convert relative number strings (+= or -=) to relative numbers. #7345
97                         if ( type === "string" && rrelNum.test( value ) ) {
98                                 value = +value.replace( rrelNumFilter, "" ) + parseFloat( jQuery.css( elem, name ) );
99                         }
101                         // If a number was passed in, add 'px' to the (except for certain CSS properties)
102                         if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
103                                 value += "px";
104                         }
106                         // If a hook was provided, use that value, otherwise just set the specified value
107                         if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {
108                                 // Wrapped to prevent IE from throwing errors when 'invalid' values are provided
109                                 // Fixes bug #5509
110                                 try {
111                                         style[ name ] = value;
112                                 } catch(e) {}
113                         }
115                 } else {
116                         // If a hook was provided get the non-computed value from there
117                         if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
118                                 return ret;
119                         }
121                         // Otherwise just get the value from the style object
122                         return style[ name ];
123                 }
124         },
126         css: function( elem, name, extra ) {
127                 var ret, hooks;
129                 // Make sure that we're working with the right name
130                 name = jQuery.camelCase( name );
131                 hooks = jQuery.cssHooks[ name ];
132                 name = jQuery.cssProps[ name ] || name;
134                 // cssFloat needs a special treatment
135                 if ( name === "cssFloat" ) {
136                         name = "float";
137                 }
139                 // If a hook was provided get the computed value from there
140                 if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {
141                         return ret;
143                 // Otherwise, if a way to get the computed value exists, use that
144                 } else if ( curCSS ) {
145                         return curCSS( elem, name );
146                 }
147         },
149         // A method for quickly swapping in/out CSS properties to get correct calculations
150         swap: function( elem, options, callback ) {
151                 var old = {};
153                 // Remember the old values, and insert the new ones
154                 for ( var name in options ) {
155                         old[ name ] = elem.style[ name ];
156                         elem.style[ name ] = options[ name ];
157                 }
159                 callback.call( elem );
161                 // Revert the old values
162                 for ( name in options ) {
163                         elem.style[ name ] = old[ name ];
164                 }
165         },
167         camelCase: function( string ) {
168                 return string.replace( rdashAlpha, fcamelCase );
169         }
172 // DEPRECATED, Use jQuery.css() instead
173 jQuery.curCSS = jQuery.css;
175 jQuery.each(["height", "width"], function( i, name ) {
176         jQuery.cssHooks[ name ] = {
177                 get: function( elem, computed, extra ) {
178                         var val;
180                         if ( computed ) {
181                                 if ( elem.offsetWidth !== 0 ) {
182                                         val = getWH( elem, name, extra );
184                                 } else {
185                                         jQuery.swap( elem, cssShow, function() {
186                                                 val = getWH( elem, name, extra );
187                                         });
188                                 }
190                                 if ( val <= 0 ) {
191                                         val = curCSS( elem, name, name );
193                                         if ( val === "0px" && currentStyle ) {
194                                                 val = currentStyle( elem, name, name );
195                                         }
197                                         if ( val != null ) {
198                                                 // Should return "auto" instead of 0, use 0 for
199                                                 // temporary backwards-compat
200                                                 return val === "" || val === "auto" ? "0px" : val;
201                                         }
202                                 }
204                                 if ( val < 0 || val == null ) {
205                                         val = elem.style[ name ];
207                                         // Should return "auto" instead of 0, use 0 for
208                                         // temporary backwards-compat
209                                         return val === "" || val === "auto" ? "0px" : val;
210                                 }
212                                 return typeof val === "string" ? val : val + "px";
213                         }
214                 },
216                 set: function( elem, value ) {
217                         if ( rnumpx.test( value ) ) {
218                                 // ignore negative width and height values #1599
219                                 value = parseFloat(value);
221                                 if ( value >= 0 ) {
222                                         return value + "px";
223                                 }
225                         } else {
226                                 return value;
227                         }
228                 }
229         };
232 if ( !jQuery.support.opacity ) {
233         jQuery.cssHooks.opacity = {
234                 get: function( elem, computed ) {
235                         // IE uses filters for opacity
236                         return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
237                                 ( parseFloat( RegExp.$1 ) / 100 ) + "" :
238                                 computed ? "1" : "";
239                 },
241                 set: function( elem, value ) {
242                         var style = elem.style,
243                                 currentStyle = elem.currentStyle;
245                         // IE has trouble with opacity if it does not have layout
246                         // Force it by setting the zoom level
247                         style.zoom = 1;
249                         // Set the alpha filter to set the opacity
250                         var opacity = jQuery.isNaN( value ) ?
251                                 "" :
252                                 "alpha(opacity=" + value * 100 + ")",
253                                 filter = currentStyle && currentStyle.filter || style.filter || "";
255                         style.filter = ralpha.test( filter ) ?
256                                 filter.replace( ralpha, opacity ) :
257                                 filter + " " + opacity;
258                 }
259         };
262 jQuery(function() {
263         // This hook cannot be added until DOM ready because the support test
264         // for it is not run until after DOM ready
265         if ( !jQuery.support.reliableMarginRight ) {
266                 jQuery.cssHooks.marginRight = {
267                         get: function( elem, computed ) {
268                                 // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
269                                 // Work around by temporarily setting element display to inline-block
270                                 var ret;
271                                 jQuery.swap( elem, { "display": "inline-block" }, function() {
272                                         if ( computed ) {
273                                                 ret = curCSS( elem, "margin-right", "marginRight" );
274                                         } else {
275                                                 ret = elem.style.marginRight;
276                                         }
277                                 });
278                                 return ret;
279                         }
280                 };
281         }
284 if ( document.defaultView && document.defaultView.getComputedStyle ) {
285         getComputedStyle = function( elem, name ) {
286                 var ret, defaultView, computedStyle;
288                 name = name.replace( rupper, "-$1" ).toLowerCase();
290                 if ( !(defaultView = elem.ownerDocument.defaultView) ) {
291                         return undefined;
292                 }
294                 if ( (computedStyle = defaultView.getComputedStyle( elem, null )) ) {
295                         ret = computedStyle.getPropertyValue( name );
296                         if ( ret === "" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {
297                                 ret = jQuery.style( elem, name );
298                         }
299                 }
301                 return ret;
302         };
305 if ( document.documentElement.currentStyle ) {
306         currentStyle = function( elem, name ) {
307                 var left,
308                         ret = elem.currentStyle && elem.currentStyle[ name ],
309                         rsLeft = elem.runtimeStyle && elem.runtimeStyle[ name ],
310                         style = elem.style;
312                 // From the awesome hack by Dean Edwards
313                 // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
315                 // If we're not dealing with a regular pixel number
316                 // but a number that has a weird ending, we need to convert it to pixels
317                 if ( !rnumpx.test( ret ) && rnum.test( ret ) ) {
318                         // Remember the original values
319                         left = style.left;
321                         // Put in the new values to get a computed value out
322                         if ( rsLeft ) {
323                                 elem.runtimeStyle.left = elem.currentStyle.left;
324                         }
325                         style.left = name === "fontSize" ? "1em" : (ret || 0);
326                         ret = style.pixelLeft + "px";
328                         // Revert the changed values
329                         style.left = left;
330                         if ( rsLeft ) {
331                                 elem.runtimeStyle.left = rsLeft;
332                         }
333                 }
335                 return ret === "" ? "auto" : ret;
336         };
339 curCSS = getComputedStyle || currentStyle;
341 function getWH( elem, name, extra ) {
342         var which = name === "width" ? cssWidth : cssHeight,
343                 val = name === "width" ? elem.offsetWidth : elem.offsetHeight;
345         if ( extra === "border" ) {
346                 return val;
347         }
349         jQuery.each( which, function() {
350                 if ( !extra ) {
351                         val -= parseFloat(jQuery.css( elem, "padding" + this )) || 0;
352                 }
354                 if ( extra === "margin" ) {
355                         val += parseFloat(jQuery.css( elem, "margin" + this )) || 0;
357                 } else {
358                         val -= parseFloat(jQuery.css( elem, "border" + this + "Width" )) || 0;
359                 }
360         });
362         return val;
365 if ( jQuery.expr && jQuery.expr.filters ) {
366         jQuery.expr.filters.hidden = function( elem ) {
367                 var width = elem.offsetWidth,
368                         height = elem.offsetHeight;
370                 return (width === 0 && height === 0) || (!jQuery.support.reliableHiddenOffsets && (elem.style.display || jQuery.css( elem, "display" )) === "none");
371         };
373         jQuery.expr.filters.visible = function( elem ) {
374                 return !jQuery.expr.filters.hidden( elem );
375         };
378 })( jQuery );