12 January 2016

I couldn’t figure out why a mousedown event was firing 3 times while writing some jQuery code. I googled it and most of the answers that attempted to explain it were saying something to the effect of “an event is getting bound to an element multiple times”… somehow. That seemed odd to me as my example code was short and sweet and I didn’t see how I could be accidentally triggering the same event on the same element multiple times. I tried using .off() and .unbind() to clear it but it wasn’t working. Obviously there was another reason for my particular issue and once I reminded myself the code was executing the way it was supposed to and the problem was me, I could look at it differently. It turns out my root cause is very different from some others.

One of the goals I’m trying to achieve for responsive interface is that when a user clicks on an element, that element comes to the forefront. This interface will have multiple dives and they will be draggable and resizable. Given the limited real estate, I want the user to be able to enlarge an element to see more data and I want to make sure that despite it’s position in the code, it can be on top of everything. Because I wanted it to work for anything they clicked on, I used * to select my element: $("*")

When it wasn’t working I started writing to the javascript console to help me debug. I noticed I kept getting 3 events fired for the one mousedown event:

I entered the if and id = undefined
I entered the if and id = square
I entered the if and id = undefined

This was the point I started googling and not getting anywhere. Then, when I had another episode of my recurring “The problem is my thinking and not the code executing incorrectly” epiphanies (I wonder how many of those I’ll have in a lifetime), I asked myself “How many elements are ACTUALLY in the point that I clicked?” Up until this point my unconscious assumption is that when you an event fires (mousedown, click, mouseup, mouseover, etc) it’s only acting on the element you see, i.e. the topmost element. Well it turns out that is not the case! It’s actually firing on everything along the z access of the website! Even though I was clicking on <div id=”square”></div>, that div was sitting inside of and body is inside of “document.” Or at least I’m assuming “document” (as in the page itself) is the third element the event is firing off of. To test my theory I put a wrapper div around the “square” div and low-and-behold, the event fired 4 times!

So I learned my lesson, don’t be lazy and use a wildcard. Not that I would have done it that way in the final product; I was just creating a proof of concept. Thankfully I only spent about an hour on this so that’s not much lost time. There are a few ways I can go about making a better element selector. I can either set an ID for each element and start them all with the same prefix like id=”onTopSquare” and id=”onTopCircle” so that I can select just the ones I want to be able to set on top by doing $("[id ^= onTop]"). Or, and maybe my preferred way, add a class to all the elements I want to be able to do this to and use something like $(".onTop"). I definitely don’t want to just use $("div") because I almost always have nested divs so it will always fire multiple times!

I hope this helps someone since I didn’t get a good explanation from any of the posts I stumbled upon!


There are no comments.



You must be logged in to post a comment.