Skip to content

Barbara/bookmark #187

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 43 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
1ae32a3
bookmarking attempt
bborgesr Feb 23, 2017
9321379
expanded/collapsed state of sidebar
bborgesr Feb 23, 2017
80d9399
updated comments
bborgesr Feb 23, 2017
f9ad190
added optional id to sidebar
bborgesr Feb 27, 2017
c6c8838
expanded state
bborgesr Mar 3, 2017
a41a3bb
restore input for expanded menuItem
bborgesr Mar 3, 2017
1884505
handle NULL value for dataExpanded state of sidebarMenu
bborgesr Mar 6, 2017
4ae4b3a
Divided JS code into chunks
bborgesr Mar 6, 2017
5dcac26
create js skeleton
bborgesr Mar 7, 2017
30e5b00
substitute jshint by eslint
bborgesr Mar 7, 2017
22ebfd0
clean up and comment code
bborgesr Mar 7, 2017
b6372c9
actually split the JS code into different files
bborgesr Mar 7, 2017
d05c8cb
fix error alerted by eslint, clean up eslint in gruntfie, remove obso…
bborgesr Mar 8, 2017
3d5da30
gruntfile: only build files that have changed (using 'grunt-newer')
bborgesr Mar 8, 2017
478489d
don't require parent tab to have a tabname
bborgesr Mar 9, 2017
429f4f0
trigger hide event when we click on an already expanded menuItem
bborgesr Mar 9, 2017
b8c421c
semicolon
bborgesr Mar 9, 2017
6fef03d
correct scrsjs directory for future AdminLTE updates
bborgesr Mar 9, 2017
cd2e068
add crnjs folder to rbuildignore
bborgesr Mar 9, 2017
9c2f227
add manual test app
bborgesr Mar 9, 2017
2c6f024
indentation
bborgesr Mar 9, 2017
8fa3f5a
fix tabs
bborgesr Mar 10, 2017
2719f0f
update test app
bborgesr Mar 10, 2017
ae29153
dynamic sidebar fix
bborgesr Mar 10, 2017
92e99fb
updated examples
bborgesr Mar 14, 2017
1bd0129
updated tabItemInputBinding to be a div inside the menu ul
bborgesr Mar 14, 2017
641a5ce
addressed most of Winston's feedback
bborgesr Mar 14, 2017
4ab8176
some commenting, some cleaning
bborgesr Mar 14, 2017
0c63355
changed value of sidebarCollapsed to be "true"/"false", instead of th…
bborgesr Mar 14, 2017
6635e01
more commenting, undo unintended changes (to identation mostly)
bborgesr Mar 14, 2017
b38448e
do better than ugly looking hacks
bborgesr Mar 14, 2017
97dc512
apply eslint to the srcjs documents, not the already concatenated file
bborgesr Mar 15, 2017
a193338
edge case
bborgesr Mar 15, 2017
0205dee
eslint nit
bborgesr Mar 15, 2017
c8820c5
all manner of failed attempts to trigger shown/hidden events in a les…
bborgesr Mar 15, 2017
e4a34e6
remove insanity
bborgesr Mar 15, 2017
4075a3e
more futile attempts
bborgesr Mar 16, 2017
af43ed2
back to normal; add another manuel test app to show the struggle
bborgesr Mar 16, 2017
e4a9f1d
better hiding/showing
bborgesr Mar 23, 2017
201b767
added expandedName and startExpanded params to menuItem()
bborgesr Mar 23, 2017
4c7056d
update documentation using new roxygen version (and add the new param…
bborgesr Mar 23, 2017
85e310f
make sure the inputBinding for the selected tab gets activated for th…
bborgesr Mar 23, 2017
1b5b56b
updated tests
bborgesr Mar 23, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
^.*\.Rproj$
^\.Rproj\.user$
^tools$
^srcjs$
^tests-manual$
^\.travis\.yml$
^appveyor\.yml$
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ Imports:
shiny (>= 0.12.1),
htmltools (>= 0.2.6)
BugReports: https://github.com/rstudio/shinydashboard
RoxygenNote: 5.0.1
RoxygenNote: 6.0.1
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
shinydashboard 0.5.3.9000
=========================

* Fixed [#71](https://github.com/rstudio/shinydashboard/issues/71) and [#87](https://github.com/rstudio/shinydashboard/issues/87): detect and enforce selected tab for dynamic sidebars. ([#189](https://github.com/rstudio/shinydashboard/pull/189))

* Divided JS code into chunks.

* Fixed [#127](https://github.com/rstudio/shinydashboard/issues/127) and [#177](https://github.com/rstudio/shinydashboard/issues/177): previously, if `dashboardSidebar()` was called with an explicit `width` parameter, mobile rendering would look weird (the sidebar wouldn't completely disappear when it was collapsed, and content in the dashboard body would be hidden under the still-visible sidebar). ([#204](https://github.com/rstudio/shinydashboard/pull/204))

* Fixed [#79](https://github.com/rstudio/shinydashboard/issues/79): Re-enable slight css transition when the sidebar is expanded/collapsed. ([#205](https://github.com/rstudio/shinydashboard/pull/205)).
Expand Down
6 changes: 3 additions & 3 deletions R/dashboardPage.R
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ dashboardPage <- function(header, sidebar, body, title = NULL,
body
)

# if the sidebar has the class "start-collapsed", it means that the user set
# the `collapsed` argument of `dashboardSidebar` to TRUE
collapsed <- "start-collapsed" %in% strsplit(sidebar$attribs$class, " ")[[1]]
# if the sidebar has the attribute `data-collapsed = "true"`, it means that
# the user set the `collapsed` argument of `dashboardSidebar` to TRUE
collapsed <- findAttribute(sidebar, "data-collapsed", "true")

addDeps(
tags$body(
Expand Down
54 changes: 47 additions & 7 deletions R/dashboardSidebar.R
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,19 @@ dashboardSidebar <- function(..., disable = FALSE, width = NULL, collapsed = FAL
'))))
}

# 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
# specified in the `collapsed` argument.
dataValue <- shiny::restoreInput(id = "sidebarCollapsed",
default = if (collapsed) "true" else "false")

# The expanded/collapsed state of the sidebar is actually set by adding a
# class to the body (not to the sidebar). However, it makes sense for the
# `collapsed` argument to belong in this function. So this information is
# just passed through (also as a class) to the `dashboardPage()` function
tags$aside(class = paste("main-sidebar", if (collapsed) "start-collapsed"),
custom_css,
# just passed through (as the `data-collapsed` attribute) to the
# `dashboardPage()` function
tags$aside(
class = "main-sidebar", `data-collapsed` = dataValue, custom_css,
tags$section(
class = "sidebar",
`data-disable` = if (disable) 1 else NULL,
Expand Down Expand Up @@ -236,6 +243,13 @@ sidebarSearchForm <- function(textId, buttonId, label = "Search...",
#' @param selected If \code{TRUE}, this \code{menuItem} or \code{menuSubItem}
#' will start selected. If no item have \code{selected=TRUE}, then the first
#' \code{menuItem} will start selected.
#' @param expandedName A unique name given to each \code{menuItem} that serves
#' to indicate which one (if any) is currently expanded. (This is only applicable
#' to \code{menuItem}s that have children and it is mostly only useful for
#' bookmarking state.)
#' @param startExpanded Should this \code{menuItem} be expanded on app startup?
#' (This is only applicable to \code{menuItem}s that have children, and only
#' one of these can be expanded at any given time).
#' @param ... For menu items, this may consist of \code{\link{menuSubItem}}s.
#' @param .list An optional list containing items to put in the menu Same as the
#' \code{...} arguments, but in list format. This can be useful when working
Expand Down Expand Up @@ -263,7 +277,9 @@ sidebarMenu <- function(..., id = NULL, .list = NULL) {
# Given a menuItem and a logical value for `selected`, set the
# data-start-selected attribute to the appropriate value (1 or 0).
selectItem <- function(item, selected) {
if (length(item$children) == 0) {

# in the cases that the children of menuItems are NOT menuSubItems
if (is.atomic(item) || length(item$children) == 0) {
return(item)
}

Expand All @@ -274,6 +290,7 @@ sidebarMenu <- function(..., id = NULL, .list = NULL) {
# data-start-selected="1". The []<- assignment is to preserve
# attributes.
item$children[] <- lapply(item$children, function(child) {

# Find the appropriate <a> child
if (tagMatches(child, name = "a", `data-toggle` = "tab")) {
child$attribs[["data-start-selected"]] <- value
Expand Down Expand Up @@ -328,18 +345,25 @@ sidebarMenu <- function(..., id = NULL, .list = NULL) {
item
})
}
# This is a 0 height div, whose only purpose is to hold the tabName of the currently
# selected menuItem in its `data-value` attribute. This is the DOM element that is
# bound to tabItemInputBinding in the JS side.
items[[length(items) + 1]] <- div(id = id,
class = "sidebarMenuSelectedTabItem", `data-value` = selectedTabName %OR% "null")
}

# Use do.call so that we don't add an extra list layer to the children of the
# ul tag. This makes it a little easier to traverse the tree to search for
# selected items to restore.
do.call(tags$ul, c(id = id, class = "sidebar-menu", items))
do.call(tags$ul, c(class = "sidebar-menu", items))
}

#' @rdname sidebarMenu
#' @export
menuItem <- function(text, ..., icon = NULL, badgeLabel = NULL, badgeColor = "green",
tabName = NULL, href = NULL, newtab = TRUE, selected = NULL) {
tabName = NULL, href = NULL, newtab = TRUE, selected = NULL,
expandedName = as.character(gsub("[[:space:]]", "", text)),
startExpanded = FALSE) {
subItems <- list(...)

if (!is.null(icon)) tagAssert(icon, type = "i")
Expand Down Expand Up @@ -394,6 +418,18 @@ menuItem <- function(text, ..., icon = NULL, badgeLabel = NULL, badgeColor = "gr
)
}

# If we're restoring a bookmarked app, this holds the value of what menuItem (if any)
# was expanded (this has be to stored separately from the selected menuItem, since
# these actually independent in AdminLTE). If no menuItem was expanded, `dataExpanded`
# is NULL. However, we want to this input to get passed on (and not dropped), so we
# do `%OR% ""` to assure this.
default <- if (startExpanded) expandedName else ""
dataExpanded <- shiny::restoreInput(id = "sidebarItemExpanded", default) %OR% ""

# If `dataExpanded` is not the empty string, we need to check that it is eqaul to the
# this menuItem's `expandedName``
isExpanded <- nzchar(dataExpanded) && (dataExpanded == expandedName)

tags$li(class = "treeview",
a(href = href,
icon,
Expand All @@ -403,7 +439,11 @@ menuItem <- function(text, ..., icon = NULL, badgeLabel = NULL, badgeColor = "gr
# Use do.call so that we don't add an extra list layer to the children of the
# ul tag. This makes it a little easier to traverse the tree to search for
# selected items to restore.
do.call(tags$ul, c(class = "treeview-menu", subItems))
do.call(tags$ul, c(
class = paste0("treeview-menu", if (isExpanded) " menu-open" else ""),
style = paste0("display: ", if (isExpanded) "block;" else "none;"),
`data-expanded` = expandedName,
subItems))
)
}

Expand Down
4 changes: 3 additions & 1 deletion R/deps.R
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ appendDependencies <- function(x, value) {
addDeps <- function(x) {
if (getOption("shiny.minified", TRUE)) {
adminLTE_js <- "app.min.js"
shinydashboard_js <- "shinydashboard.min.js"
adminLTE_css <- c("AdminLTE.min.css", "_all-skins.min.css")
} else {
adminLTE_js <- "app.js"
shinydashboard_js <- "shinydashboard.js"
adminLTE_css <- c("AdminLTE.css", "_all-skins.css")
}

Expand All @@ -28,7 +30,7 @@ addDeps <- function(x) {
htmlDependency("shinydashboard",
as.character(utils::packageVersion("shinydashboard")),
c(file = system.file(package = "shinydashboard")),
script = "shinydashboard.js",
script = shinydashboard_js,
stylesheet = "shinydashboard.css"
)
)
Expand Down
21 changes: 21 additions & 0 deletions R/utils.R
Original file line number Diff line number Diff line change
Expand Up @@ -198,3 +198,24 @@ tagMatches <- function(item, ..., id = NULL, name = NULL, class = NULL) {

TRUE
}

# This function takes a DOM element/tag object and reccurs within it until
# it finds a child which has an attribute called `attr` and with value `val`
# (and returns TRUE). If it finds an element with an attribute called `attr`
# whose value is NOT `val`, it returns FALSE. If it exhausts all children
# and it doesn't find an element with an attribute called `attr`, it also
# returns FALSE
findAttribute <- function(x, attr, val) {
if (is.atomic(x)) return(FALSE) # exhausted this branch of the tree

if (!is.null(x$attribs[[attr]])) { # found attribute called `attr`
if (identical(x$attribs[[attr]], val)) return(TRUE)
else return(FALSE)
}

if (length(x$children) > 0) { # recursion
return(any(unlist(lapply(x$children, findAttribute, attr, val))))
}

return(FALSE) # found no attribute called `attr`
}
2 changes: 1 addition & 1 deletion inst/AdminLTE/AdminLTE.min.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion inst/AdminLTE/_all-skins.min.css

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions inst/AdminLTE/app.js
100755 → 100644

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions inst/AdminLTE/app.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion inst/AdminLTE/app.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion inst/AdminLTE/app.min.js.map

Large diffs are not rendered by default.

Loading