" )[0],
//rsrc = /url\(["']?(.*?)["']?\)/,
rsrc = /url\(["']?(.*?)["']?\)$/,
watched = [],
positions = {
top: 0,
left: 0,
bottom: 1,
right: 1,
center: .5
};
// feature detection
if ( "backgroundSize" in div.style && !$.debugBGS ) { return; }
$.cssHooks.backgroundSize = {
set: function( elem, value ) {
var firstTime = !$.data( elem, "bgsImg" ),
pos,
$wrapper, $img;
$.data( elem, "bgsValue", value );
if ( firstTime ) {
// add this element to the 'watched' list so that it's updated on resize
watched.push( elem );
$.refreshBackgroundDimensions( elem, true );
// create wrapper and img
$wrapper = $( "
" ).css({
position: "absolute",
zIndex: -1,
top: 0,
right: 0,
left: 0,
bottom: 0,
overflow: "hidden"
});
$img = $( "
![]()
" ).css({
position: "absolute"
}).appendTo( $wrapper ),
$wrapper.prependTo( elem );
$.data( elem, "bgsImg", $img[0] );
pos = (
// Firefox, Chrome (for debug)
$.css( elem, "backgroundPosition" ) ||
// IE8
$.css( elem, "backgroundPositionX" ) + " " + $.css( elem, "backgroundPositionY" )
).split(" ");
// Only compatible with 1 or 2 percentage or keyword values,
// Not yet compatible with length values and 4 values.
$.data( elem, "bgsPos", [
positions[ pos[0] ] || parseFloat( pos[0] ) / 100,
positions[ pos[1] ] || parseFloat( pos[1] ) / 100
]);
// This is the part where we mess with the existing DOM
// to make sure that the background image is correctly zIndexed
$.css( elem, "zIndex" ) == "auto" && ( elem.style.zIndex = 0 );
$.css( elem, "position" ) == "static" && ( elem.style.position = "relative" );
$.refreshBackgroundImage( elem );
} else {
$.refreshBackground( elem );
}
},
get: function( elem ) {
return $.data( elem, "bgsValue" ) || "";
}
};
// The background should refresh automatically when changing the background-image
$.cssHooks.backgroundImage = {
set: function( elem, value ) {
// if the element has a backgroundSize, refresh its background
return $.data( elem, "bgsImg") ?
$.refreshBackgroundImage( elem, value ) :
// otherwise set the background-image normally
value;
}
};
$.refreshBackgroundDimensions = function( elem, noBgRefresh ) {
var $elem = $(elem),
currDim = {
width: $elem.innerWidth(),
height: $elem.innerHeight()
},
prevDim = $.data( elem, "bgsDim" ),
changed = !prevDim ||
currDim.width != prevDim.width ||
currDim.height != prevDim.height;
$.data( elem, "bgsDim", currDim );
if ( changed && !noBgRefresh ) {
$.refreshBackground( elem );
}
};
$.refreshBackgroundImage = function( elem, value ) {
var img = $.data( elem, "bgsImg"),
currSrc = ( rsrc.exec( value || $.css( elem, "backgroundImage" ) ) || [] )[1],
prevSrc = img && img.src,
changed = currSrc != prevSrc,
imgWidth, imgHeight;
if ( changed ) {
img.style.height = img.style.width = "auto";
img.onload = function() {
var dim = {
width: img.width,
height: img.height
};
// ignore onload on the proxy image
if ( dim.width == 1 && dim.height == 1 ) { return; }
$.data( elem, "bgsImgDim", dim );
$.data( elem, "bgsConstrain", false );
$.refreshBackground( elem );
img.style.visibility = "visible";
img.onload = null;
};
img.style.visibility = "hidden";
img.src = currSrc;
if ( img.readyState || img.complete ) {
img.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";
img.src = currSrc;
}
elem.style.backgroundImage = "none";
}
};
$.refreshBackground = function( elem ) {
var value = $.data( elem, "bgsValue" ),
elemDim = $.data( elem, "bgsDim" ),
imgDim = $.data( elem, "bgsImgDim" ),
$img = $( $.data( elem, "bgsImg" ) ),
pos = $.data( elem, "bgsPos" ),
prevConstrain = $.data( elem, "bgsConstrain" ),
currConstrain,
elemRatio = elemDim.width / elemDim.height,
imgRatio = imgDim.width / imgDim.height,
delta;
if ( value == "contain" ) {
if ( imgRatio > elemRatio ) {
$.data( elem, "bgsConstrain", ( currConstrain = "width" ) );
delta = Math.floor( ( elemDim.height - elemDim.width / imgRatio ) * pos[1] );
$img.css({
top: delta
});
// when switchin from height to with constraint,
// make sure to release contraint on height and reset left
if ( currConstrain != prevConstrain ) {
$img.css({
width: "100%",
height: "auto",
left: 0
});
}
} else {
$.data( elem, "bgsConstrain", ( currConstrain = "height" ) );
delta = Math.floor( ( elemDim.width - elemDim.height * imgRatio ) * pos[0] );
$img.css({
left: delta
});
if ( currConstrain != prevConstrain ) {
$img.css({
height: "100%",
width: "auto",
top: 0
});
}
}
} else if ( value == "cover" ) {
if ( imgRatio > elemRatio ) {
$.data( elem, "bgsConstrain", ( currConstrain = "height" ) );
delta = Math.floor( ( elemDim.height * imgRatio - elemDim.width ) * pos[0] );
$img.css({
left: -delta
});
if ( currConstrain != prevConstrain ) {
$img.css({
height:"100%",
width: "auto",
top: 0
});
}
} else {
$.data( elem, "bgsConstrain", ( currConstrain = "width" ) );
delta = Math.floor( ( elemDim.width / imgRatio - elemDim.height ) * pos[1] );
$img.css({
top: -delta
});
if ( currConstrain != prevConstrain ) {
$img.css({
width: "100%",
height: "auto",
left: 0
});
}
}
}
}
// Built-in throttledresize
var $event = $.event,
$special,
dummy = {_:0},
frame = 0,
wasResized, animRunning;
$special = $event.special.throttledresize = {
setup: function() {
$( this ).on( "resize", $special.handler );
},
teardown: function() {
$( this ).off( "resize", $special.handler );
},
handler: function( event, execAsap ) {
// Save the context
var context = this,
args = arguments;
wasResized = true;
if ( !animRunning ) {
$(dummy).animate(dummy, { duration: Infinity, step: function() {
frame++;
if ( frame > $special.threshold && wasResized || execAsap ) {
// set correct event type
event.type = "throttledresize";
$event.dispatch.apply( context, args );
wasResized = false;
frame = 0;
}
if ( frame > 9 ) {
$(dummy).stop();
animRunning = false;
frame = 0;
}
}});
animRunning = true;
}
},
threshold: 1
};
// All backgrounds should refresh automatically when the window is resized
$(window).on("throttledresize", function() {
$(watched).each(function() {
$.refreshBackgroundDimensions( this );
});
});
})(jQuery,window,document,Math);