Jump To …

11-css.js

jQuery Annotated Source.

Home | Previous Chapter | Next Chapter

CSS

var ralpha = /alpha\([^)]*\)/i,
  ropacity = /opacity=([^)]*)/,

fixed for IE9, see #8346

  rupper = /([A-Z]|^ms)/g,
  rnumpx = /^-?\d+(?:px)?$/i,
  rnum = /^-?\d/,
  rrelNum = /^[+\-]=/,
  rrelNumFilter = /[^+\-\.\de]+/g,

  cssShow = { position: "absolute", visibility: "hidden", display: "block" },
  cssWidth = [ "Left", "Right" ],
  cssHeight = [ "Top", "Bottom" ],
  curCSS,

  getComputedStyle,
  currentStyle;

jQuery.fn.css = function( name, value ) {

Setting 'undefined' is a no-op

  if ( arguments.length === 2 && value === undefined ) {
    return this;
  }

  return jQuery.access( this, name, value, true, function( elem, name, value ) {
    return value !== undefined ?
      jQuery.style( elem, name, value ) :
      jQuery.css( elem, name );
  });
};

jQuery.extend({

Add in style property hooks for overriding the default behavior of getting and setting a style property

  cssHooks: {
    opacity: {
      get: function( elem, computed ) {
        if ( computed ) {

We should always get a number back from opacity

          var ret = curCSS( elem, "opacity", "opacity" );
          return ret === "" ? "1" : ret;

        } else {
          return elem.style.opacity;
        }
      }
    }
  },

Exclude the following css properties to add px

  cssNumber: {
    "fillOpacity": true,
    "fontWeight": true,
    "lineHeight": true,
    "opacity": true,
    "orphans": true,
    "widows": true,
    "zIndex": true,
    "zoom": true
  },

Add in properties whose names you wish to fix before setting or getting the value

  cssProps: {

normalize float css property

    "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
  },

Get and set the style property on a DOM Node

  style: function( elem, name, value, extra ) {

Don't set styles on text and comment nodes

    if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
      return;
    }

Make sure that we're working with the right name

    var ret, type, origName = jQuery.camelCase( name ),
      style = elem.style, hooks = jQuery.cssHooks[ origName ];

    name = jQuery.cssProps[ origName ] || origName;

Check if we're setting a value

    if ( value !== undefined ) {
      type = typeof value;

Make sure that NaN and null values aren't set. See: #7116

      if ( type === "number" && isNaN( value ) || value == null ) {
        return;
      }

convert relative number strings (+= or -=) to relative numbers. #7345

      if ( type === "string" && rrelNum.test( value ) ) {
        value = +value.replace( rrelNumFilter, "" ) + parseFloat( jQuery.css( elem, name ) );

Fixes bug #9237

        type = "number";
      }

If a number was passed in, add 'px' to the (except for certain CSS properties)

      if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
        value += "px";
      }

If a hook was provided, use that value, otherwise just set the specified value

      if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {

Wrapped to prevent IE from throwing errors when 'invalid' values are provided Fixes bug #5509

        try {
          style[ name ] = value;
        } catch(e) {}
      }

    } else {

If a hook was provided get the non-computed value from there

      if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
        return ret;
      }

Otherwise just get the value from the style object

      return style[ name ];
    }
  },

  css: function( elem, name, extra ) {
    var ret, hooks;

Make sure that we're working with the right name

    name = jQuery.camelCase( name );
    hooks = jQuery.cssHooks[ name ];
    name = jQuery.cssProps[ name ] || name;

cssFloat needs a special treatment

    if ( name === "cssFloat" ) {
      name = "float";
    }

If a hook was provided get the computed value from there

    if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {
      return ret;

Otherwise, if a way to get the computed value exists, use that

    } else if ( curCSS ) {
      return curCSS( elem, name );
    }
  },

A method for quickly swapping in/out CSS properties to get correct calculations

  swap: function( elem, options, callback ) {
    var old = {};

Remember the old values, and insert the new ones

    for ( var name in options ) {
      old[ name ] = elem.style[ name ];
      elem.style[ name ] = options[ name ];
    }

    callback.call( elem );

Revert the old values

    for ( name in options ) {
      elem.style[ name ] = old[ name ];
    }
  }
});

DEPRECATED, Use jQuery.css() instead

jQuery.curCSS = jQuery.css;

jQuery.each(["height", "width"], function( i, name ) {
  jQuery.cssHooks[ name ] = {
    get: function( elem, computed, extra ) {
      var val;

      if ( computed ) {
        if ( elem.offsetWidth !== 0 ) {
          return getWH( elem, name, extra );
        } else {
          jQuery.swap( elem, cssShow, function() {
            val = getWH( elem, name, extra );
          });
        }

        return val;
      }
    },

    set: function( elem, value ) {
      if ( rnumpx.test( value ) ) {

ignore negative width and height values #1599

        value = parseFloat( value );

        if ( value >= 0 ) {
          return value + "px";
        }

      } else {
        return value;
      }
    }
  };
});

