Reputation: 799
I'm building a web app that has 3 components on the screen.
Navbar (sticky top)
Main Container
map container(75% of main)
chat window (25% of main)
What I want to be able to do is hide the chat footer then have the map container take up all of the main container, but if user wants to see the chat window, he clicks a button and the map shrinks back to 75% of the main and the chat window is visible again. I want this functionality to work across all the bootstrap breakpoints so from what I've read the responsive visibility classes are not what I want.
The javascript I'm using is
$('#chatToggle').click(function(e) {
console.log('in chatToggle');
var cf = document.getElementById('chatFooter');
var mc = document.getElementById('leafletMap');
if (cf.style.display === 'none') {
console.log('showing chat window');
cf.className = 'row h-15 ';
mc.className = "row h-85 map-container";
$('#chatToggle').text('Hide Chat')
} else {
console.log('hiding chat window');
cf.className = 'row h-15 d-none';
mc.className = "row h-85 map-container";
$('#chatToggle').text('Show Chat')
}
map.invalidateSize();
});
When the page first loads, it appears as I want it and the navbar responds to the breakpoints and acts like a nice responsive navbar. However, as soon as I turn off the chat footer with code above, the navbar disappears, the map takes up the whole viewport and map attribution morphs into some big mess on the top of the screen. Here are two screenshots:
Relevant HTML is:
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-primary navbar-fixed-top">
<a class="navbar-brand" href="#">
<span class=lg-view>TRACKING SYSTEM</span>
</a>
<div class="navbar-toggler">
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarContent" aria-controls="navbarContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
</div>
<div class="collapse navbar-collapse justify-content-end" id="navbarContent">
<ul class="navbar-nav " >
<li class="nav-item dropdown text-center" >
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Menu
</a>
<div class="dropdown-menu" >
<a class="dropdown-item" data-toggle="modal" href="#realTimeModal">Real-Time Tracking</a>
<a class="dropdown-item" data-toggle="modal" href="#historicalModal">Historical Tracking</a>
<a class="dropdown-item" data-toggle="modal" href="#gridsModal">Display Grids</a>
<div class="dropdown-divider"></div>
<a id="stop_tracking" class="dropdown-item" href="#">Stop Tracking</a>
<a id="clear_grids" class="dropdown-item" href="#">Clear Grids</a>
</div>
</li>
<a class="flex-fill text-center text-light nav-link" href="#chatToggle" id="chatToggle" >Hide Chat</a>
<a class="flex-fill text-center text-light nav-link" href="#contact">Settings</a>
</ul>
</div>
</nav>
<div class="container-fluid h-100">
<div class="row h-75 map-container" id="leafletMap">
</div>
<div class="row h-25" id="chatFooter">
<div class="col-sm-2 border">
<h4 class="chatLabel">Chat History</h4>
</div>
<div class="col-sm-10 border">
<textarea readonly class="chatMsgTxt w-100 border" id="chatMsgTxt" style="border: 1px black;">test data</textarea>
</div>
</div>
</div>
</body>
And in my css I have:
html,
body {
height: 100%;
}
Is it possible to accomplish what I'm trying to do with Bootstrap 4?
Upvotes: 2
Views: 2003
Reputation: 12960
I notice the fixed-top
on nav causes part of the map to be hide. Reworked example using osm:
https://www.codeply.com/p/2ly5AlChoq
so I extend the invalidateSize trick on
https://www.codeply.com/p/7YU91GQrEo
Still there're some quirks on chat about width
but shows more accurate about showing the map.
with bootstrap 3 it was just about CSS:
https://embed.plnkr.co/plunk/wH7u64
using
html, body, #container {
height: 100%;
overflow: hidden;
width: 100%;
}
#map {
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
height: 100%;
width: auto;
}
There must be a better solution using bootstrap 4, but I can find a way to create an empty div that takes rest of size left by navbar.
See leaflet specify that div container should define the height, but looks like bootstrap layout based on actual size (so kind of egg-chicken problem and why invalidateSize do the work)
Upvotes: 0
Reputation: 362700
Instead of all the extra JS to handle the button click, use the Bootstrap collapse component. Add handlers for the hide/show events to resize the map, and toggle the button text:
$('.chat').on('hide.bs.collapse',function(){
mymap.invalidateSize();
$('#chatToggle').text("Show Chat");
}).on('show.bs.collapse',function(){
mymap.invalidateSize();
$('#chatToggle').text("Hide Chat");
});
The problem you're having with resizing heights is easier solved with flexbox. Just add a class to the .map-container
so that it grows automatically in height when the chat is collapsed.
.map-container {
flex: 1 1 auto;
}
Working demo: https://www.codeply.com/go/jCa2CsQFYY
Upvotes: 1