understrap/understrap

Mobile menu won't close when using Lightbox for Bootstrap 5 node module

garryknapper opened this issue · 14 comments

Hi, I have just installed the Lightbox for Bootstrap 5 node module on a site I'm currently building and it's had an effect on the functionality of the mobile menu. The node module is this one: https://trvswgnr.github.io/bs5-lightbox/

The menu will slide down when clicked but won't slide back up again. The Javascript won't remove the 'show' class on the second click. I'm not sure if the issue is the Understrap theme, Bootstrap, the node module or a combination of these. The lightbox works perfectly fine!

Specifically, it is the 'Lightbox.initialize' which is causing the issue from the following line of code, as per the node module docs:

document.querySelectorAll('[data-toggle="lightbox"]').forEach(el => el.addEventListener('click', Lightbox.initialize));

I'm using Understrap parent theme version 1.2.2 and child theme version 1.1.0. I was wondering if you've had this issue reported before and whether you might know what's causing it. It looks to me to be some sort of script conflict between the mobile menu behaviour and the node module. I believe the node module is using Bootstrap's modal and collapse features.

I've also reported the issue to the node module developer in the hope that someone can shed some light on this.

Thanks in advance for any help you may be able to provide.

Have you checked the console for JS errors that might help to narrow down the issue? Are you using the collapse menu or the offcanvas menu?

I'm not sure if the issue is the Understrap theme, Bootstrap, the node module or a combination of these.

Have you checked whether this also happens if you use the Understrap parent theme only? Have you checked whether this also happens with using Bootstrap only?

I don't think that this has been reported before.

I've checked the console and there are no JS errors. I'm using the collapse menu.

I've set up a site with the Understrap parent theme and the same issue occurs. However, I've discovered that if I change the Bootstrap version from 5 to 4 in the theme settings, everything works normally. The node module is specifically for Bootstrap 5.

I haven't yet tested it in a static Bootstrap site so that is my next task.

Thank you! That helps. I'll have a look at it.

I tested the lightbox plugin on a static Bootstrap site and it works. The issue seems to be related to Understrap.

<!doctype html>
<html lang="en">
	
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<meta name="description" content="">
	<title>Navbar Template · Bootstrap v5.3</title>
	<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">
</head>

<body>

	<main>
		<nav class="navbar navbar-dark bg-dark" aria-label="Dark offcanvas navbar">
			<div class="container-fluid">
				<a class="navbar-brand" href="#">Dark offcanvas navbar</a>
				<button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasNavbarDark" aria-controls="offcanvasNavbarDark">
					<span class="navbar-toggler-icon"></span>
				</button>
				<div class="offcanvas offcanvas-end text-bg-dark" tabindex="-1" id="offcanvasNavbarDark" aria-labelledby="offcanvasNavbarDarkLabel">
					<div class="offcanvas-header">
						<h5 class="offcanvas-title" id="offcanvasNavbarDarkLabel">Offcanvas</h5>
						<button type="button" class="btn-close btn-close-white" data-bs-dismiss="offcanvas" aria-label="Close"></button>
					</div>
					<div class="offcanvas-body">
						<ul class="navbar-nav justify-content-end flex-grow-1 pe-3">
							<li class="nav-item"><a class="nav-link active" aria-current="page" href="#">Home</a></li>
							<li class="nav-item"><a class="nav-link" href="#">Link</a></li>
							<li class="nav-item dropdown"><a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">Dropdown</a>
								<ul class="dropdown-menu">
									<li><a class="dropdown-item" href="#">Action</a></li>
									<li><a class="dropdown-item" href="#">Another action</a></li>
									<li><hr class="dropdown-divider"></li>
									<li><a class="dropdown-item" href="#">Something else here</a></li>
								</ul>
							</li>
						</ul>
						<form class="d-flex mt-3" role="search">
							<input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
							<button class="btn btn-outline-success" type="submit">Search</button>
						</form>
					</div>
				</div>
			</div>
		</nav>

		<nav class="navbar bg-light" aria-label="Light collapse navbar">
			<div class="container-fluid">
				<a class="navbar-brand" href="#">Light collapse navbar</a>
				<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
					<span class="navbar-toggler-icon"></span>
				</button>
				<div class="collapse navbar-collapse" id="navbarSupportedContent">
					<ul class="navbar-nav me-auto mb-2 mb-lg-0">
						<li class="nav-item">
							<a class="nav-link active" aria-current="page" href="#">Home</a>
						</li>
						<li class="nav-item">
							<a class="nav-link" href="#">Link</a>
						</li>
						<li class="nav-item dropdown">
							<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
							Dropdown
							</a>
							<ul class="dropdown-menu">
								<li><a class="dropdown-item" href="#">Action</a></li>
								<li><a class="dropdown-item" href="#">Another action</a></li>
								<li><hr class="dropdown-divider"></li>
								<li><a class="dropdown-item" href="#">Something else here</a></li>
							</ul>
						</li>
						<li class="nav-item">
							<a class="nav-link disabled">Disabled</a>
						</li>
					</ul>
					<form class="d-flex" role="search">
						<input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
						<button class="btn btn-outline-success" type="submit">Search</button>
					</form>
				</div>
			</div>
		</nav>

		<div class="container my-5">
			<div class="bg-light p-5 rounded">
				<div class="col-sm-8 py-5 mx-auto">
					<h1 class="display-5 fw-normal">Lightbox example</h1>
					<p class="fs-5">This example shows how menus work the lightbox plugin.</p>
				</div>
			</div>
		</div>
		<div class="container mb-5">
			<div class="col-sm-8 mx-auto">
				<a href="https://unsplash.it/1200/768.jpg?image=251" data-toggle="lightbox">
					<img src="https://unsplash.it/600.jpg?image=251">
				</a>
			</div>
		</div>
	</main>

	<footer class="bg-dark">
		<div class="col-sm-8 mx-auto p-3">
			<p class="m-0 p-0 text-light">Testing</p>
		</div>
	</footer>

	<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js" integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN" crossorigin="anonymous"></script>
	<script src="https://cdn.jsdelivr.net/npm/bs5-lightbox@1.8.3/dist/index.bundle.min.js"></script>

