#1411336

Thanks very much for your suggestion, Mike. It helped me look quite deeply into this issue using Chrome’s debugger. I want to first apologise to you for keeping things so complicated using my in-development home page, which is quite complicated, instead of creating a test page for this topic question–which is exactly what I did to debug this issue after your reply.

It turns out that the stackoverflow suggestion doesn’t work. Their suggestion is to add itemOpts.index = index; before the mfp._openClick({mfpEl:items}, jqEl, itemOpts); line as follows:

$.fn.magnificPopup = function(options) {
	_checkInstance();

	var jqEl = $(this);

	// We call some API method of first param is a string
	if (typeof options === "string" ) {

		if(options === 'open') {
			var items,
				itemOpts = _isJQ ? jqEl.data('magnificPopup') : jqEl[0].magnificPopup,
				index = parseInt(arguments[1], 10) || 0;

			if(itemOpts.items) {
				items = itemOpts.items[index];
			} else {
				items = jqEl;
				if(itemOpts.delegate) {
					items = items.find(itemOpts.delegate);
				}
				items = items.eq( index );
			}
			itemOpts.index = index;  // Added line per https://stackoverflow.com/questions/49131727/open-all-images-on-page-with-magnific-popup
			mfp._openClick({mfpEl:items}, jqEl, itemOpts);
		} else {
			if(mfp.isOpen)
				mfp[options].apply(mfp, Array.prototype.slice.call(arguments, 1));
		}

	} else {
		// clone options obj
		options = $.extend(true, {}, options);

		/*
		 * As Zepto doesn't support .data() method for objects
		 * and it works only in normal browsers
		 * we assign "options" object directly to the DOM element. FTW!
		 */
		if(_isJQ) {
			jqEl.data('magnificPopup', options);
		} else {
			jqEl[0].magnificPopup = options;
		}

		mfp.addGroup(jqEl, options);

	}
	return jqEl;
};

The problem is that that bug fix never even gets to run because it’s encapsulated within the IF condition of typeof options === “string”, as you can see above. So if you look at BOTH:

(1) us Enfold users:

links.not(options.exclude).addClass('lightbox-added')
.magnificPopup($.avia_utilities.av_popup);

where $.avia_utilities.av_popup === {type: ‘image’, mainClass: ‘avia-popup mfp-zoom-in’, tLoading: ”, tClose: ”, removalDelay: 300, …}

(2) and the Original Poster to that stackoverflow thread:

$('#content').magnificPopup({
  items: $imgs,
  type: 'image',
  gallery: {
    enabled: true
  },
});

you can see that typeof options === “object”! So it wouldn’t work for either of us (the OP coincidentally was wanting to do the exact same thing as me, to “enable magnific popup on all images on my page”). Unfortunately, the OP never responded to the reply person’s bug fix suggestion, so the thread never went further in order to highlight the failure of the suggestion for the OP.

After ruling out magnific’s code as the culprit of my problem, I focused on avia-snippet-lightbox.js and its code at the end of its function, $.fn.avia_activate_lightbox = function(variables):

return this.each(function()
{
    var container	= $(this),
        videos		= $(options.videoElements, this).not(options.exclude).addClass('mfp-iframe'), /*necessary class for the correct lightbox markup*/
        ajaxed		= ! container.is('body') && ! container.is('.ajax_slide');
        for( var i = 0; i < options.groups.length; i++ )
        {
            container.find(options.groups[i]).each(function()
            {
                var links = $(options.autolinkElements, this);

                if( ajaxed )
                {
                    links.removeClass('lightbox-added');
                }

                links.not(options.exclude).addClass('lightbox-added').magnificPopup($.avia_utilities.av_popup);
            });
        }

});

Sure enough, this is the culprit. What’s happening in this code above is that:

