1

I'm trying to following this but it's 6 years old. Have things change 'cause my js doesn't seem to get triggered when the URL contains #slide_ ?

Linking to a certain bootstrap carousel slide from another page

My code on page2:

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>test</title>
    
    <!-- Core theme CSS (includes Bootstrap)-->
        <link href="css/styles.css?v20221223=1" rel="stylesheet" />
</head>

<body>

         
<!-- Carousel Wrapper-->

        
<div id="myCarousel" class="carousel carousel-dark slide" data-bs-interval="false" data-ride="carousel" data-pause="hover">
  
  <div class="carousel-inner">
    <div class="carousel-item active">
      <img src="https://www.w3schools.com/bootstrap/chicago.jpg" alt="..." class="d-block img-fluid">
    </div>
    <div class="carousel-item">
      <img src="https://www.w3schools.com/bootstrap/la.jpg" alt="..." class="d-block img-fluid">
    </div>
    <div class="carousel-item">
      <img src="https://www.w3schools.com/bootstrap/ny.jpg" alt="..." class="d-block img-fluid">
    </div>
   </div>
</div>
</div>
<!-- END Carousel Wrapper-->

<!-- Bootstrap core JS - versionas as of Dec 2022-->
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script>
    
    <!-- JS for loading a particular slide from another page -->
        <script>
            
            function qs(key) {
                key = key.replace(/[*+?^$.\[\]{}()|\\\/]/g, "\\$&"); 
                var match = location.search.match(new RegExp("[?&]" + key + "=([^&]+)(&|$)"));
                var slide = match && decodeURIComponent(match[1].replace(/\+/g, " "));
                if (Math.floor(slide) == slide && $.isNumeric(slide))
                    return parseInt(slide);
                else
                    return 0; 
                }
            //why this isn't working???
            $('#myCarousel').carousel(qs('slide'));
        </script>
    
</body>
</html>

And the link on page 1

<a href="page1.html#slide=2">slide 2</a>

I'm stuck...

