Mercurial > web-octave
comparison js/foundation/foundation.reveal.js @ 0:7abe02bf29ec
initial commit
author | Alex Krolick <whokilledtheelectricmonk@gmail.com> |
---|---|
date | Sat, 07 Nov 2015 18:04:42 -0800 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:7abe02bf29ec |
---|---|
1 ;(function ($, window, document, undefined) { | |
2 'use strict'; | |
3 | |
4 var openModals = []; | |
5 | |
6 Foundation.libs.reveal = { | |
7 name : 'reveal', | |
8 | |
9 version : '5.5.3', | |
10 | |
11 locked : false, | |
12 | |
13 settings : { | |
14 animation : 'fadeAndPop', | |
15 animation_speed : 250, | |
16 close_on_background_click : true, | |
17 close_on_esc : true, | |
18 dismiss_modal_class : 'close-reveal-modal', | |
19 multiple_opened : false, | |
20 bg_class : 'reveal-modal-bg', | |
21 root_element : 'body', | |
22 open : function(){}, | |
23 opened : function(){}, | |
24 close : function(){}, | |
25 closed : function(){}, | |
26 on_ajax_error: $.noop, | |
27 bg : $('.reveal-modal-bg'), | |
28 css : { | |
29 open : { | |
30 'opacity' : 0, | |
31 'visibility' : 'visible', | |
32 'display' : 'block' | |
33 }, | |
34 close : { | |
35 'opacity' : 1, | |
36 'visibility' : 'hidden', | |
37 'display' : 'none' | |
38 } | |
39 } | |
40 }, | |
41 | |
42 init : function (scope, method, options) { | |
43 $.extend(true, this.settings, method, options); | |
44 this.bindings(method, options); | |
45 }, | |
46 | |
47 events : function (scope) { | |
48 var self = this, | |
49 S = self.S; | |
50 | |
51 S(this.scope) | |
52 .off('.reveal') | |
53 .on('click.fndtn.reveal', '[' + this.add_namespace('data-reveal-id') + ']:not([disabled])', function (e) { | |
54 e.preventDefault(); | |
55 | |
56 if (!self.locked) { | |
57 var element = S(this), | |
58 ajax = element.data(self.data_attr('reveal-ajax')), | |
59 replaceContentSel = element.data(self.data_attr('reveal-replace-content')); | |
60 | |
61 self.locked = true; | |
62 | |
63 if (typeof ajax === 'undefined') { | |
64 self.open.call(self, element); | |
65 } else { | |
66 var url = ajax === true ? element.attr('href') : ajax; | |
67 self.open.call(self, element, {url : url}, { replaceContentSel : replaceContentSel }); | |
68 } | |
69 } | |
70 }); | |
71 | |
72 S(document) | |
73 .on('click.fndtn.reveal', this.close_targets(), function (e) { | |
74 e.preventDefault(); | |
75 if (!self.locked) { | |
76 var settings = S('[' + self.attr_name() + '].open').data(self.attr_name(true) + '-init') || self.settings, | |
77 bg_clicked = S(e.target)[0] === S('.' + settings.bg_class)[0]; | |
78 | |
79 if (bg_clicked) { | |
80 if (settings.close_on_background_click) { | |
81 e.stopPropagation(); | |
82 } else { | |
83 return; | |
84 } | |
85 } | |
86 | |
87 self.locked = true; | |
88 self.close.call(self, bg_clicked ? S('[' + self.attr_name() + '].open:not(.toback)') : S(this).closest('[' + self.attr_name() + ']')); | |
89 } | |
90 }); | |
91 | |
92 if (S('[' + self.attr_name() + ']', this.scope).length > 0) { | |
93 S(this.scope) | |
94 // .off('.reveal') | |
95 .on('open.fndtn.reveal', this.settings.open) | |
96 .on('opened.fndtn.reveal', this.settings.opened) | |
97 .on('opened.fndtn.reveal', this.open_video) | |
98 .on('close.fndtn.reveal', this.settings.close) | |
99 .on('closed.fndtn.reveal', this.settings.closed) | |
100 .on('closed.fndtn.reveal', this.close_video); | |
101 } else { | |
102 S(this.scope) | |
103 // .off('.reveal') | |
104 .on('open.fndtn.reveal', '[' + self.attr_name() + ']', this.settings.open) | |
105 .on('opened.fndtn.reveal', '[' + self.attr_name() + ']', this.settings.opened) | |
106 .on('opened.fndtn.reveal', '[' + self.attr_name() + ']', this.open_video) | |
107 .on('close.fndtn.reveal', '[' + self.attr_name() + ']', this.settings.close) | |
108 .on('closed.fndtn.reveal', '[' + self.attr_name() + ']', this.settings.closed) | |
109 .on('closed.fndtn.reveal', '[' + self.attr_name() + ']', this.close_video); | |
110 } | |
111 | |
112 return true; | |
113 }, | |
114 | |
115 // PATCH #3: turning on key up capture only when a reveal window is open | |
116 key_up_on : function (scope) { | |
117 var self = this; | |
118 | |
119 // PATCH #1: fixing multiple keyup event trigger from single key press | |
120 self.S('body').off('keyup.fndtn.reveal').on('keyup.fndtn.reveal', function ( event ) { | |
121 var open_modal = self.S('[' + self.attr_name() + '].open'), | |
122 settings = open_modal.data(self.attr_name(true) + '-init') || self.settings ; | |
123 // PATCH #2: making sure that the close event can be called only while unlocked, | |
124 // so that multiple keyup.fndtn.reveal events don't prevent clean closing of the reveal window. | |
125 if ( settings && event.which === 27 && settings.close_on_esc && !self.locked) { // 27 is the keycode for the Escape key | |
126 self.close.call(self, open_modal); | |
127 } | |
128 }); | |
129 | |
130 return true; | |
131 }, | |
132 | |
133 // PATCH #3: turning on key up capture only when a reveal window is open | |
134 key_up_off : function (scope) { | |
135 this.S('body').off('keyup.fndtn.reveal'); | |
136 return true; | |
137 }, | |
138 | |
139 open : function (target, ajax_settings) { | |
140 var self = this, | |
141 modal; | |
142 | |
143 if (target) { | |
144 if (typeof target.selector !== 'undefined') { | |
145 // Find the named node; only use the first one found, since the rest of the code assumes there's only one node | |
146 modal = self.S('#' + target.data(self.data_attr('reveal-id'))).first(); | |
147 } else { | |
148 modal = self.S(this.scope); | |
149 | |
150 ajax_settings = target; | |
151 } | |
152 } else { | |
153 modal = self.S(this.scope); | |
154 } | |
155 | |
156 var settings = modal.data(self.attr_name(true) + '-init'); | |
157 settings = settings || this.settings; | |
158 | |
159 | |
160 if (modal.hasClass('open') && target !== undefined && target.attr('data-reveal-id') == modal.attr('id')) { | |
161 return self.close(modal); | |
162 } | |
163 | |
164 if (!modal.hasClass('open')) { | |
165 var open_modal = self.S('[' + self.attr_name() + '].open'); | |
166 | |
167 if (typeof modal.data('css-top') === 'undefined') { | |
168 modal.data('css-top', parseInt(modal.css('top'), 10)) | |
169 .data('offset', this.cache_offset(modal)); | |
170 } | |
171 | |
172 modal.attr('tabindex','0').attr('aria-hidden','false'); | |
173 | |
174 this.key_up_on(modal); // PATCH #3: turning on key up capture only when a reveal window is open | |
175 | |
176 // Prevent namespace event from triggering twice | |
177 modal.on('open.fndtn.reveal', function(e) { | |
178 if (e.namespace !== 'fndtn.reveal') return; | |
179 }); | |
180 | |
181 modal.on('open.fndtn.reveal').trigger('open.fndtn.reveal'); | |
182 | |
183 if (open_modal.length < 1) { | |
184 this.toggle_bg(modal, true); | |
185 } | |
186 | |
187 if (typeof ajax_settings === 'string') { | |
188 ajax_settings = { | |
189 url : ajax_settings | |
190 }; | |
191 } | |
192 | |
193 var openModal = function() { | |
194 if(open_modal.length > 0) { | |
195 if(settings.multiple_opened) { | |
196 self.to_back(open_modal); | |
197 } else { | |
198 self.hide(open_modal, settings.css.close); | |
199 } | |
200 } | |
201 | |
202 // bl: add the open_modal that isn't already in the background to the openModals array | |
203 if(settings.multiple_opened) { | |
204 openModals.push(modal); | |
205 } | |
206 | |
207 self.show(modal, settings.css.open); | |
208 }; | |
209 | |
210 if (typeof ajax_settings === 'undefined' || !ajax_settings.url) { | |
211 openModal(); | |
212 } else { | |
213 var old_success = typeof ajax_settings.success !== 'undefined' ? ajax_settings.success : null; | |
214 $.extend(ajax_settings, { | |
215 success : function (data, textStatus, jqXHR) { | |
216 if ( $.isFunction(old_success) ) { | |
217 var result = old_success(data, textStatus, jqXHR); | |
218 if (typeof result == 'string') { | |
219 data = result; | |
220 } | |
221 } | |
222 | |
223 if (typeof options !== 'undefined' && typeof options.replaceContentSel !== 'undefined') { | |
224 modal.find(options.replaceContentSel).html(data); | |
225 } else { | |
226 modal.html(data); | |
227 } | |
228 | |
229 self.S(modal).foundation('section', 'reflow'); | |
230 self.S(modal).children().foundation(); | |
231 | |
232 openModal(); | |
233 } | |
234 }); | |
235 | |
236 // check for if user initalized with error callback | |
237 if (settings.on_ajax_error !== $.noop) { | |
238 $.extend(ajax_settings, { | |
239 error : settings.on_ajax_error | |
240 }); | |
241 } | |
242 | |
243 $.ajax(ajax_settings); | |
244 } | |
245 } | |
246 self.S(window).trigger('resize'); | |
247 }, | |
248 | |
249 close : function (modal) { | |
250 var modal = modal && modal.length ? modal : this.S(this.scope), | |
251 open_modals = this.S('[' + this.attr_name() + '].open'), | |
252 settings = modal.data(this.attr_name(true) + '-init') || this.settings, | |
253 self = this; | |
254 | |
255 if (open_modals.length > 0) { | |
256 | |
257 modal.removeAttr('tabindex','0').attr('aria-hidden','true'); | |
258 | |
259 this.locked = true; | |
260 this.key_up_off(modal); // PATCH #3: turning on key up capture only when a reveal window is open | |
261 | |
262 modal.trigger('close.fndtn.reveal'); | |
263 | |
264 if ((settings.multiple_opened && open_modals.length === 1) || !settings.multiple_opened || modal.length > 1) { | |
265 self.toggle_bg(modal, false); | |
266 self.to_front(modal); | |
267 } | |
268 | |
269 if (settings.multiple_opened) { | |
270 var isCurrent = modal.is(':not(.toback)'); | |
271 self.hide(modal, settings.css.close, settings); | |
272 if(isCurrent) { | |
273 // remove the last modal since it is now closed | |
274 openModals.pop(); | |
275 } else { | |
276 // if this isn't the current modal, then find it in the array and remove it | |
277 openModals = $.grep(openModals, function(elt) { | |
278 var isThis = elt[0]===modal[0]; | |
279 if(isThis) { | |
280 // since it's not currently in the front, put it in the front now that it is hidden | |
281 // so that if it's re-opened, it won't be .toback | |
282 self.to_front(modal); | |
283 } | |
284 return !isThis; | |
285 }); | |
286 } | |
287 // finally, show the next modal in the stack, if there is one | |
288 if(openModals.length>0) { | |
289 self.to_front(openModals[openModals.length - 1]); | |
290 } | |
291 } else { | |
292 self.hide(open_modals, settings.css.close, settings); | |
293 } | |
294 } | |
295 }, | |
296 | |
297 close_targets : function () { | |
298 var base = '.' + this.settings.dismiss_modal_class; | |
299 | |
300 if (this.settings.close_on_background_click) { | |
301 return base + ', .' + this.settings.bg_class; | |
302 } | |
303 | |
304 return base; | |
305 }, | |
306 | |
307 toggle_bg : function (modal, state) { | |
308 if (this.S('.' + this.settings.bg_class).length === 0) { | |
309 this.settings.bg = $('<div />', {'class': this.settings.bg_class}) | |
310 .appendTo('body').hide(); | |
311 } | |
312 | |
313 var visible = this.settings.bg.filter(':visible').length > 0; | |
314 if ( state != visible ) { | |
315 if ( state == undefined ? visible : !state ) { | |
316 this.hide(this.settings.bg); | |
317 } else { | |
318 this.show(this.settings.bg); | |
319 } | |
320 } | |
321 }, | |
322 | |
323 show : function (el, css) { | |
324 // is modal | |
325 if (css) { | |
326 var settings = el.data(this.attr_name(true) + '-init') || this.settings, | |
327 root_element = settings.root_element, | |
328 context = this; | |
329 | |
330 if (el.parent(root_element).length === 0) { | |
331 var placeholder = el.wrap('<div style="display: none;" />').parent(); | |
332 | |
333 el.on('closed.fndtn.reveal.wrapped', function () { | |
334 el.detach().appendTo(placeholder); | |
335 el.unwrap().unbind('closed.fndtn.reveal.wrapped'); | |
336 }); | |
337 | |
338 el.detach().appendTo(root_element); | |
339 } | |
340 | |
341 var animData = getAnimationData(settings.animation); | |
342 if (!animData.animate) { | |
343 this.locked = false; | |
344 } | |
345 if (animData.pop) { | |
346 css.top = $(window).scrollTop() - el.data('offset') + 'px'; | |
347 var end_css = { | |
348 top: $(window).scrollTop() + el.data('css-top') + 'px', | |
349 opacity: 1 | |
350 }; | |
351 | |
352 return setTimeout(function () { | |
353 return el | |
354 .css(css) | |
355 .animate(end_css, settings.animation_speed, 'linear', function () { | |
356 context.locked = false; | |
357 el.trigger('opened.fndtn.reveal'); | |
358 }) | |
359 .addClass('open'); | |
360 }, settings.animation_speed / 2); | |
361 } | |
362 | |
363 css.top = $(window).scrollTop() + el.data('css-top') + 'px'; | |
364 | |
365 if (animData.fade) { | |
366 var end_css = {opacity: 1}; | |
367 | |
368 return setTimeout(function () { | |
369 return el | |
370 .css(css) | |
371 .animate(end_css, settings.animation_speed, 'linear', function () { | |
372 context.locked = false; | |
373 el.trigger('opened.fndtn.reveal'); | |
374 }) | |
375 .addClass('open'); | |
376 }, settings.animation_speed / 2); | |
377 } | |
378 | |
379 return el.css(css).show().css({opacity : 1}).addClass('open').trigger('opened.fndtn.reveal'); | |
380 } | |
381 | |
382 var settings = this.settings; | |
383 | |
384 // should we animate the background? | |
385 if (getAnimationData(settings.animation).fade) { | |
386 return el.fadeIn(settings.animation_speed / 2); | |
387 } | |
388 | |
389 this.locked = false; | |
390 | |
391 return el.show(); | |
392 }, | |
393 | |
394 to_back : function(el) { | |
395 el.addClass('toback'); | |
396 }, | |
397 | |
398 to_front : function(el) { | |
399 el.removeClass('toback'); | |
400 }, | |
401 | |
402 hide : function (el, css) { | |
403 // is modal | |
404 if (css) { | |
405 var settings = el.data(this.attr_name(true) + '-init'), | |
406 context = this; | |
407 settings = settings || this.settings; | |
408 | |
409 var animData = getAnimationData(settings.animation); | |
410 if (!animData.animate) { | |
411 this.locked = false; | |
412 } | |
413 if (animData.pop) { | |
414 var end_css = { | |
415 top: - $(window).scrollTop() - el.data('offset') + 'px', | |
416 opacity: 0 | |
417 }; | |
418 | |
419 return setTimeout(function () { | |
420 return el | |
421 .animate(end_css, settings.animation_speed, 'linear', function () { | |
422 context.locked = false; | |
423 el.css(css).trigger('closed.fndtn.reveal'); | |
424 }) | |
425 .removeClass('open'); | |
426 }, settings.animation_speed / 2); | |
427 } | |
428 | |
429 if (animData.fade) { | |
430 var end_css = {opacity : 0}; | |
431 | |
432 return setTimeout(function () { | |
433 return el | |
434 .animate(end_css, settings.animation_speed, 'linear', function () { | |
435 context.locked = false; | |
436 el.css(css).trigger('closed.fndtn.reveal'); | |
437 }) | |
438 .removeClass('open'); | |
439 }, settings.animation_speed / 2); | |
440 } | |
441 | |
442 return el.hide().css(css).removeClass('open').trigger('closed.fndtn.reveal'); | |
443 } | |
444 | |
445 var settings = this.settings; | |
446 | |
447 // should we animate the background? | |
448 if (getAnimationData(settings.animation).fade) { | |
449 return el.fadeOut(settings.animation_speed / 2); | |
450 } | |
451 | |
452 return el.hide(); | |
453 }, | |
454 | |
455 close_video : function (e) { | |
456 var video = $('.flex-video', e.target), | |
457 iframe = $('iframe', video); | |
458 | |
459 if (iframe.length > 0) { | |
460 iframe.attr('data-src', iframe[0].src); | |
461 iframe.attr('src', iframe.attr('src')); | |
462 video.hide(); | |
463 } | |
464 }, | |
465 | |
466 open_video : function (e) { | |
467 var video = $('.flex-video', e.target), | |
468 iframe = video.find('iframe'); | |
469 | |
470 if (iframe.length > 0) { | |
471 var data_src = iframe.attr('data-src'); | |
472 if (typeof data_src === 'string') { | |
473 iframe[0].src = iframe.attr('data-src'); | |
474 } else { | |
475 var src = iframe[0].src; | |
476 iframe[0].src = undefined; | |
477 iframe[0].src = src; | |
478 } | |
479 video.show(); | |
480 } | |
481 }, | |
482 | |
483 data_attr : function (str) { | |
484 if (this.namespace.length > 0) { | |
485 return this.namespace + '-' + str; | |
486 } | |
487 | |
488 return str; | |
489 }, | |
490 | |
491 cache_offset : function (modal) { | |
492 var offset = modal.show().height() + parseInt(modal.css('top'), 10) + modal.scrollY; | |
493 | |
494 modal.hide(); | |
495 | |
496 return offset; | |
497 }, | |
498 | |
499 off : function () { | |
500 $(this.scope).off('.fndtn.reveal'); | |
501 }, | |
502 | |
503 reflow : function () {} | |
504 }; | |
505 | |
506 /* | |
507 * getAnimationData('popAndFade') // {animate: true, pop: true, fade: true} | |
508 * getAnimationData('fade') // {animate: true, pop: false, fade: true} | |
509 * getAnimationData('pop') // {animate: true, pop: true, fade: false} | |
510 * getAnimationData('foo') // {animate: false, pop: false, fade: false} | |
511 * getAnimationData(null) // {animate: false, pop: false, fade: false} | |
512 */ | |
513 function getAnimationData(str) { | |
514 var fade = /fade/i.test(str); | |
515 var pop = /pop/i.test(str); | |
516 return { | |
517 animate : fade || pop, | |
518 pop : pop, | |
519 fade : fade | |
520 }; | |
521 } | |
522 }(jQuery, window, window.document)); |