2

I have 4 SVG buttons as part of a main menu on my personal webpage.

enter image description here

/----------------------------------------------------------------------------------------------------------------------------------/

When one is clicked, all 4 buttons retract to the corners and the respective section is revealed (i.e. AboutMe button --> AboutMe section). enter image description here

Originally I had the SVG objects embedded in an img tag like so:

<img class = "button active" id = "person-icon" src = "resources/main-page-icons/person-icon.svg"/>

I did it like this because I read that when there is no need to animate an SVG it isn't necessary to embed it in an object/embed tag. However, I decided today that I wanted to create a hover effect for the SVG element. I had to change the img tag to an object to allow for styling/animating

<object class = "button active" id = "person-icon" data = "resources/main-page-icons/person-icon.svg" type = "image/svg+xml"></object>

The hover effect works as expected, BUT now I can't click it. Inspecting the element reveals that I'm clicking on the SVG itself and not the object it's embedded in. Wrapping it in a div did not solve the problem either.

Question: Is there a way I can animate the SVG element while handling click events on the object element it's embedded in?

In case someone asks "Why not handle the click event within the SVG element?" I don't think it's possible or would make sense for an SVG element's behavior to influence other elements which is why I handled the click events OUTSIDE of the SVG element (i.e. click 1 button --> other buttons expand, content faded in = bad). Maybe you can, but I didn't think it made sense and it wasn't necessary initially.

Thanks for the help in advance.

GHOST-34
  • 359
  • 1
  • 19
  • Images are not interactive by design. If you have a mental model of an image that their capabilities are on a par with a raster you won't go far wrong. – Robert Longson Apr 22 '16 at 05:44
  • It's not clear to me what you're saying/suggesting. I understand that images are not interactive, that's why I changed to an object tag. – GHOST-34 Apr 22 '16 at 18:53
  • If you don't send the click events to the object you can't trigger the animation can you? It's a bit hard to be definitive as you've not provided the image source code or any details of how the animation works. – Robert Longson Apr 22 '16 at 21:42
  • Because this case obviously had to do with the changing of the element type I figured it was more of a fundamental JQuery/HTML problem and didn't require specific code. I was able to find the answer on my own after a while. Thanks for the input nonetheless. – GHOST-34 Apr 22 '16 at 23:21

2 Answers2

1

I found the answer here after some time Googling:

This kind of tag needs some content to show up on the page.

Your tag:

<object data="images/logo.svg" type="image/svg+xml" class="icon-logo"></object>

is not having any inner HTML-Content, so you won't be able to click it.

This has to do with an object requiring some sort of innerHTML in order to be recognized by the DOM. If I added some text like <object>Zoot!</object> then I could click it. Additionally, the SVG DOM differs fundamentally than the HTML DOM and lacks innerHTML. More on that here.

The work around was to use an image tag and surround it in a div that I can animate/style on. This works for the most part, but in my case the div is a circle (border-radius: 50%) and when translated across the screen skews the shape. Looks goofy when a background/border is applied and the skewing is visible. That's for another post though!

Community
  • 1
  • 1
GHOST-34
  • 359
  • 1
  • 19
1

This is because, for security reasons, events that occur on framed documents won't bubble to the main document.
<object> element's content is a framed document and do suffer from this restrictions too.

To workaround this, you have to attach the event onto the element's contentWindow, or any element inside its contentDocument.

But the document will not be accessible for cross-domain resources loaded into the element.

So you may try some kind of a hack like proposed here by @PaulDrapper which listens for the blur event and check what is the actual activeElement of the main document.

But there may be some false-positives if the user set the focus on the element using Tab navigation.

function attachClickEvent(obj, callback) {
  // no cross-domain restrictions
  if (obj.contentWindow) {
    obj.contentWindow.addEventListener('click', function() {
      callback();
    });
  } else {
    // hacky workaround
    window.addEventListener('blur', function() {
      // activeElement may not have been updated yet
      requestAnimationFrame(function() {
        // check that our element is the active one
        if (document.activeElement === obj) {
          callback();
          // so we can detect it multiple times
          obj.blur()
        }
      });
    });
    // we need to set the focus on the document
    var inp = document.createElement('input');
    inp.style.position = 'absolute';
    inp.style.opacity = 0;
    document.body.appendChild(inp);
    inp.focus();
    document.body.removeChild(inp);
  }

};

// call it when the element has loaded
crossDomain.onload = function() {
  attachClickEvent(this, function() {
    snippet.log('clicked on the doc')
  })
};
// for some UA, the load event may already have fired, so reload it ;-)
crossDomain.data = crossDomain.data;
<!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

<object width="200px" id="crossDomain" data="https://upload.wikimedia.org/wikipedia/commons/f/fd/Ghostscript_Tiger.svg"></object>
Community
  • 1
  • 1
Kaiido
  • 123,334
  • 13
  • 219
  • 285