VegaLite.jl icon indicating copy to clipboard operation
VegaLite.jl copied to clipboard

width="container" not working

Open oheil opened this issue 5 years ago • 22 comments

Implementing example https://vega.github.io/vega-lite/examples/bar_size_responsive.html as

using VegaLite, VegaDatasets

dataset("cars") |>
@vlplot(
    height=250,
    width="container",
    :bar,
    x="Origin:n",
    y="count()",
)

does not give the desired result. It seems that the preset container of the result has 0 width.

From opening the VegaLite Editor and checking the code it seems that the proper code is generated.

Any ideas, whats wrong?

oheil avatar Jan 07 '20 22:01 oheil

Hm, maybe the HTML that we generate isn't properly resizing the containing container? This is the HTML that gets used when things are shown in the browser. @domoritz, are there some things we need to set in the HTML for the auto resizing to work?

I think the various Jupyter front-ends haven't shipped with support for the latest vega and vega-lite yet, so that probably explains why it doesn't work there?

@TonyLianLong, ElectronDisplay#master currently also doesn't handle that properly. I assume that is the same problem that we have in our regular HTML.

davidanthoff avatar Jan 08 '20 00:01 davidanthoff

Can you send me a block of HTML to try? I'm not immediately sure what's missing.

domoritz avatar Jan 08 '20 02:01 domoritz

Maybe this is a version thing? Which versions of Vega and VegaLite are used? The responsiveness has been introduced here: https://github.com/vega/vega-lite/releases/tag/v4.0.0 And from the documents this may be relevant: https://vega.github.io/vega-lite/docs/size.html#specifying-responsive-width-and-height

After setting width or height to "container", you need to ensure that the container’s width or height is determined outside the plot. For example, the container can be a

element that has style width: 100%; height: 300px. When the container is not available or its size is not defined (e.g., in server-side rendering), the default width and height are config.view.continuousWidth and config.view.continuousHeight, respectively.

But this is not working:

dataset("cars") |>
       @vlplot(
           height=250,
           width=:container,
           :bar,
           x="Origin:n",
           y="count()",
           config={view={continuousWidth=500}
       )

oheil avatar Jan 08 '20 06:01 oheil

@domoritz Here is an HTML file with this.

@oheil I don't think it is a versioning thing, VegaLite#master should bring the latest versions of the packages along. But I do think that we need to do something about the container, I'm just not sure what. My CSS skills are not there :)

davidanthoff avatar Jan 08 '20 19:01 davidanthoff

<body>
    <div id="vghXa" style="width:90%;"></div>
</body>

would do. (90% looks better than 100%)

But I can't say if this is a real solution or brings other problems.

oheil avatar Jan 08 '20 20:01 oheil

In file https://github.com/queryverse/VegaLite.jl/blob/master/src/rendering/render.jl I changed every occurence of <div id="$divid"></div> to <div id="$divid" style="width:100%;height:100%;"></div> and results are fine for those examples I checked. But only if I use a browser tab to view the plots.

Using e.g. Visual Studio Code with the Plot pane as display, it doesn't work. I guess it is because for this to work file https://github.com/julia-vscode/julia-vscode/blob/master/src/repl.ts has to be changed accordingly.

I didn't found a way to somehow inject some CSS or JavaScript code to set the container width and height from within VegaLite.jl, to avoid the need for changing other packages/software/plugins like julia-vscode, but this seems to be not possible.

oheil avatar Jan 10 '20 15:01 oheil

I think we should just change that in VS Code and ElectronDisplay as well, those are not complicated changes at all :) Those are the three "clients" we have on the Julia side of things.

davidanthoff avatar Jan 10 '20 23:01 davidanthoff

I already tried for the VS Code extension but failed to create the VSIX package. Actually the extension package was build but using it failed inside VS Code with a crash. I followed https://github.com/julia-vscode/julia-vscode/wiki/Updating-to-the-latest-version Option 3 and used the v0.13.1 tagged version but the result crashed inside VSCode.

So I have a untested Fork with the small changes. I think its not necessary to create a PR from this, but I would if you want it. These are the changes: https://github.com/oheil/julia-vscode/commit/e79b907db5119d5f460564cc21a15763097f2ef4

oheil avatar Jan 11 '20 12:01 oheil

Ok, I fixed this in VS Code, see https://github.com/julia-vscode/julia-vscode/pull/932.

@TonyLianLong could you make a similar adjustment for ElectronDisplay, if we need it?

@oheil are you preparing a PR for the HTML that gets created here in VegaLite.jl? I think once we have those fixed, we should be all good.

davidanthoff avatar Jan 13 '20 02:01 davidanthoff

@davidanthoff Sure, I would add the same thing to the tsx files.

TonyLianLong avatar Jan 13 '20 04:01 TonyLianLong

https://github.com/queryverse/VegaLite.jl/pull/254

