1

How to expand nested Bootstrap 4 Collapse from URL?

I have a nested Bootstrap 4 Collapse. The outer Collapse consists of Days, whereas the inner Collapse consists of Events, that take place on that particular day. It looks approximately like this...

<!-- HEADER DAY 1-->
<div data-toggle="collapse" data-target="#day-unixtimestamp1" role="button" aria-expanded="false" aria-controls="#day-unixtimestamp1" >
DAY ONE (e.g. October 25th, 2021)  
</div>
  
<!-- BODY DAY 1 --> 
<div class="body collapse" id="day-unixtimestamp1">


    <!-- HEADER EVENT 1-->
    <div data-toggle="collapse" data-target="#event-unixtimestamp1-event1" role="button" aria-expanded="false" aria-controls="#event-unixtimestamp1-event1" >
    NAME EVENT 1  
    </div>
      
    <!-- BODY EVENT 1 --> 
    <div class="body collapse" id="event-unixtimestamp1-event1">
    ...some content
    </div>

    <!-- HEADER EVENT 2-->
    <div data-toggle="collapse" data-target="#event-unixtimestamp1-event2" role="button" aria-expanded="false" aria-controls="#event-unixtimestamp1-event2" >
    NAME EVENT 2  
    </div>
      
    <!-- BODY EVENT 2 --> 
    <div class="body collapse" id="event-unixtimestamp1-event2">
    ...some content
    </div>


</div>

I use WordPress and custom code to load the days and events from the database and loop over them. That works fine so far.

After a user creates a new event through submitting a form, he should be redirected to the page with the nested Bootstrap 4 Collapse and both sould be open: the Collapse of the new Event and the Collapse of associated Day.

I can expand the Event with the following URL: https://website.de/nested-collapse-page/#event-unixtimestamp1-event1

and the code below...

<script>
jQuery($ => {
  
  if (window.location.hash) {   
    
    var hash = window.location.hash;    
       
    $(hash).collapse('show');
    
    $('html, body').animate({
    scrollTop: $(hash).offset().top - 180
    }, 500 );
    
  }
});
</script>

But I am a bit clueless how I open the acssociated Day too... I'm very gratefull for hints : )

2 Answers2

1

What you're testing :

Here, you just the content after window.location.href

Scenario: if your content is

google.com/welcome#chapter4

you'll get

#chapter4

What i'll do :

Based on this subject about getting querystring with pure JS (no jQuery), you can define this function :

function getParameterByName(name, url = window.location.href) {
    name = name.replace(/[\[\]]/g, '\\$&');
    var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
        results = regex.exec(url);
    if (!results) return null;
    if (!results[2]) return '';
    return decodeURIComponent(results[2].replace(/\+/g, ' '));
}

Then use is to get data in your URL like so :

getParameterByName('day')

In your case :

Adding ?day=currentDay to your URL will proving your local JS an information about the day. In short, trigger the bootstrap collapse event based on the content of this query string.

Full Example :

// Set the function to get query strings
function getParameterByName(name, url = window.location.href) {
    name = name.replace(/[\[\]]/g, '\\$&');
    var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
        results = regex.exec(url);
    if (!results) return null;
    if (!results[2]) return '';
    return decodeURIComponent(results[2].replace(/\+/g, ' '));
}

// Store day spevified in url in a var
var whichDayInURL = getParameterByName('day');

// Test content and trigger related collapse menu
switch (whichDayInURL) {

    case 'dayOfEvent1':
        $(event-unixtimestamp1-event1).collapse('show');
        break;
    case 'dayOfEvent2':
        $(event-unixtimestamp1-event2).collapse('show');
        break;
    case 'dayOfEvent3':
        $(event-unixtimestamp1-event3).collapse('show');
        break;

}
z4nzi
  • 71
  • 1
  • 2
  • 7
  • 1
    Many thanks for your answer. It guided me in the right direction. I have a question: What is the difference between "window.location.href" and "window.location.hash". I'm only familiar with "window.location.hash". I have never seen "window.location.href" before. – Lara Kreisz Oct 28 '21 at 21:20
  • 1
    Glad it helped and thanks for the shoutout in your answer ;) https://developer.mozilla.org/fr/docs/Web/API/Window/location might be helpful but in short, window.location returns an actual "Location" object. So window.location.href accesses the property href of the Location object. href stands for Hypertext REFerence, so this is the actual URL of you current page. window.location.hash accesses the hash property of this Location object with the hash ('#chapter2' and not just 'chapter2'). What might help aswell is playing with the JS Console in your browser's devtool – z4nzi Oct 29 '21 at 13:27
  • 1
    You're most welcome : ) . Many thanks for the explanation too. Now I understand the difference. Due to your explanation I have noticed a little things in your answer. I think on line 2 you accidently used `window.location.href` instead of `window.location.hash`. Because you echo "#chapter4". Also I would modify `var whichDayInURL = getParameterByName('day');` to `var whichDayInURL = "#" + getParameterByName('day');`, because `$(event-unixtimestamp1-event1).collapse('show');` needs a "event-unixtimestamp1-event1", that starts with a #, like "#event-1323423424-23121" [-> div id] : ) – Lara Kreisz Oct 31 '21 at 10:00