BeachNut
  • 49
  • 5
  • `$('#myCarousel').carousel(qs('slide'));` This is jQuery and you don't have it included in your ``, at least not in your example code. [Here's how to include it.](https://releases.jquery.com/) – Cooleronie Dec 26 '22 at 23:59
  • Thanks. I added it within and confirmed jqeury loads, but the link to a specific slide still doesn't work. It always shows the first slide. (the third slide is in color).. – BeachNut Dec 27 '22 at 01:03

1 Answers1

2

In your example you added your JS in page 2, but your link redirects the user to page 1. Make sure you get your URLs correct, so based on your example it should be <a href="page2.html#slide=2">slide 2</a> on page 1.

Furthermore, the function function qs(key) {..} extracts the hash on ? not on #.

Don't worry though, what you want is simple, so I wrote a quick example for you.

Explaining the snippet below

You can achieve your desired functionality without needing jQuery.

In my example I created a function called getSlideNumber(). This first checks if the location hash exists, then we get it's value and split it on the = to get to the slide number. After that, we convert value into an integer using parseInt(). If that fails, the parseInt() function returns NaN so we also make sure our slide number is in fact an integer before we return it using Number.isInteger(). This way we protect ourselves against any malicious hashes.

We then call that function to get our slide number and use Bootstrap's method getOrCreateInstance to get the carousal instance that's on our page and make it cycle to the slide number using to().

And that's all it is!

Usage

We can't extract a hash in a snippet, so I don't call the function getSlideNumber() in my example. Therefore, make sure you delete the line const slideNumber = 2 and remove the // in front of the line above it when you want to use this code for your own project. Like so:

  const slideNumber = getSlideNumber(); 
  const element = document.querySelector('#carouselExample')
  const caroursal = bootstrap.Carousel.getOrCreateInstance(element).to(slideNumber);

Also, note that the first slide of a carousal has an index of 0, similar to an array.

Lastly, you can edit the carousal HTML as you please, I used the basic example from the documentation.

The snippet

window.onload = function(){

  function getSlideNumber() {
    if(location.hash && location.hash.length) {
      const value = location.hash.substr(1).split('=')[1];
      const int = parseInt(value);

      if (Number.isInteger(int)) {
        return int;
      } else {
        return 0;
      }      
    }
    return 0;
  }
   
  //const slideNumber = getSlideNumber();
  const slideNumber = 2; // Uncomment the line above and remove this line, it's only for demonstration purposes.
  const element = document.querySelector('#carouselExample')
  const caroursal = bootstrap.Carousel.getOrCreateInstance(element).to(slideNumber);

};
<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">
<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>

<div class="container">
  <div id="carouselExample" class="carousel slide">
    <div class="carousel-inner">
      <div class="carousel-item active">
        <img src="https://www.w3schools.com/bootstrap/chicago.jpg" class="d-block w-100" alt="...">
      </div>
      <div class="carousel-item">
        <img src="https://www.w3schools.com/bootstrap/la.jpg" class="d-block w-100" alt="...">
      </div>
      <div class="carousel-item">
        <img src="https://www.w3schools.com/bootstrap/ny.jpg" class="d-block w-100" alt="...">
      </div>
    </div>
    <button class="carousel-control-prev" type="button" data-bs-target="#carouselExample" data-bs-slide="prev">
      <span class="carousel-control-prev-icon" aria-hidden="true"></span>
      <span class="visually-hidden">Previous</span>
    </button>
    <button class="carousel-control-next" type="button" data-bs-target="#carouselExample" data-bs-slide="next">
      <span class="carousel-control-next-icon" aria-hidden="true"></span>
      <span class="visually-hidden">Next</span>
    </button>
  </div>
</div>

Solution with jQuery

But wait! What if you can't live without jQuery? Worry no more, use this instead:

$(document).ready(function() {

  function getSlideNumber() {
    if(location.hash && location.hash.length) {
      const value = location.hash.substr(1).split('=')[1];
      const int = parseInt(value);

      if (Number.isInteger(int)) {
        return int;
      } else {
        return 0;
      }      
    }
    return 0;
  }

  const slideNumber = getSlideNumber();
  $("#carouselExample").carousel(slideNumber);

});

Multiple carousals on one page

Assuming all carousals should be set to slideNumber we can target all carousals on the page with the class .carousal and then loop through them, like so:

const slideNumber = getSlideNumber(); 
const carousels = document.querySelectorAll('.carousel');
carousels.forEach(carousel => {
  bootstrap.Carousel.getOrCreateInstance(carousel).to(slideNumber);
});

This works fine, but all carousals will cycle to the same slideNumber. If say your hash contains multiple values like page2.html#slide=2&slide=3 and you want the second carousal to cycle to slide 3 you would have to make getSlideNumber() return an object with all the slide numbers, then get the id of carousal inside the forEach loop and apply the corresponding slide number you have in the previous mentioned object in the to() method on the carousal id. That would be just one possible way of doing it.

Hope that helps. Good luck!

Cooleronie
  • 1,225
  • 1
  • 9
  • 9
  • If there are 2 carousels on page 2, called 'carouselExample1' and 'carouselExample2' what would I need to add to the non-jquery solution so that both carousels would open on say slide2? – BeachNut Dec 28 '22 at 09:44
  • @BeachNut You're welcome! Please "Accept" the answer if you haven't already! For your question, I made an edit in my post on the bottom. That should satisfy your needs. Good luck! – Cooleronie Dec 28 '22 at 11:42
  • Thanks but I couldn't get the multiple carousels code working - is there a typo/something missing in the 3rd line? – BeachNut Dec 29 '22 at 01:45
  • @BeachNut [Here's that code working in a JSFiddle](https://jsfiddle.net/etx2y5zp/). Do you get an error in the console? Make sure your carousels have the class `carousel`. If you're still stuck you should create a new question with your code. – Cooleronie Dec 29 '22 at 11:57
  • Great - working now - not sure what I was doing wrong earlier - thanks for the fiddle. – BeachNut Dec 29 '22 at 13:15
  • I have an owl based carousel on a separate page. Is it possible to link to a specific slide on that type of carousel from another page, using the same concept? – BeachNut Jan 02 '23 at 14:07
  • @BeachNut Assuming you use the latest version of `owl.carousel.js`: it has a build-in feature do exactly that. See their demo: https://owlcarousel2.github.io/OwlCarousel2/demos/urlhashnav.html#five . I included the hash `#five` in the URL, so the demo carousel will cycle to slide 5. Follow the instructions on that page, and/or look at the source code to see how it works. No need for any of the code in my answer. If you struggle with it, create a new SO question with your attempt. You can then put the link of the new question in a comment here and I'll see it. Good luck. – Cooleronie Jan 02 '23 at 15:12
  • I've been trying to get this working all week. Still no luck, Link to SO question. https://stackoverflow.com/questions/75027315/carousel-linking-to-slide-from-another-page-why-url-hash-navigation-not-work – BeachNut Jan 06 '23 at 05:40