event.path undefined with Firefox and Vue.js

First I am using Vue.js and Node.js

I have a problem with Firefox.

I use event.path[n].id and with Firefox I get an error

event.path undefined

But It works fine in other browsers.

Do you have any idea why?

Answers:

Answer

The path property of Event objects is non-standard. The standard equivalent is composedPath, which is a method. But it's new.

So you may want to try falling back to that, e.g.:

var path = event.path || (event.composedPath && event.composedPath());
if (path) {
    // You got some path information
} else {
    // This browser doesn't supply path information
}

Obviously that won't give you path information if the browser doesn't supply it, but it allows for both the old way and the new, standard way, and so will do its best cross-browser.

Example:

document.getElementById("target").addEventListener("click", function(e) {
  // Just for demonstration purposes
  if (e.path) {
    if (e.composedPath) {
      console.log("Supports `path` and `composedPath`");
    } else {
      console.log("Supports `path` but not `composedPath`");
    }
  } else if (e.composedPath) {
    console.log("Supports `composedPath` (but not `path`)");
  } else {
    console.log("Supports neither `path` nor `composedPath`");
  }
  
  // Per the above, get the path if we can
  var path = e.path || (e.composedPath && e.composedPath());
  
  // Show it if we got it
  if (path) {
    console.log("Path (" + path.length + ")");
    Array.prototype.forEach.call(
      path,
      function(entry) {
        console.log(entry.nodeName);
      }
    );
  }
}, false);
<div id="target">Click me</div>

In my tests (updated May 2018), neither IE11 nor Edge supports either path or composedPath. Firefox supports composedPath. Chrome supports both path (it was Google's original idea) and composedPath.

So I don't think you can get the path information directly on IE11 or Edge. You can, obviously, get the path via e.target.parentNode and each subsequent parentNode, which is usually the same, but of course the point of path/composedPath is that it's not always the same (if something modifies the DOM after the event was triggered but before your handler got called).

Answer

You can create your own composedPath function if it's not implemented in the browser:

function composedPath (el) {

    var path = [];

    while (el) {

        path.push(el);

        if (el.tagName === 'HTML') {

            path.push(document);
            path.push(window);

            return path;
       }

       el = el.parentElement;
    }
}

The returned value is equivalent to event.path of Google Chrome.

Example:

document.getElementById('target').addEventListener('click', function(event) {

    var path = event.path || (event.composedPath && event.composedPath()) || composedPath(event.target);
});
Answer

This function serves as a polyfill for Event.composedPath() or Event.Path

function eventPath(evt) {
    var path = (evt.composedPath && evt.composedPath()) || evt.path,
        target = evt.target;

    if (path != null) {
        // Safari doesn't include Window, but it should.
        return (path.indexOf(window) < 0) ? path.concat(window) : path;
    }

    if (target === window) {
        return [window];
    }

    function getParents(node, memo) {
        memo = memo || [];
        var parentNode = node.parentNode;

        if (!parentNode) {
            return memo;
        }
        else {
            return getParents(parentNode, memo.concat(parentNode));
        }
    }

    return [target].concat(getParents(target), window);
}
Answer

Use composePath() and use a polyfill for IE: https://gist.github.com/rockinghelvetica/00b9f7b5c97a16d3de75ba99192ff05c

include above file or paste code:

// Event.composedPath
(function(e, d, w) {
  if(!e.composedPath) {
    e.composedPath = function() {
      if (this.path) {
        return this.path;
      } 
    var target = this.target;

    this.path = [];
    while (target.parentNode !== null) {
      this.path.push(target);
      target = target.parentNode;
    }
    this.path.push(d, w);
    return this.path;
    }
  }
})(Event.prototype, document, window);

and then use:

var path = event.path || (event.composedPath && event.composedPath());
Answer

I had the same issue. I need the name of the html element. In Chrome I get the name with path. In firefox I trieed with composedPath but it return a different value.

For solved my problem I used this e.target.nodeName. With target function you can retrieve the HTML element in Chrome, Firefox and Safari.

This is my fucntion in Vue:

selectFile(e) {
        this.nodeNameClicked = e.target.nodeName
        if (this.nodeNameClicked === 'FORM' || this.nodeNameClicked === 'INPUT' || this.nodeNameClicked === 'SPAN') {
          this.$refs.singlefile.click()
      }
    }

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.