How to init map correctly when hidden? - leaflet

I have a map, which is displayed or hidden depending on a button click.
I init the map while it is hidden, add layer, add markers, and call fitBounds() for the markers.
My problem is that when the map is hidden, fitBounds doesn't work. After switching to visible, the map is shown but fully zoomed out. When I call fitBounds again, the map is shown correctly.
How do I know when the map is ready? I tried mapReady, but it is also called when the map is hidden.
Is there another way?
Thanks!

How do I know when the map is ready?
FWIW, it is indeed when the map.whenReady(callback) executes your callback.
Your issue is probably not about the map not being ready (as you figured out, the map is ready even when hidden), but in the fact that it is originally hidden, hence it (the map container) does not have its final size. It needs that size (height and width) as it impacts your map.fitBounds().
You probably just need to call map.invalidateSize() and re-perform your fitBounds once you show your map.
See also: Data-toggle tab does not download Leaflet map

You might easily create valid div with width & height. Also you need to setup it as absolute.
Then, add this div to relative one, which is displayed. That is all.
<div style="display: block; position: relative; overflow: hidden;">
<div style="display: absolute; width: 100px; height: 100px; left: -1000px; top: -1000px;" id="map"></div>
</div>
That might be enough

Related

Leaflet - Gray stripes after panning

EDIT
This question is not a duplicate of How to get a leaflet map canvas to have a 100% height? as for the obvious reason, that you can see my map spanning the 100% height (compare the attribution on my picture being in the gray zone, while the container of the other question obviously ends before the blank zone. Also i can identify the size of my container spanning the 100% of the parent container in the developer tools. Just take a look at my css and and a very close look at the picture and maybe at leaftlet if you don't know how it works.)
Original
I use leaflet 1.5.1 in ionic 3.
After panning the map a bit, oftentimes the contents for gray parts are not being loaded (no network requests/traffic indicated in my browsers dev tools) and i am left with gray parts/stripes in the map as in the picture (the gray horizontal stripe below).
When i pan a lot further the missing map parts are loaded, but sometimes not (especially in iOS).
My map page's HTML using my map component (below)
<map style="height: 100%; width: 100%;">
The map component's HTML
<div id='map'></div>
The component's scss file
map {
#map{
height:100%;
width: 100%;
}
}
And here the component's typescript which creates the map
this.map = L.map('map', {
center: L.LatLng(center.latitude, center.longitude),
zoom: 13,
attribution: Attribution,
tap: false
});
//Add OSM Layer
L.tileLayer("https://{s}.tile.openstreetmap.se/hydda/full/{z}/{x}/{y}.png", { attribution: Attribution }).addTo(this.map);
this.map.setView([center.latitude, center.longitude], 14);
Any hints on what i'm doing wrong?
The solution was to trigger a resizing event via window.dispatchEvent(new Event('resize')) every time the user enters the tab page holding all the tabs including the map tab.
The map is reacting to this by adjusting itself to the "new" size.

How to add a ionic v3 component in ion-content but put the component's child button in ion-footer

I’ve created a few components that handle form submission functionality. In each of these components, I want the form submit/cancel buttons to be fixed at the bottom of the view, much like the functionality available via ion-footer. The submit button needs reference to the variables + methods in the component for [disabled] + (tap) functionality, for example [disabled]="!formGroup.valid" (tap)="submitForm()"
If the component is a child of ion-content then there is no way to add ion-footer as it will be contained within ion-content, instead of below ion-content. At first glance, having ion-footer inside ion-content appears to view properly, but the rendering can be buggy especially in scroll situations. I went as far as setting a force-bottom css class with fixed position/bottom but it looks like the ionic javascript overrides fixed positioning when inside ion-content, so a pure CSS solution does not seem to be possible.
<ion-content>
<a-form-component>
</a-form-component>
</ion-content>
<ion-footer>
<!-- add a-form-component's button here -->
</ion-footer>
Any recommendations on how to achieve the desired functionality?
TIA
Let's say you have a page called page and a component called cp
inside page.html you have the component <cp></cp>
Inside cp.html you have
<div>anything goes here</div>
<div>anything goes here</div>
<div>anything goes here</div>
<div>anything goes here</div>
<div id="the-footer">
<button>login<button>
</div>
inside page.scss:
#the-footer{
background-color: #efefef;
text-align: center;
position: fixed;
width: 100%;
bottom: 0px;
z-index: 99999;
}
This will achieve the same result as ion-footer.
The div containing the button will always be visible regardless of the scrolling.
hope it helps

slideToggle at top to push all content below down, not overlay when other divs have different z-index?

