This is a migrated thread and some comments may be shown as answers.

Google maps won't show up from second shop view

5 Answers 152 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
Mate
Top achievements
Rank 2
Mate asked on 15 Sep 2013, 02:21 PM
Hi,

I am building a test rails/kendo mobile application which have three main models: Organizations, Shops and Categories.
The shop model has latitude and longitude among its attributes. This is because I would like to show a map on the Shop details view with a marker where the shop is. The first time I view a random shop, the code works fine, and the map renders with the marker. But when I click the back button (browser back button) or the Shops link (in tabstrip) then try to navigate to another shop the map won't show up only if I hit refresh on the browser.

First I thought that this happens because of the changing coordinates (which are placed directly inside the javascript like this: .LatLng(<%=@shop.latitude%>, <%=@shop.longitude%>) ). But no. Even with a simple map like this it won't show up from the second shop view:
       function shopMap(e) {
            var myOptions = {
                center: new google.maps.LatLng(-34.397, 150.644),
                zoom: 8,
                mapTypeId: google.maps.MapTypeId.ROADMAP
            };

            var mapElement = $("#shopmap");
            var container = e.view.content;

            var map = new google.maps.Map(mapElement[0], myOptions);
        }

I tried to place the above code directly inside the the view where the shop data is rendered, which would be my preferred way of doing this to be able to change the coordinates dynamically from db, but also tried to place the code in application.html.erb, but no effect (to mimic the google maps example in the code library).

I tried to init the map with the following data attributes:
data-init
data-before-show
data-show

Also tried to set:
data-reload="true"

but none of them and none of their combinations seems to work.

Here is the code for the shop view:
<div data-role="view" data-layout="default" data-show="shopMap" data-reload="true" data-init="shopMap" data-after-show="shopMap" data-title="<%= @shop.title %>" data-zoom="true">
    <h1 id="shoptitle"><%= @shop.title %></h1>
    <%= image_tag(@shop.logo.thumb.url) %>
    <p><%= @shop.description.html_safe %></p>
    <p id="latitude"><%= @shop.latitude %></p>
    <p id="longitude"><%= @shop.longitude %></p>
    <div id="shopmap">
        
    </div>
    <script>
        function shopMap() {
            var myOptions = {
                center: new google.maps.LatLng(<%= @shop.latitude %>, <%= @shop.longitude %>),
                zoom: 8,
                mapTypeId: google.maps.MapTypeId.ROADMAP
            };

            var mapElement = $("#shopmap");
            var container = e.view.content;

            var map = new google.maps.Map(mapElement[0], myOptions);
        }  
    </script>
</div>

The reason why I gave ids to the p tags which contain the latitude and longitude is that I tried to place their values inside js variables to pass them to the shopMap function. But that doesn't work either.

I also tried the kendoMap plugin. But it doesn't work either with the basic settings.

My end goal is to make the map appear without page refresh with the marker which belongs to the currently viewed shop.

Please give me some suggestions, pointers to make this happen!

Best Wishes,
Matt

5 Answers, 1 is accepted

Sort by
0
Alexander Valchev
Telerik team
answered on 18 Sep 2013, 07:36 AM
Hi Mate,

If I understood correctly the problem is that google maps does not retain its position when the user navigates through the Views. I prepared a small demo page where everything seems to work as expected. Could you please check it and let me know what I am missing?

Note that the map should be initialized at the init event of its parent View. Building the map at show event will cause multiple initialization which is not supported.

If you would like to change dynamically the coordinates of the map, please do not re-initialize it but set position of the marker through the JavaScript API at view-show event.

Regards,
Alexander Valchev
Telerik
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Mate
Top achievements
Rank 2
answered on 18 Sep 2013, 03:41 PM
Hi,

Thank You for Your answer! I think You checked the wrong map which is at: http://mapp.bevisible.hu/#/map
That one works fine without problems.
The problem occurs when I visit a shop page (shop = üzlet in hungarian) like this one:
http://mapp.bevisible.hu/#/categories/1/shops/1
As You can see there is no problem with the map this time. It loads below the shop data.
The problem is when right after I visited a page like the above, I want to visit another shop details page (without refresh) like this:
http://mapp.bevisible.hu/#/categories/5/shops/2
Because this time the map won't load only if I refresh the browser.
Basically what I want to achieve is to show the map with a marker on the location of the current shop without refresh.

