Lara Kreisz
Lara Kreisz

Reputation: 41

How to expand nested Bootstrap 4 Collapse from URL?

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 : )

Upvotes: 1

Views: 382

Answers (2)

Lara Kreisz
Lara Kreisz

Reputation: 41

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>

Upvotes: 1

z4nzi
z4nzi

Reputation: 81

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;

}

Upvotes: 1

Related Questions