Weird rendering of google maps inside Bootstrap carousel - google-maps-api-3

I am trying to load google map directions as one of the slides inside Bootstrap carousel.
Not really sure why this map is loading the way it is. If I remove the first item in the carousel, then the map loads fine. Its only if the map is the second item does it load weirdly.
Any ideas how to fix this and load the map correctly?
http://jsfiddle.net/ax9jF/4/
HTML:
<div id="carousel-1" class="carousel slide">
<ol class="carousel-indicators">
<li data-target="#carousel-1" data-slide-to="0" class="active"></li>
<li data-target="#carousel-1" data-slide-to="1" ></li>
</ol>
<div class="carousel-inner">
<div class="item active" style="height: 450px; width: 100%;">
ABC
</div>
<div class="item">
<div id="map-canvas" style="height: 450px; width: 100%;">
</div>
</div>
</div>
<!-- Carousel Controls -->
<a class="left carousel-control" href="#carousel-1" data-slide="prev">
<span class="glyphicon glyphicon-chevron-left"></span>
</a>
<a class="right carousel-control" href="#carousel-1" data-slide="next">
<span class="glyphicon glyphicon-chevron-right"></span>
</a>
</div>
Javascript
$(document).ready(function(){
var $canvas = $('#map-canvas');
var dstLatLng = new google.maps.LatLng(37.403867, -121.975405);
var orgLatLng = new google.maps.LatLng(37.4321365, -122.0988141);
var directionsRenderer = new google.maps.DirectionsRenderer();
var directionsService = new google.maps.DirectionsService();
var request = {
origin: orgLatLng,
destination: dstLatLng,
travelMode: google.maps.TravelMode.DRIVING
};
var mapOptions = {
zoom: 8,
center: dstLatLng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map($canvas[0], mapOptions);
directionsRenderer.setMap(map);
directionsService.route(request, function(result, status) {
if (status === google.maps.DirectionsStatus.OK) {
return directionsRenderer.setDirections(result);
}
});
$('.carousel').carousel();
})

This is actually the same problem as with google-maps inside tabs. The solution is the off-left technique, i.e. instead hiding the maps using display: none, you hide by adding the following class:
.off-left_hide {
display: block !important;
position: absolute !important;
left: -10000px !important;
top: -10000px !important;
}
The challenge is then to persuade your library to use this way instead of the classical hide(). For example, in jQueryUI 1.10+ (maybe even older version) they no longer use classes for hiding, so I had to patch the library myself. There are some "new solutions" of this problem that don't use the off-left technique (since it has been harder and harder with new libraries, sadly), but these solutions are often unreliable and produce glitches (you will see the incomplete map for a while before it loads etc.). The off-left technique works much better, but in many times you cannot use it without modifying your favorite javascript library.

Related

How to put a banner above the fixed navbar of bootstrap which disappears when scrolling down?

I"m currently working on a project for school to make a ASP.NET MVC website. When i created a new project, bootstrap files were automatically added. So i decided to work with it, but i never did so before.
The first thing i noticed was the fixed navbar at the top of the website. I want a header/banner above it, followed by the navbar. But i didn't manage to do it. I have this code below in the layout view:
<div class="movdb-header"></div> <!-- this is the header i want to display above navbar -->
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
#Html.ActionLink("Home", "Index", "Home", new {area = ""}, new {#class = "navbar-brand"})
#Html.ActionLink("Inloggen", "Index", "User", new {area = ""}, new {#class = "navbar-brand"})
#Html.ActionLink("Uitloggen", "Index", "Logout", new {area = ""}, new {#class = "navbar-brand"})
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
</ul>
</div>
</div>
CSS:
.movdb-header {
background-color: red;
height: 110px;
width: 100%;
}
I searched earlier about this problem and people talked about removing the navbar-fixed-top class and then putting your div above it. But i want the navbar to stay fixed but below the personal banner and if scrolled down only the navbar is visible on top. So the banner disappears when scrolling down.
How can i solve this problem?
Thanks in advance.
You can give your .movdb-header fixed position and give top: 110px position to your navbar. It is set on top: 0 now.
EDIT:
.navbar {
position: relative;
}
$(document).ready(function(){
$(window).scroll(function(){
if ($(window).scrollTop() > 100){
$('.navbar').css('position','fixed');
}
else{
$('.navbar').css('position','relative');
}
});
});

D3 Elements are invisible despite existing in DOM

I have a bootstrap tab panel and I want to display a different d3 chart for each tab.
When the document loads, the first D3 chart is present in the DOM but its elements are invisible. Here's an example: http://i.imgur.com/7ATTyhI.png
Here is the setup for my tab pane in bootstrap:
<div role="tabpanel">
<!-- Nav tabs -->
<ul class="nav nav-tabs" role="tablist">
<li role="presentation" class="active"><a href="#ghg-co2" aria-controls="ghg-co2" role="tab" data-toggle="tab">
<h4>Change in CO<sub>2</sub></h4></a>
</li>
<li role="presentation"><a href="#ghg-ch4" aria-controls="ghg-ch4" role="tab" data-toggle="tab">
<h4>Change in CH4 (Methane)</h4></a>
</li>
<li role="presentation"><a href="#ghg-nos" aria-controls="ghg-nos" role="tab" data-toggle="tab">
<h4>Change in Nitrous Oxide</h4></a>
</li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
<script src="js/ghg.js"></script>
<div role="tabpanel" class="tab-pane active fade fade-in" id="ghg-co2">
<div id="chart-ghg-co2" class="d3-chart"></div>
</div>
<div role="tabpanel" class="tab-pane fade fade-in" id="ghg-ch4">
<div id="chart-ghg-ch4" class="d3-chart"></div>
</div>
<div role="tabpanel" class="tab-pane fade fade-in" id="ghg-nos">
<div id="chart-ghg-nos" class="d3-chart"></div>
</div>
</div>
</div>
I have had issues with bootstrap displaying content in the tab pane correctly. I am using this hack in my style.css to override some bootstrap properties:
/* bootstrap hack: fix content width inside hidden tabs */
.tab-content > .tab-pane,
.pill-content > .pill-pane {
display: block; /* undo display:none */
height: 0; /* height:0 is also invisible */
overflow-y: hidden; /* no-overflow */
}
.tab-content > .active,
.pill-content > .active {
height: auto; /* let the content decide it */
} /* bootstrap hack end */
I got it from this thread
My D3 function is almost identical to this example: d3 scatterplot
but with different data.
At the bottom of my HTML, I have:
<script>
// Check if DOM is ready for D3
$( document ).ready(ghgco2()); // Names of my three D3 chart functions
$( document ).ready(ghgch4());
$( document ).ready(ghgnos());
</script>
I suspect the problem is that my d3 function, ghgco2() is attempting to render before the div in which it resides, .chart-ghg-co2 is ready. For some reason, the svg has the correct dimensions, and the elements are all present, but it's completely blank. This is resolved when I switch between tabs on the bootstrap pane.
Any and all help is appreciated.

Link within a list-group-item class (itself a link) in Twitter Bootstrap

(How) Can I place a link within a twitter bootstrap "list-group-item" that is itself a link without messing up the list-group-item format? (see below)
<div class="list-group">
<a href="#" class="list-group-item active">
<h4 class="list-group-item-heading">List group item heading</h4>
<p class="list-group-item-text">...</p>
<a href="https://www.facebook.com/sharer/sharer.php?u=http" target="_blank">
Share on Facebook
</a>
</a>
</div>
You can't use <a> tags inside other <a> tags, that's invalid HTML. Check this question.
You can make it clickable with jQuery though, with an hack like this:
HTML - use a div instead with a custom class and some data-tags:
<div class="list-group">
<div class="list-group-item active list-group-item-linkable"
data-link="http://www.google.com">
<h4 class="list-group-item-heading">List group item heading</h4>
<p class="list-group-item-text">...</p>
<a href="https://www.facebook.com/sharer/sharer.php?u=http"
target="_blank">
Share on Facebook
</a>
</div>
</div>
CSS - make it seem like a link:
.list-group-item-linkable:hover {
color: #555;
text-decoration: none;
background-color: #f5f5f5;
cursor: pointer;
}
JS - the fun part:
$(document).ready(function() {
$('.list-group-item-linkable').on('click', function() {
// same window/tab:
window.location.href = $(this).data('link');
// new window/tab:
//window.open($(this).data('link'));
});
$('.list-group-item-linkable a, .list-group-item-linkable button')
.on('click', function(e) {
e.stopPropagation();
});
});
I've also created a JSFiddle.
I am confused, you want the entire thing to be a link? It may take a couple more steps - nothing a little copy-and-pasting cant handle - but why not just manually provide an 'a' tag to each of the children of the "list-group"

Bootstrap 3.0 affix with list changes width

I'm migrating to bootstrap 3.0.0 and I'm having issues with an affixed menu to the left: as soon as it becomes affixed (after 10px scroll), its width changes. In this fiddle it gets smaller, in my real site it gets wider and expands on the actual content.
It worked perfectly with bootstrap v2.3.2. After checking it looks like the list items don't play well with the .affix {position: fixed;} that appears.
Any ideas?
SOLUTION: based on the latest comments I have finally added this JS piece which fixes it nicely without having to set a fixed width to the affixed element:
$(function() {
var $affixElement = $('div[data-spy="affix"]');
$affixElement.width($affixElement.parent().width());
});
I had the same problem and fixed with this:
$(window).resize(function () {
$('#category-nav.affix').width($('#content').width());
});
basically in an event of resize I calculate the content div's width and set the width of affixed element to that.
$(window).scroll(function () {
$('#secondary .widget-area.affix').width($('#secondary').width());
});
Here's another version:
$('.sitebar .affix-top').width($('.sitebar .affix-top').width());
$(window).resize(function () {
$('.sitebar .affix').width($('.sitebar .affix-top').width());
});
$(window).scroll(function () {
$('.sitebar .affix').width($('.sitebar .affix-top').width());
});
Here's my version.
var fixAffixWidth = function() {
$('[data-spy="affix"]').each(function() {
$(this).width( $(this).parent().width() );
});
}
fixAffixWidth();
$(window).resize(fixAffixWidth);
CSS
div.affix {
position: fixed !important;
}
had the same problem once (only in BS 2.3.2).
Not an answer, more a hack: I gave the affixed element a width. That sucked, because i had to set width for all resolutions (RWD) and actually the value should be standard column width (e.g. .span4).
Yes: position: fixed takes the element out of the given context (in your case col-md-3).
I use this code to fix the width of the affix.
$(document).on('affixed.bs.affix',function(e){
$('.affix').each(function(){
var elem = $(this);
var parentPanel = $(elem).parent();
var resizeFn = function () {
var parentAffixWidth = $(parentPanel).width();
elem.width(parentAffixWidth);
};
resizeFn();
//$(window).resize(resizeFn);
});
});
The affix get the width of his parent and check that width on every scroll the web. Uncommenting the last line, execute too on resize window event.
I used $('.affix-element').width($('.affix-element-parent').width()).affix()
Works well :)
My solution as well:
$('.menu-card').affix();
$(document).on('affix.bs.affix', '.menu-card', function() {
$(this).width($(this).width());
});
(.menu-card is my sticky div)
I added this for supporting the window resizing:
Let's assume the affix are in a parent div #menu-card-pane.
$(window).resize(function () {
var parentSize = $('#menu-card-pane').width();
$('.affix').each(function() {
var affixPadding = $(this).innerWidth() - $(this).width();
$(this).width(parentSize - affixPadding);
});
});
Here is my HTML
<div class="sidebar-nav">
<div class="navbar navbar-default" role="navigation">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#committees-navbar">
<span class="sr-only"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<span class="visible-xs navbar-brand">Committees</span>
</div>
<div id="committees-navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav nav-stacked" data-spy="affix" data-offset-top="250">
<li class="col-xs-12"><a ng-click="scrollTo('boardCommittee')">BOARD OF DIRECTORS</a></li>
<li class="col-xs-12"><a ng-click="scrollTo('madrasaCommittee')">MADRASATUL JAMALIYAH</a></li>
<li class="col-xs-12"><a ng-click="scrollTo('shababCommittee')">SHABAB</a></li>
<li class="col-xs-12"><a ng-click="scrollTo('bwaCommittee')">BURHANI WOMEN</a></li>
<li class="col-xs-12"><a ng-click="scrollTo('tncCommittee')">TAISEER UN NIKAH</a></li>
<li class="col-xs-12"><a ng-click="scrollTo('fmbCommittee')">FAIZUL MAWAIDUL BURHANIYAH</a></li>
<li class="col-xs-12"><a ng-click="scrollTo('websiteCommittee')">WEBSITE</a></li>
<li class="col-xs-12"><a ng-click="scrollTo('tadfeenCommittee')">TADFEEN</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
And this is my JS fix
$(function () {
var resize = function () {
var sidebarNav = $(".sidebar-nav");
var sidebarNavAffix = $(".sidebar-nav .affix");
if (sidebarNavAffix.length && (sidebarNavAffix.width() !== sidebarNav.width())) {
sidebarNavAffix.width(sidebarNav.width());
}
}
$(window).on({"scroll" : resize, "resize" : resize});
});

