JavaScript用于更新活动侧边栏菜单链接到 Jmeter 板中的TabPanel的子项

wljmcqd8  于 9个月前  发布在  Java
关注(0)|答案(1)|浏览(82)

我正在尝试建立一个闪亮的 Jmeter 板与menuSubItems,应该对应于TabPanels。我还需要一个按钮,在主页上移动到这些TabPanels。这一部分是不是工作得很糟糕。问题来了,当我试图使用一些JavaScript代码来更新哪些是'活动'的项目在侧边栏(以下可重现的例子)。
我的主要问题如下:
1.我无法在侧边栏中将正确的menuSubItem设置为“active”:在js控制台中,我看到<li>项被正确选择,但由于未知原因,classList.add('active');(或remove)仍然无效。
1.当我从“Tabpan”menuSubItems切换到Home或Settings时,我希望“Tab 1”menuItem折叠起来;在这里,我也尝试过用js(将类更新为style.display = 'none';)来折叠;有时它能工作,有时它不能工作(如果它总是工作或不工作,会更容易理解...)。
1.有些“随机”行为我不理解。Tabpan 1和Tabpan 2(以及它们对应的observeEvent)是以完全相同的方式构建的(使用lapply),但Tabpan 2似乎比Tabpan 1工作得更好。此外,有时从Tabpan 1切换到设置会起作用,有时则不会。
如何调试以下应用程序?

require(shiny)
require(shinyjs)
require(shinydashboard)
require(shinydashboardPlus)
mymenu <- list(list(menuitem=c("Tab1" = "tab1"),
                    subitems=c("Tabpan1" = "tsp1_tabpan1", "Tapan2"="tsp1_tabpan2"),
                    icon="upload"))
