VegaLite.jl
VegaLite.jl copied to clipboard
width="container" not working
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?
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.
Can you send me a block of HTML to try? I'm not immediately sure what's missing.
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} )
@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 :)
<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.
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.
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.
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
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 Sure, I would add the same thing to the tsx files.
https://github.com/queryverse/VegaLite.jl/pull/254
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:
@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?
Don't set the container size of the embed container to 100%. You can have a container around it with 100% width.
@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.
The editor supports responsive charts: https://vega.github.io/editor/.
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.
Uh, that is not great...
Well, you need something to set the size of the container, either the visualization from the inside or the user from the outside.
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.
The current situation is:
- div container with undefined size
- VegaLite size option "container" does not work
- setting a single div container size to 100%
- VegaLite Editor Menu missplaced, outside of visible area
- 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 thediv
for the figure as either resizing based on the parent or based on the content, depending on what the spec has in itswidth
andheight
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.
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)