stla / jsTreeR

A wrapper of the jQuery plugin `jsTree`.
Other
45 stars 3 forks source link

Misaligned grid if search is activated #19

Closed ismirsehregal closed 10 months ago

ismirsehregal commented 10 months ago

When setting search = TRUE for a jstree() using a grid, the rows are no longer aligned (please find the example code below):

image

I'm wondering if the (overall) search box can be placed above the table or column-wise search boxes as shown here can be realized instead (Maybe with an option to place the search boxes on top, but below the column titles, just like datatables column search) using the searchColumn function provided by the grid plugin:

image

library(jsTreeR)
library(shiny)

nodes <- list(
  list(
    text = "Fruits",
    type = "fruit",
    icon = "supertinyicon-transparent-raspberry_pi",
    a_attr = list(class = "helvetica"),
    children = list(
      list(
        text = "Apple",
        type = "fruit",
        data = list(
          price = 0.1,
          quantity = 20,
          cssclass = "lightorange"
        )
      ),
      list(
        text = "Banana",
        type = "fruit",
        data = list(
          price = 0.2,
          quantity = 31,
          cssclass = "lightorange"
        )
      ),
      list(
        text = "Grapes",
        type = "fruit",
        data = list(
          price = 1.99,
          quantity = 34,
          cssclass = "lightorange"
        )
      ),
      list(
        text = "Mango",
        type = "fruit",
        data = list(
          price = 0.5,
          quantity = 8,
          cssclass = "lightorange"
        )
      ),
      list(
        text = "Melon",
        type = "fruit",
        data = list(
          price = 0.8,
          quantity = 4,
          cssclass = "lightorange"
        )
      ),
      list(
        text = "Pear",
        type = "fruit",
        data = list(
          price = 0.1,
          quantity = 30,
          cssclass = "lightorange"
        )
      ),
      list(
        text = "Strawberry",
        type = "fruit",
        data = list(
          price = 0.15,
          quantity = 32,
          cssclass = "lightorange"
        )
      )
    ),
    state = list(
      opened = TRUE
    )
  ),
  list(
    text = "Vegetables",
    type = "vegetable",
    icon = "supertinyicon-transparent-vegetarian",
    a_attr = list(class = "helvetica"),
    children = list(
      list(
        text = "Aubergine",
        type = "vegetable",
        data = list(
          price = 0.5,
          quantity = 8,
          cssclass = "lightgreen"
        )
      ),
      list(
        text = "Broccoli",
        type = "vegetable",
        data = list(
          price = 0.4,
          quantity = 22,
          cssclass = "lightgreen"
        )
      ),
      list(
        text = "Carrot",
        type = "vegetable",
        data = list(
          price = 0.1,
          quantity = 32,
          cssclass = "lightgreen"
        )
      ),
      list(
        text = "Cauliflower",
        type = "vegetable",
        data = list(
          price = 0.45,
          quantity = 18,
          cssclass = "lightgreen"
        )
      ),
      list(
        text = "Potato",
        type = "vegetable",
        data = list(
          price = 0.2,
          quantity = 38,
          cssclass = "lightgreen"
        )
      )
    )
  )
)

grid <- list(
  columns = list(
    list(
      width = 200,
      header = "Product",
      headerClass = "bolditalic yellow centered",
      wideValueClass = "cssclass"
    ),
    list(
      width = 150,
      value = "price",
      header = "Price",
      wideValueClass = "cssclass",
      headerClass = "bolditalic yellow centered",
      wideCellClass = "centered"
    ),
    list(
      width = 150,
      value = "quantity",
      header = "Quantity",
      wideValueClass = "cssclass",
      headerClass = "bolditalic yellow centered",
      wideCellClass = "centered"
    )
  ),
  width = 600
)

types <- list(
  fruit = list(
    a_attr = list(
      class = "lightorange"
    ),
    icon = "supertinyicon-transparent-symantec"
  ),
  vegetable = list(
    a_attr = list(
      class = "lightgreen"
    ),
    icon = "supertinyicon-transparent-symantec"
  )
)

ui <-   fluidPage(
  tags$head(
    tags$style(
      HTML(c(
        ".lightorange {background-color: #fed8b1;}",
        ".lightgreen {background-color: #98ff98;}",
        ".bolditalic {font-weight: bold; font-style: italic; font-size: large;}",
        ".yellow {background-color: yellow !important;}",
        ".centered {text-align: center; font-family: cursive;}",
        ".helvetica {font-weight: 700; font-family: Helvetica; font-size: larger;}"
      ))
    )
  ),
  titlePanel("jsTree grid"),
  jstreeOutput("jstree")
)

