UNPKG

8.58 kBJavaScriptView Raw
1(function ($) {
2
3 $.fn.materialbox = function () {
4
5 return this.each(function() {
6
7 if ($(this).hasClass('initialized')) {
8 return;
9 }
10
11 $(this).addClass('initialized');
12
13 var overlayActive = false;
14 var doneAnimating = true;
15 var inDuration = 275;
16 var outDuration = 200;
17 var origin = $(this);
18 var placeholder = $('<div></div>').addClass('material-placeholder');
19 var originalWidth = 0;
20 var originalHeight = 0;
21 var ancestorsChanged;
22 var ancestor;
23 origin.wrap(placeholder);
24
25
26 origin.on('click', function(){
27 var placeholder = origin.parent('.material-placeholder');
28 var windowWidth = window.innerWidth;
29 var windowHeight = window.innerHeight;
30 var originalWidth = origin.width();
31 var originalHeight = origin.height();
32
33
34 // If already modal, return to original
35 if (doneAnimating === false) {
36 returnToOriginal();
37 return false;
38 }
39 else if (overlayActive && doneAnimating===true) {
40 returnToOriginal();
41 return false;
42 }
43
44
45 // Set states
46 doneAnimating = false;
47 origin.addClass('active');
48 overlayActive = true;
49
50 // Set positioning for placeholder
51 placeholder.css({
52 width: placeholder[0].getBoundingClientRect().width,
53 height: placeholder[0].getBoundingClientRect().height,
54 position: 'relative',
55 top: 0,
56 left: 0
57 });
58
59 // Find ancestor with overflow: hidden; and remove it
60 ancestorsChanged = undefined;
61 ancestor = placeholder[0].parentNode;
62 var count = 0;
63 while (ancestor !== null && !$(ancestor).is(document)) {
64 var curr = $(ancestor);
65 if (curr.css('overflow') !== 'visible') {
66 curr.css('overflow', 'visible');
67 if (ancestorsChanged === undefined) {
68 ancestorsChanged = curr;
69 }
70 else {
71 ancestorsChanged = ancestorsChanged.add(curr);
72 }
73 }
74 ancestor = ancestor.parentNode;
75 }
76
77 // Set css on origin
78 origin.css({
79 position: 'absolute',
80 'z-index': 1000,
81 'will-change': 'left, top, width, height'
82 })
83 .data('width', originalWidth)
84 .data('height', originalHeight);
85
86 // Add overlay
87 var overlay = $('<div id="materialbox-overlay"></div>')
88 .css({
89 opacity: 0
90 })
91 .click(function(){
92 if (doneAnimating === true)
93 returnToOriginal();
94 });
95
96 // Put before in origin image to preserve z-index layering.
97 origin.before(overlay);
98
99 // Set dimensions if needed
100 var overlayOffset = overlay[0].getBoundingClientRect();
101 overlay.css({
102 width: windowWidth,
103 height: windowHeight,
104 left: -1 * overlayOffset.left,
105 top: -1 * overlayOffset.top
106 })
107
108 // Animate Overlay
109 overlay.velocity({opacity: 1},
110 {duration: inDuration, queue: false, easing: 'easeOutQuad'} );
111
112 // Add and animate caption if it exists
113 if (origin.data('caption') !== "") {
114 var $photo_caption = $('<div class="materialbox-caption"></div>');
115 $photo_caption.text(origin.data('caption'));
116 $('body').append($photo_caption);
117 $photo_caption.css({ "display": "inline" });
118 $photo_caption.velocity({opacity: 1}, {duration: inDuration, queue: false, easing: 'easeOutQuad'});
119 }
120
121 // Resize Image
122 var ratio = 0;
123 var widthPercent = originalWidth / windowWidth;
124 var heightPercent = originalHeight / windowHeight;
125 var newWidth = 0;
126 var newHeight = 0;
127
128 if (widthPercent > heightPercent) {
129 ratio = originalHeight / originalWidth;
130 newWidth = windowWidth * 0.9;
131 newHeight = windowWidth * 0.9 * ratio;
132 }
133 else {
134 ratio = originalWidth / originalHeight;
135 newWidth = (windowHeight * 0.9) * ratio;
136 newHeight = windowHeight * 0.9;
137 }
138
139 // Animate image + set z-index
140 if(origin.hasClass('responsive-img')) {
141 origin.velocity({'max-width': newWidth, 'width': originalWidth}, {duration: 0, queue: false,
142 complete: function(){
143 origin.css({left: 0, top: 0})
144 .velocity(
145 {
146 height: newHeight,
147 width: newWidth,
148 left: $(document).scrollLeft() + windowWidth/2 - origin.parent('.material-placeholder').offset().left - newWidth/2,
149 top: $(document).scrollTop() + windowHeight/2 - origin.parent('.material-placeholder').offset().top - newHeight/ 2
150 },
151 {
152 duration: inDuration,
153 queue: false,
154 easing: 'easeOutQuad',
155 complete: function(){doneAnimating = true;}
156 }
157 );
158 } // End Complete
159 }); // End Velocity
160 }
161 else {
162 origin.css('left', 0)
163 .css('top', 0)
164 .velocity(
165 {
166 height: newHeight,
167 width: newWidth,
168 left: $(document).scrollLeft() + windowWidth/2 - origin.parent('.material-placeholder').offset().left - newWidth/2,
169 top: $(document).scrollTop() + windowHeight/2 - origin.parent('.material-placeholder').offset().top - newHeight/ 2
170 },
171 {
172 duration: inDuration,
173 queue: false,
174 easing: 'easeOutQuad',
175 complete: function(){doneAnimating = true;}
176 }
177 ); // End Velocity
178 }
179
180 }); // End origin on click
181
182
183 // Return on scroll
184 $(window).scroll(function() {
185 if (overlayActive) {
186 returnToOriginal();
187 }
188 });
189
190 // Return on ESC
191 $(document).keyup(function(e) {
192
193 if (e.keyCode === 27 && doneAnimating === true) { // ESC key
194 if (overlayActive) {
195 returnToOriginal();
196 }
197 }
198 });
199
200
201 // This function returns the modaled image to the original spot
202 function returnToOriginal() {
203
204 doneAnimating = false;
205
206 var placeholder = origin.parent('.material-placeholder');
207 var windowWidth = window.innerWidth;
208 var windowHeight = window.innerHeight;
209 var originalWidth = origin.data('width');
210 var originalHeight = origin.data('height');
211
212 origin.velocity("stop", true);
213 $('#materialbox-overlay').velocity("stop", true);
214 $('.materialbox-caption').velocity("stop", true);
215
216
217 $('#materialbox-overlay').velocity({opacity: 0}, {
218 duration: outDuration, // Delay prevents animation overlapping
219 queue: false, easing: 'easeOutQuad',
220 complete: function(){
221 // Remove Overlay
222 overlayActive = false;
223 $(this).remove();
224 }
225 });
226
227 // Resize Image
228 origin.velocity(
229 {
230 width: originalWidth,
231 height: originalHeight,
232 left: 0,
233 top: 0
234 },
235 {
236 duration: outDuration,
237 queue: false, easing: 'easeOutQuad'
238 }
239 );
240
241 // Remove Caption + reset css settings on image
242 $('.materialbox-caption').velocity({opacity: 0}, {
243 duration: outDuration, // Delay prevents animation overlapping
244 queue: false, easing: 'easeOutQuad',
245 complete: function(){
246 placeholder.css({
247 height: '',
248 width: '',
249 position: '',
250 top: '',
251 left: ''
252 });
253
254 origin.css({
255 height: '',
256 top: '',
257 left: '',
258 width: '',
259 'max-width': '',
260 position: '',
261 'z-index': '',
262 'will-change': ''
263 });
264
265 // Remove class
266 origin.removeClass('active');
267 doneAnimating = true;
268 $(this).remove();
269
270 // Remove overflow overrides on ancestors
271 if (ancestorsChanged) {
272 ancestorsChanged.css('overflow', '');
273 }
274 }
275 });
276
277 }
278 });
279 };
280
281 $(document).ready(function(){
282 $('.materialboxed').materialbox();
283 });
284
285}( jQuery ));