Search code examples
javascriptjqueryapilightboxlightgallery

Jquery custom sorting issue


I have a page that loads photos on page load from an API.

** Edit: Here is a CodePen with the page, error happing there: http://codepen.io/nathan-anderson/pen/GqXbvK

When initially loading the page I use this to call on the info and use the lightgallery plugin:

// ----------------------------------------------------------------//
// ---------------// Unsplash Photos //---------------//
// ----------------------------------------------------------------//
    function displayPhotos(data) {
        var photoData = '';
      $.each(data, function (i, photo) {
          photoData += '<a class="tile"' + 'data-sub-html="#' + photo.id + '"'+ 'data-src="' + photo.urls.regular + '">' + '<img alt class="photo" src="' + photo.urls.regular + '">' + '<div class="caption-box" id="' +  photo.id + '">' + '<h1 class="photo-title">' + 'Photo By: ' + photo.user.name + '</h1>' + '<p class="photo-description"> Description: Awesome photo by ' + photo.user.name + ' (aka:' + '<a target="_blank" href="' + photo.links.html + '">' + photo.user.username + ')</a>' + ' So far this photo has ' + '<span>' + photo.likes + '</span>' + ' Likes.' + ' You can download this photo if you wish, it has a free <a target="_blank" href="https://unsplash.com/license"> Do whatever you want </a> license. <a target="_blank" href="' + photo.links.download + '"><i class="fa fa-download" aria-hidden="true"></i> </a> </p>' + '</div>' + '</a>';
      });
            // Putitng into HTML
      $('#photoBox').html(photoData);

            //--------//
            // Calling Lightbox
            //--------//
      $('#photoBox').lightGallery({
      selector: '.tile',
      download: false,
      counter: false,
      zoom: false,
      thumbnail: false,
      mode: 'lg-fade'
        });
        } // End Displayphotos function

// Show popular photos on pageload
$.getJSON(unsplashAPI, popularPhotos, displayPhotos);

I have multiple buttons for showing different orders of the photos. The API grabs different photos based on the "order_by" option.

This is my code to show the different sections:

var popularPhotos = {
    order_by: "popular",
    format: "json"
};
var latestPhotos = {
    order_by: "latest",
    format: "json"
};
var oldestPhotos = {
    order_by: "oldest",
    format: "json"
};
// Button Click Changes
    $('button').click(function () {
        $('button').removeClass("active");
        $(this).addClass("active");
    }); // End button

// Show Popular Photos
    $('#popular').click(function () {
        $.getJSON(unsplashAPI, popularPhotos, displayPhotos);
    }); // End button
// Show latest Photos
    $('#latest').click(function () {
        $.getJSON(unsplashAPI, latestPhotos, displayPhotos);
    }); // End button
// Show oldest Photos
    $('#oldest').click(function () {
        $.getJSON(unsplashAPI, oldestPhotos, displayPhotos);
    }); // End button

This does load the new photos on button click but it breaks the function of the lightbox plugin.

Any thoughts? Anyone else running into this?

-- Thanks


