rafaelw / mutation-summary

A JavaScript library that makes observing changes to the DOM easy
Apache License 2.0
702 stars 160 forks source link

SVG support #27

Open TheLaughableCoder opened 7 years ago

TheLaughableCoder commented 7 years ago

Great project. I love what you've done. I've played with it through Live Helper.https://livehelperchat.com/ and the co-browsing feature they have. At the moment it doesn't seem to support SVGs.

I have a site that requires the use of SVG and this project doesn't seem to send through that data. Is there any reason that SVG support is left out?

SirenHound commented 7 years ago

Related #23

byronrwalker commented 7 years ago

I ran into this issue with inline svg xml not working within an iframe and was able to resolve the issue by setting the innerHTML to itself.

VanillaJS

var iframe = document.querySelector("iframe");
var frame_body = iframe.contentDocument.body;
frame_body.innerHTML = frame_body.innerHTML;

Jquery

var $frame = $("iframe");
var $frame_body = $frame_body = $($frame[0].contentDocument.body);
$frame_body.html($frame_body.html())
kyleramirez commented 6 years ago

For those who are coming to this question later, if you're using the tree-mirror, you realize SVG doesn't work out of the box. TreeMirror does provide a hook for createElement, internally called delegate, which is great. It allows us to set up SVG elements properly.

What you'll find in the screen_sharing_extension example is it overrides the creation of <script /> tags.

if (tagName == 'SCRIPT') {
  var node = document.createElement('NO-SCRIPT');
  node.style.display = 'none';
  return node;
}

What you'll need to do is create a similar override for SVG and its elements. Here is what I did:

/* Somewhere outside the function (no need to recreate this every time an element is created */
const svgElems = ["altGlyph","altGlyphDef","altGlyphItem","animate","animateColor","animateMotion","animateTransform","circle","clipPath","color-profile","cursor","defs","desc","discard","ellipse","feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feDistantLight","feDropShadow","feFlood","feFuncA","feFuncB","feFuncG","feFuncR","feGaussianBlur","feImage","feMerge","feMergeNode","feMorphology","feOffset","fePointLight","feSpecularLighting","feSpotLight","feTile","feTurbulence","filter","font","font-face","font-face-format","font-face-name","font-face-src","font-face-uri","foreignObject","g","glyph","glyphRef","hatch","hatchpath","hkern","image","line","linearGradient","marker","mask","mesh","meshgradient","meshpatch","meshrow","metadata","missing-glyph","mpath","path","pattern","polygon","polyline","radialGradient","rect","set","solidcolor","stop","svg","switch","symbol","text","textPath","tref","tspan","unknown","use","view","vkern"].join("|")
const svgMatch = new RegExp(`^(${svgElems})$`)

/* Now in the createElement function */
if (svgMatch.test(tagName)) {
  const node = this.moviePlayer.mountedProjector.frame.contentDocument.createElementNS(
    "http://www.w3.org/2000/svg",
    tagName
  )
  return node
}