','
','
'].join('')),closeButtonSelector = '.'+self.namespace+'-close' + (self.otherClose ? ',' + self.otherClose : '');self.$instance = $background.clone().addClass(self.variant); /* clone DOM for the background, wrapper and the close button *//* close when click on background/anywhere/null or closebox */self.$instance.on(self.closeTrigger+'.'+self.namespace, function(event) {var $target = $(event.target);if( ('background' === self.closeOnClick && $target.is('.'+self.namespace))|| 'anywhere' === self.closeOnClick|| $target.closest(closeButtonSelector).length ){self.close(event);event.preventDefault();}});return this;},/* this method prepares the content and converts it into a jQuery object or a promise */getContent: function(){if(this.persist !== false && this.$content) {return this.$content;}var self = this,filters = this.constructor.contentFilters,readTargetAttr = function(name){ return self.$currentTarget && self.$currentTarget.attr(name); },targetValue = readTargetAttr(self.targetAttr),data = self.target || targetValue || '';/* Find which filter applies */var filter = filters[self.type]; /* check explicit type like {type: 'image'} *//* check explicit type like data-featherlight="image" */if(!filter && data in filters) {filter = filters[data];data = self.target && targetValue;}data = data || readTargetAttr('href') || '';/* check explicity type & content like {image: 'photo.jpg'} */if(!filter) {for(var filterName in filters) {if(self[filterName]) {filter = filters[filterName];data = self[filterName];}}}/* otherwise it's implicit, run checks */if(!filter) {var target = data;data = null;$.each(self.contentFilters, function() {filter = filters[this];if(filter.test) {data = filter.test(target);}if(!data && filter.regex && target.match && target.match(filter.regex)) {data = target;}return !data;});if(!data) {if('console' in window){ window.console.error('Featherlight: no content filter found ' + (target ? ' for "' + target + '"' : ' (no target specified)')); }return false;}}/* Process it */return filter.process.call(self, data);},/* sets the content of $instance to $content */setContent: function($content){var self = this;/* we need a special class for the iframe */if($content.is('iframe') || $('iframe', $content).length > 0){self.$instance.addClass(self.namespace+'-iframe');}self.$instance.removeClass(self.namespace+'-loading');/* replace content by appending to existing one before it is removed this insures that featherlight-inner remain at the same relative position to any other items added to featherlight-content */self.$instance.find('.'+self.namespace+'-inner').not($content) /* excluded new content, important if persisted */.slice(1).remove().end() /* In the unexpected event where there are many inner elements, remove all but the first one */.replaceWith($.contains(self.$instance[0], $content[0]) ? '' : $content);self.$content = $content.addClass(self.namespace+'-inner');return self;},/* opens the lightbox. "this" contains $instance with the lightbox, and with the config.Returns a promise that is resolved after is successfully opened. */open: function(event){var self = this;self.$instance.hide().appendTo(self.root);if((!event || !event.isDefaultPrevented())&& self.beforeOpen(event) !== false) {if(event){event.preventDefault();}var $content = self.getContent();if($content) {opened.push(self);toggleGlobalEvents(true);self.$instance.fadeIn(self.openSpeed);self.beforeContent(event);/* Set content and show */return $.when($content).always(function($content){self.setContent($content);self.afterContent(event);}).then(self.$instance.promise())/* Call afterOpen after fadeIn is done */.done(function(){ self.afterOpen(event); });}}self.$instance.detach();return $.Deferred().reject().promise();},/* closes the lightbox. "this" contains $instance with the lightbox, and with the configreturns a promise, resolved after the lightbox is successfully closed. */close: function(event){var self = this,deferred = $.Deferred();if(self.beforeClose(event) === false) {deferred.reject();} else {if (0 === pruneOpened(self).length) {toggleGlobalEvents(false);}self.$instance.fadeOut(self.closeSpeed,function(){self.$instance.detach();self.afterClose(event);deferred.resolve();});}return deferred.promise();},/* resizes the content so it fits in visible area and keeps the same aspect ratio.Does nothing if either the width or the height is not specified.Called automatically on window resize.Override if you want different behavior. */resize: function(w, h) {if (w && h) {/* Reset apparent image size first so container grows */this.$content.css('width', '').css('height', '');/* Calculate the worst ratio so that dimensions fit */var ratio = Math.max(w / parseInt(this.$content.parent().css('width'),10),h / parseInt(this.$content.parent().css('height'),10));/* Resize content */if (ratio > 1) {this.$content.css('width', '' + w / ratio + 'px').css('height', '' + h / ratio + 'px');}}},/* Utility function to chain callbacks [Warning: guru-level] Used be extensions that want to let users specify callbacks but also need themselves to use the callbacks. The argument 'chain' has callback names as keys and function(super, event) as values. That function is meant to call `super` at some point.*/chainCallbacks: function(chain) {for (var name in chain) {this[name] = $.proxy(chain[name], this, $.proxy(this[name], this));}}};$.extend(Featherlight, {id: 0, /* Used to id single featherlight instances */autoBind: '[data-featherlight]', /* Will automatically bind elements matching this selector. Clear or set before onReady */defaults: Featherlight.prototype, /* You can access and override all defaults using $.featherlight.defaults, which is just a synonym for $.featherlight.prototype *//* Contains the logic to determine content */contentFilters: {jquery: {regex: /^[#.]\w/, /* Anything that starts with a class name or identifiers */test: function(elem) { return elem instanceof $ && elem; },process: function(elem) { return this.persist !== false ? $(elem) : $(elem).clone(true); }},image: {regex: /\.(png|jpg|jpeg|gif|tiff|bmp|svg)(\?\S*)?$/i,process: function(url) {var self = this,deferred = $.Deferred(),img = new Image(),$img = $('');img.onload = function() {/* Store naturalWidth & height for IE8 */$img.naturalWidth = img.width; $img.naturalHeight = img.height;deferred.resolve( $img );};img.onerror = function() { deferred.reject($img); };img.src = url;return deferred.promise();}},html: {regex: /^\s*<[\w!][^<]*>/, /* Anything that starts with some kind of valid tag */process: function(html) { return $(html); }},ajax: {regex: /./, /* At this point, any content is assumed to be an URL */process: function(url) {var self = this,deferred = $.Deferred();/* we are using load so one can specify a target with: url.html #targetelement */var $container = $('
').load(url, function(response, status){if ( status !== "error" ) {deferred.resolve($container.contents());}deferred.fail();});return deferred.promise();}},iframe: {process: function(url) {var deferred = new $.Deferred();var $content = $('
').hide().attr('src', url).css(structure(this, 'iframe')).on('load', function() { deferred.resolve($content.show()); })// We can't move an