forked from jquery-backstretch/jquery-backstretch
-
Notifications
You must be signed in to change notification settings - Fork 134
/
jquery.anystretch.js
171 lines (143 loc) · 8.12 KB
/
jquery.anystretch.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/*
* jQuery Anystretch
* Version 1.2 (@jbrooksuk / me.itslimetime.com)
* https://github.com/jbrooksuk/jquery-anystretch
* Based on Dan Millar's Port
* https://github.com/danmillar/jquery-anystretch
*
* Add a dynamically-resized background image to the body
* of a page or any other block level element within it
*
* Copyright (c) 2012 Dan Millar (@danmillar / decode.uk.com)
* Dual licensed under the MIT and GPL licenses.
*
* This is a fork of jQuery Backstretch (v1.2)
* Copyright (c) 2011 Scott Robbin (srobbin.com)
*/
;(function($) {
$.fn.anystretch = function(src, options, callback) {
var isBody = this.selector.length ? false : true; // Decide whether anystretch is being called on an element or not
return this.each(function(i){
var defaultSettings = {
positionX: 'center', // Should we center the image on the X axis?
positionY: 'center', // Should we center the image on the Y axis?
speed: 0, // fadeIn speed for background after image loads (e.g. "fast" or 500)
elPosition: 'relative', // position of containing element when not being added to the body
dataName: 'stretch' // The data-* name used to search for
},
el = $(this),
container = isBody ? $('.anystretch') : el.children(".anystretch"),
settings = container.data("settings") || defaultSettings, // If this has been called once before, use the old settings as the default
existingSettings = container.data('settings'),
imgRatio, bgImg, bgWidth, bgHeight, bgOffset, bgCSS;
// Extend the settings with those the user has provided
if(options && typeof options == "object") $.extend(settings, options);
// Just in case the user passed in a function without options
if(options && typeof options == "function") callback = options;
// Initialize
$(document).ready(_init);
// For chaining
return this;
function _init() {
// Prepend image, wrapped in a DIV, with some positioning and zIndex voodoo
if(src || el.length >= 1) {
var img;
if(!isBody) {
// If not being added to the body set position to elPosition (default: relative) to keep anystretch contained
el.css({position: settings.elPosition, background: "none"});
}
// If this is the first time that anystretch is being called
if(container.length == 0) {
container = $("<div />").attr("class", "anystretch")
.css({left: 0, top: 0, position: (isBody ? "fixed" : "absolute"), overflow: "hidden", zIndex: (isBody ? -999999 : -999998), margin: 0, padding: 0, height: "100%", width: "100%"});
} else {
// Prepare to delete any old images
container.find("img").addClass("deleteable");
}
img = $("<img />").css({position: "absolute", display: "none", margin: 0, padding: 0, border: "none", zIndex: -999999})
.bind("load", function(e) {
var self = $(this),
imgWidth, imgHeight;
self.css({width: "auto", height: "auto"});
imgWidth = this.width || $(e.target).width();
imgHeight = this.height || $(e.target).height();
imgRatio = imgWidth / imgHeight;
_adjustBG(function() {
self.fadeIn(settings.speed, function(){
// Remove the old images, if necessary.
container.find('.deleteable').remove();
// Callback
if(typeof callback == "function") callback();
});
});
})
.appendTo(container);
// Append the container to the body, if it's not already there
if(el.children(".anystretch").length == 0) {
if(isBody) {
$('body').append(container);
} else {
el.append(container);
}
}
// Attach the settings
container.data("settings", settings);
var imgSrc = "";
if(src) {
imgSrc = src;
}else if(el.data(settings.dataName)) {
imgSrc = el.data(settings.dataName);
}else{
return;
}
img.attr("src", imgSrc); // Hack for IE img onload event
// Adjust the background size when the window is resized or orientation has changed (iOS)
$(window).resize(_adjustBG);
}
}
function _adjustBG(fn) {
try {
bgCSS = {left: 0, top: 0};
bgWidth = _width();
bgHeight = bgWidth / imgRatio;
// Make adjustments based on image ratio
// Note: Offset code provided by Peter Baker (http://ptrbkr.com/). Thanks, Peter!
if(bgHeight >= _height()) {
bgOffset = (bgHeight - _height()) /2;
if(settings.positionY == 'center' || settings.centeredY) { //
$.extend(bgCSS, {top: "-" + bgOffset + "px"});
} else if(settings.positionY == 'bottom') {
$.extend(bgCSS, {top: "auto", bottom: "0px"});
}
} else {
bgHeight = _height();
bgWidth = bgHeight * imgRatio;
bgOffset = (bgWidth - _width()) / 2;
if(settings.positionX == 'center' || settings.centeredX) {
$.extend(bgCSS, {left: "-" + bgOffset + "px"});
} else if(settings.positionX == 'right') {
$.extend(bgCSS, {left: "auto", right: "0px"});
}
}
container.children("img:not(.deleteable)").width( bgWidth ).height( bgHeight )
.filter("img").css(bgCSS);
} catch(err) {
// IE7 seems to trigger _adjustBG before the image is loaded.
// This try/catch block is a hack to let it fail gracefully.
}
// Executed the passed in function, if necessary
if (typeof fn == "function") fn();
}
function _width() {
return isBody ? el.width() : el.innerWidth();
}
function _height() {
return isBody ? el.height() : el.innerHeight();
}
});
};
$.anystretch = function(src, options, callback) {
var el = ("onorientationchange" in window) ? $(document) : $(window); // hack to acccount for iOS position:fixed shortcomings
el.anystretch(src, options, callback);
};
})(jQuery);