ebailey78 / shinyBS

Twitter Bootstrap Components for Shiny
182 stars 47 forks source link

popify not showing buttons #120

Open LukasK13 opened 4 years ago

LukasK13 commented 4 years ago

Since version 1.4.0 shiny is now using bootstrap with version 3.4.1. This version of bootstrap introduced the sanitation of popover content. This causes some contents to be not rendered (see also this issue). In order to be able to render for example buttons in a popover, this sanitation needs to be disabled, hence it should be possible to include boolean values in the options:

popify(actionButton("foo", "bar"), "Title", "<button>Test</button>", options = list(sanitize = F))

Currently this will be translated into the following JSON-object: {'title': 'Title', 'content': '<button>Test</button>', 'sanitize': 'FALSE'} Please note that the boolean value is treated as string. The list of objects should be checked for the file type for proper conversion to JSON. Alternatively, the library jsonlite could be used for the conversion.

LukasK13 commented 4 years ago

As this repository doesn't seem very active, I developed the following temporary fix: Overwrite the function popify:

#'popify
#'
#'\code{popify} can be wrapped around any shiny UI element to add a popover to the
#'wrapped element. This should be a safer way to add popovers to elements created with
#'\code{\link{renderUI}}.
#'
#'@param el A shiny UI element.
#'@param title The title of the popover.
#'@param content The main content of the popover.
#'@param placement Where the popover should appear relative to its target 
#'(\code{top}, \code{bottom}, \code{left}, or \code{right}). Defaults to \code{"bottom"}.
#'@param trigger What action should cause the popover to appear? (\code{hover},
#'\code{focus}, \code{click}, or \code{manual}). Defaults to \code{"hover"}.
#'@param options A named list of additional options to be set on the popover.
#'
#'@export
popify <- function(el, title, content, placement = "bottom", trigger = "hover", options = NULL) {
  pop = do.call(shinyBS::popify, args = list(el, title, content, placement, trigger, options))
  pop[[2]]$children[[1]][[1]] = gsub("shinyBS.addTooltip", "addTooltip_sanitize", pop[[2]]$children[[1]][[1]])
  return(pop)
}

Add the following JavaScript code to the app:

addTooltip_sanitize = function(id, type, opts) {
  var $id = shinyBS.getTooltipTarget(id);
  var dopts = {html: true, sanitize: false};
  opts = $.extend(opts, dopts);

  if(type == "tooltip") {
    $id.tooltip("destroy");
    $id.tooltip(opts);
  } else if(type == "popover") {
    $id.popover("destroy");
    $id.popover(opts);
  }
};
almerzybyl commented 1 year ago

Hi,

I saved the JavaScript code as popify_mod.js in my www folder and then put the following at the beginning of my ui:

tags$script(src = "popify_mod.js")

I have put the function overwrite at different locations (ui, server, before both), I still don't get it to work. I run Bootswatch version 5 themes but when I change my bs_theme() call to version 3, it works. Not for versions 4 and 5 though.

Am I doing a mistake on my end or have there been developments to make this solution not work anymore? Any recommendations about other functions instead of popify to use for the same purpose (graphics when hovering over object)?