Solution

  • So, the reason is a known issue with the library when attaching lightGallery without properly destroying previous listeners:

    A soln in this case is a simple destroy before reinitialising it inside the displayPhotos function.

    Just declare a variable gallery in outside scope like : var gallery;

    then update the displayPhotos function reinit like:

    //destroy if existing
    if(gallery) gallery.data('lightGallery').destroy(true);
    //initialise the plugin
    gallery = $('#photoBox').lightGallery({
        selector: '.tile',
        download: false,
        counter: false,
        zoom: false,
        thumbnail: false,
        mode: 'lg-fade'
    });
    

    Updated CodePen: http://codepen.io/alokrajiv/pen/pbOXmp

    WORKING SNIPPET HERE:

    // ----------------------------------------------------------------//
    // ---------------// Variables //---------------//
    // ----------------------------------------------------------------//
    var unsplashAPI = "https://api.unsplash.com/users/nathananderson/photos/?client_id=1fc3cf0554dd08f8491af5cd37ac945bebde6b5032613d61419f2b92ddde1d9a&per_page=20";
    var popularPhotos = {
      order_by: "popular",
      format: "json"
    };
    var latestPhotos = {
      order_by: "latest",
      format: "json"
    };
    var oldestPhotos = {
      order_by: "oldest",
      format: "json"
    };
    
    // ----------------------------------------------------------------//
    // ---------------// Unsplash Photos //---------------//
    // ----------------------------------------------------------------//
    var gallery;
    
    function displayPhotos(data) {
        var photoData = '';
        $.each(data, function(i, photo) {
          photoData += '<a class="tile"' + 'data-sub-html="#' + photo.id + '"' + 'data-src="' + photo.urls.regular + '">' + '<img alt class="photo" src="' + photo.urls.regular + '">' + '<div class="caption-box" id="' + photo.id + '">' + '<h1 class="photo-title">' + 'Photo By: ' + photo.user.name + '</h1>' + '<p class="photo-description"> Description: Awesome photo by ' + photo.user.name + ' (aka:' + '<a target="_blank" href="' + photo.links.html + '">' + photo.user.username + ')</a>' + ' So far this photo has ' + '<span>' + photo.likes + '</span>' + ' Likes.' + ' You can download this photo if you wish, it has a free <a target="_blank" href="https://unsplash.com/license"> Do whatever you want </a> license. <a target="_blank" href="' + photo.links.download + '"><i class="fa fa-download" aria-hidden="true"></i> </a> </p>' + '</div>' + '</a>';
        });
        // Putitng into HTML
        $('#photoBox').html(photoData);
        //-----------------------------------//
        // -------  Calling Lightbox ------- //
        //-----------------------------------//
        if (gallery) gallery.data('lightGallery').destroy(true);
        gallery = $('#photoBox').lightGallery({
          selector: '.tile',
          download: false,
          counter: false,
          zoom: false,
          thumbnail: false,
          mode: 'lg-fade'
        });
      } // End Displayphotos function
    
    // Show popular photos on pageload
    $.getJSON(unsplashAPI, popularPhotos, displayPhotos);
    
    
    // Button Click Changes
    $('button').click(function() {
      $('button').removeClass("active");
      $(this).addClass("active");
    }); // End button
    
    // Show Popular Photos
    $('#popular').click(function() {
      $.getJSON(unsplashAPI, popularPhotos, displayPhotos);
    }); // End button
    // Show latest Photos
    $('#latest').click(function() {
      $.getJSON(unsplashAPI, latestPhotos, displayPhotos);
    }); // End button
    // Show oldest Photos
    $('#oldest').click(function() {
      $.getJSON(unsplashAPI, oldestPhotos, displayPhotos);
    }); // End button
    html {
      box-sizing: border-box;
    }
    *,
    *::after,
    *::before {
      box-sizing: inherit;
    }
    /* Generated by Font Squirrel (https://www.fontsquirrel.com) on July 25, 2016 */
    
    @font-face {
      font-family: 'courier_primeregular';
      src: url("../fonts/courier_prime-webfont.woff2") format("woff2"), url("../fonts/courier_prime-webfont.woff") format("woff");
    }
    @font-face {
      font-family: 'courier_primeitalic';
      src: url("../fonts/courier_prime_italic-webfont.woff2") format("woff2"), url("../fonts/courier_prime_italic-webfont.woff") format("woff");
    }
    @font-face {
      font-family: 'courier_primebold';
      src: url("../fonts/courier_prime_bold-webfont.woff2") format("woff2"), url("../fonts/courier_prime_bold-webfont.woff") format("woff");
    }
    body,
    .filter-box .filter:hover,
    .filter-box .filter.active,
    .lg-actions .lg-prev:after,
    .lg-actions .lg-next:before {
      font-family: 'courier_primeregular', sans-serif;
      font-weight: 400;
      font-style: normal;
      font-stretch: normal;
    }
    .filter-box .filter,
    .photo-description span {
      font-family: 'courier_primebold', sans-serif;
      text-weight: 600;
    }
    header span {
      font-family: 'courier_primeitalic', sans-serif;
    }
    html,
    body {
      margin: 0;
      padding: 0;
    }
    a:hover {
      cursor: pointer;
    }
    p {
      margin-top: 0;
    }
    h1,
    h2,
    h3,
    h4,
    h5,
    h6 {
      font-family: inherit;
      line-height: inherit;
      font-weight: inherit;
      margin-top: 0;
    }
    img {
      vertical-align: middle;
    }
    figure {
      margin: 0;
    }
    /* Global Layout Set-up */
    
    * {
      box-sizing: border-box;
    }
    .justify-end {
      justify-content: flex-end;
    }
    .no-grow {
      flex-grow: 0;
    }
    /* Because... Fun */
    
    ::selection {
      background: #000000;
      color: #FFFFFF;
    }
    /* Becuase I can't stand these */
    
    *:focus {
      outline: none;
    }
    body {
      margin: 0;
      padding: 0;
      height: 100vh;
      background-color: #FFFFFF;
      color: #000000;
    }
    #top,
    #bottom,
    #left,
    #right {
      background: #000000;
      position: fixed;
    }
    #left,
    #right {
      top: 0;
      bottom: 0;
      width: 10px;
    }
    #left {
      left: 0;
    }
    #right {
      right: 0;
    }
    #top,
    #bottom {
      left: 0;
      right: 0;
      height: 10px;
    }
    #top {
      top: 0;
    }
    #bottom {
      bottom: 0;
    }
    a {
      color: #000000;
    }
    .current a {
      color: #000000;
      text-decoration: underline;
    }
    header {
      display: flex;
      padding: 1.5em 1.5em 0 1.5em;
      flex-direction: column;
    }
    header h1 {
      color: #000000;
      text-align: left;
      font-size: 2em;
    }
    @media only screen and (min-width: 480px) {
      header h1 {
        margin-bottom: 0;
      }
    }
    header span {
      display: none;
    }
    @media only screen and (min-width: 480px) {
      header span {
        display: inline;
        text-align: left;
      }
    }
    @media only screen and (min-width: 480px) {
      header {
        padding: 2.5em 2.5em 1em 2.5em;
      }
    }
    .filter-box {
      display: flex;
      align-content: flex-start;
      flex-wrap: wrap;
      padding: 0 1.5em;
    }
    .filter-box .filter {
      font-size: 1em;
      background: #FFFFFF;
      color: #000000;
      border: 3.5px solid #000000;
      padding: 0.35em 2.25em;
      margin: 0.5em 0.5em;
      cursor: pointer;
      transition: background 0.2s;
    }
    .filter-box .filter:first-of-type {
      padding: 0.35em 1.5em;
    }
    .filter-box .filter:hover {
      color: #FFFFFF;
      background: #000000;
      cursor: pointer;
    }
    @media only screen and (min-width: 480px) {
      .filter-box .filter {
        margin: 1em 1em;
      }
    }
    .filter-box .filter.active {
      color: #FFFFFF;
      background: #000000;
    }
    @media only screen and (min-width: 480px) {
      .filter-box {
        padding-left: 1.5em;
      }
    }
    /* Edits for styles on lightgallery plugin */
    
    .lg-backdrop {
      background: rgba(0, 0, 0, 0.9);
    }
    .lg-outer .lg-img-wrap,
    .lg-outer .lg-item {
      max-width: 100%;
      height: 100%;
    }
    .lg-outer .lg-img-wrap .lg-image,
    .lg-outer .lg-item .lg-image {
      max-width: 100%;
      border: 10px solid #000000;
      vertical-align: top;
      margin-top: 10%;
    }
    @media only screen and (min-width: 480px) {
      .lg-outer .lg-img-wrap .lg-image,
      .lg-outer .lg-item .lg-image {
        max-width: 850px;
        margin-top: 0;
        vertical-align: middle;
      }
    }
    .lg-outer .lg-img-wrap .lg-item,
    .lg-outer .lg-item .lg-item {
      background: none;
    }
    .lg-actions .lg-next,
    .lg-actions .lg-prev,
    .lg-toolbar {
      background: none;
    }
    .lg-actions .lg-prev:after {
      content: 'Back';
      right: -100px;
      position: absolute;
      top: 0;
      color: #FFFFFF;
    }
    .lg-actions .lg-next:before {
      content: 'Next';
      left: -60px;
      position: absolute;
      top: 50%;
      color: #FFFFFF;
    }
    @media (max-width: 1100px) {
      .lg-actions .lg-next:before {
        color: transparent;
      }
    }
    @media (max-width: 1100px) {
      .lg-actions .lg-prev:after {
        color: transparent;
      }
    }
    .lg-sub-html {
      max-width: 850px;
      margin: 0 auto 18.2% auto;
      background: #FFFFFF;
      color: #000000;
      border: 10px solid #000000;
      text-align: left;
      padding-left: 1em;
    }
    .lg-sub-html p {
      margin: 0;
      font-size: 1em;
    }
    .lg-sub-html .photo-title {
      margin-bottom: 0em;
      font-size: 2em;
    }
    .lg-sub-html .photo-description {
      padding: 1em 0;
      line-height: 1.5;
    }
    @media (max-height: 1250px) {
      .lg-sub-html {
        margin-bottom: 0;
      }
    }
    @media (min-width: 1250px) {
      .lg-sub-html {
        margin: 0 auto 5% auto;
      }
    }
    /* Hide toolbar becuase I don't need these right now */
    
    div.lg-toolbar.group {
      display: none;
    }
    .content {
      column-count: 1;
      column-gap: 0;
      padding: 0 2em;
      padding-bottom: 2em;
    }
    .content .tile {
      margin-top: 1em;
      display: inline-block;
      width: 100%;
      background-color: #000000;
    }
    .content .tile:hover {
      opacity: 0.9;
      transition: all 0.2s ease-in-out;
    }
    .content .tile .photo {
      width: 100%;
    }
    @media only screen and (min-width: 480px) {
      .content {
        padding-left: 2.5em;
        padding-right: 2.5em;
        column-count: 3;
        column-gap: 1em;
      }
    }
    .caption-box {
      display: none;
    }
    .photo-description {
      padding: 0.25em 0;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    <script src="http://nathanworking.com/unsplash/lightgallery-all.min.js"></script>
    
    <link href="http://nathanworking.com/unsplash/lightgallery.min.css" rel="stylesheet" />
    
    <!-- Borders all the way around, all day everyday -->
    <div id="left"></div>
    <div id="right"></div>
    <div id="top"></div>
    <div id="bottom"></div>
    
    <header>
      <h1> My Favorite Photos from Unsplash </h1>
      <span> It just so happens they’re  my photos, go figure ;) </span>
    </header>
    
    <div class="filter-box">
    
      <button type="button" id="popular" class="filter active">popular</button>
      <button type="button" id="latest" class="filter">latest</button>
      <button type="button" id="oldest" class="filter">oldest</button>
    
    </div>
    
    <div class="content" id="photoBox"></div>