Leaftlet on Ionic Tabs App shows only first tile - javascript

I have an Ionic Tabs App (I used the Cordova templates on Visual Studio 2015) with a Leaflet map on the second tab. On the first tab I have some search parameters for POIs that I want to show on the map with markers. Everything is working fine, including the map is showing all the tiles, until I start interacting with the controls on the first tab. Specifically, when I enter an input control and the soft keyboard appears, if I then go to the second tab, the map is only showing the first tile. If I zoom in or out, the map refreshes but shows only the first tile. The problem is solved though if I change orientation of the device.
The soft keyboard is not the only thing that causes the problem. On Ripple for example, the soft keyboard does not show (I use the laptop keyboard) but after a while manipulating the search parameters on the first tab, the map stops working properly.
Also, I have tried with the Mapbox API instead of Leaflet and the problem occurs exactly the same way.

The L.Map instance is unable to correctly get/calculate it's dimensions because at initialization the instance's parent container has a style of display: none. You can call invalidateSize on your map instance to make it recalculate it's dimensions when the tab containing your map is shown:
Checks if the map container size changed and updates the map if so — call it after you've changed the map size dynamically, also animating pan by default.
http://leafletjs.com/reference.html#map-invalidatesize
I'm by far no ionic expert but according to the docs/reference, ion-tab has a on-select callback where you could do this:
Called when this tab is selected.
http://ionicframework.com/docs/api/directive/ionTab/
<ion-tab on-select="onTabSelected()"></ion-tab>
function onTabSelected () {
//Assuming 'map' holds a reference to your map instance.
map.invalidateSize();
}
As mentioned in the comments below by the question poster, the above works, but so does listening for the $ionicView.enter event and using invalidateSize in it's callback:
$scope.$on('$ionicView.enter', function () {
map.invalidateSize();
});

Related

How to zoom out container, after Leaflet reached minZoom?

On one of our main pages, Leaflet map occupies 90% of the page with only the top nav (position: fixed;)
But on touch devices, user can accidentally zoom-in not on a map, but on the entire page. If they do - there is no way for them to un-zoom to see the top nav, because any touch action would zoom-in-out the map.
Ideally, I'm trying to find solution so that the page would zoom-out, after Leaflet reaches minZoom level. Any other ideas are welcome! Thanks!
Cannot be done.
Leaflet relies on the touch-action CSS property to prevent the browser from pinch-zooming the whole page.
Note how there is no value for that property that allows to pinch-zoom only out. Leaflet can only enable/disable pinch-zooming as a whole.
You could disable the touchZoom handler of the map by running something like map.touchZoom.disable(), or map.on('zoomend', function(){ if (map.getZoom()===map.options.minZoom) map.touchZoom.disable() }) but that will disable all pinch-zooming in Leaflet, and enable all pinch-zooming of the whole page.

Call Mapbox GL Function from jQuery

