fancybox
fancybox copied to clipboard
dynamically add/remove slides to existing instance
hi
wouldn't it be a nice feature being able to add or remove slides to/from an existing instance of fancybox, something like:
var instance = $.fancybox.getInstance();
var opts = {
...
};
instance.appendSlides( $(".newFancyItems"), opts );
var posArr = [0, 3, 8, 9];
instance.removeSlides( posArr );
thanks dsheyp
Hi,
When I was designing the api, I could not decide whether to implement such functionality or not. I could not figure out the use case where it would be needed, therefore it was not implemented. So, do you really need this and why? I think it would be weird when suddenly the group would change and navigation elements, thumbnails would appear or disappear.
Hi,
i agree, that for the cases where i think fancybox is mostly used for (image galleries), it doesn't seem to be a very useful feature to add/remove slides, with thumbnails disappearing or the like.
i try to use fancybox as a general "overlay library". it allows me to show contextual content on an overlay layer while keeping a more aggregated view on the first layer. fancybox does this really well for my project. where i do have some problems is, when i want to switch from one contextual overlay to another. let's say a product detail page of my shop application is opened as an overlay over the general shop page, then i want to navigate to the shopping cart, which will also be opened as an overlay page. while i would "next/prev" in the product detail context like to navigate to the next/previous product detail, it is different in the cart context. here i would like that "next" navigates to a login or address page. on the way from the product detail page to the shopping cart i would like to keep fancybox open in order to have a fluent transition without opening/closing animations. so it would be useful for my case, if i was able to reconfigure the existing instance of fancybox with new slides and options. i almost achieved the add/remove functionality by extending fancybox. in order to do so, i use fancybox with only one slide and always set the content on beforeLoad. the only problem i have with that approach are transitions between slides, because i can only start to set the new content into the slide when transition ends and after that i can animate the slide with its new content. this makes no fluent transition between slides.
i would need at least two slides and alternate between those when setting new content - may be i'll try that later.
so much about my use case, that's basically why i was asking for the feature.
thanks for the great fancybox dsheyp
Are you aware that you can open multiple instances simultaneously? From your description, I think that it would be better for you to simply open cart view/login form over the quick view overlay. Similarly to this example - http://fancyapps.com/fancybox/3/#ajax - just the other way. Or like here - https://codepen.io/fancyapps/pen/ZKqaKO - click on "Add to cart" button after opening an item.
i am aware of the possibility of stacking multiple instances. i do this for modal dialogs (e.g. showing the terms & conditions) but i'd like to avoid stacking of instances for general navigation purposes in order to not generate a situation, where users have to close two contextual layers to return to the base content layer. however, if i don't manage to have fluent transitions between slides i'll may be have to rethink my decision of having only two content layers in the application...
my second reason for trying to stick to only one layer of contextual content has to do with the implementation of my app. when a page opens it checks for the presence of a fancybox instance and if it finds one, it loads itself into that instance instead of opening a new instance. having more than one instances of fancybox opened at the same time, means i'll have to implement some logic to decide into which instance a page has to load. i didn't think too much about that approach by now, so may be it could be easily done.
thanks dsheyp
hi
the approach with two slides did work for my case, transitions are fluent now. from my side there's no need for add/remove slides functionality any more. if there's no broader requirement for this feature my request could be closed...
thanks dsheyp
Hi Jānis!
First and foremost, we absolutely love the app, thank you!
I would like to +1 on the add / remove slides dynamically.
Background: Using the ajax modal with search results and pagination. 6 cards load, then 3 each time you scroll (infinite scroll).
Use case: Fire pagination on second to the last slide and update those in the gallery, so you could eternally swipe/scroll through all the posts on our site (10,000+).
Getting the index and firing the pagination is easy, but the gallery doesn't update. I was considering destroy() or close() and open() on the last slide, but that's just sloppy.
- Jayson
Hi, Thanks for your kind words!
Adding new content is quite simple using addContent method 😄 (available from v3.3). Example:
$.fancybox.getInstance().addContent({src:'https://source.unsplash.com/EMSDtjVHdQ8/1279x853'});
But removing is not implemented and is not planned for v3. I guess it is not so much needed anyway, because max 3 items are loaded at the same time
Re-positing metafizzy/infinite-scroll#784 here
You can use fancybox's addContent with Infinite Scroll's append event. See demo https://codepen.io/desandro/pen/GdRzmL
var fancybox = $.fancybox.getInstance();
// with Infinite Scroll initialized in vanilla JS
infScroll.on( 'append', function( response, path, items ) {
fancybox.addContent( items );
});
var fancybox = $.fancybox.getInstance();
// with Infinite Scroll initialized in jQuery
$container.on( 'append.infiniteScroll', function( event, response, path, items ) {
fancybox.addContent( items );
});
Thanks Jānis & David!
- Jayson
Hi Jānis,
I was wondering if you can help? I've been trying to dynamically add slides to an existing instance of Fancybox (using InfiniteScroll) but am encountering a weird issue where duplicate content starts appearing in Fancybox after the second InfiniteScroll page is reached.
I'm using Fancybox to check when approaching the last slide in the current group, then loading the next page of InfiniteScroll content (6 items per page) and appending to the Fancybox group:
Example code, using David's suggestion (@desandro) above:
// Fancybox
$().fancybox({
selector: '[data-fancybox="images"]',
loop: false,
beforeShow: function(instance, current) {
// When we reach the last item in current Fancybox instance,
// load more images with Infinite Scroll and append them to Fancybox
if (current.index === instance.group.length - 1) {
// 1. Check if at end of group
console.log('reaching end of current fancybox group'); // MARKER
// 2. Trigger infinite scroll to load next set of images
$container.infiniteScroll('loadNextPage');
console.log('new infinite scroll page loaded'); // MARKER
// 3. Get the newly loaded set of images
$container.on( 'append.infiniteScroll', function( event, response, path, items ) {
//4. And append to the Fancybox instance
instance.addContent( items );
console.log('new scroll items added to fancybox'); // MARKER
console.log( items ); // DIAGNOSTIC
});
}
}
}); // end Fancybox
Here's what's happening in the console log (duplicate content marked with ***):
[Log] JQMIGRATE: Migrate is installed, version 1.4.1 (jquery-migrate.min.js, line 2)
[Log] [InfiniteScroll] pageIndex. current page determined to be: 1 from next link (infinite-scroll.pkgd.min.js, line 12)
[Log] [InfiniteScroll] initialized. on grid masonry-container masonry (infinite-scroll.pkgd.min.js, line 12)
[Log] reaching end of current infinite scroll group (collage, line 296)
[Log] [InfiniteScroll] request. URL: https://wordpress-153471-712046.cloudwaysapps.com/collage/page/2/ (infinite-scroll.pkgd.min.js, line 12)
[Log] new infinite scroll group loaded (collage, line 300)
[Log] [InfiniteScroll] load. Collage – Page 2 – Sally Ducrow. URL: https://wordpress-153471-712046.cloudwaysapps.com/collage/page/2/ (infinite-scroll.pkgd.min.js, line 12)
[Log] [InfiniteScroll] append. 6 items. URL: https://wordpress-153471-712046.cloudwaysapps.com/collage/page/2/ (infinite-scroll.pkgd.min.js, line 12)
[Log] new items added to fancybox (collage, line 306)
[Log] NodeList [<div class="masonry-brick grid-cell sm-grid-1-1 md-grid-1-3">, <div class="masonry-brick grid-cell sm-grid-1-1 md-grid-1-3">, <div class="masonry-brick grid-cell sm-grid-1-1 md-grid-1-3">, <div class="masonry-brick grid-cell sm-grid-1-1 md-grid-1-3">, <div class="masonry-brick grid-cell sm-grid-1-1 md-grid-1-3">, <div class="masonry-brick grid-cell sm-grid-1-1 md-grid-1-3">] (6) (collage, line 307)
(All fine up to here. Then ...)
[Log] reaching end of current infinite scroll group (collage, line 296)
[Log] [InfiniteScroll] request. URL: https://wordpress-153471-712046.cloudwaysapps.com/collage/page/3/ (infinite-scroll.pkgd.min.js, line 12)
[Log] new infinite scroll group loaded (collage, line 300)
[Log] [InfiniteScroll] load. Collage – Page 3 – Sally Ducrow. URL: https://wordpress-153471-712046.cloudwaysapps.com/collage/page/3/ (infinite-scroll.pkgd.min.js, line 12)
[Log] [InfiniteScroll] append. 6 items. URL: https://wordpress-153471-712046.cloudwaysapps.com/collage/page/3/ (infinite-scroll.pkgd.min.js, line 12)
[Log] new items added to fancybox (collage, line 306)
***[Log] NodeList [<div class="masonry-brick grid-cell sm-grid-1-1 md-grid-1-3">, <div class="masonry-brick grid-cell sm-grid-1-1 md-grid-1-3">, <div class="masonry-brick grid-cell sm-grid-1-1 md-grid-1-3">, <div class="masonry-brick grid-cell sm-grid-1-1 md-grid-1-3">, <div class="masonry-brick grid-cell sm-grid-1-1 md-grid-1-3">, <div class="masonry-brick grid-cell sm-grid-1-1 md-grid-1-3">] (6) (collage, line 307)
[Log] new items added to fancybox (collage, line 306)
***[Log] NodeList [<div class="masonry-brick grid-cell sm-grid-1-1 md-grid-1-3">, <div class="masonry-brick grid-cell sm-grid-1-1 md-grid-1-3">, <div class="masonry-brick grid-cell sm-grid-1-1 md-grid-1-3">, <div class="masonry-brick grid-cell sm-grid-1-1 md-grid-1-3">, <div class="masonry-brick grid-cell sm-grid-1-1 md-grid-1-3">, <div class="masonry-brick grid-cell sm-grid-1-1 md-grid-1-3">] (6) (collage, line 307)
[Log] reaching end of current infinite scroll group (collage, line 296)
[Log] [InfiniteScroll] request. URL: https://wordpress-153471-712046.cloudwaysapps.com/collage/page/4/ (infinite-scroll.pkgd.min.js, line 12)
[Log] new infinite scroll group loaded (collage, line 300)
[Log] [InfiniteScroll] load. Collage – Page 4 – Sally Ducrow. URL: https://wordpress-153471-712046.cloudwaysapps.com/collage/page/4/ (infinite-scroll.pkgd.min.js, line 12)
[Log] [InfiniteScroll] append. 6 items. URL: https://wordpress-153471-712046.cloudwaysapps.com/collage/page/4/ (infinite-scroll.pkgd.min.js, line 12)
[Log] new items added to fancybox (collage, line 306)
***[Log] NodeList [<div class="masonry-brick grid-cell sm-grid-1-1 md-grid-1-3">, <div class="masonry-brick grid-cell sm-grid-1-1 md-grid-1-3">, <div class="masonry-brick grid-cell sm-grid-1-1 md-grid-1-3">, <div class="masonry-brick grid-cell sm-grid-1-1 md-grid-1-3">, <div class="masonry-brick grid-cell sm-grid-1-1 md-grid-1-3">, <div class="masonry-brick grid-cell sm-grid-1-1 md-grid-1-3">] (6) (collage, line 307)
[Log] new items added to fancybox (collage, line 306)
***[Log] NodeList [<div class="masonry-brick grid-cell sm-grid-1-1 md-grid-1-3">, <div class="masonry-brick grid-cell sm-grid-1-1 md-grid-1-3">, <div class="masonry-brick grid-cell sm-grid-1-1 md-grid-1-3">, <div class="masonry-brick grid-cell sm-grid-1-1 md-grid-1-3">, <div class="masonry-brick grid-cell sm-grid-1-1 md-grid-1-3">, <div class="masonry-brick grid-cell sm-grid-1-1 md-grid-1-3">] (6) (collage, line 307)
[Log] new items added to fancybox (collage, line 306)
***[Log] NodeList [<div class="masonry-brick grid-cell sm-grid-1-1 md-grid-1-3">, <div class="masonry-brick grid-cell sm-grid-1-1 md-grid-1-3">, <div class="masonry-brick grid-cell sm-grid-1-1 md-grid-1-3">, <div class="masonry-brick grid-cell sm-grid-1-1 md-grid-1-3">, <div class="masonry-brick grid-cell sm-grid-1-1 md-grid-1-3">, <div class="masonry-brick grid-cell sm-grid-1-1 md-grid-1-3">] (6) (collage, line 307)
And here's a link to the dev site: https://wordpress-153471-712046.cloudwaysapps.com/collage/
I've been working on this for several weeks, so would really appreciate any help you could offer.
I've also tried the following code, but am met with the same issue:
// Fancybox
$().fancybox({
selector: '[data-fancybox="images"]',
loop: false,
beforeShow: function(instance, current) {
// When we reach the last item in current Fancybox instance,
// load more images with Infinite Scroll and append them to Fancybox
if (current.index === instance.group.length - 1) {
// 1. Check if at end of group
console.log('reaching end of current fancybox group'); // MARKER
// 2. Trigger infinite scroll to load next set of images
$container.infiniteScroll('loadNextPage');
console.log('new infinite scroll group loaded'); // MARKER
// 3. Get the newly loaded set of images
$container.on( 'load.infiniteScroll', function( event, response ) {
console.log('add new images from infinite scroll to fancybox group'); // MARKER
var $posts = $(response).find('.masonry-brick');
// 4. Set up an array to put them in
var newImages = [];
$($posts).each( function( index, element ){
// 5. Construct the objects
var a = {};
a['type'] = 'image';
a['src'] = $(this).find('a').attr('href');
// 6. Add them to the array
newImages.push(a);
});
// 7. And append to the Fancybox instance
console.log(newImages); // DIAGNOSTIC
instance.addContent(newImages); // add images to fancybox
});
}
}
}); // end Fancybox
Hi Jānis, thanks for all the hard work you've put into fancybox, really liking it so far and the docs are really helpful.
I've recently had to add the dynamic removal feature to an old codebase using fancybox. After adding a custom button and some experimentation, this worked:
var fancybox = null;
$('...').fancybox({
onInit: function (instance) {
fancybox = instance;
}
});
$(document).on('click', '[data-fancybox-delete]', function () {
var index = fancybox.current.index;
fancybox.next();
fancybox.group.splice(index, 1);
delete fancybox.slides[index];
// not sure if updating all these properties is necessary
fancybox.current.index = index;
fancybox.current.pos = index;
fancybox.currIndex = index;
fancybox.currPos = index;
fancybox.updateControls();
fancybox.group.forEach(function (slide, slideIndex) {
slide.index = slideIndex;
});
});
There are some additional checks specific to my project, but that's basically it. It would be great if fancybox had a removeSlide(index) method so I could get rid of this nasty code.
Here's a more complete version of the removeSlide method, inspired from the code from @lkrhl :
$('...').fancybox({
onInit: function (instance) {
// Add the removeSlide method for the current instance
instance.removeSlide = function(removeIndex) {
if (instance.isClosing || instance.isAnimating || !instance.current) {
return;
}
// No more items
if (instance.group.length <= 1) {
instance.close();
return;
}
var curIndex = instance.current.index;
var indexAdjust = -1;
// console.log('remove index', removeIndex)
// console.log('initial index', curIndex)
// Load the next slide
if (curIndex == removeIndex) {
if (instance.next() === false) {
instance.previous();
indexAdjust = 0;
}
}
curIndex = instance.current.index;
// console.log('jump index', curIndex)
var newIndex = (curIndex > 0 && curIndex >= removeIndex) ? (curIndex + indexAdjust) : curIndex;
var transitionDuration = instance.current.opts.transitionDuration;
var $thumbs = instance.Thumbs.$list.children();
var $thumb = $thumbs.eq(removeIndex);
$thumbs = $thumbs.not($thumb);
// Remove instance from group
instance.group.splice(removeIndex, 1);
// Remake the group indices
instance.group.forEach(function(slide, slideIndex) {
slide.index = slideIndex;
$thumbs.eq(slideIndex).attr('data-index', slideIndex)
// Update the data-index from the the custom delete button above the thumb
.find('.fb-remove-item').attr('data-index', slideIndex);
});
// Remove the slide
if (instance.slides[removeIndex]) {
instance.slides[removeIndex].$slide.remove();
delete instance.slides[removeIndex];
}
var oldSlides = $.extend({}, instance.slides);
instance.slides = {};
// Remake the slides indices
Object.keys(oldSlides).forEach(function(slideIndex) {
if (slideIndex > removeIndex) {
oldSlides[slideIndex].index = oldSlides[slideIndex].pos = slideIndex - 1;
instance.slides[slideIndex - 1] = oldSlides[slideIndex];
}
else {
instance.slides[slideIndex] = oldSlides[slideIndex];
}
});
oldSlides = null;
// Update instance indices
instance.currIndex = newIndex;
instance.currPos = newIndex;
instance.prevIndex = 0;
instance.prevPos = 0;
// Update controls
instance.updateControls();
// Remake the slides
instance.preload('image');
// Remove the thumb with animation
$thumb.fadeOut(transitionDuration, function() {
$thumb.remove();
});
};
}
});