I have a sliding toggle div that is hidden on page load and when a button is clicked gets revealed. The div is 250px in height and is positioned top 0px. I have also tried bottom 100% which sort of does the same thing. I am using several layers of z-index and have had to position some divs using absolute in order to get the layout I wanted. But I was hoping there is a way to push all of these divs down by 250px when the sliding toggle is revealed. I was thinking that instead of using toggle div, maybe there is a way to scroll the page to -250px so that all the content appears the same but is pushed down?
This is the css for the div I am using in case there is something that can be done here:
#slidingTopBar
{
background:#199651;
display:inline-block;
position: fixed;
height:250px;
width:100%;
left:0px;
top:0px;
z-index:56;
}
The script for the toggle is being used as follows:
$(document).ready(function(){
$("#slidingTopBar").hide();
$(".show_hide").css('position','absolute').show();
$('.show_hide').click(function(){
$("#slidingTopBar").css('position','absolute').slideToggle();
}); });
And the toggle is being called using this html:
<div id="TopBar">SHOW</div>
Which is all working, except it is overlaying the content that is already there whereas I want it to push it all down.
Any help appreciated.
Using the clearfix method directly below the toggle div or it's wrapper should fix this:
HTML: <div class="clearfix"></div>
CSS: .clearfix { clear: both; }

horizontal scroll in jQuery mobile in iPhone

I am writing a simple program for iPhone using jQuery mobile, I have created a div with number of images but the scroller that is coming is vertical which I don't want. I want vertical space to be fixed and overflow of images horizontally. I know there a re scrolling plugin like iScroll but in my case I cant use them because those scrolling plugins uses <li> with fixed number of elements to be showed on that page but I want to keep this dynamic, if user rotates his device horizontally then more images can fit in the screen so I want that adjustment that if user keep his device vertical then horizontally there is less space so images should scroll horizontally but if he rotates device horizontally then he gets more space horizontally and more images can fit in and leftover images will again scroll horizontally.
I fixed the height of div and tried overflow property to let images flow horizontally but I guess jQuery is preventing that behavior.
can you please put me on correct path.
I think you could still use iScroll for horizontal scrolling, but you need to call refresh method whenever the content dimensions change. In your case, you could listen to the orientationchange event and perform in that case refresh of your iScroll object.
Check the section "Mastering the refresh() method" in iScroll documentation.
Hope it helps!
EDIT. You can start testing with a quick example like this:
<div data-role="page" id="loadPage">
<div data-role="content">
Add text
<div id="scroller" style="border: 1px solid green; white-space: nowrap; width: 300px;">
<div id="text" style="border: 1px solid red; height: 20px; width: 0px;"></div>
</div>
</div>
<script type="text/javascript">
var iscrollPage = null;
$('#loadPage').bind('pagebeforeshow', function () {
iscrollPage = new iScroll($('#scroller').get(0), { vScroll: false, hScroll: true });
});
function addText() {
$('#text').append((new Date()).getTime()).css('width', '+=140');
iscrollPage.refresh();
}
</script>
</div>

How to achieve the following slide / toggle effect with jQuery?

Right now on my website I have the following JavaScript that shows and hides a
<div class="commentBox"></div>
when user clicks a
Show Comments
Full Code:
<script type="text/javascript">
function toggleSlideBox(x){if($('#'+x).is(":hidden")){$(".comentBox").slideUp(200);$('#'+x).slideDown(200)}else{$('#'+x).slideUp(200)}}
</script>
Show Comments
<div class="commentBox">Content</div>
The effect can be illustrated like this:
I wanted to modify this function to act differently, but I couldn't figure it out. Basically what I wanted was to show content that is at the bottom once it starts expanding and have a fade in effect.
This is what I was hoping to achieve:
Could anyone suggest how to achieve the slide / toggle effect that is shown in image 2? so when user clicks a link it expands like that and when link is clicked again it shrinks.
The effect you describe looks just like the JQuery UI slide effect to me (rather than the blind effect that you have at present). This doesn't provide the opacity animation but provides a very simple solution otherwise. Or maybe I am misunderstanding you?
(The method accepts a parameter to slide down, rather than right-to-left of course)
$("#test").show("slide", {direction: "up"}, 1000);
JSFiddle here
If you are just animating a background image, like that rabbit just set the background position like this:
background-position: 0 100%;
This will align the background to the bottom edge rather than the top.
For text content the same principle applies. You just have to position the content absolutely to the bottom edge. For example:
<div class="container">
<div class="content">
<p>Text</p>
</div>
</div>
Then use this CSS:
.container {
position: relative;
overflow: hidden;
}
.content {
position: absolute;
bottom: 0; left: 0;
}
The only issue with this is that you need to find the height of the content so that you know how much to expand the container.
To do this, you can use this jQuery:
var height = $('.content').outerHeight();
Then on the click event just animate to the correct height:
$('.container').animate({
'height': height
});
Hope that helps :)