1

In implementing an advanced shiny popup solution from K. Rohde, I've run into a problem using a navbarPage and tabPanels. Per the linked solution, the following code is in the appropriate tabPanel:

tabPanel("Multiple Locations",
  uiOutput("script"),
  tags$div(id="garbage"),
  ...rest of UI...
)

If Multiple Locations is the only tabPanel, or if navbarPage(selected="Multiple Locations") is set, everything works wonderfully (I have implemented nearly identically to the example in the linked solution). But if navbarPage(selected="someOtherPanel") is set, and the user subsequently navigates to the Multiple Locations tabPanel, the popups show up empty.

I've tried moving the uiOutput("script") and tags$div(id="garbage") lines into the other tabPanel (the one that's active on startup), I've tried moving it right under the navbarPage (before any tabPanel elements), and I've tried duplicating it in those locations as well, to no avail. Moving it right under the navbarMenu() appears to insert a div into the menu itself. Here's the setup that works:

ui<-navbarPage(id="page", selected="Multiple Locations",
  tags$head(tags$link(href="myfavicon.ico", rel="icon"),
            includeCSS("www/style.css"),
            tags$script(type="text/javascript", src = "baranim.js")
            ),
  navbarMenu("Explorer",
    tabPanel("Single Location",
      ...UI elements...
    ),
    tabPanel("Multiple Locations",
        uiOutput("script"),
        tags$div(id="garbage"),
        ...UI elements...
    )
  )
)

Though the app is not yet complete, I don't imagine I'll have users starting on the Multiple Locations tabPanel. But clearly, I'd still like the popups to function.

Many thanks to K. Rohde for the original solution.

Community
  • 1
  • 1
Andrew Brick
  • 115
  • 8

1 Answers1

3

First off, I really appreciate that you liked my post. This is very encouraging.

So I tried to reconstruct your situation and managed to reproduce the behavior you explained. My detective work showed, that you have another leaflet inside the Single Locations tab. Is that correct? The solution you linked was only designed for one single leaflet. It addresses the div of class leaflet-popup-pane, but if there are more than one, only the first one which is rendered, will be adressed. This explains the behavior with the tab choice in the beginning.

I have modified the script such that all available leaflet-popup-panes are addressed:

output$script <- renderUI({
  tags$script(HTML('
    var observer = new MutationObserver(function(mutations) {
      mutations.forEach(function(mutation) {
        if(mutation.addedNodes.length > 0){
          Shiny.bindAll(".leaflet-popup-content");
        };
        if(mutation.removedNodes.length > 0){
          var popupNode = mutation.removedNodes[0].childNodes[1].childNodes[0].childNodes[0];

          var garbageCan = document.getElementById("garbage");
          garbageCan.appendChild(popupNode);

          Shiny.unbindAll("#garbage");
          garbageCan.innerHTML = "";
        };
      });    
    });

    $(".leaflet-popup-pane").each(function() {
      observer.observe(this, {childList: true});
    });
  '))
})

This should do the trick.

Some advice on placement: The garbage-div must only be placed once, to avoid duplicate Id problems. But it can be placed anywhere in the ui. If you have multiple leaflets with expanded popups, place one script output beneath each of those (or one beneath the last if there are several on the same page). Especially with tabPanels, this ensures that your leaflets have been fully rendered when the script is executed.

Please comment, if this doesn't solve your problem or if there is something I missed.

K. Rohde
  • 9,439
  • 1
  • 31
  • 51
  • Yes, you are correct that I have multiple leaflets in the app. I'll give this a shot when I get home from my work trip. Thanks! – Andrew Brick Jun 12 '16 at 12:26
  • thanks for the answer; I have adapted to potentially add sparklines in mapview https://github.com/environmentalinformatics-marburg/mapview/issues/30 – timelyportfolio Jun 26 '16 at 12:59
  • Wondering if you @K.Rohde might know how/why these popups would be offset from the default position. I had gotten around it with `.leaflet-popup.leaflet-zoom-animated { left: -170px !important; }` in my stylesheet, where 170px is (about) half the width of my popup. But that's ghetto and is now interfering with other popups I've added. inlineCSS doesn't seem to help, and I can't find a shiny option to pass a custom popup anchor. If having the popup be offset isn't expected with this solution, perhaps the culprit is elsewhere in my code. – Andrew Brick Jul 04 '16 at 21:04
  • Another issue coming up in testing this new solution: if a marker is clicked, and the popup is closed, and then the same marker is clicked, the popup appears and immediately disappears. The problem persists until another marker is clicked (or if, in my app, another marker is added to the map.) Each subsequent time a single marker is clicked twice (three times, technically, as the second click dismisses the popup), popups exhibit the same appear/disappear behavior. – Andrew Brick Jul 04 '16 at 21:43
  • @AndrewBrick Hm.. sounds odd. From the top of my head, I would think the first one is related to unset dimensions of the popup at the time its initially rendered. And the second could be some delay in the mutationObserver. I think it would be best if you opened another Question with a sample code and we can try to debug this. – K. Rohde Jul 05 '16 at 07:02