UPDATE:
To make it more clear. The google maps in my code is inside a remote view (the shop details page view). In the example You attached it is on the same page.
The shop details page view looks like this right now:
<div data-role="view" data-layout="default" data-init="shopMap" data-reload="true" data-title="<%= @shop.title %>" data-zoom="true">
    <h1 id="shoptitle"><%= @shop.title %></h1>
    <% if @shop.address %>
        <p><%= @shop.address %></p>
    <% end %>
    <% if @shop.phone %>
        <p><%= @shop.phone %></p>
    <% end %>
    <% if @shop.website %>
        <p><%= @shop.website %></p>
    <% end %>
    <% if @shop.fb %>
        <p><a href="<%= @shop.fb %>">Facebook</a></p>
    <% end %>
    <p><%= @shop.description.html_safe %></p>
    <p id="lat"><%= @shop.lat %></p>
    <p id="lon"><%= @shop.lon %></p>
    <div id="shopmap">
        
    </div>
    <script>
        
        var lat = $('p#lat').text();
        var lon = $('p#lon').text();
        var map;
        function shopMap(e) {
          var latlng = new google.maps.LatLng(lat, lon);
                var myOptions = {
                    center: latlng,
                    zoom: 8,
                    mapTypeId: google.maps.MapTypeId.ROADMAP
                };

                var mapElement = $("#shopmap");
                var container = e.view.content;

                var map = new google.maps.Map(mapElement[0], myOptions);

                var marker = new google.maps.Marker({
                position: latlng,
                map: map,
                title: 'This is the shop name: <%= @shop.title %>'
            });
            }
    </script>
</div>

As You can see I init the map in the view div and the maps script is in the same view as I need to dynamically change its values based on the url which tells Rails which shop is being viewed. I've already tried to place it inside my application.html.erb (layout view) without dynamic values but it still won't display the map without page refresh. There is no js errors in the console either.
If You say that I should only init the map once then how can I achieve this with the code above? Because it loads everytime when someone views a shop detail page. Is there a way to check if google map has been inited already?

If needed I can attach my Rails views in a zip file to the support ticket I've sent.

Best Wishes,
Matt

0
Petyo
Telerik team
answered on 20 Sep 2013, 10:22 AM
Hello Mate,

As Alex already suggested, you should not re-instantiate the map, but rather change the marker position using the API exposed. Please try following the suggestions outlined in his previous response. 

Regards,
Petyo
Telerik
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Mate
Top achievements
Rank 2
answered on 22 Sep 2013, 06:50 PM
Hi Guys,

Sorry, but the answer doesn't seem to help. I attached a screenvideo with comments to show the problem.
Here is what I did based on Your suggestions:
I divided up the google maps code, and created 2 functions:
       
        function buildMap() {
            var myOptions = {
                center: new google.maps.LatLng(-34.397, 150.644),
                zoom: 8,
                mapTypeId: google.maps.MapTypeId.ROADMAP
            };

            shopMap = new google.maps.Map(document.getElementById('shoplocmap'), myOptions);
            //google.maps.event.addListener(shopMap, "idle", function(){
            //    google.maps.event.trigger(shopMap, 'resize');
            //});
        };

        function placeMarker() {
          var shopCoord = new google.maps.LatLng(lat,lon);
          var marker = new google.maps.Marker({
              position: shopCoord,
              map: shopMap
          });
          shopMap.setCenter(shopCoord);
        };

