I have a custom element and would like to detect clicks outside of it. For example
<dom-module id="simple-element">
<style>
</style>
<template>
<content></content>
</template>
</dom-module>
<script>
(function() {
Polymer({
is: 'simple-element',
listeners: {
'tap': 'regularTap'
},
regularTap: function() {
console.log("i was tapped");
}
});
})();
</script>
Is there an event where I can listen to which will tell me when user has clicked outside of the element? Thanks.
Something along these lines should do what you want:
window.addEventListener('click', (e) => {
var target = event.target;
while(target != this && target != document.body) {
target = Polymer.dom(target).node.domHost.parentNode;
// might need some additional steps to get the parent from inside custom elements
// don't know by heart
}
if(target == this) {
// inside element
} else {
// outside element
}
});
Modified the code so that it actually works:
var that = this;
window.addEventListener("click", function(e){
var target = e.target;
while (target != that && target != document.body) {
target = Polymer.dom(target).node.parentElement;
}
if (target == that) {
console.log("inside element");
} else {
console.log("outside element");
}
});
You can use a behavior like this:
<script>
/** @polymerBehavior Polymer.HarleyClickOutsideBehavior */
Polymer.HarleyClickOutsideBehavior = {
ready: function () {
// bind listener method
this.clickOutsideListenerBinded = this._clickOutsideListener.bind(this)
},
detached: function () {
this._clickOutsideUnlisten()
},
clickOutsideListen: function () {
// run this method to start listening
this._clickOutsideUnlisten()
window.addEventListener('click', this.clickOutsideListenerBinded, false)
},
_clickOutsideUnlisten: function () {
window.removeEventListener('click', this.clickOutsideListenerBinded, false)
},
_clickOutsideListener: function (ev) {
// check if the user has clicked on my component or on my children
var isOutside = !ev.path.find(function (path) {
return path === this
}.bind(this))
if (isOutside) {
this.onClickOutside()
this._clickOutsideUnlisten()
}
},
onClickOutside: function () {
// overwrite this method to be notified
}
}
</script>
I've found a simpler solution haven't tested it on all browsers yet, but makes sense. So I add a global listener to window, and a listener to the custom element. This way click inside will call both, click outside will only call global..
listenToClickOutside() {
this.addEventListener("click", thisClick, false);
window.addEventListener("click", windowClick, false);
var clicksInside = 0;
var thisRef = this;
function thisClick() {
clicksInside++
}
function windowClick(event) {
clicksInside--;
if (clicksInside < 0) {
thisRef.removeEventListener("click", thisClick, false);
window.removeEventListener("click", windowClick, false);
// CLICKED outside
}
}
}