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
outputarea.js: Wrap inline SVGs inside an iframe #4250
Conversation
But hold on, isn't this also true about HTML/JavaScript output as well? In On Sun, Sep 22, 2013 at 4:14 AM, Pablo de Oliveira Castro <
Brian E. Granger |
Yes I believe you can also have collisions with HTML and JavaScript generated in cells. (Sorry most of my examples are in R, because that is what I'm more familiar with) The difference, I think, is that usually when using HTML or Javascript, the user finely The problem with SVG is that most of the time, it's not inlined but embeded (as an external image). %%R
require(ggplot2)
ggplot(data = data.frame(x = runif(1000)), aes(x=x)) + geom_histogram() to generate an histogram of a 1000 uniform sampling. <symbol overflow="visible" id="glyph0-1">
<path style="stroke:none;" d="M 2.640625 -6.796875 ... "/>
</symbol> Now if in the next cell I plot a second figure, the name The same problem may happen when the user includes multiple SVG figures from a foreign URL link. A thourough discussion of the issue is available in the original issue #1866 |
I'm torn. one one end this is nice to have a workaround. I'm pondering also the fact that iframing might prevent people to use SVG+js to have dynamic graphs. |
I agree that there is a trade-off here. Something like:
But this would require to add an extra parameter to the SVG format in the notebook. |
Updated, now SVG scoping is disabled by default but it can be enabled using the proposed scoped=True syntax. |
instead of adding a class, what do you think to 'just' make make the scope attribute be part of the metadata sent along the svg like we do with |
Sure, excellent idea. I did not realize that 60b728b uses metadata instead of a class. |
No problem, I'm feeling better to have this like that. I'm then wondering; (I know I can be annoying Probably can bring it up in Thursday live meeting. |
@Carreau: Could you please bring this up in tomorrow live meeting if time allows ? Thanks :) |
Has been discused durring hangout, recap is we will add a global metada flag to all output type :
The spec should not say that element are in iframes, but are isolated (we keep the possibility to change mechanism later),hence we won't give easy access to @pablooliveira |
Sure! I'm currently traveling but I can work on it this coming week. |
No hurry :-) |
Mathias, could you also give a brief outline of the thinking to get to this |
The rational was mostly that the problem of scoping does not apply only to svg, but things like html/javascript (example, There was arguing that then people just had to publish iframe themselves, but then you cannot use thoses iframes in nbconvert except for html. Seeing that publishing with display can carry along arbitrary metadata, we think that the notebook frontend can look at those metadata, and if the metadata tells the output need "protection" it will be wrapped in an iframe. It compares to other solution in the sens that :
|
Thank you, that is very helpful. |
I have committed a first tentative implementation for supporting "isolated" metadata on any content. I have tried it successfully on Firefox and Chrome:
I have tried isolating: svgs, html, javascript and cython annotations. There are two problems left: 2# can fixed with a timer that resizes the iframe periodically, but it seems ugly and a battery eater. Any suggestions ? I cannot find an event that is fired on the inner iframe that would allow me to avoid polling. Thanks for your reviews! |
@stefanv: |
I meant to link to the first entry: Which seems to have the ability to watch for changes. On Mon, Oct 7, 2013 at 1:03 PM, Pablo de Oliveira Castro <
|
@stefanv: I just had a look at the Iframe-Height-Jquery-Plugin. It uses a periodic timer to update the iframe. |
c6211c5 fixes issue 1#. Only issue 2# remains: should we resize iframe when the content changes dynamically ? In the current implementation, if the content becomes larger after page load, a scroll bar appears Iframe can be resized but this needs to set up a periodic timer that check the iframe content. I'm not sure we want to support 2#. Dynamic resizable isolated content is a rare use-case and can be avoided |
Added a CasperJS test for "isolated" and rebased on master. |
That's what I like to hear! |
me too, given how much I spent wrestling with JS on that, glad to see it put to use so quickly. :) I tried this out and it seems sensible to me, so I'm 👍. The only caveat is that having IFrames like this allows for a breaking of our regular layout a bit (if the SVG is wide enough, for example, the code cell doing the execution also becomes much wiser. I don't think there's much we can do about that, and I presume (though not certain) that this would also be the case if one were to make an HTML repr that created an IFrame (without asking for isolation), that it would do the same thing. |
Javascript tests in IPython! I am crying liquid golden tears of purest joy. |
@ivanov :
Congratulations, the CasperJS integration is very nice!
The layout breaks for a very large iframe, but for me it also breaks when I use a very large SVG without iframe, so this is not specific to the "isolated" support. I'm not sure, as you said, there is much we can do about that. (EDIT: btw, this seems to happen only in Firefox, in Chrome the code cell size is not affected by the SVG size.) |
When multiple inline SVGs are included in a single document, they share the same parse tree. Therefore, style collisions and use id collisions can occur and upset the rendering. This patch wraps each SVG inside an individual iframe, ensuring that SVG's declarations do not collide. (The SVG representation is kept as XML and not converted to a binary format, so I do not think this approach precludes the use of d3.js) Tested on: * Chrome Version 29.0.1547.57 Debian 7.1 (217859) * Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130806 Firefox/17.0 Iceweasel/17.0.8 Closes ipython#1866
SVG scoping is disabled by default, to enable it the user must call the core.display.SVG constructor with the scoped=True keyword parameter.
Instead of using a svg class to pass scope information use notebook metadata. Suggested by Matthias Bussonnier
Any content whose metadata contains an `isolated` tag will be isolated from the rest of the document. The current implementation wraps isolated content into an iframe.
In Firefox, if the iframe initial height is set to 0, the reported scrollHeight is too large. Workaround: set the initial height to 1.
In my opinion this PR is ready for merge. Any bugs or improvements left? |
@Carreau : Are you happy with this implementation of what we decided? |
hang on, from IPython.core.display import SVG, display_svg
s1 = '''<svg width='1cm' height='1cm' viewBox='0 0 1000 500'><defs><style>rect {fill:red;}; </style></defs><rect id='r1' x='200' y='100' width='600' height='300' /></svg>'''
s2 = '''<svg width='1cm' height='1cm' viewBox='0 0 1000 500'><rect id='r2' x='200' y='100' width='600' height='300' /></svg>'''
display_svg(SVG(s1), metadata=dict(isolated=True))
display_svg(SVG(s2), metadata=dict(isolated=True)) works as advertised, but the following does not: from IPython.display import display
display(SVG(s1), metadata=dict(isolated=True))
display(SVG(s2), metadata=dict(isolated=True)) the problem is that the _svg calls create a MIME type-keyed metadata dict, i.e. |
@ivanov: that is correct. This PR triggers isolation for mime-specific metadata such as The semantics are not clear for non-mime-specific metadata such as But I agree it's not nice that I think one good way to fix this would be to add a metadata keyword to the |
The problem I see with adding to the class constructor is that we're sort of hard-coding how they should be displayed into the objects themselves, which isn't so nice. The approach I consider reasonable for |
This should work nicely for |
Ok, I'm merging this and will start working on refactoring the display code so that metadata is passed around to the individual mime-keyed entries (i.e. as supported by the implementation in this PR) |
outputarea.js: Wrap inline SVGs inside an iframe
Thanks for the merge and review ! |
outputarea.js: Wrap inline SVGs inside an iframe
When multiple inline SVGs are included in a single document,
they share the same parse tree. Therefore, style collisions and
use id collisions can occur and upset the rendering.
This patch wraps each SVG inside an individual iframe, ensuring
that SVG's declarations do not collide.
(The SVG representation is kept as XML and not converted to a binary
format, so I do not think this approach precludes the use of d3.js)
Tested on:
Closes #1866
This PR wraps SVG figures inside an iframe (originally suggested by @Carreau in #1866).