</body>

</html>

The menu works when using Bootstrap 4 because the lightbox plugin stops to work.

Here's a quick fix: in rollup.config.js rename the bundle generated by Understrap from "understrap" to "bootstrap" and add this to your functions.php:

add_action( 'wp_enqueue_scripts', 'slug_load_lightbox_for_bs5_plugin' );
function slug_load_lightbox_for_bs5_plugin() {
    wp_enqueue_script(
        'bs5-lightbox',
        'https://cdn.jsdelivr.net/npm/bs5-lightbox@1.8.3/dist/index.bundle.min.js', // <------ replace if necessary 
        'understrap-scripts', // <------- replace if necessary
        null, // <------- replace if necessary
        true
    );
}

Alternative, assuming you installed the lightbox plugin via npm.

In rollup.config.js:

input: [
	path.resolve( __dirname, `../js/${ bsSrcFile }` ),
+	path.resolve( __dirname, `../js/bs5-lightbox.js` ),
	path.resolve( __dirname, '../js/skip-link-focus-fix.js' ),
	path.resolve( __dirname, '../js/custom-javascript.js' ),
],

In package.json:

    "copy-assets": "node src/build/copy-assets.js",
+   "copy-assets-lightbox": "node src/build/copy-assets-lightbox.js",
    "dist": "npm-run-all --parallel css js css-bs4 js-bs4",

New file src/build/copy-assets-lightbox.js:

const fs = require('fs');
fs.readFile( './node_modules/bs5-lightbox/src/index.js', 'utf-8', function(err, data) {
    if (err) console.log(err);
    fs.writeFile('./src/js/bs5-lightbox.js', data.replace("from 'bootstrap'", "from './bootstrap'"), 'utf-8', function(err, data) {
        if (err) console.log(err);
        console.log('Done!');
    })
})

The problem originates from line 1 in bs5-lightbox/src/index.js import { Modal, Carousel } from 'bootstrap'; which clashes with

export { default as Carousel } from 'bootstrap/js/src/carousel';
export { default as Modal } from 'bootstrap/js/src/modal';

from src/js/bootstrap.js.

The proposed solution above reads the lightbox source file, replaces the conflicting import statement with import { Modal, Carousel } from './bootstrap'; (i.e. the lightbox plugin now imports from Understrap's bootstrap.js; note that Understrap or your child theme must import the Modal and Carousel component for this to work) and saves the file in the theme's src folder. Rollup then uses this file to create the bundle.

Please let us know whether one of these solutions suits you.

Thank you so much for these solutions, I have used the second one to adjust the lightbox plugin to import from Understrap's bootstrap and it's all working well now. I also uninstalled the node module so that it wasn't pulling in the scripts twice!

Thanks again for your help.

Thank you so much for these solutions, I have used the second one to adjust the lightbox plugin to import from Understrap's bootstrap and it's all working well now.

Perfect!

I also uninstalled the node module so that it wasn't pulling in the scripts twice!

Which node module and what was pulled twice? Are you talking about the bs5-lightbox node module? You'll need that for the copy-assets-lightbox task to work.

Yes I ran the copy-assets-lightbox task so that the bs5-lightbox node module was copied into the src/js folder. When I then tested the site, the mobile navigation was still not working. Upon further investigation, I noticed the lightbox code was duplicated in the child-theme.js file. That's when I uninstalled the bs5-lightbox node module so that it was removed from my package.json file. The lightbox code was then no longer duplicated and both the navigation and lightbox were working as they should.

There must be something else going on here. I tested #2085 (comment) on my local install and the lightbox script was not rolled up twice! Is there a reference to the lightbox node module (not the file copied to the theme src folder) in your rollup.config.js?

I discovered it was due to the 'import Lightbox from 'bs5-lightbox' line of code in my custom-javascript.js. I've removed this and reinstalled the node module and it's all working properly again. When this line of code was added, the lightbox was coming up twice for each image so this line is no longer needed.

Is the issue then resolved and can be closed?

Yes this issue can be closed now. Thank you for your help.