oheil avatar Jan 13 '20 08:01 oheil

Setting the container size to 100% is better than before but there is a side effect:

The vega embed menu is now displaced, see image:

Unbenannt

oheil avatar Jan 13 '20 13:01 oheil

@oheil, ah, that is kind of annoying, but maybe not the end of the world?

@domoritz, any idea how we might get around this vega embed placement issue?

davidanthoff avatar Jan 13 '20 17:01 davidanthoff

Don't set the container size of the embed container to 100%. You can have a container around it with 100% width.

domoritz avatar Jan 14 '20 23:01 domoritz

@domoritz Do you have a code (html, css) example? I tried: <div style="width:100%;height:100%;"><div id="$divid"></div></div> Didn't work for the original "container" issue. Tried also "display:inherit", and others display properties none worked.

oheil avatar Jan 15 '20 07:01 oheil

The editor supports responsive charts: https://vega.github.io/editor/.

domoritz avatar Jan 15 '20 19:01 domoritz

The editor supports responsive charts: https://vega.github.io/editor/.

Yes, this is true. I was searching on how this fact may help and now I belief that we can't solve the problem with just a general HTML/CSS container solution suitable for all plots.

Instead what Julia/VegaLite.jl has to do is to create the container conditionally if the size of the plot is dynamic or if the size of the plot is explicitly set to some pixels.

That is what the vega editor does: if e.g. width="container" is part of the definition, the editor wraps the plot in a fancy resizable container using css and javascript.

oheil avatar Jan 17 '20 10:01 oheil

Uh, that is not great...

davidanthoff avatar Jan 17 '20 17:01 davidanthoff

Well, you need something to set the size of the container, either the visualization from the inside or the user from the outside.

domoritz avatar Jan 17 '20 18:01 domoritz

Couldn't this be solved that the container of the parent element that will host the div that gets the vega stuff is always auto resizing, and then the vega/vega-lite code will configure the div for the figure as either resizing based on the parent or based on the content, depending on what the spec has in its width and height property? It just seems that the vega/vega-lite code already has to look at the spec and decide what kind it is, so it would be nice if we didn't have to duplicate that logic outside the vega/vega-lite code again.

davidanthoff avatar Jan 20 '20 03:01 davidanthoff

The current situation is:

  1. div container with undefined size
    • VegaLite size option "container" does not work
  2. setting a single div container size to 100%
    • VegaLite Editor Menu missplaced, outside of visible area
  3. resizable div container
    • additional special JavaScript code (complex, browser compatibility)
    • visibility of the resize widget (lower right corner) bad
    • initial size of the container may not be appropriate (e.g. if plot is small)

None of the above is satisfying.

Couldn't this be solved that the container of the parent element that will host the div that gets the vega stuff is always auto resizing, and then the vega/vega-lite code will configure the div for the figure as either resizing based on the parent or based on the content, depending on what the spec has in its width and height property? It just seems that the vega/vega-lite code already has to look at the spec and decide what kind it is, so it would be nice if we didn't have to duplicate that logic outside the vega/vega-lite code again.

I am not sure if this issue will be solved by the Vega/Lite people. I understand your proposal as this, that the Vega/Lite developers should add something intelligent to the VegaLite JavaScript engine? For this we need to find where Vega/Lite has an issue, which needs to be solved.

https://vega.github.io/vega-lite/docs/size.html

It would all be solved if config.view.continuousWidth and config.view.continuousHeight would work as described in the docs. Both values are 200 per default, but the plot isn't 200x200px if the container has no size attributes.

oheil avatar Jan 20 '20 09:01 oheil

I have played around again for hours and I come to the conclusion, that we have to introspect the spec and set the container size according to:

if width is "container" => set div style width=100% if height is "container" => set div style height=100% if width is NOT "container" AND if height is NOT "container" => don't set div styles

Or we provide a user interface to set/unset width and/or height of the container div, e.g. analog of the global setting functions renderer and actionlinks: VegaLite.setContainerSize( width::String = "", height::String = "" ) These strings are inserted as style of the container div as given by the user, e.g. the user can use: VegaLite.setContainerSize( "1000px", "500px" ) and will get: <div style="width:1000px;height:500px;" id="$divid"></div>

Or even more flexible: VegaLite.setContainerStyle( style::String = "" ) Now the user has to use e.g.: VegaLite.setContainerStyle( "style=\"width:1000px;height:500px;\"" ) and could do tricks like: VegaLite.setContainerStyle( "class=\"myOwnContainer\" style=\"width:1000px;height=500px;\"" ) With this the user would be able to inject his own JavaScript to get a resizable container, e.g. with VegaLite.setContainerStyle( "><div style=\"width:1000px;height=500px;\"" )

(fantasy is going wild)

oheil avatar Jan 20 '20 12:01 oheil