From 0d4b0e362bb9d2d10f2a047f72d3c0056a41770f Mon Sep 17 00:00:00 2001 From: Craig Williams Date: Thu, 5 Feb 2026 10:55:30 +0000 Subject: [PATCH] Added methods for manipulating element classes and improved the optional/required when fieldset is used --- NAMESPACE | 3 +++ R/htmlClassManipulation.R | 49 +++++++++++++++++++++++++++++++++++++++ R/htmlMarkOptional.R | 4 +++- R/htmlMarkRequired.R | 9 +++++-- man/htmlAddClasses.Rd | 23 ++++++++++++++++++ man/htmlButtonStyle.Rd | 23 ++++++++++++++++++ man/htmlRemoveClasses.Rd | 23 ++++++++++++++++++ 7 files changed, 131 insertions(+), 3 deletions(-) create mode 100644 R/htmlClassManipulation.R create mode 100644 man/htmlAddClasses.Rd create mode 100644 man/htmlButtonStyle.Rd create mode 100644 man/htmlRemoveClasses.Rd diff --git a/NAMESPACE b/NAMESPACE index d82ac60..b0918d1 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -3,12 +3,15 @@ export(htmlAddBoxAttributes) export(htmlAddBoxHelpLink) export(htmlAddBoxRegionFromTitle) +export(htmlAddClasses) +export(htmlButtonStyle) export(htmlDisableAutocomplete) export(htmlFixBoxCollapseButtonAria) export(htmlMarkOptional) export(htmlMarkRequired) export(htmlRemoveAttributes) export(htmlRemoveBoxTitle) +export(htmlRemoveClasses) export(htmlReplaceBoxTitleLevel) export(htmlSetMaxLength) export(htmlSetMinLength) diff --git a/R/htmlClassManipulation.R b/R/htmlClassManipulation.R new file mode 100644 index 0000000..04db5da --- /dev/null +++ b/R/htmlClassManipulation.R @@ -0,0 +1,49 @@ +#' Add classes to an HTML element +#' +#' @param el The element to add the class(es) to +#' @param classes The class(es) to be added +#' +#' @return The modified element +#' @export +#' +#' @examples +#' x <- shiny::tags$div() +#' htmlAddClasses(x, "btn-warning") +htmlAddClasses <- function(el, classes) { + htmltools::tagQuery(el)$addClass(classes)$allTags() +} + +#' Remove classes from an HTML element +#' +#' @param el The element to remove the class(es) from +#' @param classes The class(es) to be added +#' +#' @return The modified element +#' @export +#' +#' @examples +#' x <- shiny::tags$div(class = "btn btn-warning") +#' htmlRemoveClasses(x, "btn-warning") +htmlRemoveClasses <- function(el, classes) { + htmltools::tagQuery(el)$removeClass(classes)$allTags() +} + +#' Changes the style of a button from btn-default to another style +#' +#' @param el The button +#' @param style The style to change the button on +#' +#' @return The modified element +#' @export +#' +#' @examples +#' x <- shiny::tags$div(class = "btn btn-warning") +#' htmlButtonStyle(x, "warning") +htmlButtonStyle <- function(el, style) { + stopifnot(style %in% c( + "default", "primary", "info", "warning", "success", "danger", "link" + )) + el <- htmlRemoveClasses(el, "btn-default") + el <- htmlAddClasses(el, paste0("btn-", style)) + el +} diff --git a/R/htmlMarkOptional.R b/R/htmlMarkOptional.R index 1f789e2..95fadf4 100644 --- a/R/htmlMarkOptional.R +++ b/R/htmlMarkOptional.R @@ -12,7 +12,9 @@ htmlMarkOptional <- function(input, optClass = "text-muted font-italic") { opt_span <- htmltools::tags$span(class = optClass, " (optional)") tq <- htmltools::tagQuery(input) - if (tq$hasClass("shiny-input-checkboxgroup")) { + if (tq$find("legend")$length() > 0) { + tq <- tq$children("legend")$append(opt_span)$reset() + } else if (tq$hasClass("shiny-input-checkboxgroup")) { tq <- tq$children("label")$append(opt_span)$reset() } else if (tq$find(".shiny-options-group")$length() > 0) { tq <- tq$children("label")$append(opt_span)$reset() diff --git a/R/htmlMarkRequired.R b/R/htmlMarkRequired.R index ab0041d..6539d20 100644 --- a/R/htmlMarkRequired.R +++ b/R/htmlMarkRequired.R @@ -12,12 +12,17 @@ htmlMarkRequired <- function(input, reqClass = "text-danger required") { req_span <- htmltools::tags$span(class = reqClass, "*") tq <- htmltools::tagQuery(input) - if (tq$hasClass("shiny-input-checkboxgroup")) { + if (tq$find("legend")$length() > 0) { + tq <- tq$children("legend")$append(req_span)$reset() + tq <- tq$find("input")$addAttr( + required = "true", `aria-required` = "true" + )$reset() + } else if (tq$hasClass("shiny-input-checkboxgroup")) { tq <- tq$addAttr(`aria-required` = "true")$reset() tq <- tq$children("label")$append(req_span)$reset() } else if (tq$find(".shiny-options-group")$length() > 0) { - tq <- tq$children("label")$append(req_span)$reset() tq <- tq$addAttr(`aria-required` = "true")$reset() + tq <- tq$children("label")$append(req_span)$reset() tq <- tq$find("input")$addAttr( required = "true", `aria-required` = "true" )$reset() diff --git a/man/htmlAddClasses.Rd b/man/htmlAddClasses.Rd new file mode 100644 index 0000000..3f377fa --- /dev/null +++ b/man/htmlAddClasses.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/htmlClassManipulation.R +\name{htmlAddClasses} +\alias{htmlAddClasses} +\title{Add classes to an HTML element} +\usage{ +htmlAddClasses(el, classes) +} +\arguments{ +\item{el}{The element to add the class(es) to} + +\item{classes}{The class(es) to be added} +} +\value{ +The modified element +} +\description{ +Add classes to an HTML element +} +\examples{ +x <- shiny::tags$div() +htmlAddClasses(x, "btn-warning") +} diff --git a/man/htmlButtonStyle.Rd b/man/htmlButtonStyle.Rd new file mode 100644 index 0000000..9eb55e9 --- /dev/null +++ b/man/htmlButtonStyle.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/htmlClassManipulation.R +\name{htmlButtonStyle} +\alias{htmlButtonStyle} +\title{Changes the style of a button from btn-default to another style} +\usage{ +htmlButtonStyle(el, style) +} +\arguments{ +\item{el}{The button} + +\item{style}{The style to change the button on} +} +\value{ +The modified element +} +\description{ +Changes the style of a button from btn-default to another style +} +\examples{ +x <- shiny::tags$div(class = "btn btn-warning") +htmlButtonStyle(x, "warning") +} diff --git a/man/htmlRemoveClasses.Rd b/man/htmlRemoveClasses.Rd new file mode 100644 index 0000000..8c38944 --- /dev/null +++ b/man/htmlRemoveClasses.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/htmlClassManipulation.R +\name{htmlRemoveClasses} +\alias{htmlRemoveClasses} +\title{Remove classes from an HTML element} +\usage{ +htmlRemoveClasses(el, classes) +} +\arguments{ +\item{el}{The element to remove the class(es) from} + +\item{classes}{The class(es) to be added} +} +\value{ +The modified element +} +\description{ +Remove classes from an HTML element +} +\examples{ +x <- shiny::tags$div(class = "btn btn-warning") +htmlRemoveClasses(x, "btn-warning") +}