(1) the outer loop, controlled by the FOR loop, searches the <body> DOM for each class in the options object (.avia-slideshow, .avia-gallery, .av-horizontal-gallery, .av-instagram-pics, .portfolio-preview-page, .portfolio-preview-content, .isotope, .post-entry, .sidebar, #main, .main-menu, & .woocommerce-product-gallery); and if it finds the current options[i] in the <body> DOM, then:

(2) the inner loop, controlled by “.each(function()”, looks for every instance of that options[i] in body and adds the images within that sub-DOM instance to the links object “array”. In other words, it creates multiple lightboxes per page–and, in fact, NOT JUST a separate one for each options[i] image set (from the outer loop), BUT ALSO a separate lightbox for each instance of options[i] as well.

But I want a single lightbox for all linked images on a page, i.e. a single image set that is sent to magnific. Specifically, for me, options[7]===’.post-entry’ is not only found in outer 1/1, 1/2, etc. layout sections, in which I may put images, but also in Color Sections, in which I will definitely put images, perhaps in inner 1/1, 1/2, etc. layout sections within the Color Sections. It’s the Color Section that ends up separating out ‘.post-entry’ images from each other, creating multiple image sets sent to magnific for separate lightboxes (notice the <div class=’post-entry post-entry-type-page post-entry-31′> line):

<div class='avia-section av-lib3uyi7-57ce06e0452ac92eb7d4393a8384e180 main_color avia-section-default avia-no-border-styling  avia-builder-el-62  el_after_av_section  el_before_av_section  mainPageBodyThreeCols avia-bg-style-scroll container_wrap fullsize'  >
    <div class='container av-section-cont-open' >
        <div class='template-page content  av-content-full alpha units'>
            <div class='post-entry post-entry-type-page post-entry-31'>
                <div class='entry-content-wrapper clearfix'>
                    <div  class='flex_column av-i3z0f-243165cc077a80e50bbee8f020d21535 av_one_third  avia-builder-el-63  el_before_av_one_third  avia-builder-el-first  first flex_column_div  '     >
                        <div  class='avia-image-container av-lib47uf4-9660e94fab46a96b36ab619c8b679a09 av-styling- avia-align-center  avia-builder-el-64  el_before_av_textblock  avia-builder-el-first  av-group-lightbox'   itemprop="image" itemscope="itemscope" itemtype="https://schema.org/ImageObject" >
                            <div class="avia-image-container-inner">
                                <div class="avia-image-overlay-wrap">
                                    <a href="...dentures.jpg" class='avia_image' >
                                        <img decoding="async" class='wp-image-699 avia-img-lazy-loading-not-699 avia_image ' src="...dentures-300x264.jpg" alt='...'  height="264" width="300"  itemprop="thumbnailUrl" srcset="..." sizes="(max-width: 300px) 100vw, 300px" />
                                    </a>
                                </div>
                            </div>
                        </div>...

In other words, each .avia-section (Color Section) has its own class=’post-entry post-entry-type-page post-entry-31′, so the images under that DOM are collected as a separate image set for a lightbox.

So I ended up just bypassing all of it, and replaced the code in avia-snippet-lightbox.js with my own child_avia-snippet-lightbox.js:

return this.each(function()
{
    //Find all linked images
    var myLinks = $(options.autolinkElements, this);
    
    //Note: ".not(options.exclude)" is left out of this "myLinks.not(options.exclude).addClass(..." on purpose to impose the policy: if you want to exclude an image from the all-images set in the lightbox, just don't make it a link. Linked images excluded from the lightbox means if the user clicks on that linked image, it will follow that link, which is to open it's full size image, but without the lightbox's closing mechanism. Then the only way for the user to go back to the page is to click the Back button--which is bad UX.

	myLinks.addClass('lightbox-added').magnificPopup($.avia_utilities.av_popup);
});

And adding this to my child functions.php file:

add_action('wp_enqueue_scripts', 'magnific_script_fix', 100);
function magnific_script_fix()
{
    wp_dequeue_script('avia-lightbox-activation');
    wp_enqueue_script('child_avia-lightbox-activation', get_stylesheet_directory_uri().'/child_avia-snippet-lightbox.js', array('jquery'));
}

Also, as you can see, I’ve left out “.not(options.exclude)” from myLinks.not(options.exclude).addClass(‘lightbox-added’).magnificPopup($.avia_utilities.av_popup) for the following reason: If I put it in, then, yes, the images with those exclusion classes will be excluded from the lightbox. But they are still linked images: so if a user clicks on one of them, it will follow that link, which is to open it’s full size image, but without the lightbox’s closing mechanism. So the only way for the user to go back to the page is to click the Back button–which is bad UX.

FYI: I attempted to figure out a way to add each of those excluded images in its own individual one-image lightbox, but I just couldn’t even figure out how Enfold does the not(options.exclude), as a starting point (going step by step in the debugger to see how it’s doing it was a bewildering experience), so I just gave up. So I just gave myself the policy: if you want to exclude an image from the all-images set in the lightbox, just don’t make it a link. Lol. Yes, I could have left the .not(options.exclude) in there and just not used it per my policy, but I wanted to make sure the UX stays correct by preventing me (or anyone else maintaining the site) from having any effect to forgetting the policy and adding e.g. “noLightbox” to an image’s Custom CSS Class field, expecting it to be excluded from the lightbox, but still keeping the image’s link active. No: if I (or they) go into the code, they’ll see there is no .not(options.exclude) at all, and read the comment in the code, to see why their image is not getting excluded from the lightbox.

So, anyway, that’s my solution to my particular problem. I appreciate your help, Mike. Unless you have some solution code for me to include those excluded images in their own individual one-image lightboxes (which would be helpful to just round up this solution, in case others want to use it), you may close this thread.

Thanks very much,
Gary

  • This reply was modified 2 years, 1 month ago by garysch37.