LICENSE
4 years ago
README.md
1 year ago
featherlight.css
4 years ago
featherlight.gallery.css
4 years ago
featherlight.gallery.js
5 years ago
featherlight.gallery.min.css
4 years ago
featherlight.gallery.min.js
4 years ago
featherlight.js
4 years ago
featherlight.min.css
4 years ago
featherlight.min.js
4 years ago
featherlight.gallery.js
196 lines
| 1 | /** |
| 2 | * Featherlight Gallery – an extension for the ultra slim jQuery lightbox |
| 3 | * Version 1.7.14-UMD - http://noelboss.github.io/featherlight/ |
| 4 | * |
| 5 | * Copyright 2019, Noël Raoul Bossart (http://www.noelboss.com) |
| 6 | * MIT Licensed. |
| 7 | **/ |
| 8 | (function (factory) { |
| 9 | if (typeof define === 'function' && define.amd) { |
| 10 | // AMD. Register as an anonymous module. |
| 11 | define(['jquery'], factory); |
| 12 | } else if (typeof module === 'object' && module.exports) { |
| 13 | // Node/CommonJS |
| 14 | module.exports = function (root, jQuery) { |
| 15 | if (jQuery === undefined) { |
| 16 | // require('jQuery') returns a factory that requires window to |
| 17 | // build a jQuery instance, we normalize how we use modules |
| 18 | // that require this pattern but the window provided is a noop |
| 19 | // if it's defined (how jquery works) |
| 20 | if (typeof window !== 'undefined') { |
| 21 | jQuery = require('jquery'); |
| 22 | } else { |
| 23 | jQuery = require('jquery')(root); |
| 24 | } |
| 25 | } |
| 26 | factory(jQuery); |
| 27 | return jQuery; |
| 28 | }; |
| 29 | } else { |
| 30 | // Browser globals |
| 31 | factory(jQuery); |
| 32 | } |
| 33 | })(function($) { |
| 34 | "use strict"; |
| 35 | |
| 36 | var warn = function(m) { |
| 37 | if(window.console && window.console.warn) { |
| 38 | window.console.warn('FeatherlightGallery: ' + m); |
| 39 | } |
| 40 | }; |
| 41 | |
| 42 | if('undefined' === typeof $) { |
| 43 | return warn('Too much lightness, Featherlight needs jQuery.'); |
| 44 | } else if(!$.featherlight) { |
| 45 | return warn('Load the featherlight plugin before the gallery plugin'); |
| 46 | } |
| 47 | |
| 48 | var isTouchAware = ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch, |
| 49 | jQueryConstructor = $.event && $.event.special.swipeleft && $, |
| 50 | hammerConstructor = window.Hammer && function($el){ |
| 51 | var mc = new window.Hammer.Manager($el[0]); |
| 52 | mc.add(new window.Hammer.Swipe()); |
| 53 | return mc; |
| 54 | }, |
| 55 | swipeAwareConstructor = isTouchAware && (jQueryConstructor || hammerConstructor); |
| 56 | if(isTouchAware && !swipeAwareConstructor) { |
| 57 | warn('No compatible swipe library detected; one must be included before featherlightGallery for swipe motions to navigate the galleries.'); |
| 58 | } |
| 59 | |
| 60 | var callbackChain = { |
| 61 | afterClose: function(_super, event) { |
| 62 | var self = this; |
| 63 | self.$instance.off('next.'+self.namespace+' previous.'+self.namespace); |
| 64 | if (self._swiper) { |
| 65 | self._swiper |
| 66 | .off('swipeleft', self._swipeleft) /* See http://stackoverflow.com/questions/17367198/hammer-js-cant-remove-event-listener */ |
| 67 | .off('swiperight', self._swiperight); |
| 68 | self._swiper = null; |
| 69 | } |
| 70 | return _super(event); |
| 71 | }, |
| 72 | beforeOpen: function(_super, event){ |
| 73 | var self = this; |
| 74 | |
| 75 | self.$instance.on('next.'+self.namespace+' previous.'+self.namespace, function(event){ |
| 76 | var offset = event.type === 'next' ? +1 : -1; |
| 77 | self.navigateTo(self.currentNavigation() + offset); |
| 78 | }); |
| 79 | |
| 80 | if (swipeAwareConstructor) { |
| 81 | self._swiper = swipeAwareConstructor(self.$instance) |
| 82 | .on('swipeleft', self._swipeleft = function() { self.$instance.trigger('next'); }) |
| 83 | .on('swiperight', self._swiperight = function() { self.$instance.trigger('previous'); }); |
| 84 | |
| 85 | self.$instance |
| 86 | .addClass(this.namespace+'-swipe-aware', swipeAwareConstructor); |
| 87 | } |
| 88 | |
| 89 | self.$instance.find('.'+self.namespace+'-content') |
| 90 | .append(self.createNavigation('previous')) |
| 91 | .append(self.createNavigation('next')); |
| 92 | |
| 93 | return _super(event); |
| 94 | }, |
| 95 | beforeContent: function(_super, event) { |
| 96 | var index = this.currentNavigation(); |
| 97 | var len = this.slides().length; |
| 98 | this.$instance |
| 99 | .toggleClass(this.namespace+'-first-slide', index === 0) |
| 100 | .toggleClass(this.namespace+'-last-slide', index === len - 1); |
| 101 | return _super(event); |
| 102 | }, |
| 103 | onKeyUp: function(_super, event){ |
| 104 | var dir = { |
| 105 | 37: 'previous', /* Left arrow */ |
| 106 | 39: 'next' /* Rigth arrow */ |
| 107 | }[event.keyCode]; |
| 108 | if(dir) { |
| 109 | this.$instance.trigger(dir); |
| 110 | return false; |
| 111 | } else { |
| 112 | return _super(event); |
| 113 | } |
| 114 | } |
| 115 | }; |
| 116 | |
| 117 | function FeatherlightGallery($source, config) { |
| 118 | if(this instanceof FeatherlightGallery) { /* called with new */ |
| 119 | $.featherlight.apply(this, arguments); |
| 120 | this.chainCallbacks(callbackChain); |
| 121 | } else { |
| 122 | var flg = new FeatherlightGallery($.extend({$source: $source, $currentTarget: $source.first()}, config)); |
| 123 | flg.open(); |
| 124 | return flg; |
| 125 | } |
| 126 | } |
| 127 | |
| 128 | $.featherlight.extend(FeatherlightGallery, { |
| 129 | autoBind: '[data-featherlight-gallery]' |
| 130 | }); |
| 131 | |
| 132 | $.extend(FeatherlightGallery.prototype, { |
| 133 | /** Additional settings for Gallery **/ |
| 134 | previousIcon: '◀', /* Code that is used as previous icon */ |
| 135 | nextIcon: '▶', /* Code that is used as next icon */ |
| 136 | galleryFadeIn: 100, /* fadeIn speed when image is loaded */ |
| 137 | galleryFadeOut: 300, /* fadeOut speed before image is loaded */ |
| 138 | |
| 139 | slides: function() { |
| 140 | if (this.filter) { |
| 141 | return this.$source.find(this.filter); |
| 142 | } |
| 143 | return this.$source; |
| 144 | }, |
| 145 | |
| 146 | images: function() { |
| 147 | warn('images is deprecated, please use slides instead'); |
| 148 | return this.slides(); |
| 149 | }, |
| 150 | |
| 151 | currentNavigation: function() { |
| 152 | return this.slides().index(this.$currentTarget); |
| 153 | }, |
| 154 | |
| 155 | navigateTo: function(index) { |
| 156 | var self = this, |
| 157 | source = self.slides(), |
| 158 | len = source.length, |
| 159 | $inner = self.$instance.find('.' + self.namespace + '-inner'); |
| 160 | index = ((index % len) + len) % len; /* pin index to [0, len[ */ |
| 161 | |
| 162 | this.$instance.addClass(this.namespace+'-loading'); |
| 163 | self.$currentTarget = source.eq(index); |
| 164 | self.beforeContent(); |
| 165 | return $.when( |
| 166 | self.getContent(), |
| 167 | $inner.fadeTo(self.galleryFadeOut,0.2) |
| 168 | ).always(function($newContent) { |
| 169 | self.setContent($newContent); |
| 170 | self.afterContent(); |
| 171 | $newContent.fadeTo(self.galleryFadeIn,1); |
| 172 | }); |
| 173 | }, |
| 174 | |
| 175 | createNavigation: function(target) { |
| 176 | var self = this; |
| 177 | return $('<span title="'+target+'" class="'+this.namespace+'-'+target+'"><span>'+this[target+'Icon']+'</span></span>').on( 'click', function(evt){ |
| 178 | $(this).trigger(target+'.'+self.namespace); |
| 179 | evt.preventDefault(); |
| 180 | }); |
| 181 | } |
| 182 | }); |
| 183 | |
| 184 | $.featherlightGallery = FeatherlightGallery; |
| 185 | |
| 186 | /* extend jQuery with selector featherlight method $(elm).featherlight(config, elm); */ |
| 187 | $.fn.featherlightGallery = function(config) { |
| 188 | FeatherlightGallery.attach(this, config); |
| 189 | return this; |
| 190 | }; |
| 191 | |
| 192 | /* bind featherlight on ready if config autoBind is set */ |
| 193 | $(document).ready(function(){ FeatherlightGallery._onReady(); }); |
| 194 | |
| 195 | }); |
| 196 |