server <-   function(input, output){
  output[["jstree"]] <-
    renderJstree(jstree(nodes, search = TRUE, grid = grid, types = types))
}

shinyApp(ui, server)
stla commented 10 months ago

Terrific! Thank you for this request.

remotes::install_github("stla/jsTreeR@gridsearch")
ismirsehregal commented 10 months ago

Awesome, looks great!

stla commented 10 months ago

Yeah!

There's just one problem: one cannot use two grids in one app with search = TRUE.

stla commented 10 months ago

There's just one problem: one cannot use two grids in one app with search = TRUE.

I didn't try yet, but that should be possible now.

stla commented 10 months ago

Yes, it works 👍

ismirsehregal commented 10 months ago

@stla I have a question regarding this feature:

How is the width of the search inputs determined?

When I'm using a grid without predefined width, they no longer fit the column widths:

grid <- list(
  columns = list(
    list(
      # width = 200,
      header = "Product",
      headerClass = "bolditalic yellow centered",
      wideValueClass = "cssclass"
    ),
    list(
      # width = 150,
      value = "price",
      header = "Price",
      wideValueClass = "cssclass",
      headerClass = "bolditalic yellow centered",
      wideCellClass = "centered"
    ),
    list(
      # width = 150,
      value = "quantity",
      header = "Quantity",
      wideValueClass = "cssclass",
      headerClass = "bolditalic yellow centered",
      wideCellClass = "centered"
    )
  ),
  resizable = TRUE
  # , width = 600
)

image

Edit: same issue, when providing relative css units:

grid <- list(
  columns = list(
    list(
      width = "40vw",
      header = "Product",
      headerClass = "bolditalic yellow centered",
      wideValueClass = "cssclass"
    ),
    list(
      width = "20vw",
      value = "price",
      header = "Price",
      wideValueClass = "cssclass",
      headerClass = "bolditalic yellow centered",
      wideCellClass = "centered"
    ),
    list(
      width = "20vw",
      value = "quantity",
      header = "Quantity",
      wideValueClass = "cssclass",
      headerClass = "bolditalic yellow centered",
      wideCellClass = "centered"
    )
  ),
  resizable = TRUE
  # , width = 600
)
stla commented 10 months ago

The width is determined by the value of width which must be a number of pixels.

ismirsehregal commented 10 months ago

Stéphane, I just had a look. We can make it more flexible. Please check my PR.

ismirsehregal commented 10 months ago

Ah I forgot one thing. We need to check whether a number was passed by the user and append "px".

ismirsehregal commented 10 months ago

Should work fine now.

stla commented 10 months ago

The doc of jstree-grid says:

width: width of the column in pixels.

stla commented 10 months ago

Ah but there are some examples with percentages...

ismirsehregal commented 10 months ago

Yes, it seems the docs need an update. Relative units are working fine.

stla commented 10 months ago

I tried and that really doesn't work well. 50% for a search box does not correspond to 50% for the corresponding column.

ismirsehregal commented 10 months ago

I tested it with my above example using vw, which was working fine. I currently can't test with %. I'll check tomorrow.

stla commented 10 months ago

Indeed, it works fine with vw.

ismirsehregal commented 10 months ago

Mhm, yes I guess the input-width % has a different reference (parent of different size) than the columns. The viewport size on the other hand is the same for all elements.

ismirsehregal commented 10 months ago

I modified the PR to fix usage of %. I think an even better solution would be to place the search boxes below the header into the table. But yeah - more work.

stla commented 10 months ago

Thanks for the PR.

I never tried the resizable option for the grid. It would be great if the search boxes followed the resizing.

stla commented 10 months ago

I think this is not doable since there's no callback for the resizing, and no event triggered (the doc says nothing about that).

ismirsehregal commented 10 months ago

I created another PR: https://github.com/stla/jsTreeR/pull/21 which inserts the search boxes into the table below the header (my initial goal - just like DataTable does it).

This way we can simply set the width of the inputs to 100%.

Edit - the resizable option also works now:

screen

stla commented 10 months ago

Nice! Thank you!

ismirsehregal commented 10 months ago

Yesterday I forgot to replace a hard coded treeID wit el.id in one of the classes used in my PR. I just fixed that.