if ( !jQuery.support.opacity ) {
  jQuery.cssHooks.opacity = {
    get: function( elem, computed ) {

IE uses filters for opacity

      return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
        ( parseFloat( RegExp.$1 ) / 100 ) + "" :
        computed ? "1" : "";
    },

    set: function( elem, value ) {
      var style = elem.style,
        currentStyle = elem.currentStyle;

IE has trouble with opacity if it does not have layout Force it by setting the zoom level

      style.zoom = 1;

Set the alpha filter to set the opacity

      var opacity = jQuery.isNaN( value ) ?
        "" :
        "alpha(opacity=" + value * 100 + ")",
        filter = currentStyle && currentStyle.filter || style.filter || "";

      style.filter = ralpha.test( filter ) ?
        filter.replace( ralpha, opacity ) :
        filter + " " + opacity;
    }
  };
}

jQuery(function() {

This hook cannot be added until DOM ready because the support test for it is not run until after DOM ready

  if ( !jQuery.support.reliableMarginRight ) {
    jQuery.cssHooks.marginRight = {
      get: function( elem, computed ) {

WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right Work around by temporarily setting element display to inline-block

        var ret;
        jQuery.swap( elem, { "display": "inline-block" }, function() {
          if ( computed ) {
            ret = curCSS( elem, "margin-right", "marginRight" );
          } else {
            ret = elem.style.marginRight;
          }
        });
        return ret;
      }
    };
  }
});

if ( document.defaultView && document.defaultView.getComputedStyle ) {
  getComputedStyle = function( elem, name ) {
    var ret, defaultView, computedStyle;

    name = name.replace( rupper, "-$1" ).toLowerCase();

    if ( !(defaultView = elem.ownerDocument.defaultView) ) {
      return undefined;
    }

    if ( (computedStyle = defaultView.getComputedStyle( elem, null )) ) {
      ret = computedStyle.getPropertyValue( name );
      if ( ret === "" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {
        ret = jQuery.style( elem, name );
      }
    }

    return ret;
  };
}

if ( document.documentElement.currentStyle ) {
  currentStyle = function( elem, name ) {
    var left,
      ret = elem.currentStyle && elem.currentStyle[ name ],
      rsLeft = elem.runtimeStyle && elem.runtimeStyle[ name ],
      style = elem.style;

From the awesome hack by Dean Edwards http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291

If we're not dealing with a regular pixel number but a number that has a weird ending, we need to convert it to pixels

    if ( !rnumpx.test( ret ) && rnum.test( ret ) ) {

Remember the original values

      left = style.left;

Put in the new values to get a computed value out

      if ( rsLeft ) {
        elem.runtimeStyle.left = elem.currentStyle.left;
      }
      style.left = name === "fontSize" ? "1em" : (ret || 0);
      ret = style.pixelLeft + "px";

Revert the changed values

      style.left = left;
      if ( rsLeft ) {
        elem.runtimeStyle.left = rsLeft;
      }
    }

    return ret === "" ? "auto" : ret;
  };
}

curCSS = getComputedStyle || currentStyle;

function getWH( elem, name, extra ) {

Start with offset property

  var val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
    which = name === "width" ? cssWidth : cssHeight;

  if ( val > 0 ) {
    if ( extra !== "border" ) {
      jQuery.each( which, function() {
        if ( !extra ) {
          val -= parseFloat( jQuery.css( elem, "padding" + this ) ) || 0;
        }
        if ( extra === "margin" ) {
          val += parseFloat( jQuery.css( elem, extra + this ) ) || 0;
        } else {
          val -= parseFloat( jQuery.css( elem, "border" + this + "Width" ) ) || 0;
        }
      });
    }

    return val + "px";
  }

Fall back to computed then uncomputed css if necessary

  val = curCSS( elem, name, name );
  if ( val < 0 || val == null ) {
    val = elem.style[ name ] || 0;
  }

Normalize "", auto, and prepare for extra

  val = parseFloat( val ) || 0;

Add padding, border, margin

  if ( extra ) {
    jQuery.each( which, function() {
      val += parseFloat( jQuery.css( elem, "padding" + this ) ) || 0;
      if ( extra !== "padding" ) {
        val += parseFloat( jQuery.css( elem, "border" + this + "Width" ) ) || 0;
      }
      if ( extra === "margin" ) {
        val += parseFloat( jQuery.css( elem, extra + this ) ) || 0;
      }
    });
  }

  return val + "px";
}

if ( jQuery.expr && jQuery.expr.filters ) {
  jQuery.expr.filters.hidden = function( elem ) {
    var width = elem.offsetWidth,
      height = elem.offsetHeight;

    return (width === 0 && height === 0) || (!jQuery.support.reliableHiddenOffsets && (elem.style.display || jQuery.css( elem, "display" )) === "none");
  };

  jQuery.expr.filters.visible = function( elem ) {
    return !jQuery.expr.filters.hidden( elem );
  };
}