3

By default it looks like fancybox takes the items in the gallery in the order they are added in the HTML.

Is there another option that by adding an optional data- attribute, it will reorder them when they are opened, but when they are displayed in the page (not in the gallery popup), they will remain the same?

The code looks like this:

<a class="fancybox" rel="gallery1" href="http://farm2.staticflickr.com/1617/24108587812_6c9825d0da_b.jpg" title="Morning Godafoss (Brads5)">
    <img src="http://farm2.staticflickr.com/1617/24108587812_6c9825d0da_m.jpg" alt="" />
</a>
<a class="fancybox" rel="gallery1" href="http://farm4.staticflickr.com/3691/10185053775_701272da37_b.jpg" title="Vertical - Special Edition! (cedarsphoto)">
    <img src="http://farm4.staticflickr.com/3691/10185053775_701272da37_m.jpg" alt="" />
</a>
<a class="fancybox" rel="gallery1" href="http://farm1.staticflickr.com/574/22407305427_69cc6e845f_b.jpg" title="Racing against the Protons (tom.leuzi)">
    <img src="http://farm1.staticflickr.com/574/22407305427_69cc6e845f_m.jpg" alt="" />
</a>
<a class="fancybox" rel="gallery1" href="http://farm1.staticflickr.com/291/18653638823_a86b58523c_b.jpg" title="Lupines (Kiddi Einars)">
    <img src="http://farm1.staticflickr.com/291/18653638823_a86b58523c_m.jpg" alt="" />
</a>

And the JS:

$(".fancybox").fancybox();

JSFiddle

How to keep the same HTML code, but to open them in the popup in the following order: 3, 1, 4, 2 (for example)?

I would like something like this:

<a class="fancybox" rel="gallery1" data-fancybox-order="3" ... >
<a class="fancybox" rel="gallery1" data-fancybox-order="1" ... >
<a class="fancybox" rel="gallery1" data-fancybox-order="4" ... >
<a class="fancybox" rel="gallery1" data-fancybox-order="2" ... >

Then if we open in the popup the second image (data-fancybox-order="1"), there will be no previous button. But if we click next, it will open the forth image. Then, after clicking next again, it will open the first image and then the third image (data-fancybox-order="4"). In that moment, the next button will disappear.

What's the cleanest way to do this?

Ionică Bizău
  • 109,027
  • 88
  • 289
  • 474

1 Answers1

1

Unfortunately fancybox doesn't offer that option. You may need to create and launch the fancybox gallery programmatically in the order you want.

First, you need to add a data attribute to each html element to set the order in which they will be displayed in the fancybox gallery, something like:

<a class="fancybox" href="image03.jpg" title="title 3" data-order="3">...
<a class="fancybox" href="image01.jpg" title="title 1" data-order="1">...
<a class="fancybox" href="image04.jpg" title="title 4" data-order="4">...
<a class="fancybox" href="image02.jpg" title="title 2" data-order="2">...

Note that, since the gallery will be built programmatically, the rel attribute becomes irrelevant.

Second, instead of using the regular fancybox initialization script $(".fancybox").fancybox() you need to bind a click event to create and launch the fancybox gallery:

$(".fancybox").click(function(){
    // build fancybox gallery here
    return false; // prevent event default and propagation
});

Once we click any of the html thumbnails, we will proceed as follow:

  • get the index of the clicked image (data-order attribute)
  • gather all html elements with class fancybox (querySelectorAll())
  • initialize the fancybox gallery of elements array
  • iterate through the html elements and push them into the fancybox gallery array
  • sort the fancybox array

Since the fancybox gallery object will be an array of objects, we need a function to sort such array by a selected property. We will borrow that function from this answer :

// sort array of objects by a property
var sortObjectsBy = function(field, reverse, primer) {
  var key = primer ? function(x) {
    return primer(x[field])
  } : function(x) {
    return x[field]
  };
  reverse = !reverse ? 1 : -1;
  return function(a, b) {
    return a = key(a),
      b = key(b),
      reverse * ((a > b) - (b > a));
  }
}

Then we will put all the pieces together after the click event:

$(".fancybox").on("click", function() {
  // get the index of the clicked image
  var thisIndex = this.dataset.order - 1;
  // gather all html elements
  var elements = document.querySelectorAll(".fancybox");
  // initialize fancybox gallery array
  var fancyElements = [];
  // push the html elements into fancybox gallery
  for (var i = 0, elLength = elements.length; i < elLength; i++) {
    fancyElements.push({
      href: elements[i].href,
      title: elements[i].title + " - " + elements[i].dataset.order,
      order: elements[i].dataset.order
    });
  }
  // sort the fancybox array of objects by the "order" property
  fancyElements.sort(sortObjectsBy("order", false, function(a) {
    return a;
  }));
  // launch fancybox programmatically
  $.fancybox(fancyElements, {
    helpers: {
      title: {
        type: "inside"
      }
    },
    // force index
    index: thisIndex // start gallery from the clicked element
  })
  return false;
});

Please note you can add whatever fancybox options to the script as I did with the title type. Please also notice that I added the order to the title for illustration purposes so you can verify that the gallery is being displayed in the order set by the data-order attribute.

BTW, the order property is not required by fancybox but we used it to sort the array only.

See JSFIDDLE

Community
  • 1
  • 1
JFK
  • 40,963
  • 31
  • 133
  • 306
  • 1
    If anyone is interested, here is updated code to work with fancyBox v3 - https://codepen.io/anon/pen/rGLmzX?editors=1010 – Janis Sep 21 '17 at 05:52