/*! magnific popup - v0.9.9 - 2013-11-15 * http://dimsemenov.com/plugins/magnific-popup/ * copyright (c) 2013 dmitry semenov; */ ;(function($) { /*>>core*/ /** * * magnific popup core js file * */ /** * private static constants */ var close_event = 'close', before_close_event = 'beforeclose', after_close_event = 'afterclose', before_append_event = 'beforeappend', markup_parse_event = 'markupparse', open_event = 'open', change_event = 'change', ns = 'mfp', event_ns = '.' + ns, ready_class = 'mfp-ready', removing_class = 'mfp-removing', prevent_close_class = 'mfp-prevent-close'; /** * private vars */ var mfp, // as we have only one instance of magnificpopup object, we define it locally to not to use 'this' magnificpopup = function(){}, _isjq = !!(window.jquery), _prevstatus, _window = $(window), _body, _document, _prevcontenttype, _wrapclasses, _currpopuptype; /** * private functions */ var _mfpon = function(name, f) { mfp.ev.on(ns + name + event_ns, f); }, _getel = function(classname, appendto, html, raw) { var el = document.createelement('div'); el.classname = 'mfp-'+classname; if(html) { el.innerhtml = html; } if(!raw) { el = $(el); if(appendto) { el.appendto(appendto); } } else if(appendto) { appendto.appendchild(el); } return el; }, _mfptrigger = function(e, data) { mfp.ev.triggerhandler(ns + e, data); if(mfp.st.callbacks) { // converts "mfpeventname" to "eventname" callback and triggers it if it's present e = e.charat(0).tolowercase() + e.slice(1); if(mfp.st.callbacks[e]) { mfp.st.callbacks[e].apply(mfp, $.isarray(data) ? data : [data]); } } }, _getclosebtn = function(type) { if(type !== _currpopuptype || !mfp.currtemplate.closebtn) { mfp.currtemplate.closebtn = $( mfp.st.closemarkup.replace('%title%', mfp.st.tclose ) ); _currpopuptype = type; } return mfp.currtemplate.closebtn; }, // initialize magnific popup only when called at least once _checkinstance = function() { if(!$.magnificpopup.instance) { mfp = new magnificpopup(); mfp.init(); $.magnificpopup.instance = mfp; } }, // css transition detection, http://stackoverflow.com/questions/7264899/detect-css-transitions-using-javascript-and-without-modernizr supportstransitions = function() { var s = document.createelement('p').style, // 's' for style. better to create an element if body yet to exist v = ['ms','o','moz','webkit']; // 'v' for vendor if( s['transition'] !== undefined ) { return true; } while( v.length ) { if( v.pop() + 'transition' in s ) { return true; } } return false; }; /** * public functions */ magnificpopup.prototype = { constructor: magnificpopup, /** * initializes magnific popup plugin. * this function is triggered only once when $.fn.magnificpopup or $.magnificpopup is executed */ init: function() { var appversion = navigator.appversion; mfp.isie7 = appversion.indexof("msie 7.") !== -1; mfp.isie8 = appversion.indexof("msie 8.") !== -1; mfp.islowie = mfp.isie7 || mfp.isie8; mfp.isandroid = (/android/gi).test(appversion); mfp.isios = (/iphone|ipad|ipod/gi).test(appversion); mfp.supportstransition = supportstransitions(); // we disable fixed positioned lightbox on devices that don't handle it nicely. // if you know a better way of detecting this - let me know. mfp.probablymobile = (mfp.isandroid || mfp.isios || /(opera mini)|kindle|webos|blackberry|(opera mobi)|(windows phone)|iemobile/i.test(navigator.useragent) ); _body = $(document.body); _document = $(document); mfp.popupscache = {}; }, /** * opens popup * @param data [description] */ open: function(data) { var i; if(data.isobj === false) { // convert jquery collection to array to avoid conflicts later mfp.items = data.items.toarray(); mfp.index = 0; var items = data.items, item; for(i = 0; i < items.length; i++) { item = items[i]; if(item.parsed) { item = item.el[0]; } if(item === data.el[0]) { mfp.index = i; break; } } } else { mfp.items = $.isarray(data.items) ? data.items : [data.items]; mfp.index = data.index || 0; } // if popup is already opened - we just update the content if(mfp.isopen) { mfp.updateitemhtml(); return; } mfp.types = []; _wrapclasses = ''; if(data.mainel && data.mainel.length) { mfp.ev = data.mainel.eq(0); } else { mfp.ev = _document; } if(data.key) { if(!mfp.popupscache[data.key]) { mfp.popupscache[data.key] = {}; } mfp.currtemplate = mfp.popupscache[data.key]; } else { mfp.currtemplate = {}; } mfp.st = $.extend(true, {}, $.magnificpopup.defaults, data ); mfp.fixedcontentpos = mfp.st.fixedcontentpos === 'auto' ? !mfp.probablymobile : mfp.st.fixedcontentpos; if(mfp.st.modal) { mfp.st.closeoncontentclick = false; mfp.st.closeonbgclick = false; mfp.st.showclosebtn = false; mfp.st.enableescapekey = false; } // building markup // main containers are created only once if(!mfp.bgoverlay) { // dark overlay mfp.bgoverlay = _getel('bg').on('click'+event_ns, function() { mfp.close(); }); mfp.wrap = _getel('wrap').attr('tabindex', -1).on('click'+event_ns, function(e) { if(mfp._checkifclose(e.target)) { mfp.close(); } }); mfp.container = _getel('container', mfp.wrap); } mfp.contentcontainer = _getel('content'); if(mfp.st.preloader) { mfp.preloader = _getel('preloader', mfp.container, mfp.st.tloading); } // initializing modules var modules = $.magnificpopup.modules; for(i = 0; i < modules.length; i++) { var n = modules[i]; n = n.charat(0).touppercase() + n.slice(1); mfp['init'+n].call(mfp); } _mfptrigger('beforeopen'); if(mfp.st.showclosebtn) { // close button if(!mfp.st.closebtninside) { mfp.wrap.append( _getclosebtn() ); } else { _mfpon(markup_parse_event, function(e, template, values, item) { values.close_replacewith = _getclosebtn(item.type); }); _wrapclasses += ' mfp-close-btn-in'; } } if(mfp.st.aligntop) { _wrapclasses += ' mfp-align-top'; } if(mfp.fixedcontentpos) { mfp.wrap.css({ overflow: mfp.st.overflowy, overflowx: 'hidden', overflowy: mfp.st.overflowy }); } else { mfp.wrap.css({ top: _window.scrolltop(), position: 'absolute' }); } if( mfp.st.fixedbgpos === false || (mfp.st.fixedbgpos === 'auto' && !mfp.fixedcontentpos) ) { mfp.bgoverlay.css({ height: _document.height(), position: 'absolute' }); } if(mfp.st.enableescapekey) { // close on esc key _document.on('keyup' + event_ns, function(e) { if(e.keycode === 27) { mfp.close(); } }); } _window.on('resize' + event_ns, function() { mfp.updatesize(); }); if(!mfp.st.closeoncontentclick) { _wrapclasses += ' mfp-auto-cursor'; } if(_wrapclasses) mfp.wrap.addclass(_wrapclasses); // this triggers recalculation of layout, so we get it once to not to trigger twice var windowheight = mfp.wh = _window.height(); var windowstyles = {}; if( mfp.fixedcontentpos ) { if(mfp._hasscrollbar(windowheight)){ var s = mfp._getscrollbarsize(); if(s) { windowstyles.marginright = s; } } } if(mfp.fixedcontentpos) { if(!mfp.isie7) { windowstyles.overflow = 'hidden'; } else { // ie7 double-scroll bug $('body, html').css('overflow', 'hidden'); } } var classestoadd = mfp.st.mainclass; if(mfp.isie7) { classestoadd += ' mfp-ie7'; } if(classestoadd) { mfp._addclasstomfp( classestoadd ); } // add content mfp.updateitemhtml(); _mfptrigger('buildcontrols'); // remove scrollbar, add margin e.t.c $('html').css(windowstyles); // add everything to dom mfp.bgoverlay.add(mfp.wrap).prependto( document.body ); // save last focused element mfp._lastfocusedel = document.activeelement; // wait for next cycle to allow css transition settimeout(function() { if(mfp.content) { mfp._addclasstomfp(ready_class); mfp._setfocus(); } else { // if content is not defined (not loaded e.t.c) we add class only for bg mfp.bgoverlay.addclass(ready_class); } // trap the focus in popup _document.on('focusin' + event_ns, mfp._onfocusin); }, 16); mfp.isopen = true; mfp.updatesize(windowheight); _mfptrigger(open_event); return data; }, /** * closes the popup */ close: function() { if(!mfp.isopen) return; _mfptrigger(before_close_event); mfp.isopen = false; // for css3 animation if(mfp.st.removaldelay && !mfp.islowie && mfp.supportstransition ) { mfp._addclasstomfp(removing_class); settimeout(function() { mfp._close(); }, mfp.st.removaldelay); } else { mfp._close(); } }, /** * helper for close() function */ _close: function() { _mfptrigger(close_event); var classestoremove = removing_class + ' ' + ready_class + ' '; mfp.bgoverlay.detach(); mfp.wrap.detach(); mfp.container.empty(); if(mfp.st.mainclass) { classestoremove += mfp.st.mainclass + ' '; } mfp._removeclassfrommfp(classestoremove); if(mfp.fixedcontentpos) { var windowstyles = {marginright: ''}; if(mfp.isie7) { $('body, html').css('overflow', ''); } else { windowstyles.overflow = ''; } $('html').css(windowstyles); } _document.off('keyup' + event_ns + ' focusin' + event_ns); mfp.ev.off(event_ns); // clean up dom elements that aren't removed mfp.wrap.attr('class', 'mfp-wrap').removeattr('style'); mfp.bgoverlay.attr('class', 'mfp-bg'); mfp.container.attr('class', 'mfp-container'); // remove close button from target element if(mfp.st.showclosebtn && (!mfp.st.closebtninside || mfp.currtemplate[mfp.curritem.type] === true)) { if(mfp.currtemplate.closebtn) mfp.currtemplate.closebtn.detach(); } if(mfp._lastfocusedel) { $(mfp._lastfocusedel).focus(); // put tab focus back } mfp.curritem = null; mfp.content = null; mfp.currtemplate = null; mfp.prevheight = 0; _mfptrigger(after_close_event); }, updatesize: function(winheight) { if(mfp.isios) { // fixes ios nav bars https://github.com/dimsemenov/magnific-popup/issues/2 var zoomlevel = document.documentelement.clientwidth / window.innerwidth; var height = window.innerheight * zoomlevel; mfp.wrap.css('height', height); mfp.wh = height; } else { mfp.wh = winheight || _window.height(); } // fixes #84: popup incorrectly positioned with position:relative on body if(!mfp.fixedcontentpos) { mfp.wrap.css('height', mfp.wh); } _mfptrigger('resize'); }, /** * set content of popup based on current index */ updateitemhtml: function() { var item = mfp.items[mfp.index]; // detach and perform modifications mfp.contentcontainer.detach(); if(mfp.content) mfp.content.detach(); if(!item.parsed) { item = mfp.parseel( mfp.index ); } var type = item.type; _mfptrigger('beforechange', [mfp.curritem ? mfp.curritem.type : '', type]); // beforechange event works like so: // _mfpon('beforechange', function(e, prevtype, newtype) { }); mfp.curritem = item; if(!mfp.currtemplate[type]) { var markup = mfp.st[type] ? mfp.st[type].markup : false; // allows to modify markup _mfptrigger('firstmarkupparse', markup); if(markup) { mfp.currtemplate[type] = $(markup); } else { // if there is no markup found we just define that template is parsed mfp.currtemplate[type] = true; } } if(_prevcontenttype && _prevcontenttype !== item.type) { mfp.container.removeclass('mfp-'+_prevcontenttype+'-holder'); } var newcontent = mfp['get' + type.charat(0).touppercase() + type.slice(1)](item, mfp.currtemplate[type]); mfp.appendcontent(newcontent, type); item.preloaded = true; _mfptrigger(change_event, item); _prevcontenttype = item.type; // append container back after its content changed mfp.container.prepend(mfp.contentcontainer); _mfptrigger('afterchange'); }, /** * set html content of popup */ appendcontent: function(newcontent, type) { mfp.content = newcontent; if(newcontent) { if(mfp.st.showclosebtn && mfp.st.closebtninside && mfp.currtemplate[type] === true) { // if there is no markup, we just append close button element inside if(!mfp.content.find('.mfp-close').length) { mfp.content.append(_getclosebtn()); } } else { mfp.content = newcontent; } } else { mfp.content = ''; } _mfptrigger(before_append_event); mfp.container.addclass('mfp-'+type+'-holder'); mfp.contentcontainer.append(mfp.content); }, /** * creates magnific popup data object based on given data * @param {int} index index of item to parse */ parseel: function(index) { var item = mfp.items[index], type = item.type; if(item.tagname) { item = { el: $(item) }; } else { item = { data: item, src: item.src }; } if(item.el) { var types = mfp.types; // check for 'mfp-type' class for(var i = 0; i < types.length; i++) { if( item.el.hasclass('mfp-'+types[i]) ) { type = types[i]; break; } } item.src = item.el.attr('data-mfp-src'); if(!item.src) { item.src = item.el.attr('href'); } } item.type = type || mfp.st.type || 'inline'; item.index = index; item.parsed = true; mfp.items[index] = item; _mfptrigger('elementparse', item); return mfp.items[index]; }, /** * initializes single popup or a group of popups */ addgroup: function(el, options) { var ehandler = function(e) { e.mfpel = this; mfp._openclick(e, el, options); }; if(!options) { options = {}; } var ename = 'click.magnificpopup'; options.mainel = el; if(options.items) { options.isobj = true; el.off(ename).on(ename, ehandler); } else { options.isobj = false; if(options.delegate) { el.off(ename).on(ename, options.delegate , ehandler); } else { options.items = el; el.off(ename).on(ename, ehandler); } } }, _openclick: function(e, el, options) { var midclick = options.midclick !== undefined ? options.midclick : $.magnificpopup.defaults.midclick; if(!midclick && ( e.which === 2 || e.ctrlkey || e.metakey ) ) { return; } var disableon = options.disableon !== undefined ? options.disableon : $.magnificpopup.defaults.disableon; if(disableon) { if($.isfunction(disableon)) { if( !disableon.call(mfp) ) { return true; } } else { // else it's number if( _window.width() < disableon ) { return true; } } } if(e.type) { e.preventdefault(); // this will prevent popup from closing if element is inside and popup is already opened if(mfp.isopen) { e.stoppropagation(); } } options.el = $(e.mfpel); if(options.delegate) { options.items = el.find(options.delegate); } mfp.open(options); }, /** * updates text on preloader */ updatestatus: function(status, text) { if(mfp.preloader) { if(_prevstatus !== status) { mfp.container.removeclass('mfp-s-'+_prevstatus); } if(!text && status === 'loading') { text = mfp.st.tloading; } var data = { status: status, text: text }; // allows to modify status _mfptrigger('updatestatus', data); status = data.status; text = data.text; mfp.preloader.html(text); mfp.preloader.find('a').on('click', function(e) { e.stopimmediatepropagation(); }); mfp.container.addclass('mfp-s-'+status); _prevstatus = status; } }, /* "private" helpers that aren't private at all */ // check to close popup or not // "target" is an element that was clicked _checkifclose: function(target) { if($(target).hasclass(prevent_close_class)) { return; } var closeoncontent = mfp.st.closeoncontentclick; var closeonbg = mfp.st.closeonbgclick; if(closeoncontent && closeonbg) { return true; } else { // we close the popup if click is on close button or on preloader. or if there is no content. if(!mfp.content || $(target).hasclass('mfp-close') || (mfp.preloader && target === mfp.preloader[0]) ) { return true; } // if click is outside the content if( (target !== mfp.content[0] && !$.contains(mfp.content[0], target)) ) { if(closeonbg) { // last check, if the clicked element is in dom, (in case it's removed onclick) if( $.contains(document, target) ) { return true; } } } else if(closeoncontent) { return true; } } return false; }, _addclasstomfp: function(cname) { mfp.bgoverlay.addclass(cname); mfp.wrap.addclass(cname); }, _removeclassfrommfp: function(cname) { this.bgoverlay.removeclass(cname); mfp.wrap.removeclass(cname); }, _hasscrollbar: function(winheight) { return ( (mfp.isie7 ? _document.height() : document.body.scrollheight) > (winheight || _window.height()) ); }, _setfocus: function() { (mfp.st.focus ? mfp.content.find(mfp.st.focus).eq(0) : mfp.wrap).focus(); }, _onfocusin: function(e) { if( e.target !== mfp.wrap[0] && !$.contains(mfp.wrap[0], e.target) ) { mfp._setfocus(); return false; } }, _parsemarkup: function(template, values, item) { var arr; if(item.data) { values = $.extend(item.data, values); } _mfptrigger(markup_parse_event, [template, values, item] ); $.each(values, function(key, value) { if(value === undefined || value === false) { return true; } arr = key.split('_'); if(arr.length > 1) { var el = template.find(event_ns + '-'+arr[0]); if(el.length > 0) { var attr = arr[1]; if(attr === 'replacewith') { if(el[0] !== value[0]) { el.replacewith(value); } } else if(attr === 'img') { if(el.is('img')) { el.attr('src', value); } else { el.replacewith( '' ); } } else { el.attr(arr[1], value); } } } else { template.find(event_ns + '-'+key).html(value); } }); }, _getscrollbarsize: function() { // thx david if(mfp.scrollbarsize === undefined) { var scrolldiv = document.createelement("div"); scrolldiv.id = "mfp-sbm"; scrolldiv.style.csstext = 'width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;'; document.body.appendchild(scrolldiv); mfp.scrollbarsize = scrolldiv.offsetwidth - scrolldiv.clientwidth; document.body.removechild(scrolldiv); } return mfp.scrollbarsize; } }; /* magnificpopup core prototype end */ /** * public static functions */ $.magnificpopup = { instance: null, proto: magnificpopup.prototype, modules: [], open: function(options, index) { _checkinstance(); if(!options) { options = {}; } else { options = $.extend(true, {}, options); } options.isobj = true; options.index = index || 0; return this.instance.open(options); }, close: function() { return $.magnificpopup.instance && $.magnificpopup.instance.close(); }, registermodule: function(name, module) { if(module.options) { $.magnificpopup.defaults[name] = module.options; } $.extend(this.proto, module.proto); this.modules.push(name); }, defaults: { // info about options is in docs: // http://dimsemenov.com/plugins/magnific-popup/documentation.html#options disableon: 0, key: null, midclick: false, mainclass: '', preloader: true, focus: '', // css selector of input to focus after popup is opened closeoncontentclick: false, closeonbgclick: true, closebtninside: true, showclosebtn: true, enableescapekey: true, modal: false, aligntop: false, removaldelay: 0, fixedcontentpos: 'auto', fixedbgpos: 'auto', overflowy: 'auto', closemarkup: '', tclose: 'close (esc)', tloading: 'loading...' } }; $.fn.magnificpopup = function(options) { _checkinstance(); var jqel = $(this); // we call some api method of first param is a string if (typeof options === "string" ) { if(options === 'open') { var items, itemopts = _isjq ? jqel.data('magnificpopup') : jqel[0].magnificpopup, index = parseint(arguments[1], 10) || 0; if(itemopts.items) { items = itemopts.items[index]; } else { items = jqel; if(itemopts.delegate) { items = items.find(itemopts.delegate); } items = items.eq( index ); } mfp._openclick({mfpel:items}, jqel, itemopts); } else { if(mfp.isopen) mfp[options].apply(mfp, array.prototype.slice.call(arguments, 1)); } } else { // clone options obj options = $.extend(true, {}, options); /* * as zepto doesn't support .data() method for objects * and it works only in normal browsers * we assign "options" object directly to the dom element. ftw! */ if(_isjq) { jqel.data('magnificpopup', options); } else { jqel[0].magnificpopup = options; } mfp.addgroup(jqel, options); } return jqel; }; //quick benchmark /* var start = performance.now(), i, rounds = 1000; for(i = 0; i < rounds; i++) { } console.log('test #1:', performance.now() - start); start = performance.now(); for(i = 0; i < rounds; i++) { } console.log('test #2:', performance.now() - start); */ /*>>core*/ /*>>inline*/ var inline_ns = 'inline', _hiddenclass, _inlineplaceholder, _lastinlineelement, _putinlineelementsback = function() { if(_lastinlineelement) { _inlineplaceholder.after( _lastinlineelement.addclass(_hiddenclass) ).detach(); _lastinlineelement = null; } }; $.magnificpopup.registermodule(inline_ns, { options: { hiddenclass: 'hide', // will be appended with `mfp-` prefix markup: '', tnotfound: 'content not found' }, proto: { initinline: function() { mfp.types.push(inline_ns); _mfpon(close_event+'.'+inline_ns, function() { _putinlineelementsback(); }); }, getinline: function(item, template) { _putinlineelementsback(); if(item.src) { var inlinest = mfp.st.inline, el = $(item.src); if(el.length) { // if target element has parent - we replace it with placeholder and put it back after popup is closed var parent = el[0].parentnode; if(parent && parent.tagname) { if(!_inlineplaceholder) { _hiddenclass = inlinest.hiddenclass; _inlineplaceholder = _getel(_hiddenclass); _hiddenclass = 'mfp-'+_hiddenclass; } // replace target inline element with placeholder _lastinlineelement = el.after(_inlineplaceholder).detach().removeclass(_hiddenclass); } mfp.updatestatus('ready'); } else { mfp.updatestatus('error', inlinest.tnotfound); el = $('