Show More
@@ -363,6 +363,30 b' class Latex(DisplayObject):' | |||||
363 |
|
363 | |||
364 | class SVG(DisplayObject): |
|
364 | class SVG(DisplayObject): | |
365 |
|
365 | |||
|
366 | def __init__(self, data=None, url=None, filename=None, scoped=False): | |||
|
367 | """Create a SVG display object given raw data. | |||
|
368 | ||||
|
369 | When this object is returned by an expression or passed to the | |||
|
370 | display function, it will result in the data being displayed | |||
|
371 | in the frontend. If the data is a URL, the data will first be | |||
|
372 | downloaded and then displayed. | |||
|
373 | ||||
|
374 | Parameters | |||
|
375 | ---------- | |||
|
376 | data : unicode, str or bytes | |||
|
377 | The Javascript source code or a URL to download it from. | |||
|
378 | url : unicode | |||
|
379 | A URL to download the data from. | |||
|
380 | filename : unicode | |||
|
381 | Path to a local file to load the data from. | |||
|
382 | scoped : bool | |||
|
383 | Should the SVG declarations be scoped. | |||
|
384 | """ | |||
|
385 | if not isinstance(scoped, (bool)): | |||
|
386 | raise TypeError('expected bool, got: %r' % scoped) | |||
|
387 | self.scoped = scoped | |||
|
388 | super(SVG, self).__init__(data=data, url=url, filename=filename) | |||
|
389 | ||||
366 | # wrap data in a property, which extracts the <svg> tag, discarding |
|
390 | # wrap data in a property, which extracts the <svg> tag, discarding | |
367 | # document headers |
|
391 | # document headers | |
368 | _data = None |
|
392 | _data = None | |
@@ -371,6 +395,8 b' class SVG(DisplayObject):' | |||||
371 | def data(self): |
|
395 | def data(self): | |
372 | return self._data |
|
396 | return self._data | |
373 |
|
397 | |||
|
398 | _scoped_class = "ipython-scoped" | |||
|
399 | ||||
374 | @data.setter |
|
400 | @data.setter | |
375 | def data(self, svg): |
|
401 | def data(self, svg): | |
376 | if svg is None: |
|
402 | if svg is None: | |
@@ -383,6 +409,12 b' class SVG(DisplayObject):' | |||||
383 | # get svg tag (should be 1) |
|
409 | # get svg tag (should be 1) | |
384 | found_svg = x.getElementsByTagName('svg') |
|
410 | found_svg = x.getElementsByTagName('svg') | |
385 | if found_svg: |
|
411 | if found_svg: | |
|
412 | # If the user request scoping, tag the svg with the | |||
|
413 | # ipython-scoped class | |||
|
414 | if self.scoped: | |||
|
415 | classes = (found_svg[0].getAttribute('class') + | |||
|
416 | " " + self._scoped_class) | |||
|
417 | found_svg[0].setAttribute('class', classes) | |||
386 | svg = found_svg[0].toxml() |
|
418 | svg = found_svg[0].toxml() | |
387 | else: |
|
419 | else: | |
388 | # fallback on the input, trust the user |
|
420 | # fallback on the input, trust the user |
@@ -494,36 +494,40 b' var IPython = (function (IPython) {' | |||||
494 |
|
494 | |||
495 |
|
495 | |||
496 | OutputArea.prototype.append_svg = function (svg, md, element) { |
|
496 | OutputArea.prototype.append_svg = function (svg, md, element) { | |
497 | // To avoid style or use collisions between multiple svg figures, |
|
497 | var wrapper = $('<div/>').addClass('output_subarea output_svg'); | |
498 | // svg figures are wrapped inside an iframe. |
|
|||
499 |
|
||||
500 | var iframe = $('<iframe/>') |
|
|||
501 | iframe.attr('frameborder', 0); |
|
|||
502 | iframe.attr('scrolling', 'no'); |
|
|||
503 |
|
||||
504 | var wrapper = $("<div/>").addClass("output_subarea output_svg"); |
|
|||
505 | wrapper.append(svg); |
|
498 | wrapper.append(svg); | |
|
499 | var svg_element = wrapper.children()[0]; | |||
|
500 | ||||
|
501 | if (svg_element.classList.contains('ipython-scoped')) { | |||
|
502 | // To avoid style or use collisions between multiple svg figures, | |||
|
503 | // svg figures are wrapped inside an iframe. | |||
|
504 | var iframe = $('<iframe/>') | |||
|
505 | iframe.attr('frameborder', 0); | |||
|
506 | iframe.attr('scrolling', 'no'); | |||
|
507 | ||||
|
508 | // Once the iframe is loaded, the svg is dynamically inserted | |||
|
509 | iframe.on('load', function() { | |||
|
510 | // Set the iframe height and width to fit the svg | |||
|
511 | // (the +10 pixel offset handles the default body margins | |||
|
512 | // in Chrome) | |||
|
513 | iframe.width(svg_element.width.baseVal.value + 10); | |||
|
514 | iframe.height(svg_element.height.baseVal.value + 10); | |||
|
515 | ||||
|
516 | // Workaround needed by Firefox, to properly render svg inside | |||
|
517 | // iframes, see http://stackoverflow.com/questions/10177190/ | |||
|
518 | // svg-dynamically-added-to-iframe-does-not-render-correctly | |||
|
519 | iframe.contents()[0].open(); | |||
|
520 | iframe.contents()[0].close(); | |||
|
521 | ||||
|
522 | // Insert the svg inside the iframe | |||
|
523 | var body = iframe.contents().find('body'); | |||
|
524 | body.html(wrapper.html()); | |||
|
525 | }); | |||
506 |
|
526 | |||
507 | // Once the iframe is loaded, the svg is dynamically inserted |
|
527 | element.append(iframe); | |
508 | iframe.on('load', function() { |
|
528 | } else { | |
509 | // Set the iframe height and width to fit the svg |
|
529 | element.append(wrapper); | |
510 | // (the +10 pixel offset handles the default body margins |
|
530 | } | |
511 | // in Chrome) |
|
|||
512 | var svg = wrapper.children()[0]; |
|
|||
513 | iframe.width(svg.width.baseVal.value + 10); |
|
|||
514 | iframe.height(svg.height.baseVal.value + 10); |
|
|||
515 |
|
||||
516 | // Workaround needed by Firefox, to properly render svg inside iframes, |
|
|||
517 | // see http://stackoverflow.com/questions/10177190/svg-dynamically-added-to-iframe-does-not-render-correctly |
|
|||
518 | iframe.contents()[0].open(); |
|
|||
519 | iframe.contents()[0].close(); |
|
|||
520 |
|
||||
521 | // Insert the svg inside the iframe |
|
|||
522 | var body = iframe.contents().find('body'); |
|
|||
523 | body.html(wrapper.html()); |
|
|||
524 | }); |
|
|||
525 |
|
||||
526 | element.append(iframe); |
|
|||
527 | }; |
|
531 | }; | |
528 |
|
532 | |||
529 |
|
533 |
General Comments 0
You need to be logged in to leave comments.
Login now