how to listen to the end of a bootstrap animation

I'm developing a website using bootstrap and its responsive JS+CSS.
At the top of the page I have a fixed navigation bar where an "expand menu" button is shown in case the viewport is too tight. This button does its magic with an animation (a CSS3 one I think) and I'm happy with it, but I would like to do something more (toggle classes with jquery) each time the animation finishes (both the open animation and the close one).
I was thinking about a javascript listener (even better by defining it thanks to jquery .on function), but I really don't know what event I should listen to!
Any ideas?
UPDATE
I've fond out that by listening to this event on the object I wanna control almost does the job well:
$("#main-navbar .nav-collapse").on("transitionend", function(event){
console.log("end of the animation");
}
the only problem is that it messes bootstrap animations up on that object: the first time it works, but wen I want to close the expanded navbar, nothing happens (it seems that my listener overrides the bootstrap ones. quite weird, huh?)
If you use bootstrap and transitions (css3 transition) you can try this:
$("body").on($.support.transition.end, '#main-navbar .nav-collapse', function(event){
console.log("end of the animation");
});
$.support.transition.end contains one of these events: webkitTransitionEnd, transitionend, oTransitionEnd otransitionend, transitionend.
But if you use css3 animation (css3 animation-name and keyframes) you can try this:
$("body").on('webkitAnimationEnd oanimationend msAnimationEnd animationend', '#main-navbar .nav-collapse', function(event){
console.log("end of the animation");
});
$target.on("shown.bs.collapse", function(event){
console.log("end of the animation");
});
Wonder that nobody mention about Util.emulateTransitionEnd() which was created on purpose and used by Bootstrap components to catch when the animation is over.
$('#nav')
.one(
'bsTransitionEnd', // Util.TRANSITION_END
handler
)
.emulateTransitionEnd(600); // Collapse.TRANSITION_DURATION
In your particular case, you might want to extend corresponding Bootstrap plugin, so that you can figure out which exactly case is yours - Collapse is used by different components.
Here is jsfiddle snippet to demo (based on Bootstrap v4).
(function($) {
var Collapse = $.fn.collapse.Constructor;
var navbar = $('#nav');
$.extend(Collapse.Default, {
navbarClass: ''
});
var _show = Collapse.prototype.show;
Collapse.prototype.show = function() {
_show.apply(this, Array.prototype.slice.apply(arguments));
var navbarClass = this._config.navbarClass;
if (navbarClass && !navbar.hasClass(navbarClass)) {
navbar.addClass(navbarClass);
}
}
var _hide = Collapse.prototype.hide;
Collapse.prototype.hide = function() {
_hide.apply(this, Array.prototype.slice.apply(arguments));
var navbarClass = this._config.navbarClass;
if (navbarClass && navbar.hasClass(navbarClass)) {
navbar
.one('bsTransitionEnd', function() { // Util.TRANSITION_END
navbar.removeClass(navbarClass);
})
.emulateTransitionEnd(300); // Collapse.TRANSITION_DURATION / 2
}
}
})(window.jQuery);
<nav id="nav" role="navigation" class="navbar fixed-top navbar-light bg-light">
<button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#nav_items" data-navbar-class="navbar-dark bg-dark" aria-expanded="false" aria-label="Menu">
<span class="text-hide">Menu</span>
<span class="navbar-toggler-icon"></span>
</button>
<div id="nav_items" class="collapse navbar-collapse">
<div class="nav navbar-nav">
<a class="nav-item nav-link active" href="">Link <span class="sr-only">Home</span></a>
<a class="nav-item nav-link" href="">Link2</a>
<a class="nav-item nav-link" href="">Link3</a>
</div>
</div>
</nav>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.3/css/bootstrap.min.css" integrity="sha384-Zug+QiDoJOrZ5t4lssLdxGhVrurbmBWopoEl+M6BdEfwnCJZtKxi1KgxUyJq13dy" crossorigin="anonymous">
<style type="text/css">
button:focus {
outline-width: 0;
}
.navbar-collapse.collapse.show {
height: 100vh;
}
.navbar-nav {
height: 100vh;
}
.navbar-toggler {
border: none;
padding: 0.25rem 0;
}
.navbar-dark .navbar-toggler-icon {
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='rgba(255,255,255,.5)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='18' y1='6' x2='6' y2='18'%3E%3C/line%3E%3Cline x1='6' y1='6' x2='18' y2='18'%3E%3C/line%3E%3C/svg%3E");
}
</style>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.3/js/bootstrap.min.js" integrity="sha384-a5N7Y/aK3qNeh15eJKGWxsqtnX/wWdSZSKp+81YjTmS15nvnvxKHuzaWwXHDli+4" crossorigin="anonymous"></script>
jQuery has an animation listener built in: http://docs.jquery.com/Selectors/animated
Example: if( $(foo).is(':animated') ) {...}
Then if an element is !animated you can can apply whatever logic you want.
$('.collapse').on('bsTransitionEnd', function(e) {
console.log('finished')
})
This worked for me for collapsible panels of any kind. You might try with a different selector.

Resources