I have a Mapbox map on a page, which loads into a sliding panel which is controlled by jQuery.
If I change the browser window size and toggle the panel, the map often appears only partially filling its container. This is a known issue with the Mapbox GL API.
From their documentation:
If you’re hiding your map initially with something like display:none
and showing it dynamically with JavaScript, it may have some problems
appearing and sizing correctly. The map can’t figure out its own size
when it’s hidden from the page, since it doesn’t have a size in the
browser’s calculation.
With Mapbox GL JS you can call map.resize() to detect and resize the
map
So, I need to call Mapbox's map.resize() function from within my jQuery code, when the sliding panel is opened. Trouble is, I can't seem to get it to work. I've tried the following:
1: $(map).trigger('resize');
2: $(window.map).resize();
3: $(window.map).trigger('resize');
as well as
4: $(window).trigger('resize');
Thing is, I'm not sure about my syntax here and the correct way to call a function residing in another script from within jQuery. I've confirmed that the 'map' object is global, as typing map.resize() directly into my browser's dev tools console works [ie. fixes the map display]. I just can't seem to get jQuery to pass the function.
Also strange is that $(window).trigger('resize') didn't work, as manually resizing the browser window automatically triggers the 'map.resize()' function too [and fixes the map rendering].
EDIT:
Should have mentioned. I've made the map object available globally with: window.map = map; inside the mapbox.js script and made sure that the mapbox.js script loads before the jQuery one, but still no joy.
I managed to solve this in the end. The problem was that the code I was using to trigger the map redraw was as follows:
//inside jQuery map click function
$("#map").slideToggle(200);
$(window.map).resize();
Being a bit of a jQuery newbie, I [idiotically] assumed that those commands would fire sequentially but, of course, the slideToggle() animation is asynchronous. Therefore jQuery was calling the Mapbox resize() function before the sliding panel had reached its final dimensions. Thus causing the map to default to its fallback size of 400x300px
All I needed to do was stick the call to Mapbox resize() into an anonymous function, triggered after the slidetoggle() has completed:
$("#map").slideToggle(200, function()
{
$(window.map).resize();
});
There is still a slight visual glitch in that the map will initially appear at 400x300px, before quickly snapping to fill its container. But since this was a bit of an edge case, dependent on the user having resized their browser window in between toggling the map open and closed, it's good enough for me to deem it solved.

Google Maps InfoBox preventing scroll

I am using InfoBox to display information boxes on a custom Google map, but when the user is scrolling around the map with dragging (ie. on an iPad or other mobile device, or with their mouse), attempting to drag on an open InfoBox window does nothing (ie. the map doesn't move).
Is there some way to allow the drag scrolling to continue, even while on an InfoBox? I feel like it should just be a simple option but I can't see anything in the documentation.
I've tried moving the InfoBox to the mapPane (instead of the floatPane) but it didn't help.

image map area unable to fire click event.afer maximize the widow or restore the window click event firing

I am working with image map i am taken two buttons in my image. in button click one popup(div)displaying .in that div i am taken image one map with areas . i am trying to click (close button and on and off button)) but not responding .after maximize the browser window it is working . could any one solve this problem.and i want make all images responsive i used JQuery Image Map it is working but . when i given div position is absolute.
it is not working. can any one provide solution for this problem
(press tab key for identify image map area's)
Although your question is hard to understand, i will try my best for 50 reps (I am young and needed the money ;)
You are using a JQuery Library from here:
https://raw.github.com/stowball/jQuery-rwdImageMaps/master/jquery.rwdImageMaps.min.js
The readme of it prints in large letters:
"Allows image maps to be used in a responsive design by recalculating the area coordinates to match the actual image size on load and window.resize"
So, your close handler doesnt trigger, because the area coords were only calculated by that "rwd" once you resize your browser window, and the readme tells us, that it is designed to do so.
Btw to make your code work:
add $('img[usemap]').rwdImageMaps(); below line 20 in your javascript code.

Duplicating mouse events to simultaniously control 2 or more stacked divs

I am working with the google plus API for photospheres.
For showing a time lapse panorama I have set up two divs on top of each other which get iframes with the embedded panorama viewer.
Then I have set up a timer which blends over from the front to the back div and it all works fine.
I have set it up here on jsfiddle
My problem is, that those panoramas are interactive so you can click in it, drag it around and click again to resume autorotate or use the mouse wheel to zoom in or out. The moment I do that my two panoramas are no longer in sync so the "illusion" of time lapse does not work any more.
Is there a way to duplicate all mouse events and send them to both divs at the same time?
I was able to register clicks using jquery and
$('#firstDiv').click(function(){$('#seconddiv').click()})
but I am struggling to replicate the mouse dragging and wheel zooming to keep the two panoramas in sync.
You could maybe give this variation a shot:
$('#firstDiv).on('click', function(){
$('#secondDiv').trigger('click');
});
But it seems that the interactive controls for the sphere are handled on the google side. So, unless there's a callback option (by passing a query string parameter to the iframe) to enable explicit control, I'd say it's not possible.

Categories