| 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;})();}));
 |