build_menu <- function(list_item){
  lapply(list_item, function(x){
    subs <- x[["subitems"]]
    men <- x[["menuitem"]]
    menusubits <- lapply(seq_along(subs), function(i){
      HTML(paste0('<li><a id="mv_',men,'_',subs[i] , '" href="#shiny-tab-',men ,'" class="action-button" data-value="',men,'">
<i class="fas fa-angles-right" role="presentation" aria-label="angles-right icon"></i> ', names(subs)[i],'</a></li>'))
    })
    menuItem(names(men), id=as.character(men), icon = icon(x[["icon"]]),menusubits)
  })
}
ui <- dashboardPage(
  dashboardHeader(title = ""),
  dashboardSidebar(
    sidebarMenu(id="sidebar",
                menuItem("Accueil",tabName = "home", icon = icon("igloo")),
                build_menu(mymenu),
                menuItem("Réglages", tabName = "settings", icon = icon("gears"))
    )),
  dashboardBody(
    useShinyjs(),
    tabItems(
      tabItem(tabName = "home",
              h1("Home"),
              HTML('<br><br><ul><li><a id="see_tab1_pan1" class="action-button" >
                                  Go to tab1 pan1</a></li><br><br>
                                  <li><a id="see_tab1_pan2" class="action-button" >
                                  Go to tab1 pan2</a></li>'),),
      tabItem(tabName = "tab1",
              h1("Tab1"),
              tabsetPanel(id="tab1_tabset",
              tabPanel("TabPan1", value=paste0("tab1_tsp1_tabpan1"),
                       h4("tp tit1")
              ),
            tabPanel("TabPan2", value=paste0("tab1_tsp1_tabpan2"),
                     h4("tp tit2")
            ),)),
      tabItem(tabName = "settings",
              h1("Settings")
    ))))

  server = function(input, output, session) {
    observeEvent(input$see_tab1_pan1,{
      cat(paste0("click_test\n"))
      # debug see_tab1_pan2 first :-)
    })
    observeEvent(input$see_tab1_pan2,{
      cat(paste0("click_test\n"))
      runjs(paste0(
        # emulate a click on menusubitem :
        "var x = document.getElementById('", "mv_tab1_tsp1_tabpan2", "'); ",
        "console.log(x);",
        "x.click();",
        # "// leaving Home -> remove active class ",
        "const $parent = $('.sidebar-menu [data-value=\"home\"]').closest('li');",
        "console.log('parent');",
        "console.log($parent);",
        "$parent.removeClass('active');",
        #"// expand the correspondign menuitem
        "var y = document.getElementById('", "tab1", "'); ",
        "console.log('y');",
        "console.log(y);",
        "y.style.display = 'block';",
        "y.classList.add('menu-open');"#,
    ))})
    ### collapse menuitems if I am in home or settings
    observe({
      if(input$sidebar == "home" | input$sidebar == "settings"){
        #"// collapse the tab1 menuitem
        runjs(paste0("var y = document.getElementById('", "tab1", "'); ",
        "console.log('y');",
        "console.log(y);",
        "y.style.display = 'none';",
        "y.classList.remove('menu-open');"#,
        ))
      }
    })

    lapply(mymenu, function(x){
      men <- as.character(x[["menuitem"]])
      stopifnot(length(men) == 1)
      subits <- x[["subitems"]]
      lapply(seq_along(subits), function(i){
        btnid <- paste0("mv_", men, "_", subits[i])
        observeEvent(input[[btnid]],{
         cat( paste0("click ",btnid,"\n") )
          updateTabItems(session, "sidebar", selected = men)
          updateTabItems(session, inputId = paste0(men, "_tabset"),
                         selected = paste0(men, "_", subits[i]))
          runjs(paste0(
      #"// find all other <li> elements of the menuitem and remove active class",
        "var btn = document.getElementById('", btnid, "');",
        "console.log('btn');",
        "console.log(btn);",
               "var allLi = btn.closest('ul').getElementsByTagName('li');",
               " for (var i = 0; i < allLi.length; i++) {",
        "console.log('allLi[i] - BEFORE');",
        "console.log(allLi[i]);",
                 " allLi[i].classList.remove('active');", #### NOT WORKING ????
        "console.log('allLi[i] - AFTER');",
        "console.log(allLi[i]);",
                 "}" ,
      # "// add 'active' class to <li> of the corresponding menusubitem button ",
      "var z = btn.closest('li');",
      "console.log('will add active to');",
      "console.log(z);",
      "  z.classList.add('active');",
      "  console.log('after set active class');", #### NOT WORKING ????
      "console.log(z);"
      ))
        }
      )})})}

  shinyApp(ui, server)

字符串

shstlldc

shstlldc1#

我找到了以下的变通方法,但我发现它一点也不干净,还在等待更好的答案.

require(shiny)
require(shinyjs)
require(shinydashboard)
require(shinydashboardPlus)

mymenu <- list(list(menuitem=c("Tab1" = "tab1"),
                    subitems=c("Tabpan1" = "tsp1_tabpan1", "Tabpan2"="tsp1_tabpan2"),
                    menuIcon="upload",
                    subMenuIcon = "angles-right"))

getMenuSubmenuItems <- function(list_item){
  lapply(list_item, function(x){
    subs <- x[["subitems"]]
    men <- x[["menuitem"]]
    menusubits <- lapply(seq_along(subs), function(i){
      HTML(paste0('<li><a id="mv_',men,'_',subs[i] , '" href="#shiny-tab-',men ,'" class="action-button" data-value="',men,'">
<i class="fas fa-', x[["subMenuIcon"]], '" role="presentation" aria-label="',x[["subMenuIcon"]] ,' icon"></i> ', 
                  names(subs)[i],'</a></li>'))
    })
    list( HTML(paste0('<li class="treeview">
          <a href="#" id="', as.character(men) ,'_parent" class="action-button">
        <i class="fas fa-', x[["menuIcon"]],'" role="presentation" aria-label="', x[["menuIcon"]],' icon"></i>
        <span>', names(men), '</span>
        <i class="fas fa-angle-left pull-right" role="presentation" aria-label="angle-left icon"></i>
        </a>
        <ul class="treeview-menu" style="display: none;" data-expanded="', names(men),'" id="', as.character(men),'">')),
      menusubits,
      HTML("</ul></li>"))})}

generate_home_menu <-function(mymenu){
  lapply(mymenu, function(menuit){
    mi <- menuit[["menuitem"]]
    si <- menuit[["subitems"]]
    start <- paste0("<h4>", names(mi), "</h4><ul>")
    its <- paste0(sapply(seq_along(si), function(i){
      paste0('<li><a id="see_', as.character(si[i]), '" class="action-button" >
                    Go to ', names(si)[i], '</a></li><br>')
    }), collapse="")
    end <- paste0("</ul>")
    HTML(paste0(c(start, its, end), collapse=""))})}  
generate_subitem_panels <- function(mymenu){
  lapply(mymenu, function(x){
    mi <- x[["menuitem"]]
    si <- x[["subitems"]]
    tabItem(tabName = as.character(mi),
            h1(names(mi)),
            tabsetPanel(id=paste0(mi, "_tabset"),
                        ### iterate over menuSubItems to create corresponding tabPanels
                        !!!lapply(seq_along(si), function(i){
                          tabPanel(names(si)[i], value = paste0(mi, "_", si[i]),
                                   h4(names(si[i])))})))})}

getMenuItem <- function(id, label, icon){
  return(HTML(paste0('<li><a href="#shiny-tab-', id, '" id="', id , '_btn" data-toggle="tab" class="action-button"
              data-value="', id, '">
                <i class="fas fa-', icon, '" role="presentation" aria-label="', icon, ' icon"></i>
                <span>', label, '</span>
              </a></li>')))}

ui <- dashboardPage(
  dashboardHeader(title = ""),
  dashboardSidebar(
    sidebarMenu(id="sidebar",
                getMenuItem("home", "Accueil", "igloo"),
                getMenuSubmenuItems(mymenu),
            getMenuItem("settings", "Settings", "gears"))),
  dashboardBody(
    useShinyjs(),
      do.call(tabItems,c(list(
        tabItem(tabName = "home", ## tabName should match id used in getMenuItem !!
                h1("Home"),
                generate_home_menu(mymenu)
        )),
      generate_subitem_panels(mymenu),
      list(tabItem(tabName = "settings", ## tabName should match id used in getMenuItem !!
              h1("Settings")))))))
  
  server = function(input, output, session) {
    lapply(mymenu, function(mi){
      mit <- as.character(mi[["menuitem"]])
      si <- mi[["subitems"]]
      lapply(si, function(subi){
        observeEvent(input[[paste0("see_", subi)]],{
          runjs(paste0(
            "var x = document.getElementById('", paste0(mit,"_parent"), "'); 
            x.click();"))
          Sys.sleep(1)
          runjs(paste0(
            "var x = document.getElementById('", paste0("mv_", mit, "_", subi), "');
            x.click();"))})})} )
   
    lapply(c("home", "settings"), function(tab){
      observeEvent(input[[paste0(tab, "_btn")]], {
        runjs(paste0("console.log('clicked ", tab, "');
var elements = document.querySelectorAll('ul.sidebar-menu ul.treeview-menu.menu-open');
console.log(elements);
elements.forEach(function(element) {
    element.classList.remove('menu-open');
    element.style.display = 'none';});"))})})

    lapply(mymenu, function(m){
      mi <- as.character(m[["menuitem"]])
      msi <- m[["subitems"]]
      lapply(msi, function(it){
        observeEvent(input[[paste0(mi, "_tabset")]],{
          if(input[[paste0(mi, "_tabset")]] == paste0(mi, "_", it)){
            btnid <- paste0("mv_", mi, "_", it)
            runjs(paste0(
              "var btn = document.getElementById('", btnid, "');",
              "var allLi = btn.closest('ul').getElementsByTagName('li');
              for (var i = 0; i < allLi.length; i++) {
              if(allLi[i].querySelector('a').id == '",btnid, "'){",
              "allLi[i].querySelector('a').dataset.value='", mi, "';",
              "} else{",
              "allLi[i].querySelector('a').dataset.value='",mi, "_foo';",
              "}
              allLi[i].classList.remove('active');
              }
              var z = btn.closest('li');
                z.classList.add('active');"
            ))}})})}) 

    lapply(mymenu, function(x){
      men <- as.character(x[["menuitem"]])
      stopifnot(length(men) == 1)
      subits <- x[["subitems"]]
      lapply(seq_along(subits), function(i){
        btnid <- paste0("mv_", men, "_", subits[i])
        observeEvent(input[[btnid]],{
          updateTabItems(session, "sidebar", selected = men)
          updateTabItems(session, inputId = paste0(men, "_tabset"),
                         selected = paste0(men, "_", subits[i]))
        })})})}
  
  shinyApp(ui, server)

字符串
我还在纠结这一部分

runjs(paste0(
            "var x = document.getElementById('", paste0(mit,"_parent"), "'); 
            x.click();"))
          Sys.sleep(1)
          runjs(paste0(
            "var x = document.getElementById('", paste0("mv_", mit, "_", subi), "');
            x.click();"))


(转载自this other SO question

相关问题