The buildMap function is inited with data-init as You did in the attached code above. The placeMarker function is fired with data-after-show.
But as I said earlier it is in a remote view and I don't know if this changes things.
The view looks like this now:
<div data-role="view" data-layout="default" data-init="buildMap" data-after-show="placeMarker" data-title="<%= @shop.title %>">
    <h1 id="shoptitle"><%= @shop.title %></h1>
    <% if @shop.address %>
        <p><%= @shop.address %></p>
    <% end %>
    <% if @shop.phone %>
        <p><%= @shop.phone %></p>
    <% end %>
    <% if @shop.website %>
        <p><%= @shop.website %></p>
    <% end %>
    <% if @shop.fb %>
        <p><a href="<%= @shop.fb %>">Facebook</a></p>
    <% end %>
    <p><%= @shop.description.html_safe %></p>
    <p id="lat"><%= @shop.lat %></p>
    <p id="lon"><%= @shop.lon %></p>
    <div id="smap">
        <div id="shoplocmap"></div>
    </div>
    <script>
        var shopMap;
        var lon = $('p#lon').text();
        var lat = $('p#lat').text();

        function buildMap() {
            var myOptions = {
                center: new google.maps.LatLng(-34.397, 150.644),
                zoom: 8,
                mapTypeId: google.maps.MapTypeId.ROADMAP
            };

            shopMap = new google.maps.Map(document.getElementById('shoplocmap'), myOptions);
            //google.maps.event.addListener(shopMap, "idle", function(){
            //    google.maps.event.trigger(shopMap, 'resize');
            //});
        };

        function placeMarker() {
          var shopCoord = new google.maps.LatLng(lat,lon);
          var marker = new google.maps.Marker({
              position: shopCoord,
              map: shopMap
          });

          shopMap.setCenter(shopCoord);
        
        };
        
        // $(document).ajaxComplete(buildMap());
    </script>
</div>

As You can see I've also tried to init the map on ajaxComplete, and it created the same effect, even when I set data-reload="true" which is supposed to reload the view via ajax if I understood the docs properly.

UPDATE
I tried to implement Leaflet maps instead, but the exact same error occurs, except now I get an error when I try to load the second shop details page: "Error: Map container is already initialized." - which comes from leaflet.js . I think this is the error You were writing about earlier, to init only once. So now first I always remove the map container div (shoplocmap) and create/append it to its parent again with jQuery before I init the map again. This gets rid of the error message in the console, but the map still won't show up, only on refresh.

    var shopLocMap;

    function buildMap() {
      $('div#shoplocmap').remove();
      var setmap = '<div id="shoplocmap"></div>';
      $('div#smap').append(setmap);
      var shopLocMap = L.map('shoplocmap').setView([szeles, hossz], 13);

      L.tileLayer('http://{s}.tile.cloudmade.com/ccb2a690ff654f37ae8ae3ee5c635313/997/256/{z}/{x}/{y}.png', {
          attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="http://cloudmade.com">CloudMade</a>',
          maxZoom: 18
      }).addTo(shopLocMap);
    };

I've also tried to set the shopLocMap variable to null before init, but it didn't solve the problem.

UPDATE 2
I tried MapQuest. The error is the same. The map only appears after refresh, but there is a "small" difference. When I visit the first shop or refresh at any other shop page the map appears as expected. When I go to another shop the map won't show up there, but when I go back to the first shop I viewed or the one where I previously refreshed I can see the map of the second shop I visited under the first map. I attached a screenvideo which shows this effect.
It seems that when the data-init is inside a remote view and that remote view loads multiple times with different data, it runs the map init function multiple times. But I still don't understand why google maps or leaflet maps don't work if I first delete the map container then create it with jQuery again. In the case of google maps I've also tried to set the map variable to null, but it did not help.

Any ideas to solve this?

Best Wishes,
Mate
0
Petyo
Telerik team
answered on 25 Sep 2013, 07:10 AM
Hi,

Can you please try to re-create the problem in a jsbin sample? I don't think that remote views or dynamic data matter for the case to be reproduced. In that way, we will be able to accurately determine the problem and provide a solution for it.

Regards,
Petyo
Telerik
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
Tags
General Discussions
Asked by
Mate
Top achievements
Rank 2
Answers by
Alexander Valchev
Telerik team
Mate
Top achievements
Rank 2
Petyo
Telerik team
Share this question
or