From 617a4f403bde610ea124b43bb9a2def9bb180e4d Mon Sep 17 00:00:00 2001 From: DavidNojnarg Date: Fri, 16 Jun 2023 20:35:45 +0000 Subject: [PATCH 1/7] bump dev --- CRAN-SUBMISSION | 6 +++--- DESCRIPTION | 2 +- NEWS.md | 4 ++++ _pkgdown.yml | 2 +- inst/{bs4Dash-2.3.0 => bs4Dash-2.4.0.9000}/bs4Dash.css | 0 inst/{bs4Dash-2.3.0 => bs4Dash-2.4.0.9000}/bs4Dash.js | 0 inst/{bs4Dash-2.3.0 => bs4Dash-2.4.0.9000}/bs4Dash.min.js | 0 .../bs4Dash.min.js.map | 0 .../accordions-binding.js | 0 srcjs/{bs4Dash-2.3.0 => bs4Dash-2.4.0.9000}/cards.js | 0 srcjs/{bs4Dash-2.3.0 => bs4Dash-2.4.0.9000}/controlbar.js | 0 srcjs/{bs4Dash-2.3.0 => bs4Dash-2.4.0.9000}/feedbacks.js | 0 srcjs/{bs4Dash-2.3.0 => bs4Dash-2.4.0.9000}/leftSidebar.js | 0 .../{bs4Dash-2.3.0 => bs4Dash-2.4.0.9000}/miscellaneous.js | 0 srcjs/{bs4Dash-2.3.0 => bs4Dash-2.4.0.9000}/navbar.js | 0 .../output-bindings.js | 0 .../pagination-widget.js | 0 srcjs/{bs4Dash-2.3.0 => bs4Dash-2.4.0.9000}/tabs.js | 0 srcjs/{bs4Dash-2.3.0 => bs4Dash-2.4.0.9000}/userMessages.js | 0 19 files changed, 9 insertions(+), 5 deletions(-) rename inst/{bs4Dash-2.3.0 => bs4Dash-2.4.0.9000}/bs4Dash.css (100%) rename inst/{bs4Dash-2.3.0 => bs4Dash-2.4.0.9000}/bs4Dash.js (100%) rename inst/{bs4Dash-2.3.0 => bs4Dash-2.4.0.9000}/bs4Dash.min.js (100%) rename inst/{bs4Dash-2.3.0 => bs4Dash-2.4.0.9000}/bs4Dash.min.js.map (100%) rename srcjs/{bs4Dash-2.3.0 => bs4Dash-2.4.0.9000}/accordions-binding.js (100%) rename srcjs/{bs4Dash-2.3.0 => bs4Dash-2.4.0.9000}/cards.js (100%) rename srcjs/{bs4Dash-2.3.0 => bs4Dash-2.4.0.9000}/controlbar.js (100%) rename srcjs/{bs4Dash-2.3.0 => bs4Dash-2.4.0.9000}/feedbacks.js (100%) rename srcjs/{bs4Dash-2.3.0 => bs4Dash-2.4.0.9000}/leftSidebar.js (100%) rename srcjs/{bs4Dash-2.3.0 => bs4Dash-2.4.0.9000}/miscellaneous.js (100%) rename srcjs/{bs4Dash-2.3.0 => bs4Dash-2.4.0.9000}/navbar.js (100%) rename srcjs/{bs4Dash-2.3.0 => bs4Dash-2.4.0.9000}/output-bindings.js (100%) rename srcjs/{bs4Dash-2.3.0 => bs4Dash-2.4.0.9000}/pagination-widget.js (100%) rename srcjs/{bs4Dash-2.3.0 => bs4Dash-2.4.0.9000}/tabs.js (100%) rename srcjs/{bs4Dash-2.3.0 => bs4Dash-2.4.0.9000}/userMessages.js (100%) diff --git a/CRAN-SUBMISSION b/CRAN-SUBMISSION index 2b408937..c8861df0 100644 --- a/CRAN-SUBMISSION +++ b/CRAN-SUBMISSION @@ -1,3 +1,3 @@ -Version: 2.2.1 -Date: 2022-12-19 15:51:44 UTC -SHA: 1119ebead95ee388e684a36791707ad63b6e2785 \ No newline at end of file +Version: 2.3.0 +Date: 2023-06-15 20:15:12 UTC +SHA: f0452c4292e86a20aeabe440ec587c263e1811b4 diff --git a/DESCRIPTION b/DESCRIPTION index c087ebea..6d10a7ba 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: bs4Dash Type: Package Title: A 'Bootstrap 4' Version of 'shinydashboard' -Version: 2.3.0 +Version: 2.4.0.9000 Authors@R: c( person("David", "Granjon", email = "dgranjon@ymail.com", role = c("aut", "cre")), person(family = "RinteRface", role = "cph"), diff --git a/NEWS.md b/NEWS.md index c9c6001b..fa361468 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,7 @@ +# bs4Dash 2.4.0.9000 + +TBD + # bs4Dash 2.3.0 ## New feature diff --git a/_pkgdown.yml b/_pkgdown.yml index f8641995..94b212f8 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -252,7 +252,7 @@ articles: news: releases: - - text: "bs4Dash 2.3.0" + - text: "bs4Dash 2.4.0.9000" - text: "bs4Dash 2.2.1" - text: "bs4Dash 2.1.0" - text: "bs4Dash 2.0.3" diff --git a/inst/bs4Dash-2.3.0/bs4Dash.css b/inst/bs4Dash-2.4.0.9000/bs4Dash.css similarity index 100% rename from inst/bs4Dash-2.3.0/bs4Dash.css rename to inst/bs4Dash-2.4.0.9000/bs4Dash.css diff --git a/inst/bs4Dash-2.3.0/bs4Dash.js b/inst/bs4Dash-2.4.0.9000/bs4Dash.js similarity index 100% rename from inst/bs4Dash-2.3.0/bs4Dash.js rename to inst/bs4Dash-2.4.0.9000/bs4Dash.js diff --git a/inst/bs4Dash-2.3.0/bs4Dash.min.js b/inst/bs4Dash-2.4.0.9000/bs4Dash.min.js similarity index 100% rename from inst/bs4Dash-2.3.0/bs4Dash.min.js rename to inst/bs4Dash-2.4.0.9000/bs4Dash.min.js diff --git a/inst/bs4Dash-2.3.0/bs4Dash.min.js.map b/inst/bs4Dash-2.4.0.9000/bs4Dash.min.js.map similarity index 100% rename from inst/bs4Dash-2.3.0/bs4Dash.min.js.map rename to inst/bs4Dash-2.4.0.9000/bs4Dash.min.js.map diff --git a/srcjs/bs4Dash-2.3.0/accordions-binding.js b/srcjs/bs4Dash-2.4.0.9000/accordions-binding.js similarity index 100% rename from srcjs/bs4Dash-2.3.0/accordions-binding.js rename to srcjs/bs4Dash-2.4.0.9000/accordions-binding.js diff --git a/srcjs/bs4Dash-2.3.0/cards.js b/srcjs/bs4Dash-2.4.0.9000/cards.js similarity index 100% rename from srcjs/bs4Dash-2.3.0/cards.js rename to srcjs/bs4Dash-2.4.0.9000/cards.js diff --git a/srcjs/bs4Dash-2.3.0/controlbar.js b/srcjs/bs4Dash-2.4.0.9000/controlbar.js similarity index 100% rename from srcjs/bs4Dash-2.3.0/controlbar.js rename to srcjs/bs4Dash-2.4.0.9000/controlbar.js diff --git a/srcjs/bs4Dash-2.3.0/feedbacks.js b/srcjs/bs4Dash-2.4.0.9000/feedbacks.js similarity index 100% rename from srcjs/bs4Dash-2.3.0/feedbacks.js rename to srcjs/bs4Dash-2.4.0.9000/feedbacks.js diff --git a/srcjs/bs4Dash-2.3.0/leftSidebar.js b/srcjs/bs4Dash-2.4.0.9000/leftSidebar.js similarity index 100% rename from srcjs/bs4Dash-2.3.0/leftSidebar.js rename to srcjs/bs4Dash-2.4.0.9000/leftSidebar.js diff --git a/srcjs/bs4Dash-2.3.0/miscellaneous.js b/srcjs/bs4Dash-2.4.0.9000/miscellaneous.js similarity index 100% rename from srcjs/bs4Dash-2.3.0/miscellaneous.js rename to srcjs/bs4Dash-2.4.0.9000/miscellaneous.js diff --git a/srcjs/bs4Dash-2.3.0/navbar.js b/srcjs/bs4Dash-2.4.0.9000/navbar.js similarity index 100% rename from srcjs/bs4Dash-2.3.0/navbar.js rename to srcjs/bs4Dash-2.4.0.9000/navbar.js diff --git a/srcjs/bs4Dash-2.3.0/output-bindings.js b/srcjs/bs4Dash-2.4.0.9000/output-bindings.js similarity index 100% rename from srcjs/bs4Dash-2.3.0/output-bindings.js rename to srcjs/bs4Dash-2.4.0.9000/output-bindings.js diff --git a/srcjs/bs4Dash-2.3.0/pagination-widget.js b/srcjs/bs4Dash-2.4.0.9000/pagination-widget.js similarity index 100% rename from srcjs/bs4Dash-2.3.0/pagination-widget.js rename to srcjs/bs4Dash-2.4.0.9000/pagination-widget.js diff --git a/srcjs/bs4Dash-2.3.0/tabs.js b/srcjs/bs4Dash-2.4.0.9000/tabs.js similarity index 100% rename from srcjs/bs4Dash-2.3.0/tabs.js rename to srcjs/bs4Dash-2.4.0.9000/tabs.js diff --git a/srcjs/bs4Dash-2.3.0/userMessages.js b/srcjs/bs4Dash-2.4.0.9000/userMessages.js similarity index 100% rename from srcjs/bs4Dash-2.3.0/userMessages.js rename to srcjs/bs4Dash-2.4.0.9000/userMessages.js From 6d9d4f45f33ff25aebc0ca8507e8653b98603012 Mon Sep 17 00:00:00 2001 From: DavidNojnarg Date: Sat, 17 Jun 2023 10:08:59 +0000 Subject: [PATCH 2/7] Will fix #302. --- NEWS.md | 7 ++++++- R/dashboardControlbar.R | 7 +++++-- R/dashboardSidebar.R | 17 +++++++++++++++-- R/utils.R | 8 ++++++++ man/dashboardControlbar.Rd | 7 ++++--- man/dashboardSidebar.Rd | 7 ++++--- 6 files changed, 42 insertions(+), 11 deletions(-) diff --git a/NEWS.md b/NEWS.md index fa361468..bbb57e65 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,11 @@ # bs4Dash 2.4.0.9000 -TBD +## Breaking change (potential) + +- Fix #302: both `dashboardSidebar()` and `dashboardControlbar()` default __skin__ value is NULL. +This allows them to inherit from the parent `dashboardPage()` __dark__ parameter and have either +a full light or full dark skin. If not NULL, the corresponding skin is applied, regardless of the +parent `dashboardPage()`. # bs4Dash 2.3.0 diff --git a/R/dashboardControlbar.R b/R/dashboardControlbar.R index bad92aa4..fd4b8fca 100644 --- a/R/dashboardControlbar.R +++ b/R/dashboardControlbar.R @@ -10,7 +10,8 @@ #' in pixels, or a string that specifies the width in CSS units. 250 px by default. #' @param collapsed Whether the control bar on the right side is collapsed or not at start. TRUE by default. #' @param overlay Whether the sidebar covers the content when expanded. Default to TRUE. -#' @param skin Controlbar skin. "dark" or "light". +#' @param skin Controlbar skin. "dark" or "light". Matches the \link{dashboardPage} dark parameter +#' value. #' @param pinned Whether to block the controlbar state (TRUE or FALSE). Default to NULL. #' #' @author David Granjon, \email{dgranjon@@ymail.com} @@ -19,9 +20,11 @@ #' #' @export bs4DashControlbar <- function(..., id = NULL, disable = FALSE, width = 250, - collapsed = TRUE, overlay = TRUE, skin = "dark", + collapsed = TRUE, overlay = TRUE, skin = NULL, pinned = NULL) { if (is.null(id)) id <- "controlbarId" + + skin <- set_sidebar_skin(skin) controlbarTag <- shiny::tags$aside( class = paste0("control-sidebar control-sidebar-", skin), diff --git a/R/dashboardSidebar.R b/R/dashboardSidebar.R index 99e6e5ef..f35b93f0 100644 --- a/R/dashboardSidebar.R +++ b/R/dashboardSidebar.R @@ -8,7 +8,8 @@ #' @param width The width of the sidebar. This must either be a number which #' specifies the width in pixels, or a string that specifies the width in CSS #' units. -#' @param skin Sidebar skin. "dark" or "light". +#' @param skin Sidebar skin. "dark" or "light". Matches the \link{dashboardPage} dark parameter +#' value. #' @param status Sidebar status. Valid statuses are defined as follows: #' \itemize{ #' \item \code{primary}: \Sexpr[results=rd, stage=render]{bs4Dash:::rd_color_tag("#007bff")}. @@ -47,10 +48,14 @@ #' #' @export bs4DashSidebar <- function(..., disable = FALSE, width = NULL, - skin = "dark", status = "primary", + skin = NULL, status = "primary", elevation = 4, collapsed = FALSE, minified = TRUE, expandOnHover = TRUE, fixed = TRUE, id = NULL, customArea = NULL) { + # When no skin is specified, sidebar color must match the dashboard skin color + # by default which is set in the dashboardPage function. + skin <- set_sidebar_skin(skin) + if (is.null(id)) id <- "sidebarId" # If we're restoring a bookmarked app, this holds the value of whether or not the # sidebar was collapsed. If this is not the case, the default is whatever the user @@ -151,6 +156,14 @@ bs4DashSidebar <- function(..., disable = FALSE, width = NULL, } +#' @keywords internal +set_sidebar_skin <- function(skin) { + is_dark_skin <- get_parent_args()$dark + if (is.null(skin)) { + skin <- if (!is_dark_skin) "light" else "dark" + } + skin +} #' Toggle sidebar state diff --git a/R/utils.R b/R/utils.R index 464f7af2..256a4423 100644 --- a/R/utils.R +++ b/R/utils.R @@ -742,3 +742,11 @@ app_container <- function(url, deps = FALSE) { } } } + +# Get parent function arguments +get_parent_args <- function() { + cl <- sys.call(-3) + f <- get(as.character(cl[[1]]), mode = "function", sys.frame(-2)) + cl <- match.call(definition = f, call = cl) + as.list(cl)[-1] +} diff --git a/man/dashboardControlbar.Rd b/man/dashboardControlbar.Rd index 7dcf52ed..c91a0b4a 100644 --- a/man/dashboardControlbar.Rd +++ b/man/dashboardControlbar.Rd @@ -16,7 +16,7 @@ bs4DashControlbar( width = 250, collapsed = TRUE, overlay = TRUE, - skin = "dark", + skin = NULL, pinned = NULL ) @@ -47,7 +47,7 @@ dashboardControlbar( width = 250, collapsed = TRUE, overlay = TRUE, - skin = "dark", + skin = NULL, pinned = NULL ) } @@ -65,7 +65,8 @@ in pixels, or a string that specifies the width in CSS units. 250 px by default. \item{overlay}{Whether the sidebar covers the content when expanded. Default to TRUE.} -\item{skin}{Controlbar skin. "dark" or "light".} +\item{skin}{Controlbar skin. "dark" or "light". Matches the \link{dashboardPage} dark parameter +value.} \item{pinned}{Whether to block the controlbar state (TRUE or FALSE). Default to NULL.} diff --git a/man/dashboardSidebar.Rd b/man/dashboardSidebar.Rd index 95bf14ba..9db3a285 100644 --- a/man/dashboardSidebar.Rd +++ b/man/dashboardSidebar.Rd @@ -23,7 +23,7 @@ bs4DashSidebar( ..., disable = FALSE, width = NULL, - skin = "dark", + skin = NULL, status = "primary", elevation = 4, collapsed = FALSE, @@ -85,7 +85,7 @@ dashboardSidebar( ..., disable = FALSE, width = NULL, - skin = "dark", + skin = NULL, status = "primary", elevation = 4, collapsed = FALSE, @@ -152,7 +152,8 @@ updateTabItems( specifies the width in pixels, or a string that specifies the width in CSS units.} -\item{skin}{Sidebar skin. "dark" or "light".} +\item{skin}{Sidebar skin. "dark" or "light". Matches the \link{dashboardPage} dark parameter +value.} \item{status}{Sidebar status. Valid statuses are defined as follows: \itemize{ From 8fd533916e4431538bea6ad5b12b41ee78ea773a Mon Sep 17 00:00:00 2001 From: Mohammed Ali Date: Mon, 14 Aug 2023 21:29:15 +0300 Subject: [PATCH 3/7] - Fixed closable alert missing title issue --- inst/bs4Dash-2.4.0.9000/bs4Dash.js | 4 +++- inst/bs4Dash-2.4.0.9000/bs4Dash.min.js | 2 +- inst/bs4Dash-2.4.0.9000/bs4Dash.min.js.map | 2 +- srcjs/bs4Dash-2.4.0.9000/feedbacks.js | 4 +++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/inst/bs4Dash-2.4.0.9000/bs4Dash.js b/inst/bs4Dash-2.4.0.9000/bs4Dash.js index 1cfcc85b..251493ac 100644 --- a/inst/bs4Dash-2.4.0.9000/bs4Dash.js +++ b/inst/bs4Dash-2.4.0.9000/bs4Dash.js @@ -932,12 +932,14 @@ $(function () { break; default: console.warn(`${config.status} does not belong to allowed statuses!`) } + + closeButton = ''; if (config.closable) { closeButton = '' } - titleTag = `
` + titleTag = `
${config.title}
` contentTag = config.content; alertTag = `
')),t.collapsible=!0):($(a).find('[data-card-widget = "collapse"]').remove(),t.collapsible=!1)),e.options.hasOwnProperty("closable")&&e.options.closable!==t.closable&&(e.options.closable?0===$(a).find('[data-card-widget = "remove"]').length&&(0===$(a).find('[data-card-widget = "maximize"]').length?$(a).find(".card-tools.float-right").append($('')):$('').insertBefore($(a).find('[data-card-widget = "maximize"]')),t.closable=!0):($(a).find('[data-card-widget = "remove"]').remove(),t.closable=!1)),e.options.hasOwnProperty("maximizable")&&e.options.maximizable!==t.maximizable&&(e.options.maximizable?0===$(a).find('[data-card-widget = "maximize"]').length&&($(a).find(".card-tools.float-right").append($('')),t.maximizable=!0):($(a).find('[data-card-widget = "maximize"]').remove(),t.maximizable=!1)),e.options.hasOwnProperty("solidHeader")&&!n&&!i)if(e.options.solidHeader!==t.solidHeader&&$(a).hasClass("card-outline"))$(a).removeClass("card-outline"),t.solidHeader=!0;else if($(a).hasClass("card-outline")||e.options.solidHeader){if($(a).hasClass("card-outline")){o=t.status||e.options.status;e.options.background&&o?($(a).removeClass("card-outline"),t.solidHeader=!0):t.background&&o&&($(a).removeClass("card-outline"),t.solidHeader=!1)}}else{var o=t.status||e.options.status;e.options.background&&o&&(null!==e.options.background||t.background&&o)||($(a).addClass("card-outline"),t.solidHeader=!1)}if(e.options.hasOwnProperty("status")&&!n&&e.options.status!==t.status){var d,l,c;if(null===e.options.status&&null!==t.status){if(i||$(a).removeClass("card-"+t.status),$(a).hasClass("card-outline")&&!i&&$(a).addClass("card-outline"),e.options.background){var u=e.options.background;validStatusesPlus.indexOf(u)>-1?$(a).find(".btn-tool").addClass("bg-"+u):validStatuses.indexOf(u)>-1&&$(a).find(".btn-tool").addClass("btn-"+u)}}else e.options.status&&(i?(l="bg-",e.options.gradient&&(l+="gradient-"),l+=e.options.status,$(a).find(".widget-user-header").addClass(l)):(l="card-"+e.options.status,$(a).addClass(l)),t.status&&(i?(d="bg-",t.gradient&&(d+="gradient-"),d+=t.status,$(a).find(".widget-user-header").removeClass(d)):(d="card-"+t.status,$(a).removeClass(d))),$(a).hasClass("card-outline")&&!i||(validStatusesPlus.indexOf(e.options.status)>-1?$(a).find(".btn-tool").addClass("bg-"+e.options.status):validStatuses.indexOf(e.options.status)>-1&&$(a).find(".btn-tool").addClass("btn-"+e.options.status)));(t.status||t.background)&&(t.status?c=t.status:t.background&&(c=t.background),validStatusesPlus.indexOf(c)>-1?$(a).find(".btn-tool").removeClass("bg-"+c):validStatuses.indexOf(c)>-1&&$(a).find(".btn-tool").removeClass("btn-"+c)),t.status=e.options.status}if(e.options.hasOwnProperty("background")&&e.options.background!==t.background){var b="bg-";if(newBgClass=b,t.background){if(t.gradient&&(b+="gradient-"),b+=t.background,i&&!t.status&&!e.options.status){var h=$(a).find(".widget-user-header");$(h).removeClass(b)}$(a).removeClass(b)}if(e.options.background){if((t.gradient||e.options.gradient)&&(newBgClass+="gradient-"),newBgClass+=e.options.background,i&&!t.status&&!e.options.status){h=$(a).find(".widget-user-header");$(h).addClass(newBgClass)}$(a).addClass(newBgClass)}t.gradient!==e.options.gradient&&void 0!==e.options.gradient&&(t.gradient=e.options.gradient),t.background=e.options.background}e.options.hasOwnProperty("width")&&e.options.width!==t.width&&(this._updateWidth(a,t.width,e.options.width),t.width=e.options.width),e.options.hasOwnProperty("height")&&e.options.height!==t.height&&(null===e.options.height?$(a).find(".card-body").css("height",""):$(a).find(".card-body").css("height",e.options.height),t.height=e.options.height),$(a).parent().find("script[data-for='"+a.id+"']").replaceWith('\"\n );\n } else {\n if (value != \"restore\") {\n if ($(el).css(\"display\") != \"none\") {\n $(el).CardWidget(value);\n }\n } else {\n $(el).show();\n // this is needed so that the last event handler is considered\n // in the subscribe method.\n $(el).trigger(\"shown\");\n }\n }\n },\n receiveMessage: function(el, data) {\n this.setValue(el, data);\n $(el).trigger(\"change\");\n },\n\n subscribe: function(el, callback) {\n $(el).on(\"expanded.lte.cardwidget collapsed.lte.cardwidget\", function(e) {\n // set a delay so that SHiny get the input value when the collapse animation\n // is finished.\n setTimeout(function() {\n callback();\n }, 500);\n });\n\n $(el).on(\"maximized.lte.cardwidget minimized.lte.cardwidget\", function(e) {\n callback();\n });\n\n $(el).on(\"removed.lte.cardwidget\", function(e) {\n setTimeout(function() {\n callback();\n }, 500);\n });\n // we need to split removed and shown event since shown is immediate whereas close\n // takes some time\n $(el).on(\"shown.cardBinding\", function(e) {\n callback();\n });\n\n // handle change event triggered in the setValue method\n $(el).on(\"change.cardBinding\", function(event) {\n setTimeout(function() {\n callback();\n }, 500);\n });\n },\n\n unsubscribe: function(el) {\n $(el).off(\".cardBinding\");\n }\n});\n\nShiny.inputBindings.register(cardBinding);\n\n// Card sidebar input binding\nvar cardSidebarBinding = new Shiny.InputBinding();\n$.extend(cardSidebarBinding, {\n initialize: function(el) {\n // erase default to avoid seeing moving sidebars on initialization\n $(\".direct-chat-contacts, .direct-chat-messages\").css({\n transition: \"transform .0s ease-in-out\"\n });\n\n var background = $(el).attr(\"data-background\")\n ? $(el).attr(\"data-background\")\n : \"#343a40\";\n var width = $(el).attr(\"data-width\")\n ? parseInt($(el).attr(\"data-width\"))\n : 100;\n var closeTranslationRate = (100 * 100) / width;\n var contacts = $(el)\n .closest(\".direct-chat\")\n .find(\".direct-chat-contacts\");\n\n // apply width and background\n $(contacts).css({\n background: `${background}`,\n width: `${width}%`\n });\n\n // If start open, apply openTranslationRate else apply closeTranslationRate ...\n if ($(el).attr(\"data-start-open\") === \"true\") {\n var openTranslationRate = closeTranslationRate - 100;\n $(contacts).css({ transform: `translate(${openTranslationRate}%, 0)` });\n } else {\n $(contacts).css({ transform: `translate(${closeTranslationRate}%, 0)` });\n }\n\n // Restore for better transitions\n setTimeout(function() {\n $(\".direct-chat-contacts, .direct-chat-messages\").css({\n transition: \"transform .5s ease-in-out\"\n });\n }, 300);\n \n // Easyclose feature\n if ($(el).attr(\"data-easy-close\") === \"true\") {\n $(document).mouseup(function(e) {\n var container = $(\".direct-chat-contacts\");\n var openContainer = $(\".direct-chat-contacts-open\");\n // if the target of the click isn't the container nor a descendant of the container and also not if the filter symbol was clicke d\n if (!container.is(e.target) && \n container.has(e.target).length === 0 && \n $(e.target).parents('.card-tools').length !== 1) {\n openContainer\n .find(\"[data-widget='chat-pane-toggle']\")\n .click();\n }\n }); \n }\n },\n\n find: function(scope) {\n return $(scope).find('[data-widget=\"chat-pane-toggle\"]');\n },\n\n // Given the DOM element for the input, return the value\n getValue: function(el) {\n var cardWrapper = $(el).closest(\".card\");\n return $(cardWrapper).hasClass(\"direct-chat-contacts-open\");\n },\n\n // see updatebs4Card\n receiveMessage: function(el, data) {\n // In theory, adminLTE3 has a builtin function\n // we could use $(el).DirectChat('toggle');\n // However, it does not update the related input.\n // The toggled.lte.directchat event seems to be broken.\n $(el).trigger(\"click\");\n $(el).trigger(\"shown\");\n },\n\n subscribe: function(el, callback) {\n var self = this;\n $(el).on(\"click\", function(e) {\n var width = $(el).attr(\"data-width\")\n ? parseInt($(el).attr(\"data-width\"))\n : 100;\n var closeTranslationRate = (100 * 100) / width;\n var openTranslationRate = closeTranslationRate - 100;\n // set a delay so that Shiny get the input value when the collapse animation\n // is finished.\n var target = e.currentTarget;\n setTimeout(function(e = target) {\n // apply correct translation rate depending on current state\n var contacts = $(e)\n .closest(\".direct-chat\")\n .find(\".direct-chat-contacts\");\n if (self.getValue(el)) {\n $(contacts).css({\n transform: `translate(${openTranslationRate}%, 0)`\n });\n } else {\n $(contacts).css({\n transform: `translate(${closeTranslationRate}%, 0)`\n });\n }\n callback();\n }, 10);\n });\n },\n\n unsubscribe: function(el) {\n $(el).off(\".cardSidebarBinding\");\n }\n});\n\nShiny.inputBindings.register(cardSidebarBinding);\n","$(function() {\n \n // required to show a toast when the controlbar is pinned \n // for the first time. Show once since it may be annoying ...\n var showToast = true;\n const controlbarToast = () => {\n if (showToast) {\n $(document).Toasts('create', {\n title: 'Controlbar is pinned',\n close: false,\n autohide: true,\n delay: 2000\n });\n showToast = false; \n }\n };\n\n // This prevent box content from going outside their container \n // when the control-bar is on push mode\n $(\"#controlbar-toggle\").on(\"click\",\n function() {\n if ($(\"body\").hasClass(\"control-sidebar-push-slide\")) {\n $(window).trigger(\"resize\"); \n }\n });\n \n \n // The code below hande the click out of the right control bar\n $(window).click(function(e) { \n // There is a potential conflict. This function detect any click outside\n // the controlbar and close if if it is not pinned. Yet, if we click on an action // button controlling the controlbar state (see updatebs4Controlbar), it is also outside the controlbar so the toggle event will be triggered twice. The controlbar will never close as shown in https://github.com/RinteRface/bs4Dash/issues/110. Below we make sure to leave the function as soon as a click on a button holding the class action button. This is not really a fix but a reasonable workaround.\n var isActionButton = $(e.target).hasClass(\"action-button\");\n if (isActionButton) return null;\n \n if($(\"aside.control-sidebar\").find(e.target).length === 0) {\n var pinned = $(\".control-sidebar\").attr(\"data-pin\");\n if (pinned === \"false\" || pinned === undefined) {\n $(\"body\").removeClass(\"control-sidebar-slide-open\"); \n // don't forget to refresh the input binding\n $(\"#controlbar-toggle\").trigger('collapsed.lte.controlsidebar');\n }\n } \n });\n \n // handle the pin button: toggle data-pin state\n $(\"#controlbarPin\").on('click', function() {\n var $pinIcon = $(this).children();\n $pinIcon.toggleClass(\"fa-rotate-90 fa-lg\");\n \n $(\".control-sidebar\").attr(\"data-pin\",\n $(\".control-sidebar\").attr(\"data-pin\") == \"false\" ? \"true\" : \"false\");\n // toggle right sidebar control depending on the datapin\n if ($(\".control-sidebar\").attr(\"data-pin\") === \"true\") {\n $pinIcon.css(\"color\", \"#007bff\");\n $(\"#controlbar-toggle\").addClass(\"disabled\");\n controlbarToast();\n } else {\n $(\"#controlbar-toggle\").removeClass(\"disabled\");\n $pinIcon.css(\"color\", \"\");\n }\n });\n\n\nvar init = true;\n\n // Input binding\n var controlbarBinding = new Shiny.InputBinding();\n \n $.extend(controlbarBinding, {\n \n find: function(scope) {\n return $(scope).find(\".control-sidebar\");\n },\n \n // Given the DOM element for the input, return the value\n getValue: function(el) {\n // Handles the pin \n var controlbarOpen = $(\"body\").hasClass(\"control-sidebar-slide-open\");\n var pinned = $(el).attr(\"data-pin\") === \"true\";\n if (controlbarOpen && pinned && init) {\n $(\"#controlbar-toggle\").addClass(\"disabled\");\n $(\"#controlbarPin\")\n .children()\n .css(\"color\", \"#007bff\");\n controlbarToast();\n init = false;\n }\n \n // this handles the case where the controlbar is not collapsed at start\n var controlbarCollapsed = $(el).attr('data-collapsed');\n if (controlbarCollapsed === \"false\") {\n $(\"#controlbar-toggle\").ControlSidebar('toggle');\n $(el).attr('data-collapsed', \"true\");\n return true;\n } else {\n return $(\"body\").hasClass(\"control-sidebar-slide-open\");\n }\n },\n // see updatebs4Controlbar\n receiveMessage: function(el, data) {\n $(\"#controlbar-toggle\").ControlSidebar('toggle');\n },\n \n subscribe: function(el, callback) {\n $(\"#controlbar-toggle\").on(\"collapsed.lte.controlsidebar expanded.lte.controlsidebar\", function(e) {\n $(el).trigger('shown');\n // add a delay so that Shiny get the input value \n // after the AdminLTE3 animation is finished!\n setTimeout(\n function() {\n callback();\n }, 10);\n });\n },\n \n unsubscribe: function(el) {\n $(el).off(\".controlbarBinding\");\n }\n });\n \n Shiny.inputBindings.register(controlbarBinding, \"bs4Dash.controlbarBinding\");\n \n // handle controlbar overlay\n var controlbarOverlay = $('.control-sidebar').attr('data-overlay');\n if (controlbarOverlay === \"false\") {\n $('body').addClass('control-sidebar-push-slide');\n }\n\n});","$(function () {\n // handle tooltip from the server side\n Shiny.addCustomMessageHandler('create-tooltip', function (message) {\n var tooltipTarget;\n if (message.id) {\n tooltipTarget = '#' + message.id;\n } else {\n if (message.selector) {\n tooltipTarget = message.selector;\n }\n }\n $(tooltipTarget)\n .addClass('has-tooltip')\n .tooltip(message.options);\n console.log(`'Tooltip created for ${tooltipTarget}'`);\n });\n\n Shiny.addCustomMessageHandler('remove-tooltip', function (message) {\n var tooltipTarget = '#' + message;\n\n // only destroys if popover exists\n if ($(tooltipTarget).hasClass('has-tooltip')) {\n $(tooltipTarget)\n .removeClass('has-tooltip')\n .tooltip('dispose');\n console.log(`'Tooltip destroyed for ${tooltipTarget}'`);\n }\n });\n\n // handle popover from the server side\n Shiny.addCustomMessageHandler('create-popover', function (message) {\n var popoverTarget;\n if (message.id) {\n popoverTarget = '#' + message.id;\n } else {\n if (message.selector) {\n popoverTarget = message.selector;\n }\n }\n // indicate target has popover. This is for removePopover to know\n // whether the popover exists\n $(popoverTarget)\n .addClass('has-popover')\n .popover(message.options);\n console.log(`'Popover created for ${popoverTarget}'`);\n });\n\n\n Shiny.addCustomMessageHandler('remove-popover', function (message) {\n var popoverTarget = '#' + message;\n\n // only destroys if popover exists\n if ($(popoverTarget).hasClass('has-popover')) {\n $(popoverTarget)\n .removeClass('has-popover')\n .popover('dispose');\n console.log(`'Popover destroyed for ${popoverTarget}'`);\n }\n });\n\n\n // handle builtin toasts\n Shiny.addCustomMessageHandler('toast', function (message) {\n $(document).Toasts('create', message);\n });\n\n // Create an alert\n Shiny.addCustomMessageHandler('create-alert', function (message) {\n // setup target\n var alertTarget;\n if (message.id) {\n alertTarget = `#${message.id}`;\n } else {\n if (message.selector) {\n alertTarget = message.selector;\n }\n }\n\n // build the tag from options\n var config = message.options, alertCl, alertTag, iconType, closeButton, titleTag, contentTag;\n alertCl = 'alert alert-dismissible';\n if (config.status !== undefined) {\n alertCl = `${alertCl} alert-${config.status}`;\n }\n if (config.elevation !== undefined) {\n alertCl = `${alertCl} elevation-${config.elevation}`;\n }\n\n switch (config.status) {\n case 'primary': iconType = 'info';\n break;\n case 'danger': iconType = 'ban';\n break;\n case 'info': iconType = 'info';\n break;\n case 'warning': iconType = 'warning';\n break;\n case 'success': iconType = 'check';\n break;\n default: console.warn(`${config.status} does not belong to allowed statuses!`)\n }\n\n if (config.closable) {\n closeButton = ''\n }\n\n titleTag = `
`\n contentTag = config.content;\n\n alertTag = `
\n ${closeButton}${titleTag}${contentTag}\n
`\n if (config.width !== undefined) {\n alertTag = `
${alertTag}
`\n }\n\n // add it to the DOM if no existing alert is found in the anchor\n if ($(`#${message.id}-alert`).length === 0) {\n $(alertTarget).append(alertTag);\n Shiny.setInputValue(message.id, true, { priority: 'event' });\n\n // add events only after element is inserted\n\n // callback -> give ability to perform more actions on the Shiny side\n // once the alert is closed\n $(`#${message.id}-alert`).on('closed.bs.alert', function () {\n Shiny.setInputValue(message.id, false, { priority: 'event' });\n });\n // Clicking on close button does not trigger any event.\n // Trigger the closed.bs.alert event.\n $('[data-dismiss=\"alert\"]').on('click', function () {\n var alertId = $(this).parent.attr('id');\n $(`#${alertId}.`).trigger('closed.bs.alert');\n });\n\n } else {\n console.warn(`${alertTarget} already has an alert!`);\n }\n });\n\n\n Shiny.addCustomMessageHandler('close-alert', function (message) {\n // only closes if element exists\n if ($(`#${message}-alert`).length > 0) {\n $(`#${message}-alert`).alert('close');\n } else {\n console.warn('Nothing to delete!');\n }\n });\n});","// When document is ready, if there is a sidebar menu with no activated tabs,\n// activate the one specified by `data-start-selected`, or if that's not\n// present, the first one.\nvar ensureActivatedTab = function() {\n // get the selected tabs\n var $tablinks = $(\".sidebar-menu a[data-toggle='tab']\");\n\n // If there are no tabs, $startTab.length will be 0.\n var $startTab = $tablinks.filter(\"[data-start-selected='1']\");\n if ($startTab.length === 0) {\n // If no tab starts selected, use the first one, if present\n $startTab = $tablinks.first();\n }\n\n // If there's a `data-start-selected` attribute and we can find a tab with\n // that name, activate it.\n if ($startTab.length !== 0) {\n // This is just in case the user renders the tabs in a renderUI that does not\n // print immediately in the DOM. We need a bit of a delay before telling which\n // tab to show ...\n if ($(\".sidebar-menu\").hasClass(\"bs4Dash-menu-output\")) {\n setTimeout(function() {\n // we need to initialize any treeview elements that were not inserted\n // in the DOM when adminlte was first initialized!\n adminlte.Treeview._jQueryInterface.call($('[data-widget=\"treeview\"]'), 'init');\n\n $startTab.tab(\"show\");\n }, 10);\n } else {\n $startTab.tab(\"show\");\n }\n \n\n // This is indirectly setting the value of the Shiny input by setting\n // an attribute on the html element it is bound to. We cannot use the\n // inputBinding's setValue() method here because this is called too\n // early (before Shiny has fully initialized)\n $(\".sidebarMenuSelectedTabItem\").attr(\n \"data-value\",\n $startTab.attr(\"data-value\")\n );\n }\n};\n\n// This function handles a special case in the AdminLTE sidebar: when there\n// is a sidebar-menu with items, and one of those items has sub-items, and\n// they are used for tab navigation. Normally, if one of the items is\n// selected and then a sub-item is clicked, both the item and sub-item will\n// retain the \"active\" class, so they will both be highlighted. This happens\n// because they're not designed to be used together for tab panels. This\n// code ensures that only one item will have the \"active\" class.\nvar deactivateOtherTabs = function() {\n // Find all tab links under sidebar-menu even if they don't have a\n // tabName (which is why the second selector is necessary)\n var $tablinks = $(\n \".sidebar-menu a[data-toggle='tab'],\" + \".sidebar-menu li.has-treeview > a\"\n );\n\n // If any other items are active, deactivate them\n $tablinks.not($(this)).removeClass(\"active\");\n\n // also manually activate the parent link when the selected item\n // is part of a treeview. For some reason, this is not done by AdminLTE3...\n if ($(this).hasClass(\"treeview-link\")) {\n $(this)\n .parents(\".has-treeview\")\n .children()\n .eq(0)\n .addClass(\"active\");\n }\n\n // Trigger event for the tabItemInputBinding\n var $obj = $(\".sidebarMenuSelectedTabItem\");\n var inputBinding = $obj.data(\"shiny-input-binding\");\n if (typeof inputBinding !== \"undefined\") {\n inputBinding.setValue($obj, $(this).attr(\"data-value\"));\n $obj.trigger(\"change\");\n }\n};\n\n$(function() {\n // Whenever the sidebar finishes a transition (which it does every time it\n // changes from collapsed to expanded and vice versa), trigger resize,\n // so that all outputs are resized.\n $(\".main-sidebar\").on(\n \"webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend\",\n function() {\n $(window).trigger(\"resize\");\n }\n );\n\n $(document).on(\n \"shown.bs.tab\",\n '.sidebar-menu a[data-toggle=\"tab\"]',\n deactivateOtherTabs\n );\n\n ensureActivatedTab();\n\n // Whenever we expand a menuItem (to be expandable, it must have children),\n // update the value for the expandedItem's input binding (this is the\n // tabName of the fist subMenuItem inside the menuItem that is currently\n // expanded)\n $(document).on(\"click\", \".has-treeview\", function() {\n var $menu = $(this);\n // If this menuItem was already open, then clicking on it again,\n // should trigger the \"hidden\" event, so Shiny doesn't worry about\n // it while it's hidden (and vice versa).\n if ($menu.hasClass(\"menu-open\")) $menu.trigger(\"collapsed.lte.treeview\");\n else if ($menu.hasClass(\".has-treeview\"))\n $menu.trigger(\"expanded.lte.treeview\");\n\n // need to set timeout to account for the slideUp/slideDown animation\n var $obj = $(\".sidebar.shiny-bound-input\");\n setTimeout(function() {\n $obj.trigger(\"change\");\n }, 600);\n });\n\n //---------------------------------------------------------------------\n // tabItemInputBinding\n // ------------------------------------------------------------------\n // Based on Shiny.tabItemInputBinding, but customized for tabItems in\n // bs4Dash, which have a slightly different structure.\n var tabItemInputBinding = new Shiny.InputBinding();\n $.extend(tabItemInputBinding, {\n find: function(scope) {\n return $(scope).find(\".sidebarMenuSelectedTabItem\");\n },\n getValue: function(el) {\n var value = $(el).attr(\"data-value\");\n if (value === \"null\") return null;\n return value;\n },\n setValue: function(el, value) {\n var self = this;\n var anchors = $(el)\n .parent(\".sidebar-menu\")\n .find(\"li:not(.treeview)\")\n .children(\"a\");\n anchors.each(function() {\n // eslint-disable-line consistent-return\n if (self._getTabName($(this)) === value) {\n $(this).tab(\"show\");\n // this make sure that treeview items are open when we\n // use the updatebs4TabItems function on the server side\n if ($(this).hasClass(\"treeview-link\")) {\n if (\n !$(this)\n .parents(\".has-treeview\")\n .hasClass(\"menu-open\")\n ) {\n $(this)\n .parents(\".has-treeview\")\n .children()\n .eq(0)\n .trigger(\"click\");\n }\n }\n $(el).attr(\"data-value\", self._getTabName($(this)));\n return false;\n }\n });\n },\n receiveMessage: function(el, data) {\n if (data.hasOwnProperty(\"value\")) this.setValue(el, data.value);\n },\n subscribe: function(el, callback) {\n // This event is triggered by deactivateOtherTabs, which is triggered by\n // shown. The deactivation of other tabs must occur before Shiny gets the\n // input value.\n $(el).on(\"change.tabItemInputBinding\", function() {\n callback();\n });\n },\n unsubscribe: function(el) {\n $(el).off(\".tabItemInputBinding\");\n },\n _getTabName: function(anchor) {\n return anchor.attr(\"data-value\");\n }\n });\n\n Shiny.inputBindings.register(tabItemInputBinding, \"bs4Dash.tabItemInput\");\n\n //---------------------------------------------------------------------\n // sidebarInputBinding\n // ------------------------------------------------------------------\n // similar to controlbarInputBinding\n var sidebarBinding = new Shiny.InputBinding();\n\n $.extend(sidebarBinding, {\n find: function(scope) {\n return $(scope).find(\".main-sidebar\");\n },\n\n // Given the DOM element for the input, return the value\n getValue: function(el) {\n // Warning: we can't look for sidebar-open since this\n // class is only generated on mobile devices\n return !$(\"body\").hasClass(\"sidebar-collapse\");\n },\n\n // see updatebs4Controlbar\n receiveMessage: function(el, data) {\n $(\"[data-widget='pushmenu']\").PushMenu(\"toggle\");\n },\n\n subscribe: function(el, callback) {\n $(\"[data-widget='pushmenu']\").on(\n \"collapsed.lte.pushmenu.sidebarBinding shown.lte.pushmenu.sidebarBinding\",\n function(e) {\n callback();\n }\n );\n },\n\n unsubscribe: function(el) {\n $(el).off(\".sidebarBinding\");\n }\n });\n\n Shiny.inputBindings.register(sidebarBinding, \"bs4Dash.sidebarInput\");\n\n // sidebarmenuExpandedInputBinding\n // ------------------------------------------------------------------\n // This keeps tracks of what menuItem (if any) is expanded\n var sidebarmenuExpandedInputBinding = new Shiny.InputBinding();\n $.extend(sidebarmenuExpandedInputBinding, {\n find: function(scope) {\n // This will also have id=\"sidebarItemExpanded\"\n return $(scope).find(\".sidebar\");\n },\n getValue: function(el) {\n var $open = $(el)\n .find(\"li\")\n .filter(\".menu-open\")\n .find(\"ul\");\n if ($open.length === 1) return $open.attr(\"data-expanded\");\n else return null;\n },\n setValue: function(el, value) {\n // does not work (nothing is printed)\n var $menuItem = $(el).find(\"[data-expanded='\" + value + \"']\");\n // This will trigger actions defined by AdminLTE, as well as actions\n // defined in sidebar.js.\n $menuItem.prev().trigger(\"click\");\n },\n subscribe: function(el, callback) {\n $(el).on(\"change.sidebarmenuExpandedInputBinding\", function() {\n callback();\n });\n },\n unsubscribe: function(el) {\n $(el).off(\".sidebarmenuExpandedInputBinding\");\n }\n });\n Shiny.inputBindings.register(\n sidebarmenuExpandedInputBinding,\n \"bs4Dash.sidebarmenuExpandedInputBinding\"\n );\n\n // handle fixed sidebar\n if ($(\".main-sidebar\").attr(\"data-fixed\") === \"true\") {\n $(\"body\").addClass(\"layout-fixed\");\n //$('body').Layout('fixLayoutHeight');\n }\n});\n","$(function () {\n\n $navbar = $('.main-header.navbar');\n\n // Modify the shiny tabsetpanel binding to follow BS4 rules\n $(document).on('shiny:connected', function (event) {\n Shiny.unbindAll();\n $.extend(Shiny\n .inputBindings\n .bindingNames['shiny.bootstrapTabInput']\n .binding, {\n // do whathever you want to edit existing methods\n getValue: function (el) {\n var anchor = $(el).find('li:not(.dropdown)').children('a.active');\n if (anchor.length === 1)\n return this._getTabName(anchor);\n\n return null;\n }\n });\n Shiny.bindAll();\n });\n\n // footer has fixed layout?\n if ($(\".main-footer\").attr(\"data-fixed\") === \"true\") {\n $(\"body\").addClass(\"layout-footer-fixed\");\n }\n\n // add dropdown-menu-right class to correctly open the dropdown to all \n // navbar rightUi elements\n var navbarRight = $('.navbar-right').find('.dropdown-menu');\n $(navbarRight).each(function () {\n if (!$(this).hasClass('dropdown-menu-right')) {\n $(this).addClass('dropdown-menu-right');\n }\n });\n\n\n // data toggle collapse icon update\n $('.user-block [data-toggle=\"collapse\"]').on('click', function () {\n if ($(this).children('i').hasClass('fa-plus')) {\n $(this).children('i').attr('class', 'fa fa-minus');\n } else {\n $(this).children('i').attr('class', 'fa fa-plus');\n }\n });\n\n // fullscreen toggle\n if ($('body').attr('data-fullscreen') == 1) {\n var fullScreenToggle = `
  • \n \n \n \n
  • `;\n $(fullScreenToggle).insertBefore($('[data-widget=\"control-sidebar\"]').parent());\n }\n\n // slide to top button\n if ($('body').attr('data-scrollToTop') == 1) {\n var $slideToTop = $('
    ');\n\n $slideToTop.html('');\n\n $slideToTop.css({\n position: 'fixed',\n bottom: '20px',\n right: '25px',\n width: '40px',\n height: '40px',\n color: '#eee',\n 'font-size': '',\n 'line-height': '40px',\n 'text-align': 'center',\n 'background-color': '#222d32',\n cursor: 'pointer',\n 'border-radius': '5px',\n 'z-index': '99999',\n opacity: '.7',\n 'display': 'none'\n });\n\n $slideToTop.on('mouseenter', function () {\n $(this).css('opacity', '1');\n });\n\n $slideToTop.on('mouseout', function () {\n $(this).css('opacity', '.7');\n });\n\n $('.wrapper').append($slideToTop);\n\n $(window).scroll(function () {\n if ($(window).scrollTop() >= 150) {\n if (!$($slideToTop).is(':visible')) {\n $($slideToTop).fadeIn(500);\n }\n } else {\n $($slideToTop).fadeOut(500);\n }\n });\n\n $($slideToTop).click(function () {\n $('html, body').animate({\n scrollTop: 0\n }, 500);\n });\n }\n \n // nav item click also triggers scroll to top\n $('.main-sidebar .nav-item').on('click', function () {\n $('html, body').animate({\n scrollTop: 0\n }, 0);\n }); \n\n\n // tooltip/popover toggle\n if ($('body').attr('data-help') == 2 || \n $('body').attr('data-help') == 1) {\n var $help_switch_checkbox = $('', {\n type: 'checkbox',\n id: 'help_switch',\n class: 'custom-control-input'\n }).on('click', function () {\n if ($(this).is(':checked')) {\n $('[data-toggle=\"tooltip\"]').tooltip('enable');\n $('[data-toggle=\"popover\"]').popover({\n trigger: 'hover'\n });\n $('[data-toggle=\"popover\"]').popover('enable');\n } else {\n $('[data-toggle=\"tooltip\"]').tooltip('disable');\n $('[data-toggle=\"popover\"]').popover('disable');\n }\n });\n\n var $help_switch_container = $('
    ', { class: 'custom-control custom-switch mx-2 mt-2' }).append($help_switch_checkbox).append(``);\n \n // insert before $('#controlbar-toggle') whenever possible ...\n if ($('.nav-item #controlbar-toggle')) {\n $help_switch_container.insertBefore($('#controlbar-toggle').parent());\n } else {\n $navbar.append($help_switch_container);\n }\n\n // trigger first click, if necessary\n $(document).on('shiny:connected', function() {\n if ($('body').attr('data-help') == 2 || $('body').attr('data-help') == 1) {\n $help_switch_checkbox.click(); \n // Click again if option is set to FALSE\n if ($('body').attr('data-help') == 1) {\n $help_switch_checkbox.click(); \n }\n }\n }); \n }\n\n // dark mode input\n $(document).one('shiny:connected', function () {\n if ($('body').hasClass('dark-mode')) {\n Shiny.setInputValue('dark_mode', true, { priority: 'event' });\n } else {\n Shiny.setInputValue('dark_mode', false, { priority: 'event' });\n }\n });\n\n\n // Navbar colors\n getNavbarColor = function () {\n for (let color of navbar_all_colors) {\n if ($('.main-header').attr('class').search(color) > -1) {\n return color;\n }\n }\n };\n\n var navbar_dark_skins = [\n 'navbar-primary',\n 'navbar-secondary',\n 'navbar-info',\n 'navbar-success',\n 'navbar-danger',\n 'navbar-indigo',\n 'navbar-purple',\n 'navbar-pink',\n 'navbar-maroon',\n 'navbar-fuchsia',\n 'navbar-navy',\n 'navbar-lightblue',\n 'navbar-lime',\n 'navbar-teal',\n 'navbar-olive',\n 'navbar-gray-dark',\n 'navbar-gray'\n ];\n\n var navbar_light_skins = [\n 'navbar-warning',\n 'navbar-white',\n 'navbar-orange'\n ];\n\n var navbar_all_colors = navbar_dark_skins.concat(navbar_light_skins);\n \n /**\n * Update color theme to navbar tag\n *\n * @param String color Color to apply.\n * @returns void\n */\n updateNavbarTheme = function (color) {\n var $main_header = $('.main-header');\n $main_header.removeClass('navbar-dark').removeClass('navbar-light');\n navbar_all_colors.forEach(function (color) {\n $main_header.removeClass(color);\n });\n\n if (navbar_dark_skins.indexOf(color) > -1) {\n $main_header.addClass('navbar-dark');\n } else {\n $main_header.addClass('navbar-light');\n }\n\n $main_header.addClass(color);\n };\n \n /**\n * Update icon color style based on navbar color.\n *\n * @param String color Current navbar color.\n * @returns void\n */\n updateNavbarIconColor = function(color) {\n var iconThemeColor = navbar_dark_skins.indexOf(color) > -1 ? \"white\" : \"rgba(0,0,0,.5)\";\n $(\".dark-theme-icon\").css(\"color\", iconThemeColor);\n $('[for=\"help_switch\"] i').css(\"color\", iconThemeColor);\n };\n \n // automatic global theme switcher\n if ($('body').attr('data-dark') == 2 || \n $('body').attr('data-dark') == 1) {\n var $dark_mode_checkbox = $('', {\n type: 'checkbox',\n id: 'theme_switch',\n class: 'custom-control-input'\n }).on('click', function () {\n\n // get any selected navbar skin in the navbar themer\n var newNavbarColor;\n // If there is not themer, we keep the navbar current color.\n // Otherwise, we replace it by the new color.\n if ($('.navbar-themer-chip').length > 0) {\n $('.navbar-themer-chip').filter(function () {\n if ($(this).css('border-style') === 'solid') {\n newNavbarColor = 'navbar-' +\n $(this)\n .attr('class')\n .split('elevation-2')[0]\n .trim()\n .replace('bg-', '');\n }\n });\n } else {\n newNavbarColor = getNavbarColor();\n }\n\n if ($(this).is(':checked')) {\n $('body').addClass('dark-mode');\n\n // use updateNavbarTheme to correctly setup the skin as depending\n // on the required color. If no color is chosen, we use gray-dark for dark mode\n if (newNavbarColor === undefined || newNavbarColor === 'navbar-white') {\n newNavbarColor = \"navbar-gray-dark\";\n }\n updateNavbarTheme(newNavbarColor);\n\n // sidebar update \n if ($('.main-sidebar').length > 0) {\n $('.main-sidebar').attr('class', $('.main-sidebar')\n .attr('class')\n .replace('light', 'dark'));\n $('#sidebar-skin').prop(\"checked\", true);\n\n $('.sidebar-themer-icon')\n .removeClass('fa-sun')\n .addClass('fa-moon');\n }\n\n // controlbar update\n if ($('.control-sidebar').length > 0) {\n $('.control-sidebar').attr('class', $('.control-sidebar')\n .attr('class')\n .replace('light', 'dark'));\n $('#controlbar-skin').prop(\"checked\", true);\n\n $('.controlbar-themer-icon')\n .removeClass('fa-sun')\n .addClass('fa-moon');\n }\n\n\n $('.dark-theme-icon')\n .removeClass('fa-sun')\n .addClass('fa-moon');\n\n // refresh shiny input value \n Shiny.setInputValue('dark_mode', true, { priority: 'event' });\n\n } else {\n $('body').removeClass('dark-mode');\n\n // use updateNavbarTheme to correctly setup the skin as depending\n // on the required color. If no color is chosen, we use white for light mode\n if (newNavbarColor === undefined || newNavbarColor === 'navbar-gray-dark') {\n newNavbarColor = \"navbar-white\";\n }\n updateNavbarTheme(newNavbarColor);\n\n // sidebar update\n if ($('.main-sidebar').length > 0) {\n $('.main-sidebar').attr('class', $('.main-sidebar')\n .attr('class')\n .replace('dark', 'light'));\n $('#sidebar-skin').prop(\"checked\", false);\n\n $('.sidebar-themer-icon')\n .removeClass('fa-moon')\n .addClass('fa-sun');\n }\n\n // controlbar update\n if ($('.control-sidebar').length > 0) {\n $('.control-sidebar').attr('class', $('.control-sidebar')\n .attr('class')\n .replace('dark', 'light'));\n $('#controlbar-skin').prop(\"checked\", false);\n\n $('.controlbar-themer-icon')\n .removeClass('fa-moon')\n .addClass('fa-sun');\n }\n\n $('.dark-theme-icon')\n .removeClass('fa-moon')\n .addClass('fa-sun');\n\n // refresh shiny input value \n Shiny.setInputValue('dark_mode', false, { priority: 'event' });\n }\n \n // update navbar icon colors\n updateNavbarIconColor(newNavbarColor);\n });\n\n var $dark_mode_icon = $('body').hasClass('dark-mode') ? '' : '';\n var $dark_mode_container = $('
    ', { class: 'custom-control custom-switch mx-2 mt-2' }).append($dark_mode_checkbox).append(``);\n \n // insert before $('#controlbar-toggle') whenever possible ...\n if ($('.nav-item #controlbar-toggle')) {\n $dark_mode_container.insertBefore($('#controlbar-toggle').parent());\n } else {\n $navbar.append($dark_mode_container);\n }\n \n \n // Trigger dark mode\n if ($('body').attr('data-dark') == 2) {\n $(document).on('shiny:connected', function() {\n $dark_mode_checkbox.click();\n }); \n }\n }\n \n // apply correct navbar class depending on selected color\n if (getNavbarColor() !== undefined) {\n updateNavbarTheme(getNavbarColor());\n updateNavbarIconColor(getNavbarColor());\n }\n \n\n // Themer chips\n\n // Better style on hover\n $('.themer-chip').hover(function () {\n $(this).css({ opacity: 1 }).removeClass('elevation-2').addClass('elevation-4');\n }, function () {\n $(this).css({ opacity: 0.8 }).removeClass('elevation-4').addClass('elevation-2');\n });\n\n // \n $('.navbar-themer-chip').on('click', function () {\n $(this).css({ 'border-color': 'yellow', 'border-style': 'solid' });\n $('.navbar-themer-chip').not(this).css({ 'border-color': '', 'border-style': '' });\n });\n\n $('.accents-themer-chip').on('click', function () {\n $(this).css({ 'border-color': 'yellow', 'border-style': 'solid' });\n $('.accents-themer-chip').not(this).css({ 'border-color': '', 'border-style': '' });\n });\n\n $('.sidebar-themer-chip').on('click', function () {\n $(this).css({ 'border-color': 'yellow', 'border-style': 'solid' });\n $('.sidebar-themer-chip').not(this).css({ 'border-color': '', 'border-style': '' });\n });\n\n\n // Sidebar themer\n\n // detect global sidebar theme and select or not the toggle\n if ($('.main-sidebar').length > 0) {\n if ($('.main-sidebar').attr('class').match('dark')) {\n $('#sidebar-skin').prop(\"checked\", true);\n }\n }\n\n // clicking on dark/light switch changes:\n // - icon style\n // - sidebar class \n $('#sidebar-skin').on('click', function () {\n var sidebarCl;\n if ($(this).is(':checked')) {\n sidebarCl = $('.main-sidebar')\n .attr('class')\n .replace('light', 'dark');\n $('.main-sidebar').attr('class', sidebarCl);\n\n $('.sidebar-themer-icon')\n .removeClass('fa-sun')\n .addClass('fa-moon');\n } else {\n sidebarCl = $('.main-sidebar')\n .attr('class')\n .replace('dark', 'light');\n $('.main-sidebar').attr('class', sidebarCl);\n\n $('.sidebar-themer-icon')\n .removeClass('fa-moon')\n .addClass('fa-sun');\n }\n });\n\n var sidebar_colors = [\n 'bg-primary',\n 'bg-secondary',\n 'bg-info',\n 'bg-success',\n 'bg-danger',\n 'bg-indigo',\n 'bg-purple',\n 'bg-pink',\n 'bg-maroon',\n 'bg-fuchsia',\n 'bg-navy',\n 'bg-lightblue',\n 'bg-lime',\n 'bg-teal',\n 'bg-olive',\n 'bg-gray-dark',\n 'bg-gray',\n 'bg-light',\n 'bg-warning',\n 'bg-white',\n 'bg-orange'\n ];\n\n\n var sidebar_skins = [\n 'sidebar-dark-primary',\n 'sidebar-dark-secondary',\n 'sidebar-dark-info',\n 'sidebar-dark-success',\n 'sidebar-dark-danger',\n 'sidebar-dark-indigo',\n 'sidebar-dark-purple',\n 'sidebar-dark-pink',\n 'sidebar-dark-maroon',\n 'sidebar-dark-fuchsia',\n 'sidebar-dark-navy',\n 'sidebar-dark-lightblue',\n 'sidebar-dark-lime',\n 'sidebar-dark-teal',\n 'sidebar-dark-olive',\n 'sidebar-dark-gray-dark',\n 'sidebar-dark-gray',\n 'sidebar-dark-light',\n 'sidebar-dark-warning',\n 'sidebar-dark-white',\n 'sidebar-dark-orange',\n 'sidebar-light-primary',\n 'sidebar-light-secondary',\n 'sidebar-light-info',\n 'sidebar-light-success',\n 'sidebar-light-danger',\n 'sidebar-light-indigo',\n 'sidebar-light-purple',\n 'sidebar-light-pink',\n 'sidebar-light-maroon',\n 'sidebar-light-fuchsia',\n 'sidebar-light-navy',\n 'sidebar-light-lightblue',\n 'sidebar-light-lime',\n 'sidebar-light-teal',\n 'sidebar-light-olive',\n 'sidebar-light-gray-dark',\n 'sidebar-light-gray',\n 'sidebar-light-light',\n 'sidebar-light-warning',\n 'sidebar-light-white',\n 'sidebar-light-orange'\n ];\n\n\n updateSidebarTheme = function (color) {\n var sidebarCl;\n if ($('#sidebar-skin').is(':checked')) {\n sidebarCl = 'sidebar-dark-';\n } else {\n sidebarCl = 'sidebar-light-';\n }\n\n var sidebar_class = sidebarCl + color.replace('bg-', '');\n var $sidebar = $('.main-sidebar');\n sidebar_skins.forEach(function (skin) {\n $sidebar.removeClass(skin);\n });\n\n $sidebar.addClass(sidebar_class);\n };\n\n\n // Accents themer\n var accent_colors = [\n 'accent-primary',\n 'accent-secondary',\n 'accent-info',\n 'accent-success',\n 'accent-danger',\n 'accent-indigo',\n 'accent-purple',\n 'accent-pink',\n 'accent-maroon',\n 'accent-fuchsia',\n 'accent-navy',\n 'accent-lightblue',\n 'accent-lime',\n 'accent-teal',\n 'accent-olive',\n 'accent-gray-dark',\n 'accent-gray',\n 'accent-light',\n 'accent-warning',\n 'accent-white',\n 'accent-orange'\n ];\n\n\n updateAccentsTheme = function (color) {\n var accent_class = color;\n var $body = $('body');\n accent_colors.forEach(function (skin) {\n $body.removeClass(skin);\n });\n\n $body.addClass(accent_class);\n };\n\n\n // Controlbar themer\n\n // detect global controlbar theme and select or not the toggle\n if ($('.control-sidebar').length > 0) {\n if ($('.control-sidebar').attr('class').match('dark')) {\n $('#controlbar-skin').prop(\"checked\", true);\n }\n }\n\n // clicking on dark/light switch changes:\n // - icon style\n // - sidebar class \n $('#controlbar-skin').on('click', function () {\n var controlbarCl;\n if ($(this).is(':checked')) {\n controlbarCl = $('.control-sidebar')\n .attr('class')\n .replace('light', 'dark');\n $('.control-sidebar').attr('class', controlbarCl);\n\n $('.controlbar-themer-icon')\n .removeClass('fa-sun')\n .addClass('fa-moon');\n } else {\n controlbarCl = $('.control-sidebar')\n .attr('class')\n .replace('dark', 'light');\n $('.control-sidebar').attr('class', controlbarCl);\n\n $('.controlbar-themer-icon')\n .removeClass('fa-moon')\n .addClass('fa-sun');\n }\n });\n\n});","$(function () {\n // hide the right sidebar toggle \n // if no right sidebar is specified\n noControlbar = ($(\".control-sidebar\").length === 0);\n if (noControlbar) {\n $(\"#controlbar-toggle\").hide();\n }\n\n // hide the right sidebar toggle if the controlbar is disable\n disableControlbar = ($(\".control-sidebar\").attr(\"data-show\"));\n if (!disableControlbar) {\n $(\"#controlbar-toggle\").hide();\n }\n\n // controlbar slide\n controlbarSlide = ($(\".control-sidebar\").attr(\"data-slide\"));\n if (controlbarSlide) {\n $(\"#controlbar-toggle\").attr('data-controlsidebar-slide', controlbarSlide);\n }\n\n // when the sidebar is disabled, hide the sidebar toggle\n disableSidebar = ($(\".main-sidebar\").length === 0);\n if (disableSidebar) {\n $(\".nav-item > a[data-widget='pushmenu']\").css(\"visibility\", \"hidden\");\n }\n\n // handle fixed navbar\n if ($(\".navbar\").attr(\"data-fixed\") === \"true\") {\n $(\"body\").addClass(\"layout-navbar-fixed\");\n }\n\n});","var menuOutputBinding = new Shiny.OutputBinding();\n$.extend(menuOutputBinding, {\n find: function (scope) {\n return $(scope).find('.bs4Dash-menu-output');\n },\n onValueError: function (el, err) {\n Shiny.unbindAll(el);\n this.renderError(el, err);\n },\n renderValue: function (el, data) {\n Shiny.unbindAll(el);\n\n var html;\n var dependencies = [];\n if (data === null) {\n return;\n } else if (typeof (data) === 'string') {\n html = data;\n } else if (typeof (data) === 'object') {\n html = data.html;\n dependencies = data.deps;\n }\n\n var $html = $($.parseHTML(html));\n\n // Convert the inner contents to HTML, and pass to renderHtml\n Shiny.renderHtml($html.html(), el, dependencies);\n\n // Extract class of wrapper, and add them to the wrapper element\n el.className = 'bs4Dash-menu-output shiny-bound-output ' +\n $html.attr('class');\n \n // need this to activate adminLTE3 plugin for treeview \n $(el)\n .attr(\"data-widget\", \"treeview\")\n .attr(\"role\", \"menu\")\n .attr(\"data-accordion\", \"true\");\n\n Shiny.initializeInputs(el);\n Shiny.bindAll(el);\n if ($(el).hasClass(\"sidebar-menu\")) ensureActivatedTab(); // eslint-disable-line\n }\n});\nShiny.outputBindings.register(menuOutputBinding, \"bs4Dash.menuOutputBinding\");","$( document ).ready(function() {\n \n function findActivePage() {\n return $('ul.pagination').find('li.active');\n };\n \n function toggleNavigationItems(activeItem) {\n // hide pagination previous if we are at the first item\n if ($(activeItem).prev().find('a').hasClass('pagination-previous')) {\n $('.pagination-previous').parent('li').css('display', 'none');\n } else {\n $('.pagination-previous').parent('li').css('display', 'block');\n }\n \n // hide pagination next if we are at the last item\n if ($(activeItem).next().find('a').hasClass('pagination-next')) {\n $('.pagination-next').parent('li').css('display', 'none');\n } else {\n $('.pagination-next').parent('li').css('display', 'block');\n }\n }\n \n // Must run at start\n toggleNavigationItems(findActivePage());\n \n // Toggle active item button state\n $('ul.pagination a:not(.disabled, .pagination-previous, .pagination-next)')\n .on('click', function() {\n var activeItem = findActivePage();\n $(activeItem).removeClass('active');\n $(this).parent().addClass('active');\n activeItem = $(this).parent(); // store new active item\n // Also run dynamically\n toggleNavigationItems(activeItem);\n });\n \n // Previous click\n $('ul.pagination .pagination-previous').on('click', function() {\n var activeItem = findActivePage();\n \n var previousSibling = $(activeItem).prev();\n // jump back when we find a disabled sibling\n while ($(previousSibling).hasClass('disabled')) {\n previousSibling = $(previousSibling).prev();\n }\n // Only if active item has a previous sibling that is not \n // the pagination-previous itself.\n if ($(previousSibling).find('a').hasClass('pagination-previous') == false) {\n $(activeItem).removeClass('active');\n $(previousSibling).find('a').click(); \n }\n });\n \n // Next click\n $('ul.pagination .pagination-next').on('click', function() {\n var activeItem = findActivePage();\n \n var nextSibling = $(activeItem).next();\n // jump back when we find a disabled sibling\n while ($(nextSibling).hasClass('disabled')) {\n nextSibling = $(nextSibling).next();\n }\n // Only if active item has a previous sibling that is not \n // the pagination-previous itself.\n if ($(nextSibling).find('a').hasClass('pagination-next') == false) {\n $(activeItem).removeClass('active');\n $(nextSibling).find('a').click(); \n }\n });\n \n var paginationBinding = new Shiny.InputBinding();\n $.extend(paginationBinding, {\n \n initialize: function(el) {\n \n },\n \n find: function (scope) {\n return $(scope).find('ul.pagination');\n },\n \n // Given the DOM element for the input, return the value\n getValue: function (el) {\n return $(el).find('li.active a').attr('data-value');\n },\n \n setValue: function(el, value) {\n \n },\n // internal\n _disableTab: function(el, value) {\n $(el)\n .find('a[data-value=\"' + value + '\"]')\n .parent()\n .removeClass('active')\n .addClass('disabled')\n .attr('tabindex', '-1')\n },\n // see updatePagination\n receiveMessage: function (el, data) {\n // Activate new element\n if (data.hasOwnProperty('selected')) {\n // Disable active element\n $(el)\n .find('.active')\n .removeClass('active');\n // Activate new element\n var selectedItem = $(el)\n .find('a[data-value=\"' + data.selected + '\"]');\n // If the element was disabled before\n if ($(selectedItem).parent('li').hasClass('disabled')) {\n $(selectedItem)\n .parent('li')\n .removeClass('disabled')\n .removeAttr('tabindex');\n }\n $(selectedItem).click();\n }\n \n // Disable elements\n if (data.hasOwnProperty('disabled')) {\n // loop over all elements\n if (typeof data.disabled == 'string') {\n this._disableTab(el, data.disabled)\n } else {\n for (i of data.disabled) {\n // disable element \n this._disableTab(el, i)\n }\n }\n \n // Activate next or previous not disabled li\n var hasActiveItem = $(el).find('li.active').length\n if (hasActiveItem == 0) {\n // Activate first element found (maybe discussed ...)\n var newActive = $(el)\n .find('a:not(.pagination-previous, .pagination-next)')\n .parent('li:not(.disabled)');\n if (newActive.length > 0) {\n $(newActive[0]).find('a').click();\n }\n }\n }\n \n // Trigger the callback to update the input value \n // on the server side.\n $(el).trigger('change');\n },\n \n subscribe: function (el, callback) {\n $(el).find('a').on('click', function() {\n callback();\n });\n \n // Necessry for updatePagination\n $(el).on('change', function() {\n callback();\n })\n },\n \n unsubscribe: function (el) {\n $(el).off('.paginationBinding');\n }\n });\n \n Shiny.inputBindings.register(paginationBinding);\n});","var bootstrapTabInputBinding = new Shiny.InputBinding();\n$.extend(bootstrapTabInputBinding, {\n find: function(scope) {\n return $(scope).find('ul.nav.shiny-tab-input');\n },\n getValue: function(el) {\n // for Bootstrap 4, li element does not hold the active class anymore!\n // We need to look at a.active.\n var anchor = $(el).find('li:not(.dropdown)').children('a.active');\n if (anchor.length === 1)\n return this._getTabName(anchor);\n\n return null;\n },\n setValue: function(el, value) {\n let self = this;\n let success = false;\n if (value) {\n let anchors = $(el).find('li:not(.dropdown)').children('a');\n anchors.each(function() {\n if (self._getTabName($(this)) === value) {\n $(this).tab('show');\n success = true;\n return false; // Break out of each()\n }\n return true;\n });\n }\n if (!success) {\n // This is to handle the case where nothing is selected, e.g. the last tab\n // was removed using removeTab.\n $(el).trigger(\"change\");\n }\n },\n getState: function(el) {\n return { value: this.getValue(el) };\n },\n receiveMessage: function(el, data) {\n if (data.hasOwnProperty('value'))\n this.setValue(el, data.value);\n },\n subscribe: function(el, callback) {\n $(el).on('change shown.bootstrapTabInputBinding shown.bs.tab.bootstrapTabInputBinding', function(event) {\n callback();\n });\n },\n unsubscribe: function(el) {\n $(el).off('.bootstrapTabInputBinding');\n },\n _getTabName: function(anchor) {\n return anchor.attr('data-value') || anchor.text();\n }\n});\n\nShiny.inputBindings.register(bootstrapTabInputBinding, 'shiny.bootstrapTabInput');","// This code creates acustom handler for userMessages\nShiny.addCustomMessageHandler(\"user-messages\", function(message) {\n var id = message.id, action = message.action, content = message.body, index = message.index;\n \n // message text\n // We use Shiny.renderHtml to handle the case where the user pass input/outputs in the updated content that require a new dependency not available in the \n // page at startup. \n if (content.hasOwnProperty(\"text\")) {\n var text;\n if (content.text.html === undefined) {\n text = content.text;\n } else {\n text = Shiny.renderHtml(content.text.html, $([]), content.text.dependencies).html;\n } \n }\n \n // unbind all\n Shiny.unbindAll();\n \n if (action === \"remove\") {\n $(\"#\" + id).find(\".direct-chat-msg\").eq(index - 1).remove();\n } else if (action === \"add\") {\n var author = content.author, date = content.date, image = content.image, type = content.type;\n \n // build the new message \n var authorWrapper, dateWrapper;\n if (type === \"sent\") {\n authorWrapper = '' + author + '';\n dateWrapper = '' + date + '';\n } else {\n authorWrapper = '' + author + '';\n dateWrapper = '' + date + '';\n }\n\n var newMessage = `
    ${authorWrapper}${dateWrapper}
    ${text}
    `;\n \n // build wrapper\n var newMessageWrapper;\n if (type === \"sent\") {\n newMessageWrapper = '
    ' + newMessage + '
    ';\n } else {\n newMessageWrapper = '
    ' + newMessage + '
    ';\n }\n \n // append message\n $(\"#\" + id).find(\".direct-chat-messages\").append(newMessageWrapper);\n } else if (action === \"update\") {\n \n // today's date\n var d = new Date();\n var month = d.getMonth() + 1;\n var day = d.getDate();\n var today = d.getFullYear() + '/' +\n ((''+month).length<2 ? '0' : '') + month + '/' +\n ((''+day).length<2 ? '0' : '') + day;\n \n // we assume only text may be updated. Does not make sense to modify author/date\n \n $(\"#\" + id)\n .find(\".direct-chat-text\")\n .eq(index - 1)\n .replaceWith('
    (modified: ' + today +')
    ' + text + '
    ');\n }\n \n // Calls .initialize() for all of the input objects in all input bindings,\n // in the given scope (document)\n Shiny.initializeInputs();\n Shiny.bindAll(); // bind all inputs/outputs\n});"]} +{"version":3,"sources":["accordions-binding.js","cards.js","controlbar.js","feedbacks.js","leftSidebar.js","miscellaneous.js","navbar.js","output-bindings.js","pagination-widget.js","tabs.js","userMessages.js"],"names":["accordionBinding","Shiny","InputBinding","$","extend","find","scope","getValue","el","activeItem","children","index","setValue","value","removeClass","eq","addClass","click","trigger","receiveMessage","data","this","subscribe","callback","on","e","closest","hasClass","unsubscribe","off","inputBindings","register","validStatuses","validStatusesPlus","cardBinding","config","parent","id","JSON","parse","html","visible","isCollapsed","display","css","isMaximized","hide","show","collapsible","collapsed","closable","maximizable","maximized","status","solidHeader","background","width","height","_updateWidth","o","n","toggleClass","action","isUserCard","isSocialCard","options","hasOwnProperty","title","newTitle","parseHTML","tools","replaceWith","insertAfter","remove","gradient","prepend","length","append","insertBefore","cond","oldClass","newClass","indexOf","oldBgClass","newBgClass","header","undefined","stringify","CardWidget","setTimeout","event","cardSidebarBinding","initialize","transition","attr","parseInt","closeTranslationRate","contacts","openTranslationRate","transform","document","mouseup","container","openContainer","is","target","has","parents","cardWrapper","self","currentTarget","showToast","controlbarToast","Toasts","close","autohide","delay","window","pinned","$pinIcon","init","controlbarBinding","controlbarOpen","ControlSidebar","addCustomMessageHandler","message","tooltipTarget","selector","tooltip","console","log","popoverTarget","popover","alertTarget","alertCl","alertTag","iconType","closeButton","titleTag","contentTag","elevation","warn","content","setInputValue","priority","alertId","alert","ensureActivatedTab","$tablinks","$startTab","filter","first","adminlte","Treeview","_jQueryInterface","call","tab","deactivateOtherTabs","not","$obj","inputBinding","$menu","tabItemInputBinding","each","_getTabName","anchor","sidebarBinding","PushMenu","sidebarmenuExpandedInputBinding","$open","prev","$navbar","unbindAll","bindingNames","binding","bindAll","navbarRight","$slideToTop","position","bottom","right","color","font-size","line-height","text-align","background-color","cursor","border-radius","z-index","opacity","scroll","scrollTop","fadeIn","fadeOut","animate","$help_switch_checkbox","type","class","$help_switch_container","one","getNavbarColor","navbar_all_colors","search","navbar_dark_skins","concat","updateNavbarTheme","$main_header","forEach","updateNavbarIconColor","iconThemeColor","$dark_mode_checkbox","newNavbarColor","split","trim","replace","prop","$dark_mode_icon","$dark_mode_container","hover","border-color","border-style","match","sidebarCl","sidebar_skins","updateSidebarTheme","sidebar_class","$sidebar","skin","accent_colors","updateAccentsTheme","accent_class","$body","controlbarCl","noControlbar","disableControlbar","controlbarSlide","disableSidebar","menuOutputBinding","OutputBinding","onValueError","err","renderError","renderValue","dependencies","deps","$html","renderHtml","className","initializeInputs","outputBindings","ready","findActivePage","toggleNavigationItems","next","previousSibling","nextSibling","paginationBinding","_disableTab","selectedItem","selected","removeAttr","disabled","i","newActive","bootstrapTabInputBinding","success","getState","text","body","authorWrapper","dateWrapper","author","date","image","newMessageWrapper","newMessage","d","Date","month","getMonth","day","getDate","today","getFullYear"],"mappings":"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","file":"bs4Dash.min.js","sourceRoot":"../../bs4Dash-build","sourcesContent":["// This code creates an input binding for the accordion component\nvar accordionBinding = new Shiny.InputBinding();\n\n$.extend(accordionBinding, {\n find: function(scope) {\n return $(scope).find(\".accordion\");\n },\n // Given the DOM element for the input, return the value\n getValue: function(el) {\n // active is given by the setValue method\n var activeItem = $(el).children(\".card.active\").index() + 1;\n if (activeItem === 0) return;\n // returns the index of the active item from the R point of view. It is possible\n // that no item is shown at start. In this case, NULL is returned\n return activeItem;\n },\n \n setValue: function(el, value) {\n // remove active class from all other panels\n $(el).children(\".card.active\").removeClass(\"active\");\n \n // add active class to current panel\n $(el).children()\n .eq(value - 1)\n .addClass(\"active\");\n \n // click on the header to trigger a collapse\n $(el)\n .children()\n .eq(value - 1)\n .find('[data-toggle=\"collapse\"]')\n .click();\n \n // trigger change to tell Shiny to update the value\n $(el).trigger(\"change\");\n },\n\n // see updateAccordion\n receiveMessage: function(el, data) {\n this.setValue(el, data);\n },\n\n subscribe: function(el, callback) {\n // cf setValue\n $(el).on(\"change\", function(e) {\n callback();\n });\n \n // manual click will update\n $(el).find('[data-toggle=\"collapse\"]').on(\"click\", function(e) {\n if (!$(this).closest(\".card\").hasClass(\"active\")) {\n $(el).children(\".card.active\").removeClass(\"active\");\n } \n $(this).closest(\".card\").addClass(\"active\");\n callback();\n });\n },\n\n unsubscribe: function(el) {\n $(el).off(\".accordionBinding\");\n }\n});\n\nShiny.inputBindings.register(accordionBinding, \"accordion-input\");","// Buttons valid colors are part of statuses like btn-primary, ...\nconst validStatuses = [\n \"primary\",\n \"secondary\",\n \"success\",\n \"info\",\n \"warning\",\n \"danger\"\n];\n// Cards may have few additional statuses like bg-orange\nconst validStatusesPlus = [\n \"dark\",\n \"white\",\n \"lightblue\",\n \"navy\",\n \"orange\",\n \"fuchsia\",\n \"purple\",\n \"indigo\",\n \"gray\",\n \"gray-dark\",\n \"pink\",\n \"maroon\",\n \"teal\",\n \"lime\",\n \"olive\",\n \"green\",\n \"yellow\",\n \"red\",\n \"blue\"\n];\n\n// Input binding\nvar cardBinding = new Shiny.InputBinding();\n\n$.extend(cardBinding, {\n find: function(scope) {\n return $(scope).find(\".card.bs4Dash\");\n },\n\n // Given the DOM element for the input, return the value\n getValue: function(el) {\n var config = $(el)\n .parent()\n .find(\"script[data-for='\" + el.id + \"']\");\n config = JSON.parse(config.html());\n\n var isCollapsed = $(el).hasClass(\"collapsed-card\");\n var display = $(el).css(\"display\");\n var isMaximized = $(el).hasClass(\"maximized-card\");\n\n var visible;\n if (display === \"none\") {\n visible = false;\n } else {\n visible = true;\n }\n\n // toggle collapse button when maximized\n if (isMaximized) {\n $(el)\n .find(\"[data-card-widget = 'collapse']\")\n .hide();\n } else {\n $(el)\n .find(\"[data-card-widget = 'collapse']\")\n .show();\n }\n\n return {\n collapsible: config.collapsible,\n collapsed: isCollapsed,\n closable: config.closable,\n visible: visible,\n maximizable: config.maximizable,\n maximized: isMaximized,\n status: config.status,\n solidHeader: config.solidHeader,\n background: config.background,\n width: config.width,\n height: config.height\n }; // this will be a list in R\n },\n _updateWidth: function(el, o, n) {\n $(el)\n .parent()\n .toggleClass(\"col-sm-\" + o);\n $(el)\n .parent()\n .addClass(\"col-sm-\" + n);\n // trigger resize so that output resize\n $(el).trigger(\"resize\");\n },\n\n setValue: function(el, value) {\n var config = $(el)\n .parent()\n .find(\"script[data-for='\" + el.id + \"']\");\n config = JSON.parse(config.html());\n\n if (value.action === \"update\") {\n var isUserCard = $(el).hasClass(\"user-card\");\n var isSocialCard = $(el).hasClass(\"social-card\");\n\n if (value.options.hasOwnProperty(\"title\")) {\n if (value.options.title !== config.title) {\n var newTitle;\n if (typeof value.options.title !== \"string\") {\n newTitle = $.parseHTML(value.options.title[0]);\n } else {\n newTitle = $.parseHTML(value.options.title);\n }\n\n var tools = $(el).find(\".card-tools\");\n // social box\n if (isSocialCard) {\n $(el)\n .find(\".user-block\")\n .replaceWith($(newTitle));\n } else if (isUserCard) {\n // handle 2 cards types\n if (typeof value.options.title === \"string\") {\n // don't take newTitle[1] (contains some text)\n newTitle = [newTitle[0], newTitle[2]];\n // change widget-use class\n $(el)\n .removeClass(\"widget-user-2\")\n .addClass(\"widget-user\");\n // insert header and image after\n $(el)\n .find(\".widget-user-header\")\n .replaceWith($(newTitle[0]));\n $(newTitle[1]).insertAfter($(el).find(\".widget-user-header\"));\n } else {\n $(el)\n .removeClass(\"widget-user\")\n .addClass(\"widget-user-2\");\n // remove old user inage if old type was 1\n $(el)\n .find(\".widget-user-image\")\n .remove();\n $(el)\n .find(\".widget-user-header\")\n .replaceWith($(newTitle));\n\n if (value.options.status !== null) {\n if (value.options.gradient) {\n $(el)\n .find(\".widget-user-header\")\n .addClass(\"bg-gradient-\", status);\n } else {\n $(el)\n .find(\".widget-user-header\")\n .addClass(\"bg-\", status);\n }\n }\n }\n // add tools as first child of widget-user-header\n $(el)\n .find(\".widget-user-header\")\n .prepend($(tools));\n } else {\n if (!$(newTitle).hasClass(\"card-title\"))\n $(newTitle).addClass(\"card-title\");\n $(el)\n .find(\".card-title\")\n .replaceWith($(newTitle));\n }\n config.title = value.options.title;\n }\n }\n\n if (value.options.hasOwnProperty(\"collapsible\")) {\n if (value.options.collapsible !== config.collapsible) {\n if (!value.options.collapsible) {\n $(el)\n .find('[data-card-widget = \"collapse\"]')\n .remove();\n config.collapsible = false;\n } else {\n // only add if no collapsible\n if ($(el).find('[data-card-widget = \"collapse\"]').length === 0) {\n $(el)\n .find(\".card-tools.float-right\")\n .prepend(\n $(\n ''\n )\n );\n config.collapsible = true;\n }\n }\n }\n }\n\n if (value.options.hasOwnProperty(\"closable\")) {\n if (value.options.closable !== config.closable) {\n if (!value.options.closable) {\n $(el)\n .find('[data-card-widget = \"remove\"]')\n .remove();\n config.closable = false;\n } else {\n if ($(el).find('[data-card-widget = \"remove\"]').length === 0) {\n // Remove goes between collapse and maximize...\n if ($(el).find('[data-card-widget = \"maximize\"]').length === 0) {\n $(el)\n .find(\".card-tools.float-right\")\n .append(\n $(\n ''\n )\n );\n } else {\n $(\n ''\n ).insertBefore($(el).find('[data-card-widget = \"maximize\"]'));\n }\n config.closable = true;\n }\n }\n }\n }\n\n if (value.options.hasOwnProperty(\"maximizable\")) {\n if (value.options.maximizable !== config.maximizable) {\n if (!value.options.maximizable) {\n $(el)\n .find('[data-card-widget = \"maximize\"]')\n .remove();\n config.maximizable = false;\n } else {\n if ($(el).find('[data-card-widget = \"maximize\"]').length === 0) {\n $(el)\n .find(\".card-tools.float-right\")\n .append(\n $(\n ''\n )\n );\n config.maximizable = true;\n }\n }\n }\n }\n\n if (value.options.hasOwnProperty(\"solidHeader\")) {\n // only update if config an new value are different\n if (!isSocialCard && !isUserCard) {\n if (\n value.options.solidHeader !== config.solidHeader &&\n $(el).hasClass(\"card-outline\")\n ) {\n $(el).removeClass(\"card-outline\");\n config.solidHeader = true;\n } else {\n if (!$(el).hasClass(\"card-outline\") && !value.options.solidHeader) {\n var cond = config.status || value.options.status;\n // solidheader cannot be removed if status and background exist or if status is null\n if (!(value.options.background && cond)) {\n $(el).addClass(\"card-outline\");\n config.solidHeader = false;\n } else if (\n value.options.background === null &&\n !(config.background && cond)\n ) {\n $(el).addClass(\"card-outline\");\n config.solidHeader = false;\n }\n } else if ($(el).hasClass(\"card-outline\")) {\n var cond = config.status || value.options.status;\n // solidheader cannot be removed if status and background exist or if status is null\n if (value.options.background && cond) {\n $(el).removeClass(\"card-outline\");\n config.solidHeader = true;\n } else if (config.background && cond) {\n $(el).removeClass(\"card-outline\");\n config.solidHeader = false;\n }\n }\n }\n }\n }\n\n // To remove status explicitly set status = NULL in updateBox. Don't apply\n // to socialBox in AdminLTE2!!!\n if (value.options.hasOwnProperty(\"status\")) {\n if (!isSocialCard) {\n if (value.options.status !== config.status) {\n var oldClass, newClass;\n // If there was a status and the user decide to remove any status\n if (value.options.status === null && config.status !== null) {\n if (!isUserCard) $(el).removeClass(\"card-\" + config.status);\n // add class card-outline for better render (status = NULL)\n // renders with grey border which is not nice\n if ($(el).hasClass(\"card-outline\") && !isUserCard) {\n $(el).addClass(\"card-outline\");\n }\n\n // Apply new background color to buttons if any\n if (value.options.background) {\n var background = value.options.background;\n if (validStatusesPlus.indexOf(background) > -1) {\n $(el)\n .find(\".btn-tool\")\n .addClass(\"bg-\" + background);\n } else if (validStatuses.indexOf(background) > -1) {\n $(el)\n .find(\".btn-tool\")\n .addClass(\"btn-\" + background);\n }\n }\n\n // in case there is a status and it is not null (indeed we can send null through R)\n } else if (value.options.status) {\n // apply new status\n if (isUserCard) {\n newClass = \"bg-\";\n if (value.options.gradient) {\n newClass = newClass + \"gradient-\";\n }\n newClass = newClass + value.options.status;\n $(el)\n .find(\".widget-user-header\")\n .addClass(newClass);\n } else {\n newClass = \"card-\" + value.options.status;\n $(el).addClass(newClass);\n }\n\n // remove old status, if there was one ...\n if (config.status) {\n if (isUserCard) {\n oldClass = \"bg-\";\n if (config.gradient) {\n oldClass = oldClass + \"gradient-\";\n }\n oldClass = oldClass + config.status;\n $(el)\n .find(\".widget-user-header\")\n .removeClass(oldClass);\n } else {\n oldClass = \"card-\" + config.status;\n $(el).removeClass(oldClass);\n }\n }\n\n // Add new color for Buttons. We handle extra statuses in which case\n // the button class changes. Only if solidHeader\n if (!$(el).hasClass(\"card-outline\") || isUserCard) {\n if (validStatusesPlus.indexOf(value.options.status) > -1) {\n $(el)\n .find(\".btn-tool\")\n .addClass(\"bg-\" + value.options.status);\n } else if (validStatuses.indexOf(value.options.status) > -1) {\n $(el)\n .find(\".btn-tool\")\n .addClass(\"btn-\" + value.options.status);\n }\n }\n }\n\n // If there was a status or background, we must cleanup the old button status\n // since status predominate over background. We also handle extra\n // statuses ...\n var status;\n if (config.status || config.background) {\n // status dominates\n if (config.status) {\n status = config.status;\n } else if (config.background) {\n status = config.background;\n }\n\n if (validStatusesPlus.indexOf(status) > -1) {\n $(el)\n .find(\".btn-tool\")\n .removeClass(\"bg-\" + status);\n } else if (validStatuses.indexOf(status) > -1) {\n $(el)\n .find(\".btn-tool\")\n .removeClass(\"btn-\" + status);\n }\n }\n config.status = value.options.status;\n }\n }\n }\n\n // To remove background explicitly set background = NULL in updateBox\n if (value.options.hasOwnProperty(\"background\")) {\n if (value.options.background !== config.background) {\n var oldBgClass = \"bg-\";\n newBgClass = oldBgClass;\n // don't touch if null\n if (config.background) {\n // if gradient, the class has a gradient in between!\n if (config.gradient) {\n oldBgClass = oldBgClass + \"gradient-\";\n }\n oldBgClass = oldBgClass + config.background;\n // handle userBox\n // for which we also have to toggle the header bg color\n // and the box tools buttons color\n if (isUserCard && !(config.status || value.options.status)) {\n var header = $(el).find(\".widget-user-header\");\n $(header).removeClass(oldBgClass);\n }\n\n $(el).removeClass(oldBgClass);\n }\n if (value.options.background) {\n if (config.gradient || value.options.gradient) {\n newBgClass = newBgClass + \"gradient-\";\n }\n newBgClass = newBgClass + value.options.background;\n if (isUserCard && !(config.status || value.options.status)) {\n var header = $(el).find(\".widget-user-header\");\n $(header).addClass(newBgClass);\n }\n $(el).addClass(newBgClass);\n }\n if (\n config.gradient !== value.options.gradient &&\n value.options.gradient !== undefined\n ) {\n config.gradient = value.options.gradient;\n }\n config.background = value.options.background;\n }\n }\n\n if (value.options.hasOwnProperty(\"width\")) {\n if (value.options.width !== config.width) {\n this._updateWidth(el, config.width, value.options.width);\n config.width = value.options.width;\n }\n }\n\n if (value.options.hasOwnProperty(\"height\")) {\n if (value.options.height !== config.height) {\n if (value.options.height === null) {\n $(el)\n .find(\".card-body\")\n .css(\"height\", \"\");\n } else {\n $(el)\n .find(\".card-body\")\n .css(\"height\", value.options.height);\n }\n\n config.height = value.options.height;\n // don't need to trigger resize since the output height\n // is not controlled by the box size ...\n }\n }\n\n // replace the old JSON config by the new one to update the input value\n $(el)\n .parent()\n .find(\"script[data-for='\" + el.id + \"']\")\n .replaceWith(\n '\"\n );\n } else {\n if (value != \"restore\") {\n if ($(el).css(\"display\") != \"none\") {\n $(el).CardWidget(value);\n }\n } else {\n $(el).show();\n // this is needed so that the last event handler is considered\n // in the subscribe method.\n $(el).trigger(\"shown\");\n }\n }\n },\n receiveMessage: function(el, data) {\n this.setValue(el, data);\n $(el).trigger(\"change\");\n },\n\n subscribe: function(el, callback) {\n $(el).on(\"expanded.lte.cardwidget collapsed.lte.cardwidget\", function(e) {\n // set a delay so that SHiny get the input value when the collapse animation\n // is finished.\n setTimeout(function() {\n callback();\n }, 500);\n });\n\n $(el).on(\"maximized.lte.cardwidget minimized.lte.cardwidget\", function(e) {\n callback();\n });\n\n $(el).on(\"removed.lte.cardwidget\", function(e) {\n setTimeout(function() {\n callback();\n }, 500);\n });\n // we need to split removed and shown event since shown is immediate whereas close\n // takes some time\n $(el).on(\"shown.cardBinding\", function(e) {\n callback();\n });\n\n // handle change event triggered in the setValue method\n $(el).on(\"change.cardBinding\", function(event) {\n setTimeout(function() {\n callback();\n }, 500);\n });\n },\n\n unsubscribe: function(el) {\n $(el).off(\".cardBinding\");\n }\n});\n\nShiny.inputBindings.register(cardBinding);\n\n// Card sidebar input binding\nvar cardSidebarBinding = new Shiny.InputBinding();\n$.extend(cardSidebarBinding, {\n initialize: function(el) {\n // erase default to avoid seeing moving sidebars on initialization\n $(\".direct-chat-contacts, .direct-chat-messages\").css({\n transition: \"transform .0s ease-in-out\"\n });\n\n var background = $(el).attr(\"data-background\")\n ? $(el).attr(\"data-background\")\n : \"#343a40\";\n var width = $(el).attr(\"data-width\")\n ? parseInt($(el).attr(\"data-width\"))\n : 100;\n var closeTranslationRate = (100 * 100) / width;\n var contacts = $(el)\n .closest(\".direct-chat\")\n .find(\".direct-chat-contacts\");\n\n // apply width and background\n $(contacts).css({\n background: `${background}`,\n width: `${width}%`\n });\n\n // If start open, apply openTranslationRate else apply closeTranslationRate ...\n if ($(el).attr(\"data-start-open\") === \"true\") {\n var openTranslationRate = closeTranslationRate - 100;\n $(contacts).css({ transform: `translate(${openTranslationRate}%, 0)` });\n } else {\n $(contacts).css({ transform: `translate(${closeTranslationRate}%, 0)` });\n }\n\n // Restore for better transitions\n setTimeout(function() {\n $(\".direct-chat-contacts, .direct-chat-messages\").css({\n transition: \"transform .5s ease-in-out\"\n });\n }, 300);\n \n // Easyclose feature\n if ($(el).attr(\"data-easy-close\") === \"true\") {\n $(document).mouseup(function(e) {\n var container = $(\".direct-chat-contacts\");\n var openContainer = $(\".direct-chat-contacts-open\");\n // if the target of the click isn't the container nor a descendant of the container and also not if the filter symbol was clicke d\n if (!container.is(e.target) && \n container.has(e.target).length === 0 && \n $(e.target).parents('.card-tools').length !== 1) {\n openContainer\n .find(\"[data-widget='chat-pane-toggle']\")\n .click();\n }\n }); \n }\n },\n\n find: function(scope) {\n return $(scope).find('[data-widget=\"chat-pane-toggle\"]');\n },\n\n // Given the DOM element for the input, return the value\n getValue: function(el) {\n var cardWrapper = $(el).closest(\".card\");\n return $(cardWrapper).hasClass(\"direct-chat-contacts-open\");\n },\n\n // see updatebs4Card\n receiveMessage: function(el, data) {\n // In theory, adminLTE3 has a builtin function\n // we could use $(el).DirectChat('toggle');\n // However, it does not update the related input.\n // The toggled.lte.directchat event seems to be broken.\n $(el).trigger(\"click\");\n $(el).trigger(\"shown\");\n },\n\n subscribe: function(el, callback) {\n var self = this;\n $(el).on(\"click\", function(e) {\n var width = $(el).attr(\"data-width\")\n ? parseInt($(el).attr(\"data-width\"))\n : 100;\n var closeTranslationRate = (100 * 100) / width;\n var openTranslationRate = closeTranslationRate - 100;\n // set a delay so that Shiny get the input value when the collapse animation\n // is finished.\n var target = e.currentTarget;\n setTimeout(function(e = target) {\n // apply correct translation rate depending on current state\n var contacts = $(e)\n .closest(\".direct-chat\")\n .find(\".direct-chat-contacts\");\n if (self.getValue(el)) {\n $(contacts).css({\n transform: `translate(${openTranslationRate}%, 0)`\n });\n } else {\n $(contacts).css({\n transform: `translate(${closeTranslationRate}%, 0)`\n });\n }\n callback();\n }, 10);\n });\n },\n\n unsubscribe: function(el) {\n $(el).off(\".cardSidebarBinding\");\n }\n});\n\nShiny.inputBindings.register(cardSidebarBinding);\n","$(function() {\n \n // required to show a toast when the controlbar is pinned \n // for the first time. Show once since it may be annoying ...\n var showToast = true;\n const controlbarToast = () => {\n if (showToast) {\n $(document).Toasts('create', {\n title: 'Controlbar is pinned',\n close: false,\n autohide: true,\n delay: 2000\n });\n showToast = false; \n }\n };\n\n // This prevent box content from going outside their container \n // when the control-bar is on push mode\n $(\"#controlbar-toggle\").on(\"click\",\n function() {\n if ($(\"body\").hasClass(\"control-sidebar-push-slide\")) {\n $(window).trigger(\"resize\"); \n }\n });\n \n \n // The code below hande the click out of the right control bar\n $(window).click(function(e) { \n // There is a potential conflict. This function detect any click outside\n // the controlbar and close if if it is not pinned. Yet, if we click on an action // button controlling the controlbar state (see updatebs4Controlbar), it is also outside the controlbar so the toggle event will be triggered twice. The controlbar will never close as shown in https://github.com/RinteRface/bs4Dash/issues/110. Below we make sure to leave the function as soon as a click on a button holding the class action button. This is not really a fix but a reasonable workaround.\n var isActionButton = $(e.target).hasClass(\"action-button\");\n if (isActionButton) return null;\n \n if($(\"aside.control-sidebar\").find(e.target).length === 0) {\n var pinned = $(\".control-sidebar\").attr(\"data-pin\");\n if (pinned === \"false\" || pinned === undefined) {\n $(\"body\").removeClass(\"control-sidebar-slide-open\"); \n // don't forget to refresh the input binding\n $(\"#controlbar-toggle\").trigger('collapsed.lte.controlsidebar');\n }\n } \n });\n \n // handle the pin button: toggle data-pin state\n $(\"#controlbarPin\").on('click', function() {\n var $pinIcon = $(this).children();\n $pinIcon.toggleClass(\"fa-rotate-90 fa-lg\");\n \n $(\".control-sidebar\").attr(\"data-pin\",\n $(\".control-sidebar\").attr(\"data-pin\") == \"false\" ? \"true\" : \"false\");\n // toggle right sidebar control depending on the datapin\n if ($(\".control-sidebar\").attr(\"data-pin\") === \"true\") {\n $pinIcon.css(\"color\", \"#007bff\");\n $(\"#controlbar-toggle\").addClass(\"disabled\");\n controlbarToast();\n } else {\n $(\"#controlbar-toggle\").removeClass(\"disabled\");\n $pinIcon.css(\"color\", \"\");\n }\n });\n\n\nvar init = true;\n\n // Input binding\n var controlbarBinding = new Shiny.InputBinding();\n \n $.extend(controlbarBinding, {\n \n find: function(scope) {\n return $(scope).find(\".control-sidebar\");\n },\n \n // Given the DOM element for the input, return the value\n getValue: function(el) {\n // Handles the pin \n var controlbarOpen = $(\"body\").hasClass(\"control-sidebar-slide-open\");\n var pinned = $(el).attr(\"data-pin\") === \"true\";\n if (controlbarOpen && pinned && init) {\n $(\"#controlbar-toggle\").addClass(\"disabled\");\n $(\"#controlbarPin\")\n .children()\n .css(\"color\", \"#007bff\");\n controlbarToast();\n init = false;\n }\n \n // this handles the case where the controlbar is not collapsed at start\n var controlbarCollapsed = $(el).attr('data-collapsed');\n if (controlbarCollapsed === \"false\") {\n $(\"#controlbar-toggle\").ControlSidebar('toggle');\n $(el).attr('data-collapsed', \"true\");\n return true;\n } else {\n return $(\"body\").hasClass(\"control-sidebar-slide-open\");\n }\n },\n // see updatebs4Controlbar\n receiveMessage: function(el, data) {\n $(\"#controlbar-toggle\").ControlSidebar('toggle');\n },\n \n subscribe: function(el, callback) {\n $(\"#controlbar-toggle\").on(\"collapsed.lte.controlsidebar expanded.lte.controlsidebar\", function(e) {\n $(el).trigger('shown');\n // add a delay so that Shiny get the input value \n // after the AdminLTE3 animation is finished!\n setTimeout(\n function() {\n callback();\n }, 10);\n });\n },\n \n unsubscribe: function(el) {\n $(el).off(\".controlbarBinding\");\n }\n });\n \n Shiny.inputBindings.register(controlbarBinding, \"bs4Dash.controlbarBinding\");\n \n // handle controlbar overlay\n var controlbarOverlay = $('.control-sidebar').attr('data-overlay');\n if (controlbarOverlay === \"false\") {\n $('body').addClass('control-sidebar-push-slide');\n }\n\n});","$(function () {\n // handle tooltip from the server side\n Shiny.addCustomMessageHandler('create-tooltip', function (message) {\n var tooltipTarget;\n if (message.id) {\n tooltipTarget = '#' + message.id;\n } else {\n if (message.selector) {\n tooltipTarget = message.selector;\n }\n }\n $(tooltipTarget)\n .addClass('has-tooltip')\n .tooltip(message.options);\n console.log(`'Tooltip created for ${tooltipTarget}'`);\n });\n\n Shiny.addCustomMessageHandler('remove-tooltip', function (message) {\n var tooltipTarget = '#' + message;\n\n // only destroys if popover exists\n if ($(tooltipTarget).hasClass('has-tooltip')) {\n $(tooltipTarget)\n .removeClass('has-tooltip')\n .tooltip('dispose');\n console.log(`'Tooltip destroyed for ${tooltipTarget}'`);\n }\n });\n\n // handle popover from the server side\n Shiny.addCustomMessageHandler('create-popover', function (message) {\n var popoverTarget;\n if (message.id) {\n popoverTarget = '#' + message.id;\n } else {\n if (message.selector) {\n popoverTarget = message.selector;\n }\n }\n // indicate target has popover. This is for removePopover to know\n // whether the popover exists\n $(popoverTarget)\n .addClass('has-popover')\n .popover(message.options);\n console.log(`'Popover created for ${popoverTarget}'`);\n });\n\n\n Shiny.addCustomMessageHandler('remove-popover', function (message) {\n var popoverTarget = '#' + message;\n\n // only destroys if popover exists\n if ($(popoverTarget).hasClass('has-popover')) {\n $(popoverTarget)\n .removeClass('has-popover')\n .popover('dispose');\n console.log(`'Popover destroyed for ${popoverTarget}'`);\n }\n });\n\n\n // handle builtin toasts\n Shiny.addCustomMessageHandler('toast', function (message) {\n $(document).Toasts('create', message);\n });\n\n // Create an alert\n Shiny.addCustomMessageHandler('create-alert', function (message) {\n // setup target\n var alertTarget;\n if (message.id) {\n alertTarget = `#${message.id}`;\n } else {\n if (message.selector) {\n alertTarget = message.selector;\n }\n }\n\n // build the tag from options\n var config = message.options, alertCl, alertTag, iconType, closeButton, titleTag, contentTag;\n alertCl = 'alert alert-dismissible';\n if (config.status !== undefined) {\n alertCl = `${alertCl} alert-${config.status}`;\n }\n if (config.elevation !== undefined) {\n alertCl = `${alertCl} elevation-${config.elevation}`;\n }\n\n switch (config.status) {\n case 'primary': iconType = 'info';\n break;\n case 'danger': iconType = 'ban';\n break;\n case 'info': iconType = 'info';\n break;\n case 'warning': iconType = 'warning';\n break;\n case 'success': iconType = 'check';\n break;\n default: console.warn(`${config.status} does not belong to allowed statuses!`)\n }\n\n closeButton = '';\n\n if (config.closable) {\n closeButton = ''\n }\n\n titleTag = `
    ${config.title}
    `\n contentTag = config.content;\n\n alertTag = `
    \n ${closeButton}${titleTag}${contentTag}\n
    `\n if (config.width !== undefined) {\n alertTag = `
    ${alertTag}
    `\n }\n\n // add it to the DOM if no existing alert is found in the anchor\n if ($(`#${message.id}-alert`).length === 0) {\n $(alertTarget).append(alertTag);\n Shiny.setInputValue(message.id, true, { priority: 'event' });\n\n // add events only after element is inserted\n\n // callback -> give ability to perform more actions on the Shiny side\n // once the alert is closed\n $(`#${message.id}-alert`).on('closed.bs.alert', function () {\n Shiny.setInputValue(message.id, false, { priority: 'event' });\n });\n // Clicking on close button does not trigger any event.\n // Trigger the closed.bs.alert event.\n $('[data-dismiss=\"alert\"]').on('click', function () {\n var alertId = $(this).parent.attr('id');\n $(`#${alertId}.`).trigger('closed.bs.alert');\n });\n\n } else {\n console.warn(`${alertTarget} already has an alert!`);\n }\n });\n\n\n Shiny.addCustomMessageHandler('close-alert', function (message) {\n // only closes if element exists\n if ($(`#${message}-alert`).length > 0) {\n $(`#${message}-alert`).alert('close');\n } else {\n console.warn('Nothing to delete!');\n }\n });\n});","// When document is ready, if there is a sidebar menu with no activated tabs,\n// activate the one specified by `data-start-selected`, or if that's not\n// present, the first one.\nvar ensureActivatedTab = function() {\n // get the selected tabs\n var $tablinks = $(\".sidebar-menu a[data-toggle='tab']\");\n\n // If there are no tabs, $startTab.length will be 0.\n var $startTab = $tablinks.filter(\"[data-start-selected='1']\");\n if ($startTab.length === 0) {\n // If no tab starts selected, use the first one, if present\n $startTab = $tablinks.first();\n }\n\n // If there's a `data-start-selected` attribute and we can find a tab with\n // that name, activate it.\n if ($startTab.length !== 0) {\n // This is just in case the user renders the tabs in a renderUI that does not\n // print immediately in the DOM. We need a bit of a delay before telling which\n // tab to show ...\n if ($(\".sidebar-menu\").hasClass(\"bs4Dash-menu-output\")) {\n setTimeout(function() {\n // we need to initialize any treeview elements that were not inserted\n // in the DOM when adminlte was first initialized!\n adminlte.Treeview._jQueryInterface.call($('[data-widget=\"treeview\"]'), 'init');\n\n $startTab.tab(\"show\");\n }, 10);\n } else {\n $startTab.tab(\"show\");\n }\n \n\n // This is indirectly setting the value of the Shiny input by setting\n // an attribute on the html element it is bound to. We cannot use the\n // inputBinding's setValue() method here because this is called too\n // early (before Shiny has fully initialized)\n $(\".sidebarMenuSelectedTabItem\").attr(\n \"data-value\",\n $startTab.attr(\"data-value\")\n );\n }\n};\n\n// This function handles a special case in the AdminLTE sidebar: when there\n// is a sidebar-menu with items, and one of those items has sub-items, and\n// they are used for tab navigation. Normally, if one of the items is\n// selected and then a sub-item is clicked, both the item and sub-item will\n// retain the \"active\" class, so they will both be highlighted. This happens\n// because they're not designed to be used together for tab panels. This\n// code ensures that only one item will have the \"active\" class.\nvar deactivateOtherTabs = function() {\n // Find all tab links under sidebar-menu even if they don't have a\n // tabName (which is why the second selector is necessary)\n var $tablinks = $(\n \".sidebar-menu a[data-toggle='tab'],\" + \".sidebar-menu li.has-treeview > a\"\n );\n\n // If any other items are active, deactivate them\n $tablinks.not($(this)).removeClass(\"active\");\n\n // also manually activate the parent link when the selected item\n // is part of a treeview. For some reason, this is not done by AdminLTE3...\n if ($(this).hasClass(\"treeview-link\")) {\n $(this)\n .parents(\".has-treeview\")\n .children()\n .eq(0)\n .addClass(\"active\");\n }\n\n // Trigger event for the tabItemInputBinding\n var $obj = $(\".sidebarMenuSelectedTabItem\");\n var inputBinding = $obj.data(\"shiny-input-binding\");\n if (typeof inputBinding !== \"undefined\") {\n inputBinding.setValue($obj, $(this).attr(\"data-value\"));\n $obj.trigger(\"change\");\n }\n};\n\n$(function() {\n // Whenever the sidebar finishes a transition (which it does every time it\n // changes from collapsed to expanded and vice versa), trigger resize,\n // so that all outputs are resized.\n $(\".main-sidebar\").on(\n \"webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend\",\n function() {\n $(window).trigger(\"resize\");\n }\n );\n\n $(document).on(\n \"shown.bs.tab\",\n '.sidebar-menu a[data-toggle=\"tab\"]',\n deactivateOtherTabs\n );\n\n ensureActivatedTab();\n\n // Whenever we expand a menuItem (to be expandable, it must have children),\n // update the value for the expandedItem's input binding (this is the\n // tabName of the fist subMenuItem inside the menuItem that is currently\n // expanded)\n $(document).on(\"click\", \".has-treeview\", function() {\n var $menu = $(this);\n // If this menuItem was already open, then clicking on it again,\n // should trigger the \"hidden\" event, so Shiny doesn't worry about\n // it while it's hidden (and vice versa).\n if ($menu.hasClass(\"menu-open\")) $menu.trigger(\"collapsed.lte.treeview\");\n else if ($menu.hasClass(\".has-treeview\"))\n $menu.trigger(\"expanded.lte.treeview\");\n\n // need to set timeout to account for the slideUp/slideDown animation\n var $obj = $(\".sidebar.shiny-bound-input\");\n setTimeout(function() {\n $obj.trigger(\"change\");\n }, 600);\n });\n\n //---------------------------------------------------------------------\n // tabItemInputBinding\n // ------------------------------------------------------------------\n // Based on Shiny.tabItemInputBinding, but customized for tabItems in\n // bs4Dash, which have a slightly different structure.\n var tabItemInputBinding = new Shiny.InputBinding();\n $.extend(tabItemInputBinding, {\n find: function(scope) {\n return $(scope).find(\".sidebarMenuSelectedTabItem\");\n },\n getValue: function(el) {\n var value = $(el).attr(\"data-value\");\n if (value === \"null\") return null;\n return value;\n },\n setValue: function(el, value) {\n var self = this;\n var anchors = $(el)\n .parent(\".sidebar-menu\")\n .find(\"li:not(.treeview)\")\n .children(\"a\");\n anchors.each(function() {\n // eslint-disable-line consistent-return\n if (self._getTabName($(this)) === value) {\n $(this).tab(\"show\");\n // this make sure that treeview items are open when we\n // use the updatebs4TabItems function on the server side\n if ($(this).hasClass(\"treeview-link\")) {\n if (\n !$(this)\n .parents(\".has-treeview\")\n .hasClass(\"menu-open\")\n ) {\n $(this)\n .parents(\".has-treeview\")\n .children()\n .eq(0)\n .trigger(\"click\");\n }\n }\n $(el).attr(\"data-value\", self._getTabName($(this)));\n return false;\n }\n });\n },\n receiveMessage: function(el, data) {\n if (data.hasOwnProperty(\"value\")) this.setValue(el, data.value);\n },\n subscribe: function(el, callback) {\n // This event is triggered by deactivateOtherTabs, which is triggered by\n // shown. The deactivation of other tabs must occur before Shiny gets the\n // input value.\n $(el).on(\"change.tabItemInputBinding\", function() {\n callback();\n });\n },\n unsubscribe: function(el) {\n $(el).off(\".tabItemInputBinding\");\n },\n _getTabName: function(anchor) {\n return anchor.attr(\"data-value\");\n }\n });\n\n Shiny.inputBindings.register(tabItemInputBinding, \"bs4Dash.tabItemInput\");\n\n //---------------------------------------------------------------------\n // sidebarInputBinding\n // ------------------------------------------------------------------\n // similar to controlbarInputBinding\n var sidebarBinding = new Shiny.InputBinding();\n\n $.extend(sidebarBinding, {\n find: function(scope) {\n return $(scope).find(\".main-sidebar\");\n },\n\n // Given the DOM element for the input, return the value\n getValue: function(el) {\n // Warning: we can't look for sidebar-open since this\n // class is only generated on mobile devices\n return !$(\"body\").hasClass(\"sidebar-collapse\");\n },\n\n // see updatebs4Controlbar\n receiveMessage: function(el, data) {\n $(\"[data-widget='pushmenu']\").PushMenu(\"toggle\");\n },\n\n subscribe: function(el, callback) {\n $(\"[data-widget='pushmenu']\").on(\n \"collapsed.lte.pushmenu.sidebarBinding shown.lte.pushmenu.sidebarBinding\",\n function(e) {\n callback();\n }\n );\n },\n\n unsubscribe: function(el) {\n $(el).off(\".sidebarBinding\");\n }\n });\n\n Shiny.inputBindings.register(sidebarBinding, \"bs4Dash.sidebarInput\");\n\n // sidebarmenuExpandedInputBinding\n // ------------------------------------------------------------------\n // This keeps tracks of what menuItem (if any) is expanded\n var sidebarmenuExpandedInputBinding = new Shiny.InputBinding();\n $.extend(sidebarmenuExpandedInputBinding, {\n find: function(scope) {\n // This will also have id=\"sidebarItemExpanded\"\n return $(scope).find(\".sidebar\");\n },\n getValue: function(el) {\n var $open = $(el)\n .find(\"li\")\n .filter(\".menu-open\")\n .find(\"ul\");\n if ($open.length === 1) return $open.attr(\"data-expanded\");\n else return null;\n },\n setValue: function(el, value) {\n // does not work (nothing is printed)\n var $menuItem = $(el).find(\"[data-expanded='\" + value + \"']\");\n // This will trigger actions defined by AdminLTE, as well as actions\n // defined in sidebar.js.\n $menuItem.prev().trigger(\"click\");\n },\n subscribe: function(el, callback) {\n $(el).on(\"change.sidebarmenuExpandedInputBinding\", function() {\n callback();\n });\n },\n unsubscribe: function(el) {\n $(el).off(\".sidebarmenuExpandedInputBinding\");\n }\n });\n Shiny.inputBindings.register(\n sidebarmenuExpandedInputBinding,\n \"bs4Dash.sidebarmenuExpandedInputBinding\"\n );\n\n // handle fixed sidebar\n if ($(\".main-sidebar\").attr(\"data-fixed\") === \"true\") {\n $(\"body\").addClass(\"layout-fixed\");\n //$('body').Layout('fixLayoutHeight');\n }\n});\n","$(function () {\n\n $navbar = $('.main-header.navbar');\n\n // Modify the shiny tabsetpanel binding to follow BS4 rules\n $(document).on('shiny:connected', function (event) {\n Shiny.unbindAll();\n $.extend(Shiny\n .inputBindings\n .bindingNames['shiny.bootstrapTabInput']\n .binding, {\n // do whathever you want to edit existing methods\n getValue: function (el) {\n var anchor = $(el).find('li:not(.dropdown)').children('a.active');\n if (anchor.length === 1)\n return this._getTabName(anchor);\n\n return null;\n }\n });\n Shiny.bindAll();\n });\n\n // footer has fixed layout?\n if ($(\".main-footer\").attr(\"data-fixed\") === \"true\") {\n $(\"body\").addClass(\"layout-footer-fixed\");\n }\n\n // add dropdown-menu-right class to correctly open the dropdown to all \n // navbar rightUi elements\n var navbarRight = $('.navbar-right').find('.dropdown-menu');\n $(navbarRight).each(function () {\n if (!$(this).hasClass('dropdown-menu-right')) {\n $(this).addClass('dropdown-menu-right');\n }\n });\n\n\n // data toggle collapse icon update\n $('.user-block [data-toggle=\"collapse\"]').on('click', function () {\n if ($(this).children('i').hasClass('fa-plus')) {\n $(this).children('i').attr('class', 'fa fa-minus');\n } else {\n $(this).children('i').attr('class', 'fa fa-plus');\n }\n });\n\n // fullscreen toggle\n if ($('body').attr('data-fullscreen') == 1) {\n var fullScreenToggle = `
  • \n \n \n \n
  • `;\n $(fullScreenToggle).insertBefore($('[data-widget=\"control-sidebar\"]').parent());\n }\n\n // slide to top button\n if ($('body').attr('data-scrollToTop') == 1) {\n var $slideToTop = $('
    ');\n\n $slideToTop.html('');\n\n $slideToTop.css({\n position: 'fixed',\n bottom: '20px',\n right: '25px',\n width: '40px',\n height: '40px',\n color: '#eee',\n 'font-size': '',\n 'line-height': '40px',\n 'text-align': 'center',\n 'background-color': '#222d32',\n cursor: 'pointer',\n 'border-radius': '5px',\n 'z-index': '99999',\n opacity: '.7',\n 'display': 'none'\n });\n\n $slideToTop.on('mouseenter', function () {\n $(this).css('opacity', '1');\n });\n\n $slideToTop.on('mouseout', function () {\n $(this).css('opacity', '.7');\n });\n\n $('.wrapper').append($slideToTop);\n\n $(window).scroll(function () {\n if ($(window).scrollTop() >= 150) {\n if (!$($slideToTop).is(':visible')) {\n $($slideToTop).fadeIn(500);\n }\n } else {\n $($slideToTop).fadeOut(500);\n }\n });\n\n $($slideToTop).click(function () {\n $('html, body').animate({\n scrollTop: 0\n }, 500);\n });\n }\n \n // nav item click also triggers scroll to top\n $('.main-sidebar .nav-item').on('click', function () {\n $('html, body').animate({\n scrollTop: 0\n }, 0);\n }); \n\n\n // tooltip/popover toggle\n if ($('body').attr('data-help') == 2 || \n $('body').attr('data-help') == 1) {\n var $help_switch_checkbox = $('', {\n type: 'checkbox',\n id: 'help_switch',\n class: 'custom-control-input'\n }).on('click', function () {\n if ($(this).is(':checked')) {\n $('[data-toggle=\"tooltip\"]').tooltip('enable');\n $('[data-toggle=\"popover\"]').popover({\n trigger: 'hover'\n });\n $('[data-toggle=\"popover\"]').popover('enable');\n } else {\n $('[data-toggle=\"tooltip\"]').tooltip('disable');\n $('[data-toggle=\"popover\"]').popover('disable');\n }\n });\n\n var $help_switch_container = $('
    ', { class: 'custom-control custom-switch mx-2 mt-2' }).append($help_switch_checkbox).append(``);\n \n // insert before $('#controlbar-toggle') whenever possible ...\n if ($('.nav-item #controlbar-toggle')) {\n $help_switch_container.insertBefore($('#controlbar-toggle').parent());\n } else {\n $navbar.append($help_switch_container);\n }\n\n // trigger first click, if necessary\n $(document).on('shiny:connected', function() {\n if ($('body').attr('data-help') == 2 || $('body').attr('data-help') == 1) {\n $help_switch_checkbox.click(); \n // Click again if option is set to FALSE\n if ($('body').attr('data-help') == 1) {\n $help_switch_checkbox.click(); \n }\n }\n }); \n }\n\n // dark mode input\n $(document).one('shiny:connected', function () {\n if ($('body').hasClass('dark-mode')) {\n Shiny.setInputValue('dark_mode', true, { priority: 'event' });\n } else {\n Shiny.setInputValue('dark_mode', false, { priority: 'event' });\n }\n });\n\n\n // Navbar colors\n getNavbarColor = function () {\n for (let color of navbar_all_colors) {\n if ($('.main-header').attr('class').search(color) > -1) {\n return color;\n }\n }\n };\n\n var navbar_dark_skins = [\n 'navbar-primary',\n 'navbar-secondary',\n 'navbar-info',\n 'navbar-success',\n 'navbar-danger',\n 'navbar-indigo',\n 'navbar-purple',\n 'navbar-pink',\n 'navbar-maroon',\n 'navbar-fuchsia',\n 'navbar-navy',\n 'navbar-lightblue',\n 'navbar-lime',\n 'navbar-teal',\n 'navbar-olive',\n 'navbar-gray-dark',\n 'navbar-gray'\n ];\n\n var navbar_light_skins = [\n 'navbar-warning',\n 'navbar-white',\n 'navbar-orange'\n ];\n\n var navbar_all_colors = navbar_dark_skins.concat(navbar_light_skins);\n \n /**\n * Update color theme to navbar tag\n *\n * @param String color Color to apply.\n * @returns void\n */\n updateNavbarTheme = function (color) {\n var $main_header = $('.main-header');\n $main_header.removeClass('navbar-dark').removeClass('navbar-light');\n navbar_all_colors.forEach(function (color) {\n $main_header.removeClass(color);\n });\n\n if (navbar_dark_skins.indexOf(color) > -1) {\n $main_header.addClass('navbar-dark');\n } else {\n $main_header.addClass('navbar-light');\n }\n\n $main_header.addClass(color);\n };\n \n /**\n * Update icon color style based on navbar color.\n *\n * @param String color Current navbar color.\n * @returns void\n */\n updateNavbarIconColor = function(color) {\n var iconThemeColor = navbar_dark_skins.indexOf(color) > -1 ? \"white\" : \"rgba(0,0,0,.5)\";\n $(\".dark-theme-icon\").css(\"color\", iconThemeColor);\n $('[for=\"help_switch\"] i').css(\"color\", iconThemeColor);\n };\n \n // automatic global theme switcher\n if ($('body').attr('data-dark') == 2 || \n $('body').attr('data-dark') == 1) {\n var $dark_mode_checkbox = $('', {\n type: 'checkbox',\n id: 'theme_switch',\n class: 'custom-control-input'\n }).on('click', function () {\n\n // get any selected navbar skin in the navbar themer\n var newNavbarColor;\n // If there is not themer, we keep the navbar current color.\n // Otherwise, we replace it by the new color.\n if ($('.navbar-themer-chip').length > 0) {\n $('.navbar-themer-chip').filter(function () {\n if ($(this).css('border-style') === 'solid') {\n newNavbarColor = 'navbar-' +\n $(this)\n .attr('class')\n .split('elevation-2')[0]\n .trim()\n .replace('bg-', '');\n }\n });\n } else {\n newNavbarColor = getNavbarColor();\n }\n\n if ($(this).is(':checked')) {\n $('body').addClass('dark-mode');\n\n // use updateNavbarTheme to correctly setup the skin as depending\n // on the required color. If no color is chosen, we use gray-dark for dark mode\n if (newNavbarColor === undefined || newNavbarColor === 'navbar-white') {\n newNavbarColor = \"navbar-gray-dark\";\n }\n updateNavbarTheme(newNavbarColor);\n\n // sidebar update \n if ($('.main-sidebar').length > 0) {\n $('.main-sidebar').attr('class', $('.main-sidebar')\n .attr('class')\n .replace('light', 'dark'));\n $('#sidebar-skin').prop(\"checked\", true);\n\n $('.sidebar-themer-icon')\n .removeClass('fa-sun')\n .addClass('fa-moon');\n }\n\n // controlbar update\n if ($('.control-sidebar').length > 0) {\n $('.control-sidebar').attr('class', $('.control-sidebar')\n .attr('class')\n .replace('light', 'dark'));\n $('#controlbar-skin').prop(\"checked\", true);\n\n $('.controlbar-themer-icon')\n .removeClass('fa-sun')\n .addClass('fa-moon');\n }\n\n\n $('.dark-theme-icon')\n .removeClass('fa-sun')\n .addClass('fa-moon');\n\n // refresh shiny input value \n Shiny.setInputValue('dark_mode', true, { priority: 'event' });\n\n } else {\n $('body').removeClass('dark-mode');\n\n // use updateNavbarTheme to correctly setup the skin as depending\n // on the required color. If no color is chosen, we use white for light mode\n if (newNavbarColor === undefined || newNavbarColor === 'navbar-gray-dark') {\n newNavbarColor = \"navbar-white\";\n }\n updateNavbarTheme(newNavbarColor);\n\n // sidebar update\n if ($('.main-sidebar').length > 0) {\n $('.main-sidebar').attr('class', $('.main-sidebar')\n .attr('class')\n .replace('dark', 'light'));\n $('#sidebar-skin').prop(\"checked\", false);\n\n $('.sidebar-themer-icon')\n .removeClass('fa-moon')\n .addClass('fa-sun');\n }\n\n // controlbar update\n if ($('.control-sidebar').length > 0) {\n $('.control-sidebar').attr('class', $('.control-sidebar')\n .attr('class')\n .replace('dark', 'light'));\n $('#controlbar-skin').prop(\"checked\", false);\n\n $('.controlbar-themer-icon')\n .removeClass('fa-moon')\n .addClass('fa-sun');\n }\n\n $('.dark-theme-icon')\n .removeClass('fa-moon')\n .addClass('fa-sun');\n\n // refresh shiny input value \n Shiny.setInputValue('dark_mode', false, { priority: 'event' });\n }\n \n // update navbar icon colors\n updateNavbarIconColor(newNavbarColor);\n });\n\n var $dark_mode_icon = $('body').hasClass('dark-mode') ? '' : '';\n var $dark_mode_container = $('
    ', { class: 'custom-control custom-switch mx-2 mt-2' }).append($dark_mode_checkbox).append(``);\n \n // insert before $('#controlbar-toggle') whenever possible ...\n if ($('.nav-item #controlbar-toggle')) {\n $dark_mode_container.insertBefore($('#controlbar-toggle').parent());\n } else {\n $navbar.append($dark_mode_container);\n }\n \n \n // Trigger dark mode\n if ($('body').attr('data-dark') == 2) {\n $(document).on('shiny:connected', function() {\n $dark_mode_checkbox.click();\n }); \n }\n }\n \n // apply correct navbar class depending on selected color\n if (getNavbarColor() !== undefined) {\n updateNavbarTheme(getNavbarColor());\n updateNavbarIconColor(getNavbarColor());\n }\n \n\n // Themer chips\n\n // Better style on hover\n $('.themer-chip').hover(function () {\n $(this).css({ opacity: 1 }).removeClass('elevation-2').addClass('elevation-4');\n }, function () {\n $(this).css({ opacity: 0.8 }).removeClass('elevation-4').addClass('elevation-2');\n });\n\n // \n $('.navbar-themer-chip').on('click', function () {\n $(this).css({ 'border-color': 'yellow', 'border-style': 'solid' });\n $('.navbar-themer-chip').not(this).css({ 'border-color': '', 'border-style': '' });\n });\n\n $('.accents-themer-chip').on('click', function () {\n $(this).css({ 'border-color': 'yellow', 'border-style': 'solid' });\n $('.accents-themer-chip').not(this).css({ 'border-color': '', 'border-style': '' });\n });\n\n $('.sidebar-themer-chip').on('click', function () {\n $(this).css({ 'border-color': 'yellow', 'border-style': 'solid' });\n $('.sidebar-themer-chip').not(this).css({ 'border-color': '', 'border-style': '' });\n });\n\n\n // Sidebar themer\n\n // detect global sidebar theme and select or not the toggle\n if ($('.main-sidebar').length > 0) {\n if ($('.main-sidebar').attr('class').match('dark')) {\n $('#sidebar-skin').prop(\"checked\", true);\n }\n }\n\n // clicking on dark/light switch changes:\n // - icon style\n // - sidebar class \n $('#sidebar-skin').on('click', function () {\n var sidebarCl;\n if ($(this).is(':checked')) {\n sidebarCl = $('.main-sidebar')\n .attr('class')\n .replace('light', 'dark');\n $('.main-sidebar').attr('class', sidebarCl);\n\n $('.sidebar-themer-icon')\n .removeClass('fa-sun')\n .addClass('fa-moon');\n } else {\n sidebarCl = $('.main-sidebar')\n .attr('class')\n .replace('dark', 'light');\n $('.main-sidebar').attr('class', sidebarCl);\n\n $('.sidebar-themer-icon')\n .removeClass('fa-moon')\n .addClass('fa-sun');\n }\n });\n\n var sidebar_colors = [\n 'bg-primary',\n 'bg-secondary',\n 'bg-info',\n 'bg-success',\n 'bg-danger',\n 'bg-indigo',\n 'bg-purple',\n 'bg-pink',\n 'bg-maroon',\n 'bg-fuchsia',\n 'bg-navy',\n 'bg-lightblue',\n 'bg-lime',\n 'bg-teal',\n 'bg-olive',\n 'bg-gray-dark',\n 'bg-gray',\n 'bg-light',\n 'bg-warning',\n 'bg-white',\n 'bg-orange'\n ];\n\n\n var sidebar_skins = [\n 'sidebar-dark-primary',\n 'sidebar-dark-secondary',\n 'sidebar-dark-info',\n 'sidebar-dark-success',\n 'sidebar-dark-danger',\n 'sidebar-dark-indigo',\n 'sidebar-dark-purple',\n 'sidebar-dark-pink',\n 'sidebar-dark-maroon',\n 'sidebar-dark-fuchsia',\n 'sidebar-dark-navy',\n 'sidebar-dark-lightblue',\n 'sidebar-dark-lime',\n 'sidebar-dark-teal',\n 'sidebar-dark-olive',\n 'sidebar-dark-gray-dark',\n 'sidebar-dark-gray',\n 'sidebar-dark-light',\n 'sidebar-dark-warning',\n 'sidebar-dark-white',\n 'sidebar-dark-orange',\n 'sidebar-light-primary',\n 'sidebar-light-secondary',\n 'sidebar-light-info',\n 'sidebar-light-success',\n 'sidebar-light-danger',\n 'sidebar-light-indigo',\n 'sidebar-light-purple',\n 'sidebar-light-pink',\n 'sidebar-light-maroon',\n 'sidebar-light-fuchsia',\n 'sidebar-light-navy',\n 'sidebar-light-lightblue',\n 'sidebar-light-lime',\n 'sidebar-light-teal',\n 'sidebar-light-olive',\n 'sidebar-light-gray-dark',\n 'sidebar-light-gray',\n 'sidebar-light-light',\n 'sidebar-light-warning',\n 'sidebar-light-white',\n 'sidebar-light-orange'\n ];\n\n\n updateSidebarTheme = function (color) {\n var sidebarCl;\n if ($('#sidebar-skin').is(':checked')) {\n sidebarCl = 'sidebar-dark-';\n } else {\n sidebarCl = 'sidebar-light-';\n }\n\n var sidebar_class = sidebarCl + color.replace('bg-', '');\n var $sidebar = $('.main-sidebar');\n sidebar_skins.forEach(function (skin) {\n $sidebar.removeClass(skin);\n });\n\n $sidebar.addClass(sidebar_class);\n };\n\n\n // Accents themer\n var accent_colors = [\n 'accent-primary',\n 'accent-secondary',\n 'accent-info',\n 'accent-success',\n 'accent-danger',\n 'accent-indigo',\n 'accent-purple',\n 'accent-pink',\n 'accent-maroon',\n 'accent-fuchsia',\n 'accent-navy',\n 'accent-lightblue',\n 'accent-lime',\n 'accent-teal',\n 'accent-olive',\n 'accent-gray-dark',\n 'accent-gray',\n 'accent-light',\n 'accent-warning',\n 'accent-white',\n 'accent-orange'\n ];\n\n\n updateAccentsTheme = function (color) {\n var accent_class = color;\n var $body = $('body');\n accent_colors.forEach(function (skin) {\n $body.removeClass(skin);\n });\n\n $body.addClass(accent_class);\n };\n\n\n // Controlbar themer\n\n // detect global controlbar theme and select or not the toggle\n if ($('.control-sidebar').length > 0) {\n if ($('.control-sidebar').attr('class').match('dark')) {\n $('#controlbar-skin').prop(\"checked\", true);\n }\n }\n\n // clicking on dark/light switch changes:\n // - icon style\n // - sidebar class \n $('#controlbar-skin').on('click', function () {\n var controlbarCl;\n if ($(this).is(':checked')) {\n controlbarCl = $('.control-sidebar')\n .attr('class')\n .replace('light', 'dark');\n $('.control-sidebar').attr('class', controlbarCl);\n\n $('.controlbar-themer-icon')\n .removeClass('fa-sun')\n .addClass('fa-moon');\n } else {\n controlbarCl = $('.control-sidebar')\n .attr('class')\n .replace('dark', 'light');\n $('.control-sidebar').attr('class', controlbarCl);\n\n $('.controlbar-themer-icon')\n .removeClass('fa-moon')\n .addClass('fa-sun');\n }\n });\n\n});","$(function () {\n // hide the right sidebar toggle \n // if no right sidebar is specified\n noControlbar = ($(\".control-sidebar\").length === 0);\n if (noControlbar) {\n $(\"#controlbar-toggle\").hide();\n }\n\n // hide the right sidebar toggle if the controlbar is disable\n disableControlbar = ($(\".control-sidebar\").attr(\"data-show\"));\n if (!disableControlbar) {\n $(\"#controlbar-toggle\").hide();\n }\n\n // controlbar slide\n controlbarSlide = ($(\".control-sidebar\").attr(\"data-slide\"));\n if (controlbarSlide) {\n $(\"#controlbar-toggle\").attr('data-controlsidebar-slide', controlbarSlide);\n }\n\n // when the sidebar is disabled, hide the sidebar toggle\n disableSidebar = ($(\".main-sidebar\").length === 0);\n if (disableSidebar) {\n $(\".nav-item > a[data-widget='pushmenu']\").css(\"visibility\", \"hidden\");\n }\n\n // handle fixed navbar\n if ($(\".navbar\").attr(\"data-fixed\") === \"true\") {\n $(\"body\").addClass(\"layout-navbar-fixed\");\n }\n\n});","var menuOutputBinding = new Shiny.OutputBinding();\n$.extend(menuOutputBinding, {\n find: function (scope) {\n return $(scope).find('.bs4Dash-menu-output');\n },\n onValueError: function (el, err) {\n Shiny.unbindAll(el);\n this.renderError(el, err);\n },\n renderValue: function (el, data) {\n Shiny.unbindAll(el);\n\n var html;\n var dependencies = [];\n if (data === null) {\n return;\n } else if (typeof (data) === 'string') {\n html = data;\n } else if (typeof (data) === 'object') {\n html = data.html;\n dependencies = data.deps;\n }\n\n var $html = $($.parseHTML(html));\n\n // Convert the inner contents to HTML, and pass to renderHtml\n Shiny.renderHtml($html.html(), el, dependencies);\n\n // Extract class of wrapper, and add them to the wrapper element\n el.className = 'bs4Dash-menu-output shiny-bound-output ' +\n $html.attr('class');\n \n // need this to activate adminLTE3 plugin for treeview \n $(el)\n .attr(\"data-widget\", \"treeview\")\n .attr(\"role\", \"menu\")\n .attr(\"data-accordion\", \"true\");\n\n Shiny.initializeInputs(el);\n Shiny.bindAll(el);\n if ($(el).hasClass(\"sidebar-menu\")) ensureActivatedTab(); // eslint-disable-line\n }\n});\nShiny.outputBindings.register(menuOutputBinding, \"bs4Dash.menuOutputBinding\");","$( document ).ready(function() {\n \n function findActivePage() {\n return $('ul.pagination').find('li.active');\n };\n \n function toggleNavigationItems(activeItem) {\n // hide pagination previous if we are at the first item\n if ($(activeItem).prev().find('a').hasClass('pagination-previous')) {\n $('.pagination-previous').parent('li').css('display', 'none');\n } else {\n $('.pagination-previous').parent('li').css('display', 'block');\n }\n \n // hide pagination next if we are at the last item\n if ($(activeItem).next().find('a').hasClass('pagination-next')) {\n $('.pagination-next').parent('li').css('display', 'none');\n } else {\n $('.pagination-next').parent('li').css('display', 'block');\n }\n }\n \n // Must run at start\n toggleNavigationItems(findActivePage());\n \n // Toggle active item button state\n $('ul.pagination a:not(.disabled, .pagination-previous, .pagination-next)')\n .on('click', function() {\n var activeItem = findActivePage();\n $(activeItem).removeClass('active');\n $(this).parent().addClass('active');\n activeItem = $(this).parent(); // store new active item\n // Also run dynamically\n toggleNavigationItems(activeItem);\n });\n \n // Previous click\n $('ul.pagination .pagination-previous').on('click', function() {\n var activeItem = findActivePage();\n \n var previousSibling = $(activeItem).prev();\n // jump back when we find a disabled sibling\n while ($(previousSibling).hasClass('disabled')) {\n previousSibling = $(previousSibling).prev();\n }\n // Only if active item has a previous sibling that is not \n // the pagination-previous itself.\n if ($(previousSibling).find('a').hasClass('pagination-previous') == false) {\n $(activeItem).removeClass('active');\n $(previousSibling).find('a').click(); \n }\n });\n \n // Next click\n $('ul.pagination .pagination-next').on('click', function() {\n var activeItem = findActivePage();\n \n var nextSibling = $(activeItem).next();\n // jump back when we find a disabled sibling\n while ($(nextSibling).hasClass('disabled')) {\n nextSibling = $(nextSibling).next();\n }\n // Only if active item has a previous sibling that is not \n // the pagination-previous itself.\n if ($(nextSibling).find('a').hasClass('pagination-next') == false) {\n $(activeItem).removeClass('active');\n $(nextSibling).find('a').click(); \n }\n });\n \n var paginationBinding = new Shiny.InputBinding();\n $.extend(paginationBinding, {\n \n initialize: function(el) {\n \n },\n \n find: function (scope) {\n return $(scope).find('ul.pagination');\n },\n \n // Given the DOM element for the input, return the value\n getValue: function (el) {\n return $(el).find('li.active a').attr('data-value');\n },\n \n setValue: function(el, value) {\n \n },\n // internal\n _disableTab: function(el, value) {\n $(el)\n .find('a[data-value=\"' + value + '\"]')\n .parent()\n .removeClass('active')\n .addClass('disabled')\n .attr('tabindex', '-1')\n },\n // see updatePagination\n receiveMessage: function (el, data) {\n // Activate new element\n if (data.hasOwnProperty('selected')) {\n // Disable active element\n $(el)\n .find('.active')\n .removeClass('active');\n // Activate new element\n var selectedItem = $(el)\n .find('a[data-value=\"' + data.selected + '\"]');\n // If the element was disabled before\n if ($(selectedItem).parent('li').hasClass('disabled')) {\n $(selectedItem)\n .parent('li')\n .removeClass('disabled')\n .removeAttr('tabindex');\n }\n $(selectedItem).click();\n }\n \n // Disable elements\n if (data.hasOwnProperty('disabled')) {\n // loop over all elements\n if (typeof data.disabled == 'string') {\n this._disableTab(el, data.disabled)\n } else {\n for (i of data.disabled) {\n // disable element \n this._disableTab(el, i)\n }\n }\n \n // Activate next or previous not disabled li\n var hasActiveItem = $(el).find('li.active').length\n if (hasActiveItem == 0) {\n // Activate first element found (maybe discussed ...)\n var newActive = $(el)\n .find('a:not(.pagination-previous, .pagination-next)')\n .parent('li:not(.disabled)');\n if (newActive.length > 0) {\n $(newActive[0]).find('a').click();\n }\n }\n }\n \n // Trigger the callback to update the input value \n // on the server side.\n $(el).trigger('change');\n },\n \n subscribe: function (el, callback) {\n $(el).find('a').on('click', function() {\n callback();\n });\n \n // Necessry for updatePagination\n $(el).on('change', function() {\n callback();\n })\n },\n \n unsubscribe: function (el) {\n $(el).off('.paginationBinding');\n }\n });\n \n Shiny.inputBindings.register(paginationBinding);\n});","var bootstrapTabInputBinding = new Shiny.InputBinding();\n$.extend(bootstrapTabInputBinding, {\n find: function(scope) {\n return $(scope).find('ul.nav.shiny-tab-input');\n },\n getValue: function(el) {\n // for Bootstrap 4, li element does not hold the active class anymore!\n // We need to look at a.active.\n var anchor = $(el).find('li:not(.dropdown)').children('a.active');\n if (anchor.length === 1)\n return this._getTabName(anchor);\n\n return null;\n },\n setValue: function(el, value) {\n let self = this;\n let success = false;\n if (value) {\n let anchors = $(el).find('li:not(.dropdown)').children('a');\n anchors.each(function() {\n if (self._getTabName($(this)) === value) {\n $(this).tab('show');\n success = true;\n return false; // Break out of each()\n }\n return true;\n });\n }\n if (!success) {\n // This is to handle the case where nothing is selected, e.g. the last tab\n // was removed using removeTab.\n $(el).trigger(\"change\");\n }\n },\n getState: function(el) {\n return { value: this.getValue(el) };\n },\n receiveMessage: function(el, data) {\n if (data.hasOwnProperty('value'))\n this.setValue(el, data.value);\n },\n subscribe: function(el, callback) {\n $(el).on('change shown.bootstrapTabInputBinding shown.bs.tab.bootstrapTabInputBinding', function(event) {\n callback();\n });\n },\n unsubscribe: function(el) {\n $(el).off('.bootstrapTabInputBinding');\n },\n _getTabName: function(anchor) {\n return anchor.attr('data-value') || anchor.text();\n }\n});\n\nShiny.inputBindings.register(bootstrapTabInputBinding, 'shiny.bootstrapTabInput');","// This code creates acustom handler for userMessages\nShiny.addCustomMessageHandler(\"user-messages\", function(message) {\n var id = message.id, action = message.action, content = message.body, index = message.index;\n \n // message text\n // We use Shiny.renderHtml to handle the case where the user pass input/outputs in the updated content that require a new dependency not available in the \n // page at startup. \n if (content.hasOwnProperty(\"text\")) {\n var text;\n if (content.text.html === undefined) {\n text = content.text;\n } else {\n text = Shiny.renderHtml(content.text.html, $([]), content.text.dependencies).html;\n } \n }\n \n // unbind all\n Shiny.unbindAll();\n \n if (action === \"remove\") {\n $(\"#\" + id).find(\".direct-chat-msg\").eq(index - 1).remove();\n } else if (action === \"add\") {\n var author = content.author, date = content.date, image = content.image, type = content.type;\n \n // build the new message \n var authorWrapper, dateWrapper;\n if (type === \"sent\") {\n authorWrapper = '' + author + '';\n dateWrapper = '' + date + '';\n } else {\n authorWrapper = '' + author + '';\n dateWrapper = '' + date + '';\n }\n\n var newMessage = `
    ${authorWrapper}${dateWrapper}
    ${text}
    `;\n \n // build wrapper\n var newMessageWrapper;\n if (type === \"sent\") {\n newMessageWrapper = '
    ' + newMessage + '
    ';\n } else {\n newMessageWrapper = '
    ' + newMessage + '
    ';\n }\n \n // append message\n $(\"#\" + id).find(\".direct-chat-messages\").append(newMessageWrapper);\n } else if (action === \"update\") {\n \n // today's date\n var d = new Date();\n var month = d.getMonth() + 1;\n var day = d.getDate();\n var today = d.getFullYear() + '/' +\n ((''+month).length<2 ? '0' : '') + month + '/' +\n ((''+day).length<2 ? '0' : '') + day;\n \n // we assume only text may be updated. Does not make sense to modify author/date\n \n $(\"#\" + id)\n .find(\".direct-chat-text\")\n .eq(index - 1)\n .replaceWith('
    (modified: ' + today +')
    ' + text + '
    ');\n }\n \n // Calls .initialize() for all of the input objects in all input bindings,\n // in the given scope (document)\n Shiny.initializeInputs();\n Shiny.bindAll(); // bind all inputs/outputs\n});"]} diff --git a/srcjs/bs4Dash-2.4.0.9000/feedbacks.js b/srcjs/bs4Dash-2.4.0.9000/feedbacks.js index 921b8a2d..5d72084a 100644 --- a/srcjs/bs4Dash-2.4.0.9000/feedbacks.js +++ b/srcjs/bs4Dash-2.4.0.9000/feedbacks.js @@ -100,11 +100,13 @@ $(function () { default: console.warn(`${config.status} does not belong to allowed statuses!`) } + closeButton = ''; + if (config.closable) { closeButton = '' } - titleTag = `
    ` + titleTag = `
    ${config.title}
    ` contentTag = config.content; alertTag = `
    Date: Mon, 14 Aug 2023 21:32:11 +0200 Subject: [PATCH 4/7] Update NEWS.md --- NEWS.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS.md b/NEWS.md index bbb57e65..be54179d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -7,6 +7,9 @@ This allows them to inherit from the parent `dashboardPage()` __dark__ parameter a full light or full dark skin. If not NULL, the corresponding skin is applied, regardless of the parent `dashboardPage()`. +## Bug fixes +- Fix #315: alert title is not added to alert body and if Alert is not closable the header contains "undefined" key word. Thanks @MohammedFCIS. + # bs4Dash 2.3.0 ## New feature From 78fb2d5ea10be0b7c429c12a1fd574ca3c5d49e2 Mon Sep 17 00:00:00 2001 From: DavidNojnarg Date: Mon, 22 Jan 2024 17:02:27 +0000 Subject: [PATCH 5/7] Fix CRAN NOTE --- NEWS.md | 3 +++ R/useful-items.R | 2 -- man/table.Rd | 3 --- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/NEWS.md b/NEWS.md index bbb57e65..855e7d72 100644 --- a/NEWS.md +++ b/NEWS.md @@ -7,6 +7,9 @@ This allows them to inherit from the parent `dashboardPage()` __dark__ parameter a full light or full dark skin. If not NULL, the corresponding skin is applied, regardless of the parent `dashboardPage()`. +## Bug fixes +- Remove unused `headTitles` parameter from `bs4Table()`. + # bs4Dash 2.3.0 ## New feature diff --git a/R/useful-items.R b/R/useful-items.R index c0dd8add..1798da3e 100644 --- a/R/useful-items.R +++ b/R/useful-items.R @@ -2667,8 +2667,6 @@ bs4Sortable <- function(..., width = 12) { #' #' @param data Expect dataframe, tibble or list of shiny tags... See examples. #' @param cardWrap Whether to wrap the table in a card. FALSE by default. -#' @param headTitles Table header names. Must have the same length as the number of -#' \link{bs4TableItem} in \link{bs4TableItems}. Set "" to have an empty title field. #' @param bordered Whether to display border between elements. FALSE by default. #' @param striped Whether to displayed striped in elements. FALSE by default. #' @param width Table width. 12 by default. diff --git a/man/table.Rd b/man/table.Rd index 32e12e27..8c19c0c0 100644 --- a/man/table.Rd +++ b/man/table.Rd @@ -26,9 +26,6 @@ bs4TableItem(..., dataCell = FALSE) \item{...}{Any HTML element.} \item{dataCell}{Whether the cell should be contain data or text. by default.} - -\item{headTitles}{Table header names. Must have the same length as the number of -\link{bs4TableItem} in \link{bs4TableItems}. Set "" to have an empty title field.} } \description{ Build an Bootstrap 4 table container From e300829be058d5d7d46ae42e3ca9ebcebeaacdbe Mon Sep 17 00:00:00 2001 From: DavidNojnarg Date: Mon, 22 Jan 2024 17:07:56 +0000 Subject: [PATCH 6/7] prepare for CRAN --- DESCRIPTION | 2 +- NEWS.md | 2 +- inst/{bs4Dash-2.4.0.9000 => bs4Dash-2.3.3}/bs4Dash.css | 0 inst/{bs4Dash-2.4.0.9000 => bs4Dash-2.3.3}/bs4Dash.js | 0 inst/{bs4Dash-2.4.0.9000 => bs4Dash-2.3.3}/bs4Dash.min.js | 0 inst/{bs4Dash-2.4.0.9000 => bs4Dash-2.3.3}/bs4Dash.min.js.map | 0 6 files changed, 2 insertions(+), 2 deletions(-) rename inst/{bs4Dash-2.4.0.9000 => bs4Dash-2.3.3}/bs4Dash.css (100%) rename inst/{bs4Dash-2.4.0.9000 => bs4Dash-2.3.3}/bs4Dash.js (100%) rename inst/{bs4Dash-2.4.0.9000 => bs4Dash-2.3.3}/bs4Dash.min.js (100%) rename inst/{bs4Dash-2.4.0.9000 => bs4Dash-2.3.3}/bs4Dash.min.js.map (100%) diff --git a/DESCRIPTION b/DESCRIPTION index 6d10a7ba..d77de64a 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: bs4Dash Type: Package Title: A 'Bootstrap 4' Version of 'shinydashboard' -Version: 2.4.0.9000 +Version: 2.3.3 Authors@R: c( person("David", "Granjon", email = "dgranjon@ymail.com", role = c("aut", "cre")), person(family = "RinteRface", role = "cph"), diff --git a/NEWS.md b/NEWS.md index e03ef1d9..37d54db3 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,4 +1,4 @@ -# bs4Dash 2.4.0.9000 +# bs4Dash 2.3.3 ## Breaking change (potential) diff --git a/inst/bs4Dash-2.4.0.9000/bs4Dash.css b/inst/bs4Dash-2.3.3/bs4Dash.css similarity index 100% rename from inst/bs4Dash-2.4.0.9000/bs4Dash.css rename to inst/bs4Dash-2.3.3/bs4Dash.css diff --git a/inst/bs4Dash-2.4.0.9000/bs4Dash.js b/inst/bs4Dash-2.3.3/bs4Dash.js similarity index 100% rename from inst/bs4Dash-2.4.0.9000/bs4Dash.js rename to inst/bs4Dash-2.3.3/bs4Dash.js diff --git a/inst/bs4Dash-2.4.0.9000/bs4Dash.min.js b/inst/bs4Dash-2.3.3/bs4Dash.min.js similarity index 100% rename from inst/bs4Dash-2.4.0.9000/bs4Dash.min.js rename to inst/bs4Dash-2.3.3/bs4Dash.min.js diff --git a/inst/bs4Dash-2.4.0.9000/bs4Dash.min.js.map b/inst/bs4Dash-2.3.3/bs4Dash.min.js.map similarity index 100% rename from inst/bs4Dash-2.4.0.9000/bs4Dash.min.js.map rename to inst/bs4Dash-2.3.3/bs4Dash.min.js.map From b91b756b5fc1db2ef8fb050d4feb1de197ae8976 Mon Sep 17 00:00:00 2001 From: DavidNojnarg Date: Mon, 22 Jan 2024 22:29:20 +0000 Subject: [PATCH 7/7] update cran comments --- cran-comments.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cran-comments.md b/cran-comments.md index 9eca9ef6..5c2e2fdb 100644 --- a/cran-comments.md +++ b/cran-comments.md @@ -1,5 +1,5 @@ ## Test environments -* local OS X install, R 4.1.3. +* local OS X install, R 4.3.1. * RStudio Server on linux Ubuntu 20.04.3 LTS R 4.2.1. * `rhub::check_for_cran`. * Github actions. @@ -9,5 +9,4 @@ There were no ERRORs or WARNINGs or NOTEs. ## Note -I remove the svg file from /man and replaced it by a smaller png, which fixes the NOTES -on https://cran.r-project.org/web/checks/check_results_bs4Dash.html. +This release will fixe the NOTES on https://cran.r-project.org/web/checks/check_results_bs4Dash.html.