1

Many thanks to "z4nzi". He guided me in the right direction. I switched from #hash to URL parameter.

This is the final solution....

I use this URL with the parameters "tday" and "tevent":

https://website.de/nested-collapse-page/?tday=tag-1635379200&tevent=event-55700-1635379200

This is the my nested Bootstrap 4 Collapse (HTML). Make sure, that you load Bootstrap 4 on your page... :


    <!-- HEADER DAY 1-->
    <div data-toggle="collapse" data-target="#day-unixtimestamp1" role="button" aria-expanded="false" aria-controls="#day-unixtimestamp1" >
    DAY ONE (e.g. October 25th, 2021)  
    </div>
      
    <!-- BODY DAY 1 --> 
    <div class="body collapse" id="day-unixtimestamp1">
    
    
        <!-- HEADER EVENT 1-->
        <div data-toggle="collapse" data-target="#event-unixtimestamp1-event1" role="button" aria-expanded="false" aria-controls="#event-unixtimestamp1-event1" >
        NAME EVENT 1  
        </div>
          
        <!-- BODY EVENT 1 --> 
        <div class="body collapse" id="event-unixtimestamp1-event1">
        ...some content
        </div>
    
        <!-- HEADER EVENT 2-->
        <div data-toggle="collapse" data-target="#event-unixtimestamp1-event2" role="button" aria-expanded="false" aria-controls="#event-unixtimestamp1-event2" >
        NAME EVENT 2  
        </div>
          
        <!-- BODY EVENT 2 --> 
        <div class="body collapse" id="event-unixtimestamp1-event2">
        ...some content
        </div>
    
    
    </div>
    
    
    <!-- HEADER DAY 2-->
    <div data-toggle="collapse" data-target="#day-unixtimestamp2" role="button" aria-expanded="false" aria-controls="#day-unixtimestamp2" >
    DAY TWO (e.g. October 26th, 2021)  
    </div>
      
    <!-- BODY DAY 2 --> 
    <div class="body collapse" id="day-unixtimestamp2">
    
    
        <!-- HEADER EVENT 3-->
        <div data-toggle="collapse" data-target="#event-unixtimestamp2-event3" role="button" aria-expanded="false" aria-controls="#event-unixtimestamp2-event3" >
        NAME EVENT 3  
        </div>
          
        <!-- BODY EVENT 3 --> 
        <div class="body collapse" id="event-unixtimestamp2-event3">
        ...some content
        </div>
    
        <!-- HEADER EVENT 4-->
        <div data-toggle="collapse" data-target="#event-unixtimestamp2-event4" role="button" aria-expanded="false" aria-controls="#event-unixtimestamp2-event4" >
        NAME EVENT 4  
        </div>
          
        <!-- BODY EVENT 4 --> 
        <div class="body collapse" id="event-unixtimestamp2-event4">
        ...some content
        </div>
    
    
    </div>

and this is the corresponding jQuery to retriever the URL params

Source of the code: https://stackoverflow.com/a/3855394/17250476

// jQuery plugin, that retrievers all params from the URL
// Source: https://stackoverflow.com/a/3855394/17250476
<script>
(function($) {
    $.QueryString = (function(paramsArray) {
        let params = {};

        for (let i = 0; i < paramsArray.length; ++i)
        {
            let param = paramsArray[i]
                .split('=', 2);
            
            if (param.length !== 2)
                continue;
            
            params[param[0]] = decodeURIComponent(param[1].replace(/\+/g, " "));
        }
            
        return params;
    })(window.location.search.substr(1).split('&'))
})(jQuery);
</script>

... and I combinate it with my own code:

// **open nested Bootstrap 4 Collapse (both the child and the parent element) and scroll**
<script>
jQuery($ => {
  
//ExampleURL: https://website.de/nested-collapse-page/?tday=tag-1635379200&tevent=event-55700-1635379200 -> tday and tevent are the corresponding URL parameter

  // Bootstrap 4 Collapse needs the #. Otherwise the targeted element will not show
  
  var day = "#" + $.QueryString.tday;
  var event = "#" + $.QueryString.tevent;

  $(day).collapse('show');
  $(event).collapse('show'); 

  $('html, body').animate({
  scrollTop: $(day).offset().top - 200
  }, 500 ); // 500 is the speed of the animation  
 
       
});
</script>