opacity is now retrieved from stylesheet in IE. fixes #3981
[jquery.git] / src / css.js
1 // exclude the following css properties to add px
2 var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
3         // cache check for defaultView.getComputedStyle
4         getComputedStyle = document.defaultView && document.defaultView.getComputedStyle,
5         // normalize float css property
6         styleFloat = jQuery.support.cssFloat ? "cssFloat" : "styleFloat";
7
8 jQuery.fn.css = function( name, value ) {
9         var options = name, isFunction = jQuery.isFunction( value );
10
11         if ( typeof name === "string" ) {
12                 // Are we setting the style?
13                 if ( value === undefined ) {
14                         return this.length ?
15                                 jQuery.css( this[0], name ) :
16                                 null;
17
18                 // Convert name, value params to options hash format
19                 } else {
20                         options = {};
21                         options[ name ] = value;
22                 }
23         }
24
25         // For each element...
26         for ( var i = 0, l = this.length; i < l; i++ ) {
27                 var elem = this[i];
28
29                 // Set all the styles
30                 for ( var prop in options ) {
31                         value = options[prop];
32
33                         if ( isFunction ) {
34                                 value = value.call( elem, i );
35                         }
36
37                         if ( typeof value === "number" && !exclude.test(prop) ) {
38                                 value = value + "px";
39                         }
40
41                         jQuery.style( elem, prop, value );
42                 }
43         }
44
45         return this;
46 };
47
48 jQuery.extend({
49         style: function( elem, name, value ) {
50                 // don't set styles on text and comment nodes
51                 if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
52                         return undefined;
53
54                 // ignore negative width and height values #1599
55                 if ( (name == 'width' || name == 'height') && parseFloat(value) < 0 )
56                         value = undefined;
57
58                 var style = elem.style || elem, set = value !== undefined;
59
60                 // IE uses filters for opacity
61                 if ( !jQuery.support.opacity && name == "opacity" ) {
62                         if ( set ) {
63                                 // IE has trouble with opacity if it does not have layout
64                                 // Force it by setting the zoom level
65                                 style.zoom = 1;
66
67                                 // Set the alpha filter to set the opacity
68                                 style.filter = (style.filter || "").replace( /alpha\([^)]*\)/, "" ) +
69                                         (parseInt( value ) + '' == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
70                         }
71
72                         return style.filter && style.filter.indexOf("opacity=") >= 0 ?
73                                 (parseFloat( style.filter.match(/opacity=([^)]*)/)[1] ) / 100) + '':
74                                 "";
75                 }
76
77                 // Make sure we're using the right name for getting the float value
78                 if ( /float/i.test( name ) )
79                         name = styleFloat;
80
81                 name = name.replace(/-([a-z])/ig, function(all, letter){
82                         return letter.toUpperCase();
83                 });
84
85                 if ( set )
86                         style[ name ] = value;
87
88                 return style[ name ];
89         },
90
91         css: function( elem, name, force, extra ) {
92                 if ( name == "width" || name == "height" ) {
93                         var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];
94
95                         function getWH() {
96                                 val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
97
98                                 if ( extra === "border" )
99                                         return;
100
101                                 jQuery.each( which, function() {
102                                         if ( !extra )
103                                                 val -= parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
104                                         if ( extra === "margin" )
105                                                 val += parseFloat(jQuery.curCSS( elem, "margin" + this, true)) || 0;
106                                         else
107                                                 val -= parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
108                                 });
109                         }
110
111                         if ( elem.offsetWidth !== 0 )
112                                 getWH();
113                         else
114                                 jQuery.swap( elem, props, getWH );
115
116                         return Math.max(0, Math.round(val));
117                 }
118
119                 return jQuery.curCSS( elem, name, force );
120         },
121
122         curCSS: function( elem, name, force ) {
123                 var ret, style = elem.style, filter;
124
125                 // IE uses filters for opacity
126                 if ( !jQuery.support.opacity && name == "opacity" ) {
127                         filter = (filter = style.filter) && filter.indexOf("opacity=") >= 0 ?
128                                 filter :
129                                 (filter = elem.currentStyle[ 'filter' ]) && filter.indexOf("opacity=") >= 0 ?
130                                         filter :
131                                         null;
132
133                         ret = filter && filter.indexOf("opacity=") >= 0 ?
134                                 (parseFloat( filter.match(/opacity=([^)]*)/)[1] ) / 100) + '':
135                                 "";
136
137                         return ret === "" ?
138                                 "1" :
139                                 ret;
140                 }
141
142                 // Make sure we're using the right name for getting the float value
143                 if ( /float/i.test( name ) )
144                         name = styleFloat;
145
146                 if ( !force && style && style[ name ] ) {
147                         ret = style[ name ];
148
149                 } else if ( getComputedStyle ) {
150
151                         // Only "float" is needed here
152                         if ( /float/i.test( name ) )
153                                 name = "float";
154
155                         name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
156
157                         var computedStyle = elem.ownerDocument.defaultView.getComputedStyle( elem, null );
158
159                         if ( computedStyle )
160                                 ret = computedStyle.getPropertyValue( name );
161
162                         // We should always get a number back from opacity
163                         if ( name == "opacity" && ret == "" )
164                                 ret = "1";
165
166                 } else if ( elem.currentStyle ) {
167                         var camelCase = name.replace(/\-(\w)/g, function(all, letter){
168                                 return letter.toUpperCase();
169                         });
170
171                         ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
172
173                         // From the awesome hack by Dean Edwards
174                         // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
175
176                         // If we're not dealing with a regular pixel number
177                         // but a number that has a weird ending, we need to convert it to pixels
178                         if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
179                                 // Remember the original values
180                                 var left = style.left, rsLeft = elem.runtimeStyle.left;
181
182                                 // Put in the new values to get a computed value out
183                                 elem.runtimeStyle.left = elem.currentStyle.left;
184                                 style.left = ret || 0;
185                                 ret = style.pixelLeft + "px";
186
187                                 // Revert the changed values
188                                 style.left = left;
189                                 elem.runtimeStyle.left = rsLeft;
190                         }
191                 }
192
193                 return ret;
194         },
195
196         // A method for quickly swapping in/out CSS properties to get correct calculations
197         swap: function( elem, options, callback ) {
198                 var old = {};
199                 // Remember the old values, and insert the new ones
200                 for ( var name in options ) {
201                         old[ name ] = elem.style[ name ];
202                         elem.style[ name ] = options[ name ];
203                 }
204
205                 callback.call( elem );
206
207                 // Revert the old values
208                 for ( var name in options )
209                         elem.style[ name ] = old[ name ];
210         }
211 });