1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312 |
- /*!
- * justifiedGallery - v3.7.0
- * http://miromannino.github.io/Justified-Gallery/
- * Copyright (c) 2018 Miro Mannino
- * Licensed under the MIT license.
- */
- (function (factory) {
- if (typeof define === 'function' && define.amd) {
- // AMD. Register as an anonymous module.
- define(['jquery'], factory);
- } else if (typeof module === 'object' && module.exports) {
- // Node/CommonJS
- module.exports = function( root, jQuery ) {
- if ( jQuery === undefined ) {
- // require('jQuery') returns a factory that requires window to
- // build a jQuery instance, we normalize how we use modules
- // that require this pattern but the window provided is a noop
- // if it's defined (how jquery works)
- if ( typeof window !== 'undefined' ) {
- jQuery = require('jquery');
- }
- else {
- jQuery = require('jquery')(root);
- }
- }
- factory(jQuery);
- return jQuery;
- };
- } else {
- // Browser globals
- factory(jQuery);
- }
- }(function ($) {
- /**
- * Justified Gallery controller constructor
- *
- * @param $gallery the gallery to build
- * @param settings the settings (the defaults are in JustifiedGallery.defaults)
- * @constructor
- */
- var JustifiedGallery = function ($gallery, settings) {
-
- this.settings = settings;
- this.checkSettings();
-
- this.imgAnalyzerTimeout = null;
- this.entries = null;
- this.buildingRow = {
- entriesBuff : [],
- width : 0,
- height : 0,
- aspectRatio : 0
- };
- this.lastFetchedEntry = null;
- this.lastAnalyzedIndex = -1;
- this.yield = {
- every : 2, // do a flush every n flushes (must be greater than 1)
- flushed : 0 // flushed rows without a yield
- };
- this.border = settings.border >= 0 ? settings.border : settings.margins;
- this.maxRowHeight = this.retrieveMaxRowHeight();
- this.suffixRanges = this.retrieveSuffixRanges();
- this.offY = this.border;
- this.rows = 0;
- this.spinner = {
- phase : 0,
- timeSlot : 150,
- $el : $('<div class="spinner"><span></span><span></span><span></span></div>'),
- intervalId : null
- };
- this.scrollBarOn = false;
- this.checkWidthIntervalId = null;
- this.galleryWidth = $gallery.width();
- this.$gallery = $gallery;
-
- };
-
- /** @returns {String} the best suffix given the width and the height */
- JustifiedGallery.prototype.getSuffix = function (width, height) {
- var longestSide, i;
- longestSide = (width > height) ? width : height;
- for (i = 0; i < this.suffixRanges.length; i++) {
- if (longestSide <= this.suffixRanges[i]) {
- return this.settings.sizeRangeSuffixes[this.suffixRanges[i]];
- }
- }
- return this.settings.sizeRangeSuffixes[this.suffixRanges[i - 1]];
- };
-
- /**
- * Remove the suffix from the string
- *
- * @returns {string} a new string without the suffix
- */
- JustifiedGallery.prototype.removeSuffix = function (str, suffix) {
- return str.substring(0, str.length - suffix.length);
- };
-
- /**
- * @returns {boolean} a boolean to say if the suffix is contained in the str or not
- */
- JustifiedGallery.prototype.endsWith = function (str, suffix) {
- return str.indexOf(suffix, str.length - suffix.length) !== -1;
- };
-
- /**
- * Get the used suffix of a particular url
- *
- * @param str
- * @returns {String} return the used suffix
- */
- JustifiedGallery.prototype.getUsedSuffix = function (str) {
- for (var si in this.settings.sizeRangeSuffixes) {
- if (this.settings.sizeRangeSuffixes.hasOwnProperty(si)) {
- if (this.settings.sizeRangeSuffixes[si].length === 0) continue;
- if (this.endsWith(str, this.settings.sizeRangeSuffixes[si])) return this.settings.sizeRangeSuffixes[si];
- }
- }
- return '';
- };
-
- /**
- * Given an image src, with the width and the height, returns the new image src with the
- * best suffix to show the best quality thumbnail.
- *
- * @returns {String} the suffix to use
- */
- JustifiedGallery.prototype.newSrc = function (imageSrc, imgWidth, imgHeight, image) {
- var newImageSrc;
-
- if (this.settings.thumbnailPath) {
- newImageSrc = this.settings.thumbnailPath(imageSrc, imgWidth, imgHeight, image);
- } else {
- var matchRes = imageSrc.match(this.settings.extension);
- var ext = (matchRes !== null) ? matchRes[0] : '';
- newImageSrc = imageSrc.replace(this.settings.extension, '');
- newImageSrc = this.removeSuffix(newImageSrc, this.getUsedSuffix(newImageSrc));
- newImageSrc += this.getSuffix(imgWidth, imgHeight) + ext;
- }
-
- return newImageSrc;
- };
-
- /**
- * Shows the images that is in the given entry
- *
- * @param $entry the entry
- * @param callback the callback that is called when the show animation is finished
- */
- JustifiedGallery.prototype.showImg = function ($entry, callback) {
- if (this.settings.cssAnimation) {
- $entry.addClass('entry-visible');
- if (callback) callback();
- } else {
- $entry.stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback);
- $entry.find(this.settings.imgSelector).stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback);
- }
- };
-
- /**
- * Extract the image src form the image, looking from the 'safe-src', and if it can't be found, from the
- * 'src' attribute. It saves in the image data the 'jg.originalSrc' field, with the extracted src.
- *
- * @param $image the image to analyze
- * @returns {String} the extracted src
- */
- JustifiedGallery.prototype.extractImgSrcFromImage = function ($image) {
- var imageSrc = (typeof $image.data('safe-src') !== 'undefined') ? $image.data('safe-src') : $image.attr('src');
- $image.data('jg.originalSrc', imageSrc);
- return imageSrc;
- };
-
- /** @returns {jQuery} the image in the given entry */
- JustifiedGallery.prototype.imgFromEntry = function ($entry) {
- var $img = $entry.find(this.settings.imgSelector);
- return $img.length === 0 ? null : $img;
- };
-
- /** @returns {jQuery} the caption in the given entry */
- JustifiedGallery.prototype.captionFromEntry = function ($entry) {
- var $caption = $entry.find('> .caption');
- return $caption.length === 0 ? null : $caption;
- };
-
- /**
- * Display the entry
- *
- * @param {jQuery} $entry the entry to display
- * @param {int} x the x position where the entry must be positioned
- * @param y the y position where the entry must be positioned
- * @param imgWidth the image width
- * @param imgHeight the image height
- * @param rowHeight the row height of the row that owns the entry
- */
- JustifiedGallery.prototype.displayEntry = function ($entry, x, y, imgWidth, imgHeight, rowHeight) {
- $entry.width(imgWidth);
- $entry.height(rowHeight);
- $entry.css('top', y);
- $entry.css('left', x);
-
- var $image = this.imgFromEntry($entry);
- if ($image !== null) {
- $image.css('width', imgWidth);
- $image.css('height', imgHeight);
- $image.css('margin-left', - imgWidth / 2);
- $image.css('margin-top', - imgHeight / 2);
-
- // Image reloading for an high quality of thumbnails
- var imageSrc = $image.attr('src');
- var newImageSrc = this.newSrc(imageSrc, imgWidth, imgHeight, $image[0]);
-
- $image.one('error', function () {
- $image.attr('src', $image.data('jg.originalSrc')); //revert to the original thumbnail, we got it.
- });
-
- var loadNewImage = function () {
- if (imageSrc !== newImageSrc) { //load the new image after the fadeIn
- $image.attr('src', newImageSrc);
- }
- };
-
- if ($entry.data('jg.loaded') === 'skipped') {
- this.onImageEvent(imageSrc, $.proxy(function() {
- this.showImg($entry, loadNewImage);
- $entry.data('jg.loaded', true);
- }, this));
- } else {
- this.showImg($entry, loadNewImage);
- }
-
- } else {
- this.showImg($entry);
- }
-
- this.displayEntryCaption($entry);
- };
-
- /**
- * Display the entry caption. If the caption element doesn't exists, it creates the caption using the 'alt'
- * or the 'title' attributes.
- *
- * @param {jQuery} $entry the entry to process
- */
- JustifiedGallery.prototype.displayEntryCaption = function ($entry) {
- var $image = this.imgFromEntry($entry);
- if ($image !== null && this.settings.captions) {
- var $imgCaption = this.captionFromEntry($entry);
-
- // Create it if it doesn't exists
- if ($imgCaption === null) {
- var caption = $image.attr('alt');
- if (!this.isValidCaption(caption)) caption = $entry.attr('title');
- if (this.isValidCaption(caption)) { // Create only we found something
- $imgCaption = $('<div class="caption">' + caption + '</div>');
- $entry.append($imgCaption);
- $entry.data('jg.createdCaption', true);
- }
- }
-
- // Create events (we check again the $imgCaption because it can be still inexistent)
- if ($imgCaption !== null) {
- if (!this.settings.cssAnimation) $imgCaption.stop().fadeTo(0, this.settings.captionSettings.nonVisibleOpacity);
- this.addCaptionEventsHandlers($entry);
- }
- } else {
- this.removeCaptionEventsHandlers($entry);
- }
- };
-
- /**
- * Validates the caption
- *
- * @param caption The caption that should be validated
- * @return {boolean} Validation result
- */
- JustifiedGallery.prototype.isValidCaption = function (caption) {
- return (typeof caption !== 'undefined' && caption.length > 0);
- };
-
- /**
- * The callback for the event 'mouseenter'. It assumes that the event currentTarget is an entry.
- * It shows the caption using jQuery (or using CSS if it is configured so)
- *
- * @param {Event} eventObject the event object
- */
- JustifiedGallery.prototype.onEntryMouseEnterForCaption = function (eventObject) {
- var $caption = this.captionFromEntry($(eventObject.currentTarget));
- if (this.settings.cssAnimation) {
- $caption.addClass('caption-visible').removeClass('caption-hidden');
- } else {
- $caption.stop().fadeTo(this.settings.captionSettings.animationDuration,
- this.settings.captionSettings.visibleOpacity);
- }
- };
-
- /**
- * The callback for the event 'mouseleave'. It assumes that the event currentTarget is an entry.
- * It hides the caption using jQuery (or using CSS if it is configured so)
- *
- * @param {Event} eventObject the event object
- */
- JustifiedGallery.prototype.onEntryMouseLeaveForCaption = function (eventObject) {
- var $caption = this.captionFromEntry($(eventObject.currentTarget));
- if (this.settings.cssAnimation) {
- $caption.removeClass('caption-visible').removeClass('caption-hidden');
- } else {
- $caption.stop().fadeTo(this.settings.captionSettings.animationDuration,
- this.settings.captionSettings.nonVisibleOpacity);
- }
- };
-
- /**
- * Add the handlers of the entry for the caption
- *
- * @param $entry the entry to modify
- */
- JustifiedGallery.prototype.addCaptionEventsHandlers = function ($entry) {
- var captionMouseEvents = $entry.data('jg.captionMouseEvents');
- if (typeof captionMouseEvents === 'undefined') {
- captionMouseEvents = {
- mouseenter: $.proxy(this.onEntryMouseEnterForCaption, this),
- mouseleave: $.proxy(this.onEntryMouseLeaveForCaption, this)
- };
- $entry.on('mouseenter', undefined, undefined, captionMouseEvents.mouseenter);
- $entry.on('mouseleave', undefined, undefined, captionMouseEvents.mouseleave);
- $entry.data('jg.captionMouseEvents', captionMouseEvents);
- }
- };
-
- /**
- * Remove the handlers of the entry for the caption
- *
- * @param $entry the entry to modify
- */
- JustifiedGallery.prototype.removeCaptionEventsHandlers = function ($entry) {
- var captionMouseEvents = $entry.data('jg.captionMouseEvents');
- if (typeof captionMouseEvents !== 'undefined') {
- $entry.off('mouseenter', undefined, captionMouseEvents.mouseenter);
- $entry.off('mouseleave', undefined, captionMouseEvents.mouseleave);
- $entry.removeData('jg.captionMouseEvents');
- }
- };
-
- /**
- * Clear the building row data to be used for a new row
- */
- JustifiedGallery.prototype.clearBuildingRow = function () {
- this.buildingRow.entriesBuff = [];
- this.buildingRow.aspectRatio = 0;
- this.buildingRow.width = 0;
- };
-
- /**
- * Justify the building row, preparing it to
- *
- * @param isLastRow
- * @returns a boolean to know if the row has been justified or not
- */
- JustifiedGallery.prototype.prepareBuildingRow = function (isLastRow) {
- var i, $entry, imgAspectRatio, newImgW, newImgH, justify = true;
- var minHeight = 0;
- var availableWidth = this.galleryWidth - 2 * this.border - (
- (this.buildingRow.entriesBuff.length - 1) * this.settings.margins);
- var rowHeight = availableWidth / this.buildingRow.aspectRatio;
- var defaultRowHeight = this.settings.rowHeight;
- var justifiable = this.buildingRow.width / availableWidth > this.settings.justifyThreshold;
-
- //Skip the last row if we can't justify it and the lastRow == 'hide'
- if (isLastRow && this.settings.lastRow === 'hide' && !justifiable) {
- for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
- $entry = this.buildingRow.entriesBuff[i];
- if (this.settings.cssAnimation)
- $entry.removeClass('entry-visible');
- else {
- $entry.stop().fadeTo(0, 0.1);
- $entry.find('> img, > a > img').fadeTo(0, 0);
- }
- }
- return -1;
- }
-
- // With lastRow = nojustify, justify if is justificable (the images will not become too big)
- if (isLastRow && !justifiable && this.settings.lastRow !== 'justify' && this.settings.lastRow !== 'hide') {
- justify = false;
-
- if (this.rows > 0) {
- defaultRowHeight = (this.offY - this.border - this.settings.margins * this.rows) / this.rows;
- justify = defaultRowHeight * this.buildingRow.aspectRatio / availableWidth > this.settings.justifyThreshold;
- }
- }
-
- for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
- $entry = this.buildingRow.entriesBuff[i];
- imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height');
-
- if (justify) {
- newImgW = (i === this.buildingRow.entriesBuff.length - 1) ? availableWidth : rowHeight * imgAspectRatio;
- newImgH = rowHeight;
- } else {
- newImgW = defaultRowHeight * imgAspectRatio;
- newImgH = defaultRowHeight;
- }
-
- availableWidth -= Math.round(newImgW);
- $entry.data('jg.jwidth', Math.round(newImgW));
- $entry.data('jg.jheight', Math.ceil(newImgH));
- if (i === 0 || minHeight > newImgH) minHeight = newImgH;
- }
-
- this.buildingRow.height = minHeight;
- return justify;
- };
-
- /**
- * Flush a row: justify it, modify the gallery height accordingly to the row height
- *
- * @param isLastRow
- */
- JustifiedGallery.prototype.flushRow = function (isLastRow) {
- var settings = this.settings;
- var $entry, buildingRowRes, offX = this.border, i;
-
- buildingRowRes = this.prepareBuildingRow(isLastRow);
- if (isLastRow && settings.lastRow === 'hide' && buildingRowRes === -1) {
- this.clearBuildingRow();
- return;
- }
-
- if(this.maxRowHeight) {
- if(this.maxRowHeight < this.buildingRow.height) this.buildingRow.height = this.maxRowHeight;
- }
-
- //Align last (unjustified) row
- if (isLastRow && (settings.lastRow === 'center' || settings.lastRow === 'right')) {
- var availableWidth = this.galleryWidth - 2 * this.border - (this.buildingRow.entriesBuff.length - 1) * settings.margins;
-
- for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
- $entry = this.buildingRow.entriesBuff[i];
- availableWidth -= $entry.data('jg.jwidth');
- }
-
- if (settings.lastRow === 'center')
- offX += availableWidth / 2;
- else if (settings.lastRow === 'right')
- offX += availableWidth;
- }
-
- var lastEntryIdx = this.buildingRow.entriesBuff.length - 1;
- for (i = 0; i <= lastEntryIdx; i++) {
- $entry = this.buildingRow.entriesBuff[ this.settings.rtl ? lastEntryIdx - i : i ];
- this.displayEntry($entry, offX, this.offY, $entry.data('jg.jwidth'), $entry.data('jg.jheight'), this.buildingRow.height);
- offX += $entry.data('jg.jwidth') + settings.margins;
- }
-
- //Gallery Height
- this.galleryHeightToSet = this.offY + this.buildingRow.height + this.border;
- this.setGalleryTempHeight(this.galleryHeightToSet + this.getSpinnerHeight());
-
- if (!isLastRow || (this.buildingRow.height <= settings.rowHeight && buildingRowRes)) {
- //Ready for a new row
- this.offY += this.buildingRow.height + settings.margins;
- this.rows += 1;
- this.clearBuildingRow();
- this.settings.triggerEvent.call(this, 'jg.rowflush');
- }
- };
-
-
- // Scroll position not restoring: https://github.com/miromannino/Justified-Gallery/issues/221
- var galleryPrevStaticHeight = 0;
-
- JustifiedGallery.prototype.rememberGalleryHeight = function () {
- galleryPrevStaticHeight = this.$gallery.height();
- this.$gallery.height(galleryPrevStaticHeight);
- };
-
- // grow only
- JustifiedGallery.prototype.setGalleryTempHeight = function (height) {
- galleryPrevStaticHeight = Math.max(height, galleryPrevStaticHeight);
- this.$gallery.height(galleryPrevStaticHeight);
- };
-
- JustifiedGallery.prototype.setGalleryFinalHeight = function (height) {
- galleryPrevStaticHeight = height;
- this.$gallery.height(height);
- };
-
- /**
- * @returns {boolean} a boolean saying if the scrollbar is active or not
- */
- function hasScrollBar() {
- return $("body").height() > $(window).height();
- }
-
- /**
- * Checks the width of the gallery container, to know if a new justification is needed
- */
- JustifiedGallery.prototype.checkWidth = function () {
- this.checkWidthIntervalId = setInterval($.proxy(function () {
-
- // if the gallery is not currently visible, abort.
- if (!this.$gallery.is(":visible")) return;
-
- var galleryWidth = parseFloat(this.$gallery.width());
- if (hasScrollBar() === this.scrollBarOn) {
- if (Math.abs(galleryWidth - this.galleryWidth) > this.settings.refreshSensitivity) {
- this.galleryWidth = galleryWidth;
- this.rewind();
-
- this.rememberGalleryHeight();
-
- // Restart to analyze
- this.startImgAnalyzer(true);
- }
- } else {
- this.scrollBarOn = hasScrollBar();
- this.galleryWidth = galleryWidth;
- }
- }, this), this.settings.refreshTime);
- };
-
- /**
- * @returns {boolean} a boolean saying if the spinner is active or not
- */
- JustifiedGallery.prototype.isSpinnerActive = function () {
- return this.spinner.intervalId !== null;
- };
-
- /**
- * @returns {int} the spinner height
- */
- JustifiedGallery.prototype.getSpinnerHeight = function () {
- return this.spinner.$el.innerHeight();
- };
-
- /**
- * Stops the spinner animation and modify the gallery height to exclude the spinner
- */
- JustifiedGallery.prototype.stopLoadingSpinnerAnimation = function () {
- clearInterval(this.spinner.intervalId);
- this.spinner.intervalId = null;
- this.setGalleryTempHeight(this.$gallery.height() - this.getSpinnerHeight());
- this.spinner.$el.detach();
- };
-
- /**
- * Starts the spinner animation
- */
- JustifiedGallery.prototype.startLoadingSpinnerAnimation = function () {
- var spinnerContext = this.spinner;
- var $spinnerPoints = spinnerContext.$el.find('span');
- clearInterval(spinnerContext.intervalId);
- this.$gallery.append(spinnerContext.$el);
- this.setGalleryTempHeight(this.offY + this.buildingRow.height + this.getSpinnerHeight());
- spinnerContext.intervalId = setInterval(function () {
- if (spinnerContext.phase < $spinnerPoints.length) {
- $spinnerPoints.eq(spinnerContext.phase).fadeTo(spinnerContext.timeSlot, 1);
- } else {
- $spinnerPoints.eq(spinnerContext.phase - $spinnerPoints.length).fadeTo(spinnerContext.timeSlot, 0);
- }
- spinnerContext.phase = (spinnerContext.phase + 1) % ($spinnerPoints.length * 2);
- }, spinnerContext.timeSlot);
- };
-
- /**
- * Rewind the image analysis to start from the first entry.
- */
- JustifiedGallery.prototype.rewind = function () {
- this.lastFetchedEntry = null;
- this.lastAnalyzedIndex = -1;
- this.offY = this.border;
- this.rows = 0;
- this.clearBuildingRow();
- };
-
- /**
- * Update the entries searching it from the justified gallery HTML element
- *
- * @param norewind if norewind only the new entries will be changed (i.e. randomized, sorted or filtered)
- * @returns {boolean} true if some entries has been founded
- */
- JustifiedGallery.prototype.updateEntries = function (norewind) {
- var newEntries;
-
- if (norewind && this.lastFetchedEntry != null) {
- newEntries = $(this.lastFetchedEntry).nextAll(this.settings.selector).toArray();
- } else {
- this.entries = [];
- newEntries = this.$gallery.children(this.settings.selector).toArray();
- }
-
- if (newEntries.length > 0) {
-
- // Sort or randomize
- if ($.isFunction(this.settings.sort)) {
- newEntries = this.sortArray(newEntries);
- } else if (this.settings.randomize) {
- newEntries = this.shuffleArray(newEntries);
- }
- this.lastFetchedEntry = newEntries[newEntries.length - 1];
-
- // Filter
- if (this.settings.filter) {
- newEntries = this.filterArray(newEntries);
- } else {
- this.resetFilters(newEntries);
- }
-
- }
-
- this.entries = this.entries.concat(newEntries);
- return true;
- };
-
- /**
- * Apply the entries order to the DOM, iterating the entries and appending the images
- *
- * @param entries the entries that has been modified and that must be re-ordered in the DOM
- */
- JustifiedGallery.prototype.insertToGallery = function (entries) {
- var that = this;
- $.each(entries, function () {
- $(this).appendTo(that.$gallery);
- });
- };
-
- /**
- * Shuffle the array using the Fisher-Yates shuffle algorithm
- *
- * @param a the array to shuffle
- * @return the shuffled array
- */
- JustifiedGallery.prototype.shuffleArray = function (a) {
- var i, j, temp;
- for (i = a.length - 1; i > 0; i--) {
- j = Math.floor(Math.random() * (i + 1));
- temp = a[i];
- a[i] = a[j];
- a[j] = temp;
- }
- this.insertToGallery(a);
- return a;
- };
-
- /**
- * Sort the array using settings.comparator as comparator
- *
- * @param a the array to sort (it is sorted)
- * @return the sorted array
- */
- JustifiedGallery.prototype.sortArray = function (a) {
- a.sort(this.settings.sort);
- this.insertToGallery(a);
- return a;
- };
-
- /**
- * Reset the filters removing the 'jg-filtered' class from all the entries
- *
- * @param a the array to reset
- */
- JustifiedGallery.prototype.resetFilters = function (a) {
- for (var i = 0; i < a.length; i++) $(a[i]).removeClass('jg-filtered');
- };
-
- /**
- * Filter the entries considering theirs classes (if a string has been passed) or using a function for filtering.
- *
- * @param a the array to filter
- * @return the filtered array
- */
- JustifiedGallery.prototype.filterArray = function (a) {
- var settings = this.settings;
- if ($.type(settings.filter) === 'string') {
- // Filter only keeping the entries passed in the string
- return a.filter(function (el) {
- var $el = $(el);
- if ($el.is(settings.filter)) {
- $el.removeClass('jg-filtered');
- return true;
- } else {
- $el.addClass('jg-filtered').removeClass('jg-visible');
- return false;
- }
- });
- } else if ($.isFunction(settings.filter)) {
- // Filter using the passed function
- var filteredArr = a.filter(settings.filter);
- for (var i = 0; i < a.length; i++) {
- if (filteredArr.indexOf(a[i]) === -1) {
- $(a[i]).addClass('jg-filtered').removeClass('jg-visible');
- } else {
- $(a[i]).removeClass('jg-filtered');
- }
- }
- return filteredArr;
- }
- };
-
- /**
- * Destroy the Justified Gallery instance.
- *
- * It clears all the css properties added in the style attributes. We doesn't backup the original
- * values for those css attributes, because it costs (performance) and because in general one
- * shouldn't use the style attribute for an uniform set of images (where we suppose the use of
- * classes). Creating a backup is also difficult because JG could be called multiple times and
- * with different style attributes.
- */
- JustifiedGallery.prototype.destroy = function () {
- clearInterval(this.checkWidthIntervalId);
-
- $.each(this.entries, $.proxy(function(_, entry) {
- var $entry = $(entry);
-
- // Reset entry style
- $entry.css('width', '');
- $entry.css('height', '');
- $entry.css('top', '');
- $entry.css('left', '');
- $entry.data('jg.loaded', undefined);
- $entry.removeClass('jg-entry');
-
- // Reset image style
- var $img = this.imgFromEntry($entry);
- $img.css('width', '');
- $img.css('height', '');
- $img.css('margin-left', '');
- $img.css('margin-top', '');
- $img.attr('src', $img.data('jg.originalSrc'));
- $img.data('jg.originalSrc', undefined);
-
- // Remove caption
- this.removeCaptionEventsHandlers($entry);
- var $caption = this.captionFromEntry($entry);
- if ($entry.data('jg.createdCaption')) {
- // remove also the caption element (if created by jg)
- $entry.data('jg.createdCaption', undefined);
- if ($caption !== null) $caption.remove();
- } else {
- if ($caption !== null) $caption.fadeTo(0, 1);
- }
-
- }, this));
-
- this.$gallery.css('height', '');
- this.$gallery.removeClass('justified-gallery');
- this.$gallery.data('jg.controller', undefined);
- };
-
- /**
- * Analyze the images and builds the rows. It returns if it found an image that is not loaded.
- *
- * @param isForResize if the image analyzer is called for resizing or not, to call a different callback at the end
- */
- JustifiedGallery.prototype.analyzeImages = function (isForResize) {
- for (var i = this.lastAnalyzedIndex + 1; i < this.entries.length; i++) {
- var $entry = $(this.entries[i]);
- if ($entry.data('jg.loaded') === true || $entry.data('jg.loaded') === 'skipped') {
- var availableWidth = this.galleryWidth - 2 * this.border - (
- (this.buildingRow.entriesBuff.length - 1) * this.settings.margins);
- var imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height');
- if (availableWidth / (this.buildingRow.aspectRatio + imgAspectRatio) < this.settings.rowHeight) {
- this.flushRow(false);
-
- if(++this.yield.flushed >= this.yield.every) {
- this.startImgAnalyzer(isForResize);
- return;
- }
- }
-
- this.buildingRow.entriesBuff.push($entry);
- this.buildingRow.aspectRatio += imgAspectRatio;
- this.buildingRow.width += imgAspectRatio * this.settings.rowHeight;
- this.lastAnalyzedIndex = i;
-
- } else if ($entry.data('jg.loaded') !== 'error') {
- return;
- }
- }
-
- // Last row flush (the row is not full)
- if (this.buildingRow.entriesBuff.length > 0) this.flushRow(true);
-
- if (this.isSpinnerActive()) {
- this.stopLoadingSpinnerAnimation();
- }
-
- /* Stop, if there is, the timeout to start the analyzeImages.
- This is because an image can be set loaded, and the timeout can be set,
- but this image can be analyzed yet.
- */
- this.stopImgAnalyzerStarter();
-
- //On complete callback
- this.settings.triggerEvent.call(this, isForResize ? 'jg.resize' : 'jg.complete');
- this.setGalleryFinalHeight(this.galleryHeightToSet);
- };
-
- /**
- * Stops any ImgAnalyzer starter (that has an assigned timeout)
- */
- JustifiedGallery.prototype.stopImgAnalyzerStarter = function () {
- this.yield.flushed = 0;
- if (this.imgAnalyzerTimeout !== null) {
- clearTimeout(this.imgAnalyzerTimeout);
- this.imgAnalyzerTimeout = null;
- }
- };
-
- /**
- * Starts the image analyzer. It is not immediately called to let the browser to update the view
- *
- * @param isForResize specifies if the image analyzer must be called for resizing or not
- */
- JustifiedGallery.prototype.startImgAnalyzer = function (isForResize) {
- var that = this;
- this.stopImgAnalyzerStarter();
- this.imgAnalyzerTimeout = setTimeout(function () {
- that.analyzeImages(isForResize);
- }, 0.001); // we can't start it immediately due to a IE different behaviour
- };
-
- /**
- * Checks if the image is loaded or not using another image object. We cannot use the 'complete' image property,
- * because some browsers, with a 404 set complete = true.
- *
- * @param imageSrc the image src to load
- * @param onLoad callback that is called when the image has been loaded
- * @param onError callback that is called in case of an error
- */
- JustifiedGallery.prototype.onImageEvent = function (imageSrc, onLoad, onError) {
- if (!onLoad && !onError) return;
-
- var memImage = new Image();
- var $memImage = $(memImage);
- if (onLoad) {
- $memImage.one('load', function () {
- $memImage.off('load error');
- onLoad(memImage);
- });
- }
- if (onError) {
- $memImage.one('error', function() {
- $memImage.off('load error');
- onError(memImage);
- });
- }
- memImage.src = imageSrc;
- };
-
- /**
- * Init of Justified Gallery controlled
- * It analyzes all the entries starting theirs loading and calling the image analyzer (that works with loaded images)
- */
- JustifiedGallery.prototype.init = function () {
- var imagesToLoad = false, skippedImages = false, that = this;
- $.each(this.entries, function (index, entry) {
- var $entry = $(entry);
- var $image = that.imgFromEntry($entry);
-
- $entry.addClass('jg-entry');
-
- if ($entry.data('jg.loaded') !== true && $entry.data('jg.loaded') !== 'skipped') {
-
- // Link Rel global overwrite
- if (that.settings.rel !== null) $entry.attr('rel', that.settings.rel);
-
- // Link Target global overwrite
- if (that.settings.target !== null) $entry.attr('target', that.settings.target);
-
- if ($image !== null) {
-
- // Image src
- var imageSrc = that.extractImgSrcFromImage($image);
- $image.attr('src', imageSrc);
-
- /* If we have the height and the width, we don't wait that the image is loaded, but we start directly
- * with the justification */
- if (that.settings.waitThumbnailsLoad === false) {
- var width = parseFloat($image.prop('width'));
- var height = parseFloat($image.prop('height'));
- if (!isNaN(width) && !isNaN(height)) {
- $entry.data('jg.width', width);
- $entry.data('jg.height', height);
- $entry.data('jg.loaded', 'skipped');
- skippedImages = true;
- that.startImgAnalyzer(false);
- return true; // continue
- }
- }
-
- $entry.data('jg.loaded', false);
- imagesToLoad = true;
-
- // Spinner start
- if (!that.isSpinnerActive()) that.startLoadingSpinnerAnimation();
-
- that.onImageEvent(imageSrc, function (loadImg) { // image loaded
- $entry.data('jg.width', loadImg.width);
- $entry.data('jg.height', loadImg.height);
- $entry.data('jg.loaded', true);
- that.startImgAnalyzer(false);
- }, function () { // image load error
- $entry.data('jg.loaded', 'error');
- that.startImgAnalyzer(false);
- });
-
- } else {
- $entry.data('jg.loaded', true);
- $entry.data('jg.width', $entry.width() | parseFloat($entry.css('width')) | 1);
- $entry.data('jg.height', $entry.height() | parseFloat($entry.css('height')) | 1);
- }
-
- }
-
- });
-
- if (!imagesToLoad && !skippedImages) this.startImgAnalyzer(false);
- this.checkWidth();
- };
-
- /**
- * Checks that it is a valid number. If a string is passed it is converted to a number
- *
- * @param settingContainer the object that contains the setting (to allow the conversion)
- * @param settingName the setting name
- */
- JustifiedGallery.prototype.checkOrConvertNumber = function (settingContainer, settingName) {
- if ($.type(settingContainer[settingName]) === 'string') {
- settingContainer[settingName] = parseFloat(settingContainer[settingName]);
- }
-
- if ($.type(settingContainer[settingName]) === 'number') {
- if (isNaN(settingContainer[settingName])) throw 'invalid number for ' + settingName;
- } else {
- throw settingName + ' must be a number';
- }
- };
-
- /**
- * Checks the sizeRangeSuffixes and, if necessary, converts
- * its keys from string (e.g. old settings with 'lt100') to int.
- */
- JustifiedGallery.prototype.checkSizeRangesSuffixes = function () {
- if ($.type(this.settings.sizeRangeSuffixes) !== 'object') {
- throw 'sizeRangeSuffixes must be defined and must be an object';
- }
-
- var suffixRanges = [];
- for (var rangeIdx in this.settings.sizeRangeSuffixes) {
- if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(rangeIdx);
- }
-
- var newSizeRngSuffixes = {0: ''};
- for (var i = 0; i < suffixRanges.length; i++) {
- if ($.type(suffixRanges[i]) === 'string') {
- try {
- var numIdx = parseInt(suffixRanges[i].replace(/^[a-z]+/, ''), 10);
- newSizeRngSuffixes[numIdx] = this.settings.sizeRangeSuffixes[suffixRanges[i]];
- } catch (e) {
- throw 'sizeRangeSuffixes keys must contains correct numbers (' + e + ')';
- }
- } else {
- newSizeRngSuffixes[suffixRanges[i]] = this.settings.sizeRangeSuffixes[suffixRanges[i]];
- }
- }
-
- this.settings.sizeRangeSuffixes = newSizeRngSuffixes;
- };
-
- /**
- * check and convert the maxRowHeight setting
- * requires rowHeight to be already set
- * TODO: should be always called when only rowHeight is changed
- * @return number or null
- */
- JustifiedGallery.prototype.retrieveMaxRowHeight = function () {
- var newMaxRowHeight = null;
- var rowHeight = this.settings.rowHeight;
-
- if ($.type(this.settings.maxRowHeight) === 'string') {
- if (this.settings.maxRowHeight.match(/^[0-9]+%$/)) {
- newMaxRowHeight = rowHeight * parseFloat(this.settings.maxRowHeight.match(/^([0-9]+)%$/)[1]) / 100;
- } else {
- newMaxRowHeight = parseFloat(this.settings.maxRowHeight);
- }
- } else if ($.type(this.settings.maxRowHeight) === 'number') {
- newMaxRowHeight = this.settings.maxRowHeight;
- } else if (this.settings.maxRowHeight === false || this.settings.maxRowHeight == null) {
- return null;
- } else {
- throw 'maxRowHeight must be a number or a percentage';
- }
-
- // check if the converted value is not a number
- if (isNaN(newMaxRowHeight)) throw 'invalid number for maxRowHeight';
-
- // check values, maxRowHeight must be >= rowHeight
- if (newMaxRowHeight < rowHeight) newMaxRowHeight = rowHeight;
-
- return newMaxRowHeight;
- };
-
- /**
- * Checks the settings
- */
- JustifiedGallery.prototype.checkSettings = function () {
- this.checkSizeRangesSuffixes();
-
- this.checkOrConvertNumber(this.settings, 'rowHeight');
- this.checkOrConvertNumber(this.settings, 'margins');
- this.checkOrConvertNumber(this.settings, 'border');
-
- var lastRowModes = [
- 'justify',
- 'nojustify',
- 'left',
- 'center',
- 'right',
- 'hide'
- ];
- if (lastRowModes.indexOf(this.settings.lastRow) === -1) {
- throw 'lastRow must be one of: ' + lastRowModes.join(', ');
- }
-
- this.checkOrConvertNumber(this.settings, 'justifyThreshold');
- if (this.settings.justifyThreshold < 0 || this.settings.justifyThreshold > 1) {
- throw 'justifyThreshold must be in the interval [0,1]';
- }
- if ($.type(this.settings.cssAnimation) !== 'boolean') {
- throw 'cssAnimation must be a boolean';
- }
-
- if ($.type(this.settings.captions) !== 'boolean') throw 'captions must be a boolean';
- this.checkOrConvertNumber(this.settings.captionSettings, 'animationDuration');
-
- this.checkOrConvertNumber(this.settings.captionSettings, 'visibleOpacity');
- if (this.settings.captionSettings.visibleOpacity < 0 ||
- this.settings.captionSettings.visibleOpacity > 1) {
- throw 'captionSettings.visibleOpacity must be in the interval [0, 1]';
- }
-
- this.checkOrConvertNumber(this.settings.captionSettings, 'nonVisibleOpacity');
- if (this.settings.captionSettings.nonVisibleOpacity < 0 ||
- this.settings.captionSettings.nonVisibleOpacity > 1) {
- throw 'captionSettings.nonVisibleOpacity must be in the interval [0, 1]';
- }
-
- this.checkOrConvertNumber(this.settings, 'imagesAnimationDuration');
- this.checkOrConvertNumber(this.settings, 'refreshTime');
- this.checkOrConvertNumber(this.settings, 'refreshSensitivity');
- if ($.type(this.settings.randomize) !== 'boolean') throw 'randomize must be a boolean';
- if ($.type(this.settings.selector) !== 'string') throw 'selector must be a string';
-
- if (this.settings.sort !== false && !$.isFunction(this.settings.sort)) {
- throw 'sort must be false or a comparison function';
- }
-
- if (this.settings.filter !== false && !$.isFunction(this.settings.filter) &&
- $.type(this.settings.filter) !== 'string') {
- throw 'filter must be false, a string or a filter function';
- }
- };
-
- /**
- * It brings all the indexes from the sizeRangeSuffixes and it orders them. They are then sorted and returned.
- * @returns {Array} sorted suffix ranges
- */
- JustifiedGallery.prototype.retrieveSuffixRanges = function () {
- var suffixRanges = [];
- for (var rangeIdx in this.settings.sizeRangeSuffixes) {
- if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(parseInt(rangeIdx, 10));
- }
- suffixRanges.sort(function (a, b) { return a > b ? 1 : a < b ? -1 : 0; });
- return suffixRanges;
- };
-
- /**
- * Update the existing settings only changing some of them
- *
- * @param newSettings the new settings (or a subgroup of them)
- */
- JustifiedGallery.prototype.updateSettings = function (newSettings) {
- // In this case Justified Gallery has been called again changing only some options
- this.settings = $.extend({}, this.settings, newSettings);
- this.checkSettings();
-
- // As reported in the settings: negative value = same as margins, 0 = disabled
- this.border = this.settings.border >= 0 ? this.settings.border : this.settings.margins;
-
- this.maxRowHeight = this.retrieveMaxRowHeight();
- this.suffixRanges = this.retrieveSuffixRanges();
- };
-
- JustifiedGallery.prototype.defaults = {
- sizeRangeSuffixes: { }, /* e.g. Flickr configuration
- {
- 100: '_t', // used when longest is less than 100px
- 240: '_m', // used when longest is between 101px and 240px
- 320: '_n', // ...
- 500: '',
- 640: '_z',
- 1024: '_b' // used as else case because it is the last
- }
- */
- thumbnailPath: undefined, /* If defined, sizeRangeSuffixes is not used, and this function is used to determine the
- path relative to a specific thumbnail size. The function should accept respectively three arguments:
- current path, width and height */
- rowHeight: 120, // required? required to be > 0?
- maxRowHeight: false, // false or negative value to deactivate. Positive number to express the value in pixels,
- // A string '[0-9]+%' to express in percentage (e.g. 300% means that the row height
- // can't exceed 3 * rowHeight)
- margins: 1,
- border: -1, // negative value = same as margins, 0 = disabled, any other value to set the border
-
- lastRow: 'nojustify', // … which is the same as 'left', or can be 'justify', 'center', 'right' or 'hide'
-
- justifyThreshold: 0.90, /* if row width / available space > 0.90 it will be always justified
- * (i.e. lastRow setting is not considered) */
- waitThumbnailsLoad: true,
- captions: true,
- cssAnimation: true,
- imagesAnimationDuration: 500, // ignored with css animations
- captionSettings: { // ignored with css animations
- animationDuration: 500,
- visibleOpacity: 0.7,
- nonVisibleOpacity: 0.0
- },
- rel: null, // rewrite the rel of each analyzed links
- target: null, // rewrite the target of all links
- extension: /\.[^.\\/]+$/, // regexp to capture the extension of an image
- refreshTime: 200, // time interval (in ms) to check if the page changes its width
- refreshSensitivity: 0, // change in width allowed (in px) without re-building the gallery
- randomize: false,
- rtl: false, // right-to-left mode
- sort: false, /*
- - false: to do not sort
- - function: to sort them using the function as comparator (see Array.prototype.sort())
- */
- filter: false, /*
- - false, null or undefined: for a disabled filter
- - a string: an entry is kept if entry.is(filter string) returns true
- see jQuery's .is() function for further information
- - a function: invoked with arguments (entry, index, array). Return true to keep the entry, false otherwise.
- It follows the specifications of the Array.prototype.filter() function of JavaScript.
- */
- selector: 'a, div:not(.spinner)', // The selector that is used to know what are the entries of the gallery
- imgSelector: '> img, > a > img', // The selector that is used to know what are the images of each entry
- triggerEvent: function (event) { // This is called to trigger events, the default behavior is to call $.trigger
- this.$gallery.trigger(event); // Consider that 'this' is this set to the JustifiedGallery object, so it can
- } // access to fields such as $gallery, useful to trigger events with jQuery.
- };
- /**
- * Justified Gallery plugin for jQuery
- *
- * Events
- * - jg.complete : called when all the gallery has been created
- * - jg.resize : called when the gallery has been resized
- * - jg.rowflush : when a new row appears
- *
- * @param arg the action (or the settings) passed when the plugin is called
- * @returns {*} the object itself
- */
- $.fn.justifiedGallery = function (arg) {
- return this.each(function (index, gallery) {
- var $gallery = $(gallery);
- $gallery.addClass('justified-gallery');
- var controller = $gallery.data('jg.controller');
- if (typeof controller === 'undefined') {
- // Create controller and assign it to the object data
- if (typeof arg !== 'undefined' && arg !== null && $.type(arg) !== 'object') {
- if (arg === 'destroy') return; // Just a call to an unexisting object
- throw 'The argument must be an object';
- }
- controller = new JustifiedGallery($gallery, $.extend({}, JustifiedGallery.prototype.defaults, arg));
- $gallery.data('jg.controller', controller);
- } else if (arg === 'norewind') {
- // In this case we don't rewind: we analyze only the latest images (e.g. to complete the last unfinished row
- // ... left to be more readable
- } else if (arg === 'destroy') {
- controller.destroy();
- return;
- } else {
- // In this case Justified Gallery has been called again changing only some options
- controller.updateSettings(arg);
- controller.rewind();
- }
- // Update the entries list
- if (!controller.updateEntries(arg === 'norewind')) return;
- // Init justified gallery
- controller.init();
- });
- };
- }));
- /*!
- * jQuery Mousewheel 3.1.13
- *
- * Copyright jQuery Foundation and other contributors
- * Released under the MIT license
- * http://jquery.org/license
- */
- (function (factory) {
- if ( typeof define === 'function' && define.amd ) {
- // AMD. Register as an anonymous module.
- define(['jquery'], factory);
- } else if (typeof exports === 'object') {
- // Node/CommonJS style for Browserify
- module.exports = factory;
- } else {
- // Browser globals
- factory(jQuery);
- }
- }(function ($) {
- var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'],
- toBind = ( 'onwheel' in document || document.documentMode >= 9 ) ?
- ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'],
- slice = Array.prototype.slice,
- nullLowestDeltaTimeout, lowestDelta;
- if ( $.event.fixHooks ) {
- for ( var i = toFix.length; i; ) {
- $.event.fixHooks[ toFix[--i] ] = $.event.mouseHooks;
- }
- }
- var special = $.event.special.mousewheel = {
- version: '3.1.12',
- setup: function() {
- if ( this.addEventListener ) {
- for ( var i = toBind.length; i; ) {
- this.addEventListener( toBind[--i], handler, false );
- }
- } else {
- this.onmousewheel = handler;
- }
- // Store the line height and page height for this particular element
- $.data(this, 'mousewheel-line-height', special.getLineHeight(this));
- $.data(this, 'mousewheel-page-height', special.getPageHeight(this));
- },
- teardown: function() {
- if ( this.removeEventListener ) {
- for ( var i = toBind.length; i; ) {
- this.removeEventListener( toBind[--i], handler, false );
- }
- } else {
- this.onmousewheel = null;
- }
- // Clean up the data we added to the element
- $.removeData(this, 'mousewheel-line-height');
- $.removeData(this, 'mousewheel-page-height');
- },
- getLineHeight: function(elem) {
- var $elem = $(elem),
- $parent = $elem['offsetParent' in $.fn ? 'offsetParent' : 'parent']();
- if (!$parent.length) {
- $parent = $('body');
- }
- return parseInt($parent.css('fontSize'), 10) || parseInt($elem.css('fontSize'), 10) || 16;
- },
- getPageHeight: function(elem) {
- return $(elem).height();
- },
- settings: {
- adjustOldDeltas: true, // see shouldAdjustOldDeltas() below
- normalizeOffset: true // calls getBoundingClientRect for each event
- }
- };
- $.fn.extend({
- mousewheel: function(fn) {
- return fn ? this.bind('mousewheel', fn) : this.trigger('mousewheel');
- },
- unmousewheel: function(fn) {
- return this.unbind('mousewheel', fn);
- }
- });
- function handler(event) {
- var orgEvent = event || window.event,
- args = slice.call(arguments, 1),
- delta = 0,
- deltaX = 0,
- deltaY = 0,
- absDelta = 0,
- offsetX = 0,
- offsetY = 0;
- event = $.event.fix(orgEvent);
- event.type = 'mousewheel';
- // Old school scrollwheel delta
- if ( 'detail' in orgEvent ) { deltaY = orgEvent.detail * -1; }
- if ( 'wheelDelta' in orgEvent ) { deltaY = orgEvent.wheelDelta; }
- if ( 'wheelDeltaY' in orgEvent ) { deltaY = orgEvent.wheelDeltaY; }
- if ( 'wheelDeltaX' in orgEvent ) { deltaX = orgEvent.wheelDeltaX * -1; }
- // Firefox < 17 horizontal scrolling related to DOMMouseScroll event
- if ( 'axis' in orgEvent && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) {
- deltaX = deltaY * -1;
- deltaY = 0;
- }
- // Set delta to be deltaY or deltaX if deltaY is 0 for backwards compatabilitiy
- delta = deltaY === 0 ? deltaX : deltaY;
- // New school wheel delta (wheel event)
- if ( 'deltaY' in orgEvent ) {
- deltaY = orgEvent.deltaY * -1;
- delta = deltaY;
- }
- if ( 'deltaX' in orgEvent ) {
- deltaX = orgEvent.deltaX;
- if ( deltaY === 0 ) { delta = deltaX * -1; }
- }
- // No change actually happened, no reason to go any further
- if ( deltaY === 0 && deltaX === 0 ) { return; }
- // Need to convert lines and pages to pixels if we aren't already in pixels
- // There are three delta modes:
- // * deltaMode 0 is by pixels, nothing to do
- // * deltaMode 1 is by lines
- // * deltaMode 2 is by pages
- if ( orgEvent.deltaMode === 1 ) {
- var lineHeight = $.data(this, 'mousewheel-line-height');
- delta *= lineHeight;
- deltaY *= lineHeight;
- deltaX *= lineHeight;
- } else if ( orgEvent.deltaMode === 2 ) {
- var pageHeight = $.data(this, 'mousewheel-page-height');
- delta *= pageHeight;
- deltaY *= pageHeight;
- deltaX *= pageHeight;
- }
- // Store lowest absolute delta to normalize the delta values
- absDelta = Math.max( Math.abs(deltaY), Math.abs(deltaX) );
- if ( !lowestDelta || absDelta < lowestDelta ) {
- lowestDelta = absDelta;
- // Adjust older deltas if necessary
- if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) {
- lowestDelta /= 40;
- }
- }
- // Adjust older deltas if necessary
- if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) {
- // Divide all the things by 40!
- delta /= 40;
- deltaX /= 40;
- deltaY /= 40;
- }
- // Get a whole, normalized value for the deltas
- delta = Math[ delta >= 1 ? 'floor' : 'ceil' ](delta / lowestDelta);
- deltaX = Math[ deltaX >= 1 ? 'floor' : 'ceil' ](deltaX / lowestDelta);
- deltaY = Math[ deltaY >= 1 ? 'floor' : 'ceil' ](deltaY / lowestDelta);
- // Normalise offsetX and offsetY properties
- if ( special.settings.normalizeOffset && this.getBoundingClientRect ) {
- var boundingRect = this.getBoundingClientRect();
- offsetX = event.clientX - boundingRect.left;
- offsetY = event.clientY - boundingRect.top;
- }
- // Add information to the event object
- event.deltaX = deltaX;
- event.deltaY = deltaY;
- event.deltaFactor = lowestDelta;
- event.offsetX = offsetX;
- event.offsetY = offsetY;
- // Go ahead and set deltaMode to 0 since we converted to pixels
- // Although this is a little odd since we overwrite the deltaX/Y
- // properties with normalized deltas.
- event.deltaMode = 0;
- // Add event and delta to the front of the arguments
- args.unshift(event, delta, deltaX, deltaY);
- // Clearout lowestDelta after sometime to better
- // handle multiple device types that give different
- // a different lowestDelta
- // Ex: trackpad = 3 and mouse wheel = 120
- if (nullLowestDeltaTimeout) { clearTimeout(nullLowestDeltaTimeout); }
- nullLowestDeltaTimeout = setTimeout(nullLowestDelta, 200);
- return ($.event.dispatch || $.event.handle).apply(this, args);
- }
- function nullLowestDelta() {
- lowestDelta = null;
- }
- function shouldAdjustOldDeltas(orgEvent, absDelta) {
- // If this is an older event and the delta is divisable by 120,
- // then we are assuming that the browser is treating this as an
- // older mouse wheel event and that we should divide the deltas
- // by 40 to try and get a more usable deltaFactor.
- // Side note, this actually impacts the reported scroll distance
- // in older browsers and can cause scrolling to be slower than native.
- // Turn this off by setting $.event.special.mousewheel.settings.adjustOldDeltas to false.
- return special.settings.adjustOldDeltas && orgEvent.type === 'mousewheel' && absDelta % 120 === 0;
- }
- }));
- (function() {
- 'use strict';
- var defaults = {
- mode: 'lg-slide',
- // Ex : 'ease'
- cssEasing: 'ease',
- //'for jquery animation'
- easing: 'linear',
- speed: 600,
- height: '100%',
- width: '100%',
- addClass: '',
- startClass: 'lg-start-zoom',
- backdropDuration: 150,
- hideBarsDelay: 6000,
- useLeft: false,
- closable: true,
- loop: true,
- escKey: true,
- keyPress: true,
- controls: true,
- slideEndAnimatoin: true,
- hideControlOnEnd: false,
- mousewheel: true,
- getCaptionFromTitleOrAlt: true,
- // .lg-item || '.lg-sub-html'
- appendSubHtmlTo: '.lg-sub-html',
- subHtmlSelectorRelative: false,
- /**
- * @desc number of preload slides
- * will exicute only after the current slide is fully loaded.
- *
- * @ex you clicked on 4th image and if preload = 1 then 3rd slide and 5th
- * slide will be loaded in the background after the 4th slide is fully loaded..
- * if preload is 2 then 2nd 3rd 5th 6th slides will be preloaded.. ... ...
- *
- */
- preload: 1,
- showAfterLoad: true,
- selector: '',
- selectWithin: '',
- nextHtml: '',
- prevHtml: '',
- // 0, 1
- index: false,
- iframeMaxWidth: '100%',
- download: true,
- counter: true,
- appendCounterTo: '.lg-toolbar',
- swipeThreshold: 50,
- enableSwipe: true,
- enableDrag: true,
- dynamic: false,
- dynamicEl: [],
- galleryId: 1
- };
- function Plugin(element, options) {
- // Current lightGallery element
- this.el = element;
- // Current jquery element
- this.$el = $(element);
- // lightGallery settings
- this.s = $.extend({}, defaults, options);
- // When using dynamic mode, ensure dynamicEl is an array
- if (this.s.dynamic && this.s.dynamicEl !== 'undefined' && this.s.dynamicEl.constructor === Array && !this.s.dynamicEl.length) {
- throw ('When using dynamic mode, you must also define dynamicEl as an Array.');
- }
- // lightGallery modules
- this.modules = {};
- // false when lightgallery complete first slide;
- this.lGalleryOn = false;
- this.lgBusy = false;
- // Timeout function for hiding controls;
- this.hideBartimeout = false;
- // To determine browser supports for touch events;
- this.isTouch = ('ontouchstart' in document.documentElement);
- // Disable hideControlOnEnd if sildeEndAnimation is true
- if (this.s.slideEndAnimatoin) {
- this.s.hideControlOnEnd = false;
- }
- // Gallery items
- if (this.s.dynamic) {
- this.$items = this.s.dynamicEl;
- } else {
- if (this.s.selector === 'this') {
- this.$items = this.$el;
- } else if (this.s.selector !== '') {
- if (this.s.selectWithin) {
- this.$items = $(this.s.selectWithin).find(this.s.selector);
- } else {
- this.$items = this.$el.find($(this.s.selector));
- }
- } else {
- this.$items = this.$el.children();
- }
- }
- // .lg-item
- this.$slide = '';
- // .lg-outer
- this.$outer = '';
- this.init();
- return this;
- }
- Plugin.prototype.init = function() {
- var _this = this;
- // s.preload should not be more than $item.length
- if (_this.s.preload > _this.$items.length) {
- _this.s.preload = _this.$items.length;
- }
- // if dynamic option is enabled execute immediately
- var _hash = window.location.hash;
- if (_hash.indexOf('lg=' + this.s.galleryId) > 0) {
- _this.index = parseInt(_hash.split('&slide=')[1], 10);
- $('body').addClass('lg-from-hash');
- if (!$('body').hasClass('lg-on')) {
- setTimeout(function() {
- _this.build(_this.index);
- });
- $('body').addClass('lg-on');
- }
- }
- if (_this.s.dynamic) {
- _this.$el.trigger('onBeforeOpen.lg');
- _this.index = _this.s.index || 0;
- // prevent accidental double execution
- if (!$('body').hasClass('lg-on')) {
- setTimeout(function() {
- _this.build(_this.index);
- $('body').addClass('lg-on');
- });
- }
- } else {
- // Using different namespace for click because click event should not unbind if selector is same object('this')
- _this.$items.on('click.lgcustom', function(event) {
- // For IE8
- try {
- event.preventDefault();
- event.preventDefault();
- } catch (er) {
- event.returnValue = false;
- }
- _this.$el.trigger('onBeforeOpen.lg');
- _this.index = _this.s.index || _this.$items.index(this);
- // prevent accidental double execution
- if (!$('body').hasClass('lg-on')) {
- _this.build(_this.index);
- $('body').addClass('lg-on');
- }
- });
- }
- };
- Plugin.prototype.build = function(index) {
- var _this = this;
- _this.structure();
- // module constructor
- $.each($.fn.lightGallery.modules, function(key) {
- _this.modules[key] = new $.fn.lightGallery.modules[key](_this.el);
- });
- // initiate slide function
- _this.slide(index, false, false, false);
- if (_this.s.keyPress) {
- _this.keyPress();
- }
- if (_this.$items.length > 1) {
- _this.arrow();
- setTimeout(function() {
- _this.enableDrag();
- _this.enableSwipe();
- }, 50);
- if (_this.s.mousewheel) {
- _this.mousewheel();
- }
- } else {
- _this.$slide.on('click.lg', function() {
- _this.$el.trigger('onSlideClick.lg');
- });
- }
- _this.counter();
- _this.closeGallery();
- _this.$el.trigger('onAfterOpen.lg');
- // Hide controllers if mouse doesn't move for some period
- _this.$outer.on('mousemove.lg click.lg touchstart.lg', function() {
- _this.$outer.removeClass('lg-hide-items');
- clearTimeout(_this.hideBartimeout);
- // Timeout will be cleared on each slide movement also
- _this.hideBartimeout = setTimeout(function() {
- _this.$outer.addClass('lg-hide-items');
- }, _this.s.hideBarsDelay);
- });
- _this.$outer.trigger('mousemove.lg');
- };
- Plugin.prototype.structure = function() {
- var list = '';
- var controls = '';
- var i = 0;
- var subHtmlCont = '';
- var template;
- var _this = this;
- $('body').append('<div class="lg-backdrop"></div>');
- $('.lg-backdrop').css('transition-duration', this.s.backdropDuration + 'ms');
- // Create gallery items
- for (i = 0; i < this.$items.length; i++) {
- list += '<div class="lg-item"></div>';
- }
- // Create controlls
- if (this.s.controls && this.$items.length > 1) {
- controls = '<div class="lg-actions">' +
- '<button class="lg-prev lg-icon">' + this.s.prevHtml + '</button>' +
- '<button class="lg-next lg-icon">' + this.s.nextHtml + '</button>' +
- '</div>';
- }
- if (this.s.appendSubHtmlTo === '.lg-sub-html') {
- subHtmlCont = '<div class="lg-sub-html"></div>';
- }
- template = '<div class="lg-outer ' + this.s.addClass + ' ' + this.s.startClass + '">' +
- '<div class="lg" style="width:' + this.s.width + '; height:' + this.s.height + '">' +
- '<div class="lg-inner">' + list + '</div>' +
- '<div class="lg-toolbar lg-group">' +
- '<span class="lg-close lg-icon"></span>' +
- '</div>' +
- controls +
- subHtmlCont +
- '</div>' +
- '</div>';
- $('body').append(template);
- this.$outer = $('.lg-outer');
- this.$slide = this.$outer.find('.lg-item');
- if (this.s.useLeft) {
- this.$outer.addClass('lg-use-left');
- // Set mode lg-slide if use left is true;
- this.s.mode = 'lg-slide';
- } else {
- this.$outer.addClass('lg-use-css3');
- }
- // For fixed height gallery
- _this.setTop();
- $(window).on('resize.lg orientationchange.lg', function() {
- setTimeout(function() {
- _this.setTop();
- }, 100);
- });
- // add class lg-current to remove initial transition
- this.$slide.eq(this.index).addClass('lg-current');
- // add Class for css support and transition mode
- if (this.doCss()) {
- this.$outer.addClass('lg-css3');
- } else {
- this.$outer.addClass('lg-css');
- // Set speed 0 because no animation will happen if browser doesn't support css3
- this.s.speed = 0;
- }
- this.$outer.addClass(this.s.mode);
- if (this.s.enableDrag && this.$items.length > 1) {
- this.$outer.addClass('lg-grab');
- }
- if (this.s.showAfterLoad) {
- this.$outer.addClass('lg-show-after-load');
- }
- if (this.doCss()) {
- var $inner = this.$outer.find('.lg-inner');
- $inner.css('transition-timing-function', this.s.cssEasing);
- $inner.css('transition-duration', this.s.speed + 'ms');
- }
- setTimeout(function() {
- $('.lg-backdrop').addClass('in');
- });
- setTimeout(function() {
- _this.$outer.addClass('lg-visible');
- }, this.s.backdropDuration);
- if (this.s.download) {
- this.$outer.find('.lg-toolbar').append('<a id="lg-download" target="_blank" download class="lg-download lg-icon"></a>');
- }
- // Store the current scroll top value to scroll back after closing the gallery..
- this.prevScrollTop = $(window).scrollTop();
- };
- // For fixed height gallery
- Plugin.prototype.setTop = function() {
- if (this.s.height !== '100%') {
- var wH = $(window).height();
- var top = (wH - parseInt(this.s.height, 10)) / 2;
- var $lGallery = this.$outer.find('.lg');
- if (wH >= parseInt(this.s.height, 10)) {
- $lGallery.css('top', top + 'px');
- } else {
- $lGallery.css('top', '0px');
- }
- }
- };
- // Find css3 support
- Plugin.prototype.doCss = function() {
- // check for css animation support
- var support = function() {
- var transition = ['transition', 'MozTransition', 'WebkitTransition', 'OTransition', 'msTransition', 'KhtmlTransition'];
- var root = document.documentElement;
- var i = 0;
- for (i = 0; i < transition.length; i++) {
- if (transition[i] in root.style) {
- return true;
- }
- }
- };
- if (support()) {
- return true;
- }
- return false;
- };
- /**
- * @desc Check the given src is video
- * @param {String} src
- * @return {Object} video type
- * Ex:{ youtube : ["//www.youtube.com/watch?v=c0asJgSyxcY", "c0asJgSyxcY"] }
- */
- Plugin.prototype.isVideo = function(src, index) {
- var html;
- if (this.s.dynamic) {
- html = this.s.dynamicEl[index].html;
- } else {
- html = this.$items.eq(index).attr('data-html');
- }
- if (!src) {
- if(html) {
- return {
- html5: true
- };
- } else {
- console.error('lightGallery :- data-src is not pvovided on slide item ' + (index + 1) + '. Please make sure the selector property is properly configured. More info - http://sachinchoolur.github.io/lightGallery/demos/html-markup.html');
- return false;
- }
- }
- var youtube = src.match(/\/\/(?:www\.)?youtu(?:\.be|be\.com|be-nocookie\.com)\/(?:watch\?v=|embed\/)?([a-z0-9\-\_\%]+)/i);
- var vimeo = src.match(/\/\/(?:www\.)?vimeo.com\/([0-9a-z\-_]+)/i);
- var dailymotion = src.match(/\/\/(?:www\.)?dai.ly\/([0-9a-z\-_]+)/i);
- var vk = src.match(/\/\/(?:www\.)?(?:vk\.com|vkontakte\.ru)\/(?:video_ext\.php\?)(.*)/i);
- if (youtube) {
- return {
- youtube: youtube
- };
- } else if (vimeo) {
- return {
- vimeo: vimeo
- };
- } else if (dailymotion) {
- return {
- dailymotion: dailymotion
- };
- } else if (vk) {
- return {
- vk: vk
- };
- }
- };
- /**
- * @desc Create image counter
- * Ex: 1/10
- */
- Plugin.prototype.counter = function() {
- if (this.s.counter) {
- $(this.s.appendCounterTo).append('<div id="lg-counter"><span id="lg-counter-current">' + (parseInt(this.index, 10) + 1) + '</span> / <span id="lg-counter-all">' + this.$items.length + '</span></div>');
- }
- };
- /**
- * @desc add sub-html into the slide
- * @param {Number} index - index of the slide
- */
- Plugin.prototype.addHtml = function(index) {
- var subHtml = null;
- var subHtmlUrl;
- var $currentEle;
- if (this.s.dynamic) {
- if (this.s.dynamicEl[index].subHtmlUrl) {
- subHtmlUrl = this.s.dynamicEl[index].subHtmlUrl;
- } else {
- subHtml = this.s.dynamicEl[index].subHtml;
- }
- } else {
- $currentEle = this.$items.eq(index);
- if ($currentEle.attr('data-sub-html-url')) {
- subHtmlUrl = $currentEle.attr('data-sub-html-url');
- } else {
- subHtml = $currentEle.attr('data-sub-html');
- if (this.s.getCaptionFromTitleOrAlt && !subHtml) {
- subHtml = $currentEle.attr('title') || $currentEle.find('img').first().attr('alt');
- }
- }
- }
- if (!subHtmlUrl) {
- if (typeof subHtml !== 'undefined' && subHtml !== null) {
- // get first letter of subhtml
- // if first letter starts with . or # get the html form the jQuery object
- var fL = subHtml.substring(0, 1);
- if (fL === '.' || fL === '#') {
- if (this.s.subHtmlSelectorRelative && !this.s.dynamic) {
- subHtml = $currentEle.find(subHtml).html();
- } else {
- subHtml = $(subHtml).html();
- }
- }
- } else {
- subHtml = '';
- }
- }
- if (this.s.appendSubHtmlTo === '.lg-sub-html') {
- if (subHtmlUrl) {
- this.$outer.find(this.s.appendSubHtmlTo).load(subHtmlUrl);
- } else {
- this.$outer.find(this.s.appendSubHtmlTo).html(subHtml);
- }
- } else {
- if (subHtmlUrl) {
- this.$slide.eq(index).load(subHtmlUrl);
- } else {
- this.$slide.eq(index).append(subHtml);
- }
- }
- // Add lg-empty-html class if title doesn't exist
- if (typeof subHtml !== 'undefined' && subHtml !== null) {
- if (subHtml === '') {
- this.$outer.find(this.s.appendSubHtmlTo).addClass('lg-empty-html');
- } else {
- this.$outer.find(this.s.appendSubHtmlTo).removeClass('lg-empty-html');
- }
- }
- this.$el.trigger('onAfterAppendSubHtml.lg', [index]);
- };
- /**
- * @desc Preload slides
- * @param {Number} index - index of the slide
- */
- Plugin.prototype.preload = function(index) {
- var i = 1;
- var j = 1;
- for (i = 1; i <= this.s.preload; i++) {
- if (i >= this.$items.length - index) {
- break;
- }
- this.loadContent(index + i, false, 0);
- }
- for (j = 1; j <= this.s.preload; j++) {
- if (index - j < 0) {
- break;
- }
- this.loadContent(index - j, false, 0);
- }
- };
- /**
- * @desc Load slide content into slide.
- * @param {Number} index - index of the slide.
- * @param {Boolean} rec - if true call loadcontent() function again.
- * @param {Boolean} delay - delay for adding complete class. it is 0 except first time.
- */
- Plugin.prototype.loadContent = function(index, rec, delay) {
- var _this = this;
- var _hasPoster = false;
- var _$img;
- var _src;
- var _poster;
- var _srcset;
- var _sizes;
- var _html;
- var getResponsiveSrc = function(srcItms) {
- var rsWidth = [];
- var rsSrc = [];
- for (var i = 0; i < srcItms.length; i++) {
- var __src = srcItms[i].split(' ');
- // Manage empty space
- if (__src[0] === '') {
- __src.splice(0, 1);
- }
- rsSrc.push(__src[0]);
- rsWidth.push(__src[1]);
- }
- var wWidth = $(window).width();
- for (var j = 0; j < rsWidth.length; j++) {
- if (parseInt(rsWidth[j], 10) > wWidth) {
- _src = rsSrc[j];
- break;
- }
- }
- };
- if (_this.s.dynamic) {
- if (_this.s.dynamicEl[index].poster) {
- _hasPoster = true;
- _poster = _this.s.dynamicEl[index].poster;
- }
- _html = _this.s.dynamicEl[index].html;
- _src = _this.s.dynamicEl[index].src;
- if (_this.s.dynamicEl[index].responsive) {
- var srcDyItms = _this.s.dynamicEl[index].responsive.split(',');
- getResponsiveSrc(srcDyItms);
- }
- _srcset = _this.s.dynamicEl[index].srcset;
- _sizes = _this.s.dynamicEl[index].sizes;
- } else {
- if (_this.$items.eq(index).attr('data-poster')) {
- _hasPoster = true;
- _poster = _this.$items.eq(index).attr('data-poster');
- }
- _html = _this.$items.eq(index).attr('data-html');
- _src = _this.$items.eq(index).attr('href') || _this.$items.eq(index).attr('data-src');
- if (_this.$items.eq(index).attr('data-responsive')) {
- var srcItms = _this.$items.eq(index).attr('data-responsive').split(',');
- getResponsiveSrc(srcItms);
- }
- _srcset = _this.$items.eq(index).attr('data-srcset');
- _sizes = _this.$items.eq(index).attr('data-sizes');
- }
- //if (_src || _srcset || _sizes || _poster) {
- var iframe = false;
- if (_this.s.dynamic) {
- if (_this.s.dynamicEl[index].iframe) {
- iframe = true;
- }
- } else {
- if (_this.$items.eq(index).attr('data-iframe') === 'true') {
- iframe = true;
- }
- }
- var _isVideo = _this.isVideo(_src, index);
- if (!_this.$slide.eq(index).hasClass('lg-loaded')) {
- if (iframe) {
- _this.$slide.eq(index).prepend('<div class="lg-video-cont lg-has-iframe" style="max-width:' + _this.s.iframeMaxWidth + '"><div class="lg-video"><iframe class="lg-object" frameborder="0" src="' + _src + '" allowfullscreen="true"></iframe></div></div>');
- } else if (_hasPoster) {
- var videoClass = '';
- if (_isVideo && _isVideo.youtube) {
- videoClass = 'lg-has-youtube';
- } else if (_isVideo && _isVideo.vimeo) {
- videoClass = 'lg-has-vimeo';
- } else {
- videoClass = 'lg-has-html5';
- }
- _this.$slide.eq(index).prepend('<div class="lg-video-cont ' + videoClass + ' "><div class="lg-video"><span class="lg-video-play"></span><img class="lg-object lg-has-poster" src="' + _poster + '" /></div></div>');
- } else if (_isVideo) {
- _this.$slide.eq(index).prepend('<div class="lg-video-cont "><div class="lg-video"></div></div>');
- _this.$el.trigger('hasVideo.lg', [index, _src, _html]);
- } else {
- _this.$slide.eq(index).prepend('<div class="lg-img-wrap"><img class="lg-object lg-image" src="' + _src + '" /></div>');
- }
- _this.$el.trigger('onAferAppendSlide.lg', [index]);
- _$img = _this.$slide.eq(index).find('.lg-object');
- if (_sizes) {
- _$img.attr('sizes', _sizes);
- }
- if (_srcset) {
- _$img.attr('srcset', _srcset);
- try {
- picturefill({
- elements: [_$img[0]]
- });
- } catch (e) {
- console.warn('lightGallery :- If you want srcset to be supported for older browser please include picturefil version 2 javascript library in your document.');
- }
- }
- if (this.s.appendSubHtmlTo !== '.lg-sub-html') {
- _this.addHtml(index);
- }
- _this.$slide.eq(index).addClass('lg-loaded');
- }
- _this.$slide.eq(index).find('.lg-object').on('load.lg error.lg', function() {
- // For first time add some delay for displaying the start animation.
- var _speed = 0;
- // Do not change the delay value because it is required for zoom plugin.
- // If gallery opened from direct url (hash) speed value should be 0
- if (delay && !$('body').hasClass('lg-from-hash')) {
- _speed = delay;
- }
- setTimeout(function() {
- _this.$slide.eq(index).addClass('lg-complete');
- _this.$el.trigger('onSlideItemLoad.lg', [index, delay || 0]);
- }, _speed);
- });
- // @todo check load state for html5 videos
- if (_isVideo && _isVideo.html5 && !_hasPoster) {
- _this.$slide.eq(index).addClass('lg-complete');
- }
- if (rec === true) {
- if (!_this.$slide.eq(index).hasClass('lg-complete')) {
- _this.$slide.eq(index).find('.lg-object').on('load.lg error.lg', function() {
- _this.preload(index);
- });
- } else {
- _this.preload(index);
- }
- }
- //}
- };
- /**
- * @desc slide function for lightgallery
- ** Slide() gets call on start
- ** ** Set lg.on true once slide() function gets called.
- ** Call loadContent() on slide() function inside setTimeout
- ** ** On first slide we do not want any animation like slide of fade
- ** ** So on first slide( if lg.on if false that is first slide) loadContent() should start loading immediately
- ** ** Else loadContent() should wait for the transition to complete.
- ** ** So set timeout s.speed + 50
- <=> ** loadContent() will load slide content in to the particular slide
- ** ** It has recursion (rec) parameter. if rec === true loadContent() will call preload() function.
- ** ** preload will execute only when the previous slide is fully loaded (images iframe)
- ** ** avoid simultaneous image load
- <=> ** Preload() will check for s.preload value and call loadContent() again accoring to preload value
- ** loadContent() <====> Preload();
- * @param {Number} index - index of the slide
- * @param {Boolean} fromTouch - true if slide function called via touch event or mouse drag
- * @param {Boolean} fromThumb - true if slide function called via thumbnail click
- * @param {String} direction - Direction of the slide(next/prev)
- */
- Plugin.prototype.slide = function(index, fromTouch, fromThumb, direction) {
- var _prevIndex = this.$outer.find('.lg-current').index();
- var _this = this;
- // Prevent if multiple call
- // Required for hsh plugin
- if (_this.lGalleryOn && (_prevIndex === index)) {
- return;
- }
- var _length = this.$slide.length;
- var _time = _this.lGalleryOn ? this.s.speed : 0;
- if (!_this.lgBusy) {
- if (this.s.download) {
- var _src;
- if (_this.s.dynamic) {
- _src = _this.s.dynamicEl[index].downloadUrl !== false && (_this.s.dynamicEl[index].downloadUrl || _this.s.dynamicEl[index].src);
- } else {
- _src = _this.$items.eq(index).attr('data-download-url') !== 'false' && (_this.$items.eq(index).attr('data-download-url') || _this.$items.eq(index).attr('href') || _this.$items.eq(index).attr('data-src'));
- }
- if (_src) {
- $('#lg-download').attr('href', _src);
- _this.$outer.removeClass('lg-hide-download');
- } else {
- _this.$outer.addClass('lg-hide-download');
- }
- }
- this.$el.trigger('onBeforeSlide.lg', [_prevIndex, index, fromTouch, fromThumb]);
- _this.lgBusy = true;
- clearTimeout(_this.hideBartimeout);
- // Add title if this.s.appendSubHtmlTo === lg-sub-html
- if (this.s.appendSubHtmlTo === '.lg-sub-html') {
- // wait for slide animation to complete
- setTimeout(function() {
- _this.addHtml(index);
- }, _time);
- }
- this.arrowDisable(index);
- if (!direction) {
- if (index < _prevIndex) {
- direction = 'prev';
- } else if (index > _prevIndex) {
- direction = 'next';
- }
- }
- if (!fromTouch) {
- // remove all transitions
- _this.$outer.addClass('lg-no-trans');
- this.$slide.removeClass('lg-prev-slide lg-next-slide');
- if (direction === 'prev') {
- //prevslide
- this.$slide.eq(index).addClass('lg-prev-slide');
- this.$slide.eq(_prevIndex).addClass('lg-next-slide');
- } else {
- // next slide
- this.$slide.eq(index).addClass('lg-next-slide');
- this.$slide.eq(_prevIndex).addClass('lg-prev-slide');
- }
- // give 50 ms for browser to add/remove class
- setTimeout(function() {
- _this.$slide.removeClass('lg-current');
- //_this.$slide.eq(_prevIndex).removeClass('lg-current');
- _this.$slide.eq(index).addClass('lg-current');
- // reset all transitions
- _this.$outer.removeClass('lg-no-trans');
- }, 50);
- } else {
- this.$slide.removeClass('lg-prev-slide lg-current lg-next-slide');
- var touchPrev;
- var touchNext;
- if (_length > 2) {
- touchPrev = index - 1;
- touchNext = index + 1;
- if ((index === 0) && (_prevIndex === _length - 1)) {
- // next slide
- touchNext = 0;
- touchPrev = _length - 1;
- } else if ((index === _length - 1) && (_prevIndex === 0)) {
- // prev slide
- touchNext = 0;
- touchPrev = _length - 1;
- }
- } else {
- touchPrev = 0;
- touchNext = 1;
- }
- if (direction === 'prev') {
- _this.$slide.eq(touchNext).addClass('lg-next-slide');
- } else {
- _this.$slide.eq(touchPrev).addClass('lg-prev-slide');
- }
- _this.$slide.eq(index).addClass('lg-current');
- }
- if (_this.lGalleryOn) {
- setTimeout(function() {
- _this.loadContent(index, true, 0);
- }, this.s.speed + 50);
- setTimeout(function() {
- _this.lgBusy = false;
- _this.$el.trigger('onAfterSlide.lg', [_prevIndex, index, fromTouch, fromThumb]);
- }, this.s.speed);
- } else {
- _this.loadContent(index, true, _this.s.backdropDuration);
- _this.lgBusy = false;
- _this.$el.trigger('onAfterSlide.lg', [_prevIndex, index, fromTouch, fromThumb]);
- }
- _this.lGalleryOn = true;
- if (this.s.counter) {
- $('#lg-counter-current').text(index + 1);
- }
- }
- _this.index = index;
- };
- /**
- * @desc Go to next slide
- * @param {Boolean} fromTouch - true if slide function called via touch event
- */
- Plugin.prototype.goToNextSlide = function(fromTouch) {
- var _this = this;
- var _loop = _this.s.loop;
- if (fromTouch && _this.$slide.length < 3) {
- _loop = false;
- }
- if (!_this.lgBusy) {
- if ((_this.index + 1) < _this.$slide.length) {
- _this.index++;
- _this.$el.trigger('onBeforeNextSlide.lg', [_this.index]);
- _this.slide(_this.index, fromTouch, false, 'next');
- } else {
- if (_loop) {
- _this.index = 0;
- _this.$el.trigger('onBeforeNextSlide.lg', [_this.index]);
- _this.slide(_this.index, fromTouch, false, 'next');
- } else if (_this.s.slideEndAnimatoin && !fromTouch) {
- _this.$outer.addClass('lg-right-end');
- setTimeout(function() {
- _this.$outer.removeClass('lg-right-end');
- }, 400);
- }
- }
- }
- };
- /**
- * @desc Go to previous slide
- * @param {Boolean} fromTouch - true if slide function called via touch event
- */
- Plugin.prototype.goToPrevSlide = function(fromTouch) {
- var _this = this;
- var _loop = _this.s.loop;
- if (fromTouch && _this.$slide.length < 3) {
- _loop = false;
- }
- if (!_this.lgBusy) {
- if (_this.index > 0) {
- _this.index--;
- _this.$el.trigger('onBeforePrevSlide.lg', [_this.index, fromTouch]);
- _this.slide(_this.index, fromTouch, false, 'prev');
- } else {
- if (_loop) {
- _this.index = _this.$items.length - 1;
- _this.$el.trigger('onBeforePrevSlide.lg', [_this.index, fromTouch]);
- _this.slide(_this.index, fromTouch, false, 'prev');
- } else if (_this.s.slideEndAnimatoin && !fromTouch) {
- _this.$outer.addClass('lg-left-end');
- setTimeout(function() {
- _this.$outer.removeClass('lg-left-end');
- }, 400);
- }
- }
- }
- };
- Plugin.prototype.keyPress = function() {
- var _this = this;
- if (this.$items.length > 1) {
- $(window).on('keyup.lg', function(e) {
- if (_this.$items.length > 1) {
- if (e.keyCode === 37) {
- e.preventDefault();
- _this.goToPrevSlide();
- }
- if (e.keyCode === 39) {
- e.preventDefault();
- _this.goToNextSlide();
- }
- }
- });
- }
- $(window).on('keydown.lg', function(e) {
- if (_this.s.escKey === true && e.keyCode === 27) {
- e.preventDefault();
- if (!_this.$outer.hasClass('lg-thumb-open')) {
- _this.destroy();
- } else {
- _this.$outer.removeClass('lg-thumb-open');
- }
- }
- });
- };
- Plugin.prototype.arrow = function() {
- var _this = this;
- this.$outer.find('.lg-prev').on('click.lg', function() {
- _this.goToPrevSlide();
- });
- this.$outer.find('.lg-next').on('click.lg', function() {
- _this.goToNextSlide();
- });
- };
- Plugin.prototype.arrowDisable = function(index) {
- // Disable arrows if s.hideControlOnEnd is true
- if (!this.s.loop && this.s.hideControlOnEnd) {
- if ((index + 1) < this.$slide.length) {
- this.$outer.find('.lg-next').removeAttr('disabled').removeClass('disabled');
- } else {
- this.$outer.find('.lg-next').attr('disabled', 'disabled').addClass('disabled');
- }
- if (index > 0) {
- this.$outer.find('.lg-prev').removeAttr('disabled').removeClass('disabled');
- } else {
- this.$outer.find('.lg-prev').attr('disabled', 'disabled').addClass('disabled');
- }
- }
- };
- Plugin.prototype.setTranslate = function($el, xValue, yValue) {
- // jQuery supports Automatic CSS prefixing since jQuery 1.8.0
- if (this.s.useLeft) {
- $el.css('left', xValue);
- } else {
- $el.css({
- transform: 'translate3d(' + (xValue) + 'px, ' + yValue + 'px, 0px)'
- });
- }
- };
- Plugin.prototype.touchMove = function(startCoords, endCoords) {
- var distance = endCoords - startCoords;
- if (Math.abs(distance) > 15) {
- // reset opacity and transition duration
- this.$outer.addClass('lg-dragging');
- // move current slide
- this.setTranslate(this.$slide.eq(this.index), distance, 0);
- // move next and prev slide with current slide
- this.setTranslate($('.lg-prev-slide'), -this.$slide.eq(this.index).width() + distance, 0);
- this.setTranslate($('.lg-next-slide'), this.$slide.eq(this.index).width() + distance, 0);
- }
- };
- Plugin.prototype.touchEnd = function(distance) {
- var _this = this;
- // keep slide animation for any mode while dragg/swipe
- if (_this.s.mode !== 'lg-slide') {
- _this.$outer.addClass('lg-slide');
- }
- this.$slide.not('.lg-current, .lg-prev-slide, .lg-next-slide').css('opacity', '0');
- // set transition duration
- setTimeout(function() {
- _this.$outer.removeClass('lg-dragging');
- if ((distance < 0) && (Math.abs(distance) > _this.s.swipeThreshold)) {
- _this.goToNextSlide(true);
- } else if ((distance > 0) && (Math.abs(distance) > _this.s.swipeThreshold)) {
- _this.goToPrevSlide(true);
- } else if (Math.abs(distance) < 5) {
- // Trigger click if distance is less than 5 pix
- _this.$el.trigger('onSlideClick.lg');
- }
- _this.$slide.removeAttr('style');
- });
- // remove slide class once drag/swipe is completed if mode is not slide
- setTimeout(function() {
- if (!_this.$outer.hasClass('lg-dragging') && _this.s.mode !== 'lg-slide') {
- _this.$outer.removeClass('lg-slide');
- }
- }, _this.s.speed + 100);
- };
- Plugin.prototype.enableSwipe = function() {
- var _this = this;
- var startCoords = 0;
- var endCoords = 0;
- var isMoved = false;
- if (_this.s.enableSwipe && _this.doCss()) {
- _this.$slide.on('touchstart.lg', function(e) {
- if (!_this.$outer.hasClass('lg-zoomed') && !_this.lgBusy) {
- e.preventDefault();
- _this.manageSwipeClass();
- startCoords = e.originalEvent.targetTouches[0].pageX;
- }
- });
- _this.$slide.on('touchmove.lg', function(e) {
- if (!_this.$outer.hasClass('lg-zoomed')) {
- e.preventDefault();
- endCoords = e.originalEvent.targetTouches[0].pageX;
- _this.touchMove(startCoords, endCoords);
- isMoved = true;
- }
- });
- _this.$slide.on('touchend.lg', function() {
- if (!_this.$outer.hasClass('lg-zoomed')) {
- if (isMoved) {
- isMoved = false;
- _this.touchEnd(endCoords - startCoords);
- } else {
- _this.$el.trigger('onSlideClick.lg');
- }
- }
- });
- }
- };
- Plugin.prototype.enableDrag = function() {
- var _this = this;
- var startCoords = 0;
- var endCoords = 0;
- var isDraging = false;
- var isMoved = false;
- if (_this.s.enableDrag && _this.doCss()) {
- _this.$slide.on('mousedown.lg', function(e) {
- if (!_this.$outer.hasClass('lg-zoomed') && !_this.lgBusy && !$(e.target).text().trim()) {
- e.preventDefault();
- _this.manageSwipeClass();
- startCoords = e.pageX;
- isDraging = true;
- // ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723
- _this.$outer.scrollLeft += 1;
- _this.$outer.scrollLeft -= 1;
- // *
- _this.$outer.removeClass('lg-grab').addClass('lg-grabbing');
- _this.$el.trigger('onDragstart.lg');
- }
- });
- $(window).on('mousemove.lg', function(e) {
- if (isDraging) {
- isMoved = true;
- endCoords = e.pageX;
- _this.touchMove(startCoords, endCoords);
- _this.$el.trigger('onDragmove.lg');
- }
- });
- $(window).on('mouseup.lg', function(e) {
- if (isMoved) {
- isMoved = false;
- _this.touchEnd(endCoords - startCoords);
- _this.$el.trigger('onDragend.lg');
- } else if ($(e.target).hasClass('lg-object') || $(e.target).hasClass('lg-video-play')) {
- _this.$el.trigger('onSlideClick.lg');
- }
- // Prevent execution on click
- if (isDraging) {
- isDraging = false;
- _this.$outer.removeClass('lg-grabbing').addClass('lg-grab');
- }
- });
- }
- };
- Plugin.prototype.manageSwipeClass = function() {
- var _touchNext = this.index + 1;
- var _touchPrev = this.index - 1;
- if (this.s.loop && this.$slide.length > 2) {
- if (this.index === 0) {
- _touchPrev = this.$slide.length - 1;
- } else if (this.index === this.$slide.length - 1) {
- _touchNext = 0;
- }
- }
- this.$slide.removeClass('lg-next-slide lg-prev-slide');
- if (_touchPrev > -1) {
- this.$slide.eq(_touchPrev).addClass('lg-prev-slide');
- }
- this.$slide.eq(_touchNext).addClass('lg-next-slide');
- };
- Plugin.prototype.mousewheel = function() {
- var _this = this;
- _this.$outer.on('mousewheel.lg', function(e) {
- if (!e.deltaY) {
- return;
- }
- if (e.deltaY > 0) {
- _this.goToPrevSlide();
- } else {
- _this.goToNextSlide();
- }
- e.preventDefault();
- });
- };
- Plugin.prototype.closeGallery = function() {
- var _this = this;
- var mousedown = false;
- this.$outer.find('.lg-close').on('click.lg', function() {
- _this.destroy();
- });
- if (_this.s.closable) {
- // If you drag the slide and release outside gallery gets close on chrome
- // for preventing this check mousedown and mouseup happened on .lg-item or lg-outer
- _this.$outer.on('mousedown.lg', function(e) {
- if ($(e.target).is('.lg-outer') || $(e.target).is('.lg-item ') || $(e.target).is('.lg-img-wrap')) {
- mousedown = true;
- } else {
- mousedown = false;
- }
- });
-
- _this.$outer.on('mousemove.lg', function() {
- mousedown = false;
- });
- _this.$outer.on('mouseup.lg', function(e) {
- if ($(e.target).is('.lg-outer') || $(e.target).is('.lg-item ') || $(e.target).is('.lg-img-wrap') && mousedown) {
- if (!_this.$outer.hasClass('lg-dragging')) {
- _this.destroy();
- }
- }
- });
- }
- };
- Plugin.prototype.destroy = function(d) {
- var _this = this;
- if (!d) {
- _this.$el.trigger('onBeforeClose.lg');
- $(window).scrollTop(_this.prevScrollTop);
- }
- /**
- * if d is false or undefined destroy will only close the gallery
- * plugins instance remains with the element
- *
- * if d is true destroy will completely remove the plugin
- */
- if (d) {
- if (!_this.s.dynamic) {
- // only when not using dynamic mode is $items a jquery collection
- this.$items.off('click.lg click.lgcustom');
- }
- $.removeData(_this.el, 'lightGallery');
- }
- // Unbind all events added by lightGallery
- this.$el.off('.lg.tm');
- // Distroy all lightGallery modules
- $.each($.fn.lightGallery.modules, function(key) {
- if (_this.modules[key]) {
- _this.modules[key].destroy();
- }
- });
- this.lGalleryOn = false;
- clearTimeout(_this.hideBartimeout);
- this.hideBartimeout = false;
- $(window).off('.lg');
- $('body').removeClass('lg-on lg-from-hash');
- if (_this.$outer) {
- _this.$outer.removeClass('lg-visible');
- }
- $('.lg-backdrop').removeClass('in');
- setTimeout(function() {
- if (_this.$outer) {
- _this.$outer.remove();
- }
- $('.lg-backdrop').remove();
- if (!d) {
- _this.$el.trigger('onCloseAfter.lg');
- }
- }, _this.s.backdropDuration + 50);
- };
- $.fn.lightGallery = function(options) {
- return this.each(function() {
- if (!$.data(this, 'lightGallery')) {
- $.data(this, 'lightGallery', new Plugin(this, options));
- } else {
- try {
- $(this).data('lightGallery').init();
- } catch (err) {
- console.error('lightGallery has not initiated properly');
- }
- }
- });
- };
- $.fn.lightGallery.modules = {};
- })();
- /*! lg-autoplay - v1.0.4 - 2017-03-28
- * http://sachinchoolur.github.io/lightGallery
- * Copyright (c) 2017 Sachin N; Licensed GPLv3 */
- (function (root, factory) {
- if (typeof define === 'function' && define.amd) {
- // AMD. Register as an anonymous module unless amdModuleId is set
- define(['jquery'], function (a0) {
- return (factory(a0));
- });
- } else if (typeof exports === 'object') {
- // Node. Does not work with strict CommonJS, but
- // only CommonJS-like environments that support module.exports,
- // like Node.
- module.exports = factory(require('jquery'));
- } else {
- factory(jQuery);
- }
- }(this, function ($) {
- (function() {
- 'use strict';
- var defaults = {
- autoplay: false,
- pause: 5000,
- progressBar: true,
- fourceAutoplay: false,
- autoplayControls: true,
- appendAutoplayControlsTo: '.lg-toolbar'
- };
- /**
- * Creates the autoplay plugin.
- * @param {object} element - lightGallery element
- */
- var Autoplay = function(element) {
- this.core = $(element).data('lightGallery');
- this.$el = $(element);
- // Execute only if items are above 1
- if (this.core.$items.length < 2) {
- return false;
- }
- this.core.s = $.extend({}, defaults, this.core.s);
- this.interval = false;
- // Identify if slide happened from autoplay
- this.fromAuto = true;
- // Identify if autoplay canceled from touch/drag
- this.canceledOnTouch = false;
- // save fourceautoplay value
- this.fourceAutoplayTemp = this.core.s.fourceAutoplay;
- // do not allow progress bar if browser does not support css3 transitions
- if (!this.core.doCss()) {
- this.core.s.progressBar = false;
- }
- this.init();
- return this;
- };
- Autoplay.prototype.init = function() {
- var _this = this;
- // append autoplay controls
- if (_this.core.s.autoplayControls) {
- _this.controls();
- }
- // Create progress bar
- if (_this.core.s.progressBar) {
- _this.core.$outer.find('.lg').append('<div class="lg-progress-bar"><div class="lg-progress"></div></div>');
- }
- // set progress
- _this.progress();
- // Start autoplay
- if (_this.core.s.autoplay) {
- _this.$el.one('onSlideItemLoad.lg.tm', function() {
- _this.startlAuto();
- });
- }
- // cancel interval on touchstart and dragstart
- _this.$el.on('onDragstart.lg.tm touchstart.lg.tm', function() {
- if (_this.interval) {
- _this.cancelAuto();
- _this.canceledOnTouch = true;
- }
- });
- // restore autoplay if autoplay canceled from touchstart / dragstart
- _this.$el.on('onDragend.lg.tm touchend.lg.tm onSlideClick.lg.tm', function() {
- if (!_this.interval && _this.canceledOnTouch) {
- _this.startlAuto();
- _this.canceledOnTouch = false;
- }
- });
- };
- Autoplay.prototype.progress = function() {
- var _this = this;
- var _$progressBar;
- var _$progress;
- _this.$el.on('onBeforeSlide.lg.tm', function() {
- // start progress bar animation
- if (_this.core.s.progressBar && _this.fromAuto) {
- _$progressBar = _this.core.$outer.find('.lg-progress-bar');
- _$progress = _this.core.$outer.find('.lg-progress');
- if (_this.interval) {
- _$progress.removeAttr('style');
- _$progressBar.removeClass('lg-start');
- setTimeout(function() {
- _$progress.css('transition', 'width ' + (_this.core.s.speed + _this.core.s.pause) + 'ms ease 0s');
- _$progressBar.addClass('lg-start');
- }, 20);
- }
- }
- // Remove setinterval if slide is triggered manually and fourceautoplay is false
- if (!_this.fromAuto && !_this.core.s.fourceAutoplay) {
- _this.cancelAuto();
- }
- _this.fromAuto = false;
- });
- };
- // Manage autoplay via play/stop buttons
- Autoplay.prototype.controls = function() {
- var _this = this;
- var _html = '<span class="lg-autoplay-button lg-icon"></span>';
- // Append autoplay controls
- $(this.core.s.appendAutoplayControlsTo).append(_html);
- _this.core.$outer.find('.lg-autoplay-button').on('click.lg', function() {
- if ($(_this.core.$outer).hasClass('lg-show-autoplay')) {
- _this.cancelAuto();
- _this.core.s.fourceAutoplay = false;
- } else {
- if (!_this.interval) {
- _this.startlAuto();
- _this.core.s.fourceAutoplay = _this.fourceAutoplayTemp;
- }
- }
- });
- };
- // Autostart gallery
- Autoplay.prototype.startlAuto = function() {
- var _this = this;
- _this.core.$outer.find('.lg-progress').css('transition', 'width ' + (_this.core.s.speed + _this.core.s.pause) + 'ms ease 0s');
- _this.core.$outer.addClass('lg-show-autoplay');
- _this.core.$outer.find('.lg-progress-bar').addClass('lg-start');
- _this.interval = setInterval(function() {
- if (_this.core.index + 1 < _this.core.$items.length) {
- _this.core.index++;
- } else {
- _this.core.index = 0;
- }
- _this.fromAuto = true;
- _this.core.slide(_this.core.index, false, false, 'next');
- }, _this.core.s.speed + _this.core.s.pause);
- };
- // cancel Autostart
- Autoplay.prototype.cancelAuto = function() {
- clearInterval(this.interval);
- this.interval = false;
- this.core.$outer.find('.lg-progress').removeAttr('style');
- this.core.$outer.removeClass('lg-show-autoplay');
- this.core.$outer.find('.lg-progress-bar').removeClass('lg-start');
- };
- Autoplay.prototype.destroy = function() {
- this.cancelAuto();
- this.core.$outer.find('.lg-progress-bar').remove();
- };
- $.fn.lightGallery.modules.autoplay = Autoplay;
- })();
- }));
- /*! lg-fullscreen - v1.1.0 - 2019-02-19
- * http://sachinchoolur.github.io/lightGallery
- * Copyright (c) 2019 Sachin N; Licensed GPLv3 */
- (function (root, factory) {
- if (typeof define === 'function' && define.amd) {
- // AMD. Register as an anonymous module unless amdModuleId is set
- define(['jquery'], function (a0) {
- return (factory(a0));
- });
- } else if (typeof module === 'object' && module.exports) {
- // Node. Does not work with strict CommonJS, but
- // only CommonJS-like environments that support module.exports,
- // like Node.
- module.exports = factory(require('jquery'));
- } else {
- factory(root["jQuery"]);
- }
- }(this, function ($) {
- (function() {
- 'use strict';
- var defaults = {
- fullScreen: true
- };
- function isFullScreen() {
- return (
- document.fullscreenElement ||
- document.mozFullScreenElement ||
- document.webkitFullscreenElement ||
- document.msFullscreenElement
- );
- }
- var Fullscreen = function(element) {
- // get lightGallery core plugin data
- this.core = $(element).data('lightGallery');
- this.$el = $(element);
- // extend module defalut settings with lightGallery core settings
- this.core.s = $.extend({}, defaults, this.core.s);
- this.init();
- return this;
- };
- Fullscreen.prototype.init = function() {
- var fullScreen = '';
- if (this.core.s.fullScreen) {
- // check for fullscreen browser support
- if (!document.fullscreenEnabled && !document.webkitFullscreenEnabled &&
- !document.mozFullScreenEnabled && !document.msFullscreenEnabled) {
- return;
- } else {
- fullScreen = '<span class="lg-fullscreen lg-icon"></span>';
- this.core.$outer.find('.lg-toolbar').append(fullScreen);
- this.fullScreen();
- }
- }
- };
- Fullscreen.prototype.requestFullscreen = function() {
- var el = document.documentElement;
- if (el.requestFullscreen) {
- el.requestFullscreen();
- } else if (el.msRequestFullscreen) {
- el.msRequestFullscreen();
- } else if (el.mozRequestFullScreen) {
- el.mozRequestFullScreen();
- } else if (el.webkitRequestFullscreen) {
- el.webkitRequestFullscreen();
- }
- };
- Fullscreen.prototype.exitFullscreen = function() {
- if (document.exitFullscreen) {
- document.exitFullscreen();
- } else if (document.msExitFullscreen) {
- document.msExitFullscreen();
- } else if (document.mozCancelFullScreen) {
- document.mozCancelFullScreen();
- } else if (document.webkitExitFullscreen) {
- document.webkitExitFullscreen();
- }
- };
- // https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Using_full_screen_mode
- Fullscreen.prototype.fullScreen = function() {
- var _this = this;
- $(document).on('fullscreenchange.lg webkitfullscreenchange.lg mozfullscreenchange.lg MSFullscreenChange.lg', function() {
- _this.core.$outer.toggleClass('lg-fullscreen-on');
- });
- this.core.$outer.find('.lg-fullscreen').on('click.lg', function() {
- if (isFullScreen()) {
- _this.exitFullscreen();
- } else {
- _this.requestFullscreen();
- }
- });
- };
- Fullscreen.prototype.destroy = function() {
- // exit from fullscreen if activated
- if(isFullScreen()) {
- this.exitFullscreen();
- }
- $(document).off('fullscreenchange.lg webkitfullscreenchange.lg mozfullscreenchange.lg MSFullscreenChange.lg');
- };
- $.fn.lightGallery.modules.fullscreen = Fullscreen;
- })();
- }));
- /*! lg-hash - v1.0.4 - 2017-12-20
- * http://sachinchoolur.github.io/lightGallery
- * Copyright (c) 2017 Sachin N; Licensed GPLv3 */
- (function (root, factory) {
- if (typeof define === 'function' && define.amd) {
- // AMD. Register as an anonymous module unless amdModuleId is set
- define(['jquery'], function (a0) {
- return (factory(a0));
- });
- } else if (typeof exports === 'object') {
- // Node. Does not work with strict CommonJS, but
- // only CommonJS-like environments that support module.exports,
- // like Node.
- module.exports = factory(require('jquery'));
- } else {
- factory(jQuery);
- }
- }(this, function ($) {
- (function() {
- 'use strict';
- var defaults = {
- hash: true
- };
- var Hash = function(element) {
- this.core = $(element).data('lightGallery');
- this.core.s = $.extend({}, defaults, this.core.s);
- if (this.core.s.hash) {
- this.oldHash = window.location.hash;
- this.init();
- }
- return this;
- };
- Hash.prototype.init = function() {
- var _this = this;
- var _hash;
- // Change hash value on after each slide transition
- _this.core.$el.on('onAfterSlide.lg.tm', function(event, prevIndex, index) {
- if (history.replaceState) {
- history.replaceState(null, null, window.location.pathname + window.location.search + '#lg=' + _this.core.s.galleryId + '&slide=' + index);
- } else {
- window.location.hash = 'lg=' + _this.core.s.galleryId + '&slide=' + index;
- }
- });
- // Listen hash change and change the slide according to slide value
- $(window).on('hashchange.lg.hash', function() {
- _hash = window.location.hash;
- var _idx = parseInt(_hash.split('&slide=')[1], 10);
- // it galleryId doesn't exist in the url close the gallery
- if ((_hash.indexOf('lg=' + _this.core.s.galleryId) > -1)) {
- _this.core.slide(_idx, false, false);
- } else if (_this.core.lGalleryOn) {
- _this.core.destroy();
- }
- });
- };
- Hash.prototype.destroy = function() {
- if (!this.core.s.hash) {
- return;
- }
- // Reset to old hash value
- if (this.oldHash && this.oldHash.indexOf('lg=' + this.core.s.galleryId) < 0) {
- if (history.replaceState) {
- history.replaceState(null, null, this.oldHash);
- } else {
- window.location.hash = this.oldHash;
- }
- } else {
- if (history.replaceState) {
- history.replaceState(null, document.title, window.location.pathname + window.location.search);
- } else {
- window.location.hash = '';
- }
- }
- this.core.$el.off('.lg.hash');
- };
- $.fn.lightGallery.modules.hash = Hash;
- })();
- }));
- /*! lg-pager - v1.0.2 - 2017-01-22
- * http://sachinchoolur.github.io/lightGallery
- * Copyright (c) 2017 Sachin N; Licensed GPLv3 */
- (function (root, factory) {
- if (typeof define === 'function' && define.amd) {
- // AMD. Register as an anonymous module unless amdModuleId is set
- define(['jquery'], function (a0) {
- return (factory(a0));
- });
- } else if (typeof exports === 'object') {
- // Node. Does not work with strict CommonJS, but
- // only CommonJS-like environments that support module.exports,
- // like Node.
- module.exports = factory(require('jquery'));
- } else {
- factory(jQuery);
- }
- }(this, function ($) {
- (function() {
- 'use strict';
- var defaults = {
- pager: false
- };
- var Pager = function(element) {
- this.core = $(element).data('lightGallery');
- this.$el = $(element);
- this.core.s = $.extend({}, defaults, this.core.s);
- if (this.core.s.pager && this.core.$items.length > 1) {
- this.init();
- }
- return this;
- };
- Pager.prototype.init = function() {
- var _this = this;
- var pagerList = '';
- var $pagerCont;
- var $pagerOuter;
- var timeout;
- _this.core.$outer.find('.lg').append('<div class="lg-pager-outer"></div>');
- if (_this.core.s.dynamic) {
- for (var i = 0; i < _this.core.s.dynamicEl.length; i++) {
- pagerList += '<span class="lg-pager-cont"> <span class="lg-pager"></span><div class="lg-pager-thumb-cont"><span class="lg-caret"></span> <img src="' + _this.core.s.dynamicEl[i].thumb + '" /></div></span>';
- }
- } else {
- _this.core.$items.each(function() {
- if (!_this.core.s.exThumbImage) {
- pagerList += '<span class="lg-pager-cont"> <span class="lg-pager"></span><div class="lg-pager-thumb-cont"><span class="lg-caret"></span> <img src="' + $(this).find('img').attr('src') + '" /></div></span>';
- } else {
- pagerList += '<span class="lg-pager-cont"> <span class="lg-pager"></span><div class="lg-pager-thumb-cont"><span class="lg-caret"></span> <img src="' + $(this).attr(_this.core.s.exThumbImage) + '" /></div></span>';
- }
- });
- }
- $pagerOuter = _this.core.$outer.find('.lg-pager-outer');
- $pagerOuter.html(pagerList);
- $pagerCont = _this.core.$outer.find('.lg-pager-cont');
- $pagerCont.on('click.lg touchend.lg', function() {
- var _$this = $(this);
- _this.core.index = _$this.index();
- _this.core.slide(_this.core.index, false, true, false);
- });
- $pagerOuter.on('mouseover.lg', function() {
- clearTimeout(timeout);
- $pagerOuter.addClass('lg-pager-hover');
- });
- $pagerOuter.on('mouseout.lg', function() {
- timeout = setTimeout(function() {
- $pagerOuter.removeClass('lg-pager-hover');
- });
- });
- _this.core.$el.on('onBeforeSlide.lg.tm', function(e, prevIndex, index) {
- $pagerCont.removeClass('lg-pager-active');
- $pagerCont.eq(index).addClass('lg-pager-active');
- });
- };
- Pager.prototype.destroy = function() {
- };
- $.fn.lightGallery.modules.pager = Pager;
- })();
- }));
- /*! lg-thumbnail - v1.1.0 - 2017-08-08
- * http://sachinchoolur.github.io/lightGallery
- * Copyright (c) 2017 Sachin N; Licensed GPLv3 */
- (function (root, factory) {
- if (typeof define === 'function' && define.amd) {
- // AMD. Register as an anonymous module unless amdModuleId is set
- define(['jquery'], function (a0) {
- return (factory(a0));
- });
- } else if (typeof exports === 'object') {
- // Node. Does not work with strict CommonJS, but
- // only CommonJS-like environments that support module.exports,
- // like Node.
- module.exports = factory(require('jquery'));
- } else {
- factory(jQuery);
- }
- }(this, function ($) {
- (function() {
- 'use strict';
- var defaults = {
- thumbnail: true,
- animateThumb: true,
- currentPagerPosition: 'middle',
- thumbWidth: 100,
- thumbHeight: '80px',
- thumbContHeight: 100,
- thumbMargin: 5,
- exThumbImage: false,
- showThumbByDefault: true,
- toogleThumb: true,
- pullCaptionUp: true,
- enableThumbDrag: true,
- enableThumbSwipe: true,
- swipeThreshold: 50,
- loadYoutubeThumbnail: true,
- youtubeThumbSize: 1,
- loadVimeoThumbnail: true,
- vimeoThumbSize: 'thumbnail_small',
- loadDailymotionThumbnail: true
- };
- var Thumbnail = function(element) {
- // get lightGallery core plugin data
- this.core = $(element).data('lightGallery');
- // extend module default settings with lightGallery core settings
- this.core.s = $.extend({}, defaults, this.core.s);
- this.$el = $(element);
- this.$thumbOuter = null;
- this.thumbOuterWidth = 0;
- this.thumbTotalWidth = (this.core.$items.length * (this.core.s.thumbWidth + this.core.s.thumbMargin));
- this.thumbIndex = this.core.index;
- if (this.core.s.animateThumb) {
- this.core.s.thumbHeight = '100%';
- }
- // Thumbnail animation value
- this.left = 0;
- this.init();
- return this;
- };
- Thumbnail.prototype.init = function() {
- var _this = this;
- if (this.core.s.thumbnail && this.core.$items.length > 1) {
- if (this.core.s.showThumbByDefault) {
- setTimeout(function(){
- _this.core.$outer.addClass('lg-thumb-open');
- }, 700);
- }
- if (this.core.s.pullCaptionUp) {
- this.core.$outer.addClass('lg-pull-caption-up');
- }
- this.build();
- if (this.core.s.animateThumb && this.core.doCss()) {
- if (this.core.s.enableThumbDrag) {
- this.enableThumbDrag();
- }
- if (this.core.s.enableThumbSwipe) {
- this.enableThumbSwipe();
- }
- this.thumbClickable = false;
- } else {
- this.thumbClickable = true;
- }
- this.toogle();
- this.thumbkeyPress();
- }
- };
- Thumbnail.prototype.build = function() {
- var _this = this;
- var thumbList = '';
- var vimeoErrorThumbSize = '';
- var $thumb;
- var html = '<div class="lg-thumb-outer">' +
- '<div class="lg-thumb lg-group">' +
- '</div>' +
- '</div>';
- switch (this.core.s.vimeoThumbSize) {
- case 'thumbnail_large':
- vimeoErrorThumbSize = '640';
- break;
- case 'thumbnail_medium':
- vimeoErrorThumbSize = '200x150';
- break;
- case 'thumbnail_small':
- vimeoErrorThumbSize = '100x75';
- }
- _this.core.$outer.addClass('lg-has-thumb');
- _this.core.$outer.find('.lg').append(html);
- _this.$thumbOuter = _this.core.$outer.find('.lg-thumb-outer');
- _this.thumbOuterWidth = _this.$thumbOuter.width();
- if (_this.core.s.animateThumb) {
- _this.core.$outer.find('.lg-thumb').css({
- width: _this.thumbTotalWidth + 'px',
- position: 'relative'
- });
- }
- if (this.core.s.animateThumb) {
- _this.$thumbOuter.css('height', _this.core.s.thumbContHeight + 'px');
- }
- function getThumb(src, thumb, index) {
- var isVideo = _this.core.isVideo(src, index) || {};
- var thumbImg;
- var vimeoId = '';
- if (isVideo.youtube || isVideo.vimeo || isVideo.dailymotion) {
- if (isVideo.youtube) {
- if (_this.core.s.loadYoutubeThumbnail) {
- thumbImg = '//img.youtube.com/vi/' + isVideo.youtube[1] + '/' + _this.core.s.youtubeThumbSize + '.jpg';
- } else {
- thumbImg = thumb;
- }
- } else if (isVideo.vimeo) {
- if (_this.core.s.loadVimeoThumbnail) {
- thumbImg = '//i.vimeocdn.com/video/error_' + vimeoErrorThumbSize + '.jpg';
- vimeoId = isVideo.vimeo[1];
- } else {
- thumbImg = thumb;
- }
- } else if (isVideo.dailymotion) {
- if (_this.core.s.loadDailymotionThumbnail) {
- thumbImg = '//www.dailymotion.com/thumbnail/video/' + isVideo.dailymotion[1];
- } else {
- thumbImg = thumb;
- }
- }
- } else {
- thumbImg = thumb;
- }
- thumbList += '<div data-vimeo-id="' + vimeoId + '" class="lg-thumb-item" style="width:' + _this.core.s.thumbWidth + 'px; height: ' + _this.core.s.thumbHeight + '; margin-right: ' + _this.core.s.thumbMargin + 'px"><img src="' + thumbImg + '" /></div>';
- vimeoId = '';
- }
- if (_this.core.s.dynamic) {
- for (var i = 0; i < _this.core.s.dynamicEl.length; i++) {
- getThumb(_this.core.s.dynamicEl[i].src, _this.core.s.dynamicEl[i].thumb, i);
- }
- } else {
- _this.core.$items.each(function(i) {
- if (!_this.core.s.exThumbImage) {
- getThumb($(this).attr('href') || $(this).attr('data-src'), $(this).find('img').attr('src'), i);
- } else {
- getThumb($(this).attr('href') || $(this).attr('data-src'), $(this).attr(_this.core.s.exThumbImage), i);
- }
- });
- }
- _this.core.$outer.find('.lg-thumb').html(thumbList);
- $thumb = _this.core.$outer.find('.lg-thumb-item');
- // Load vimeo thumbnails
- $thumb.each(function() {
- var $this = $(this);
- var vimeoVideoId = $this.attr('data-vimeo-id');
- if (vimeoVideoId) {
- $.getJSON('//www.vimeo.com/api/v2/video/' + vimeoVideoId + '.json?callback=?', {
- format: 'json'
- }, function(data) {
- $this.find('img').attr('src', data[0][_this.core.s.vimeoThumbSize]);
- });
- }
- });
- // manage active class for thumbnail
- $thumb.eq(_this.core.index).addClass('active');
- _this.core.$el.on('onBeforeSlide.lg.tm', function() {
- $thumb.removeClass('active');
- $thumb.eq(_this.core.index).addClass('active');
- });
- $thumb.on('click.lg touchend.lg', function() {
- var _$this = $(this);
- setTimeout(function() {
- // In IE9 and bellow touch does not support
- // Go to slide if browser does not support css transitions
- if ((_this.thumbClickable && !_this.core.lgBusy) || !_this.core.doCss()) {
- _this.core.index = _$this.index();
- _this.core.slide(_this.core.index, false, true, false);
- }
- }, 50);
- });
- _this.core.$el.on('onBeforeSlide.lg.tm', function() {
- _this.animateThumb(_this.core.index);
- });
- $(window).on('resize.lg.thumb orientationchange.lg.thumb', function() {
- setTimeout(function() {
- _this.animateThumb(_this.core.index);
- _this.thumbOuterWidth = _this.$thumbOuter.width();
- }, 200);
- });
- };
- Thumbnail.prototype.setTranslate = function(value) {
- // jQuery supports Automatic CSS prefixing since jQuery 1.8.0
- this.core.$outer.find('.lg-thumb').css({
- transform: 'translate3d(-' + (value) + 'px, 0px, 0px)'
- });
- };
- Thumbnail.prototype.animateThumb = function(index) {
- var $thumb = this.core.$outer.find('.lg-thumb');
- if (this.core.s.animateThumb) {
- var position;
- switch (this.core.s.currentPagerPosition) {
- case 'left':
- position = 0;
- break;
- case 'middle':
- position = (this.thumbOuterWidth / 2) - (this.core.s.thumbWidth / 2);
- break;
- case 'right':
- position = this.thumbOuterWidth - this.core.s.thumbWidth;
- }
- this.left = ((this.core.s.thumbWidth + this.core.s.thumbMargin) * index - 1) - position;
- if (this.left > (this.thumbTotalWidth - this.thumbOuterWidth)) {
- this.left = this.thumbTotalWidth - this.thumbOuterWidth;
- }
- if (this.left < 0) {
- this.left = 0;
- }
- if (this.core.lGalleryOn) {
- if (!$thumb.hasClass('on')) {
- this.core.$outer.find('.lg-thumb').css('transition-duration', this.core.s.speed + 'ms');
- }
- if (!this.core.doCss()) {
- $thumb.animate({
- left: -this.left + 'px'
- }, this.core.s.speed);
- }
- } else {
- if (!this.core.doCss()) {
- $thumb.css('left', -this.left + 'px');
- }
- }
- this.setTranslate(this.left);
- }
- };
- // Enable thumbnail dragging and swiping
- Thumbnail.prototype.enableThumbDrag = function() {
- var _this = this;
- var startCoords = 0;
- var endCoords = 0;
- var isDraging = false;
- var isMoved = false;
- var tempLeft = 0;
- _this.$thumbOuter.addClass('lg-grab');
- _this.core.$outer.find('.lg-thumb').on('mousedown.lg.thumb', function(e) {
- if (_this.thumbTotalWidth > _this.thumbOuterWidth) {
- // execute only on .lg-object
- e.preventDefault();
- startCoords = e.pageX;
- isDraging = true;
- // ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723
- _this.core.$outer.scrollLeft += 1;
- _this.core.$outer.scrollLeft -= 1;
- // *
- _this.thumbClickable = false;
- _this.$thumbOuter.removeClass('lg-grab').addClass('lg-grabbing');
- }
- });
- $(window).on('mousemove.lg.thumb', function(e) {
- if (isDraging) {
- tempLeft = _this.left;
- isMoved = true;
- endCoords = e.pageX;
- _this.$thumbOuter.addClass('lg-dragging');
- tempLeft = tempLeft - (endCoords - startCoords);
- if (tempLeft > (_this.thumbTotalWidth - _this.thumbOuterWidth)) {
- tempLeft = _this.thumbTotalWidth - _this.thumbOuterWidth;
- }
- if (tempLeft < 0) {
- tempLeft = 0;
- }
- // move current slide
- _this.setTranslate(tempLeft);
- }
- });
- $(window).on('mouseup.lg.thumb', function() {
- if (isMoved) {
- isMoved = false;
- _this.$thumbOuter.removeClass('lg-dragging');
- _this.left = tempLeft;
- if (Math.abs(endCoords - startCoords) < _this.core.s.swipeThreshold) {
- _this.thumbClickable = true;
- }
- } else {
- _this.thumbClickable = true;
- }
- if (isDraging) {
- isDraging = false;
- _this.$thumbOuter.removeClass('lg-grabbing').addClass('lg-grab');
- }
- });
- };
- Thumbnail.prototype.enableThumbSwipe = function() {
- var _this = this;
- var startCoords = 0;
- var endCoords = 0;
- var isMoved = false;
- var tempLeft = 0;
- _this.core.$outer.find('.lg-thumb').on('touchstart.lg', function(e) {
- if (_this.thumbTotalWidth > _this.thumbOuterWidth) {
- e.preventDefault();
- startCoords = e.originalEvent.targetTouches[0].pageX;
- _this.thumbClickable = false;
- }
- });
- _this.core.$outer.find('.lg-thumb').on('touchmove.lg', function(e) {
- if (_this.thumbTotalWidth > _this.thumbOuterWidth) {
- e.preventDefault();
- endCoords = e.originalEvent.targetTouches[0].pageX;
- isMoved = true;
- _this.$thumbOuter.addClass('lg-dragging');
- tempLeft = _this.left;
- tempLeft = tempLeft - (endCoords - startCoords);
- if (tempLeft > (_this.thumbTotalWidth - _this.thumbOuterWidth)) {
- tempLeft = _this.thumbTotalWidth - _this.thumbOuterWidth;
- }
- if (tempLeft < 0) {
- tempLeft = 0;
- }
- // move current slide
- _this.setTranslate(tempLeft);
- }
- });
- _this.core.$outer.find('.lg-thumb').on('touchend.lg', function() {
- if (_this.thumbTotalWidth > _this.thumbOuterWidth) {
- if (isMoved) {
- isMoved = false;
- _this.$thumbOuter.removeClass('lg-dragging');
- if (Math.abs(endCoords - startCoords) < _this.core.s.swipeThreshold) {
- _this.thumbClickable = true;
- }
- _this.left = tempLeft;
- } else {
- _this.thumbClickable = true;
- }
- } else {
- _this.thumbClickable = true;
- }
- });
- };
- Thumbnail.prototype.toogle = function() {
- var _this = this;
- if (_this.core.s.toogleThumb) {
- _this.core.$outer.addClass('lg-can-toggle');
- _this.$thumbOuter.append('<span class="lg-toogle-thumb lg-icon"></span>');
- _this.core.$outer.find('.lg-toogle-thumb').on('click.lg', function() {
- _this.core.$outer.toggleClass('lg-thumb-open');
- });
- }
- };
- Thumbnail.prototype.thumbkeyPress = function() {
- var _this = this;
- $(window).on('keydown.lg.thumb', function(e) {
- if (e.keyCode === 38) {
- e.preventDefault();
- _this.core.$outer.addClass('lg-thumb-open');
- } else if (e.keyCode === 40) {
- e.preventDefault();
- _this.core.$outer.removeClass('lg-thumb-open');
- }
- });
- };
- Thumbnail.prototype.destroy = function() {
- if (this.core.s.thumbnail && this.core.$items.length > 1) {
- $(window).off('resize.lg.thumb orientationchange.lg.thumb keydown.lg.thumb');
- this.$thumbOuter.remove();
- this.core.$outer.removeClass('lg-has-thumb');
- }
- };
- $.fn.lightGallery.modules.Thumbnail = Thumbnail;
- })();
- }));
- /*! lg-zoom - v1.1.0 - 2017-08-08
- * http://sachinchoolur.github.io/lightGallery
- * Copyright (c) 2017 Sachin N; Licensed GPLv3 */
- (function (root, factory) {
- if (typeof define === 'function' && define.amd) {
- // AMD. Register as an anonymous module unless amdModuleId is set
- define(['jquery'], function (a0) {
- return (factory(a0));
- });
- } else if (typeof exports === 'object') {
- // Node. Does not work with strict CommonJS, but
- // only CommonJS-like environments that support module.exports,
- // like Node.
- module.exports = factory(require('jquery'));
- } else {
- factory(jQuery);
- }
- }(this, function ($) {
- (function() {
- 'use strict';
- var getUseLeft = function() {
- var useLeft = false;
- var isChrome = navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./);
- if (isChrome && parseInt(isChrome[2], 10) < 54) {
- useLeft = true;
- }
- return useLeft;
- };
- var defaults = {
- scale: 1,
- zoom: true,
- actualSize: true,
- enableZoomAfter: 300,
- useLeftForZoom: getUseLeft()
- };
- var Zoom = function(element) {
- this.core = $(element).data('lightGallery');
- this.core.s = $.extend({}, defaults, this.core.s);
- if (this.core.s.zoom && this.core.doCss()) {
- this.init();
- // Store the zoomable timeout value just to clear it while closing
- this.zoomabletimeout = false;
- // Set the initial value center
- this.pageX = $(window).width() / 2;
- this.pageY = ($(window).height() / 2) + $(window).scrollTop();
- }
- return this;
- };
- Zoom.prototype.init = function() {
- var _this = this;
- var zoomIcons = '<span id="lg-zoom-in" class="lg-icon"></span><span id="lg-zoom-out" class="lg-icon"></span>';
- if (_this.core.s.actualSize) {
- zoomIcons += '<span id="lg-actual-size" class="lg-icon"></span>';
- }
- if (_this.core.s.useLeftForZoom) {
- _this.core.$outer.addClass('lg-use-left-for-zoom');
- } else {
- _this.core.$outer.addClass('lg-use-transition-for-zoom');
- }
- this.core.$outer.find('.lg-toolbar').append(zoomIcons);
- // Add zoomable class
- _this.core.$el.on('onSlideItemLoad.lg.tm.zoom', function(event, index, delay) {
- // delay will be 0 except first time
- var _speed = _this.core.s.enableZoomAfter + delay;
- // set _speed value 0 if gallery opened from direct url and if it is first slide
- if ($('body').hasClass('lg-from-hash') && delay) {
- // will execute only once
- _speed = 0;
- } else {
- // Remove lg-from-hash to enable starting animation.
- $('body').removeClass('lg-from-hash');
- }
- _this.zoomabletimeout = setTimeout(function() {
- _this.core.$slide.eq(index).addClass('lg-zoomable');
- }, _speed + 30);
- });
- var scale = 1;
- /**
- * @desc Image zoom
- * Translate the wrap and scale the image to get better user experience
- *
- * @param {String} scaleVal - Zoom decrement/increment value
- */
- var zoom = function(scaleVal) {
- var $image = _this.core.$outer.find('.lg-current .lg-image');
- var _x;
- var _y;
- // Find offset manually to avoid issue after zoom
- var offsetX = ($(window).width() - $image.prop('offsetWidth')) / 2;
- var offsetY = (($(window).height() - $image.prop('offsetHeight')) / 2) + $(window).scrollTop();
- _x = _this.pageX - offsetX;
- _y = _this.pageY - offsetY;
- var x = (scaleVal - 1) * (_x);
- var y = (scaleVal - 1) * (_y);
- $image.css('transform', 'scale3d(' + scaleVal + ', ' + scaleVal + ', 1)').attr('data-scale', scaleVal);
- if (_this.core.s.useLeftForZoom) {
- $image.parent().css({
- left: -x + 'px',
- top: -y + 'px'
- }).attr('data-x', x).attr('data-y', y);
- } else {
- $image.parent().css('transform', 'translate3d(-' + x + 'px, -' + y + 'px, 0)').attr('data-x', x).attr('data-y', y);
- }
- };
- var callScale = function() {
- if (scale > 1) {
- _this.core.$outer.addClass('lg-zoomed');
- } else {
- _this.resetZoom();
- }
- if (scale < 1) {
- scale = 1;
- }
- zoom(scale);
- };
- var actualSize = function(event, $image, index, fromIcon) {
- var w = $image.prop('offsetWidth');
- var nw;
- if (_this.core.s.dynamic) {
- nw = _this.core.s.dynamicEl[index].width || $image[0].naturalWidth || w;
- } else {
- nw = _this.core.$items.eq(index).attr('data-width') || $image[0].naturalWidth || w;
- }
- var _scale;
- if (_this.core.$outer.hasClass('lg-zoomed')) {
- scale = 1;
- } else {
- if (nw > w) {
- _scale = nw / w;
- scale = _scale || 2;
- }
- }
- if (fromIcon) {
- _this.pageX = $(window).width() / 2;
- _this.pageY = ($(window).height() / 2) + $(window).scrollTop();
- } else {
- _this.pageX = event.pageX || event.originalEvent.targetTouches[0].pageX;
- _this.pageY = event.pageY || event.originalEvent.targetTouches[0].pageY;
- }
- callScale();
- setTimeout(function() {
- _this.core.$outer.removeClass('lg-grabbing').addClass('lg-grab');
- }, 10);
- };
- var tapped = false;
- // event triggered after appending slide content
- _this.core.$el.on('onAferAppendSlide.lg.tm.zoom', function(event, index) {
- // Get the current element
- var $image = _this.core.$slide.eq(index).find('.lg-image');
- $image.on('dblclick', function(event) {
- actualSize(event, $image, index);
- });
- $image.on('touchstart', function(event) {
- if (!tapped) {
- tapped = setTimeout(function() {
- tapped = null;
- }, 300);
- } else {
- clearTimeout(tapped);
- tapped = null;
- actualSize(event, $image, index);
- }
- event.preventDefault();
- });
- });
- // Update zoom on resize and orientationchange
- $(window).on('resize.lg.zoom scroll.lg.zoom orientationchange.lg.zoom', function() {
- _this.pageX = $(window).width() / 2;
- _this.pageY = ($(window).height() / 2) + $(window).scrollTop();
- zoom(scale);
- });
- $('#lg-zoom-out').on('click.lg', function() {
- if (_this.core.$outer.find('.lg-current .lg-image').length) {
- scale -= _this.core.s.scale;
- callScale();
- }
- });
- $('#lg-zoom-in').on('click.lg', function() {
- if (_this.core.$outer.find('.lg-current .lg-image').length) {
- scale += _this.core.s.scale;
- callScale();
- }
- });
- $('#lg-actual-size').on('click.lg', function(event) {
- actualSize(event, _this.core.$slide.eq(_this.core.index).find('.lg-image'), _this.core.index, true);
- });
- // Reset zoom on slide change
- _this.core.$el.on('onBeforeSlide.lg.tm', function() {
- scale = 1;
- _this.resetZoom();
- });
- // Drag option after zoom
- _this.zoomDrag();
- _this.zoomSwipe();
- };
- // Reset zoom effect
- Zoom.prototype.resetZoom = function() {
- this.core.$outer.removeClass('lg-zoomed');
- this.core.$slide.find('.lg-img-wrap').removeAttr('style data-x data-y');
- this.core.$slide.find('.lg-image').removeAttr('style data-scale');
- // Reset pagx pagy values to center
- this.pageX = $(window).width() / 2;
- this.pageY = ($(window).height() / 2) + $(window).scrollTop();
- };
- Zoom.prototype.zoomSwipe = function() {
- var _this = this;
- var startCoords = {};
- var endCoords = {};
- var isMoved = false;
- // Allow x direction drag
- var allowX = false;
- // Allow Y direction drag
- var allowY = false;
- _this.core.$slide.on('touchstart.lg', function(e) {
- if (_this.core.$outer.hasClass('lg-zoomed')) {
- var $image = _this.core.$slide.eq(_this.core.index).find('.lg-object');
- allowY = $image.prop('offsetHeight') * $image.attr('data-scale') > _this.core.$outer.find('.lg').height();
- allowX = $image.prop('offsetWidth') * $image.attr('data-scale') > _this.core.$outer.find('.lg').width();
- if ((allowX || allowY)) {
- e.preventDefault();
- startCoords = {
- x: e.originalEvent.targetTouches[0].pageX,
- y: e.originalEvent.targetTouches[0].pageY
- };
- }
- }
- });
- _this.core.$slide.on('touchmove.lg', function(e) {
- if (_this.core.$outer.hasClass('lg-zoomed')) {
- var _$el = _this.core.$slide.eq(_this.core.index).find('.lg-img-wrap');
- var distanceX;
- var distanceY;
- e.preventDefault();
- isMoved = true;
- endCoords = {
- x: e.originalEvent.targetTouches[0].pageX,
- y: e.originalEvent.targetTouches[0].pageY
- };
- // reset opacity and transition duration
- _this.core.$outer.addClass('lg-zoom-dragging');
- if (allowY) {
- distanceY = (-Math.abs(_$el.attr('data-y'))) + (endCoords.y - startCoords.y);
- } else {
- distanceY = -Math.abs(_$el.attr('data-y'));
- }
- if (allowX) {
- distanceX = (-Math.abs(_$el.attr('data-x'))) + (endCoords.x - startCoords.x);
- } else {
- distanceX = -Math.abs(_$el.attr('data-x'));
- }
- if ((Math.abs(endCoords.x - startCoords.x) > 15) || (Math.abs(endCoords.y - startCoords.y) > 15)) {
- if (_this.core.s.useLeftForZoom) {
- _$el.css({
- left: distanceX + 'px',
- top: distanceY + 'px'
- });
- } else {
- _$el.css('transform', 'translate3d(' + distanceX + 'px, ' + distanceY + 'px, 0)');
- }
- }
- }
- });
- _this.core.$slide.on('touchend.lg', function() {
- if (_this.core.$outer.hasClass('lg-zoomed')) {
- if (isMoved) {
- isMoved = false;
- _this.core.$outer.removeClass('lg-zoom-dragging');
- _this.touchendZoom(startCoords, endCoords, allowX, allowY);
- }
- }
- });
- };
- Zoom.prototype.zoomDrag = function() {
- var _this = this;
- var startCoords = {};
- var endCoords = {};
- var isDraging = false;
- var isMoved = false;
- // Allow x direction drag
- var allowX = false;
- // Allow Y direction drag
- var allowY = false;
- _this.core.$slide.on('mousedown.lg.zoom', function(e) {
- // execute only on .lg-object
- var $image = _this.core.$slide.eq(_this.core.index).find('.lg-object');
- allowY = $image.prop('offsetHeight') * $image.attr('data-scale') > _this.core.$outer.find('.lg').height();
- allowX = $image.prop('offsetWidth') * $image.attr('data-scale') > _this.core.$outer.find('.lg').width();
- if (_this.core.$outer.hasClass('lg-zoomed')) {
- if ($(e.target).hasClass('lg-object') && (allowX || allowY)) {
- e.preventDefault();
- startCoords = {
- x: e.pageX,
- y: e.pageY
- };
- isDraging = true;
- // ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723
- _this.core.$outer.scrollLeft += 1;
- _this.core.$outer.scrollLeft -= 1;
- _this.core.$outer.removeClass('lg-grab').addClass('lg-grabbing');
- }
- }
- });
- $(window).on('mousemove.lg.zoom', function(e) {
- if (isDraging) {
- var _$el = _this.core.$slide.eq(_this.core.index).find('.lg-img-wrap');
- var distanceX;
- var distanceY;
- isMoved = true;
- endCoords = {
- x: e.pageX,
- y: e.pageY
- };
- // reset opacity and transition duration
- _this.core.$outer.addClass('lg-zoom-dragging');
- if (allowY) {
- distanceY = (-Math.abs(_$el.attr('data-y'))) + (endCoords.y - startCoords.y);
- } else {
- distanceY = -Math.abs(_$el.attr('data-y'));
- }
- if (allowX) {
- distanceX = (-Math.abs(_$el.attr('data-x'))) + (endCoords.x - startCoords.x);
- } else {
- distanceX = -Math.abs(_$el.attr('data-x'));
- }
- if (_this.core.s.useLeftForZoom) {
- _$el.css({
- left: distanceX + 'px',
- top: distanceY + 'px'
- });
- } else {
- _$el.css('transform', 'translate3d(' + distanceX + 'px, ' + distanceY + 'px, 0)');
- }
- }
- });
- $(window).on('mouseup.lg.zoom', function(e) {
- if (isDraging) {
- isDraging = false;
- _this.core.$outer.removeClass('lg-zoom-dragging');
- // Fix for chrome mouse move on click
- if (isMoved && ((startCoords.x !== endCoords.x) || (startCoords.y !== endCoords.y))) {
- endCoords = {
- x: e.pageX,
- y: e.pageY
- };
- _this.touchendZoom(startCoords, endCoords, allowX, allowY);
- }
- isMoved = false;
- }
- _this.core.$outer.removeClass('lg-grabbing').addClass('lg-grab');
- });
- };
- Zoom.prototype.touchendZoom = function(startCoords, endCoords, allowX, allowY) {
- var _this = this;
- var _$el = _this.core.$slide.eq(_this.core.index).find('.lg-img-wrap');
- var $image = _this.core.$slide.eq(_this.core.index).find('.lg-object');
- var distanceX = (-Math.abs(_$el.attr('data-x'))) + (endCoords.x - startCoords.x);
- var distanceY = (-Math.abs(_$el.attr('data-y'))) + (endCoords.y - startCoords.y);
- var minY = (_this.core.$outer.find('.lg').height() - $image.prop('offsetHeight')) / 2;
- var maxY = Math.abs(($image.prop('offsetHeight') * Math.abs($image.attr('data-scale'))) - _this.core.$outer.find('.lg').height() + minY);
- var minX = (_this.core.$outer.find('.lg').width() - $image.prop('offsetWidth')) / 2;
- var maxX = Math.abs(($image.prop('offsetWidth') * Math.abs($image.attr('data-scale'))) - _this.core.$outer.find('.lg').width() + minX);
- if ((Math.abs(endCoords.x - startCoords.x) > 15) || (Math.abs(endCoords.y - startCoords.y) > 15)) {
- if (allowY) {
- if (distanceY <= -maxY) {
- distanceY = -maxY;
- } else if (distanceY >= -minY) {
- distanceY = -minY;
- }
- }
- if (allowX) {
- if (distanceX <= -maxX) {
- distanceX = -maxX;
- } else if (distanceX >= -minX) {
- distanceX = -minX;
- }
- }
- if (allowY) {
- _$el.attr('data-y', Math.abs(distanceY));
- } else {
- distanceY = -Math.abs(_$el.attr('data-y'));
- }
- if (allowX) {
- _$el.attr('data-x', Math.abs(distanceX));
- } else {
- distanceX = -Math.abs(_$el.attr('data-x'));
- }
- if (_this.core.s.useLeftForZoom) {
- _$el.css({
- left: distanceX + 'px',
- top: distanceY + 'px'
- });
- } else {
- _$el.css('transform', 'translate3d(' + distanceX + 'px, ' + distanceY + 'px, 0)');
- }
- }
- };
- Zoom.prototype.destroy = function() {
- var _this = this;
- // Unbind all events added by lightGallery zoom plugin
- _this.core.$el.off('.lg.zoom');
- $(window).off('.lg.zoom');
- _this.core.$slide.off('.lg.zoom');
- _this.core.$el.off('.lg.tm.zoom');
- _this.resetZoom();
- clearTimeout(_this.zoomabletimeout);
- _this.zoomabletimeout = false;
- };
- $.fn.lightGallery.modules.zoom = Zoom;
- })();
- }));
|