I have an app I am working on that requires an element on the page respond to both a click and double click event. In my case, when the user clicks or taps the element, I add a new element to the UI. If the user double clicks the target element, then I want to add a different element. This seems like something that would be a very common occurrence in a touch-centric application.
As you probably already know, when you wire up both events to an element, it will process both the click and double click event handlers when you double click the element. To be specific, the click event handler is called and then the double click handler is called. This is certainly not the desired behavior when I wire up both events, and it’s disappointing there is not a built-in way to handle things correctly. Fortunately, there is a pretty easy way to handle this so that only one event actually gets acted on.
Note: I will refer to click and double click as the user action I am interested in handling. In a touch context, these events are the same ones that would be fired for a tap or double tap. This solution will work for either tapping or mouse clicking.
First, let’s just review and show how the target element is wired up:
targetElement.onclick = myClickFunction;
targetElement.ondblclick = myDoubleClickFunction;
or if you would rather:
targetElement.addEventHandler("click",myClickFunction,false);
targetElement.addEventHandler("dblclick",myDoubleClickFunction,false);
You would put this in your app.onready handler or in your ready function for page fragments.
Now, let’s look at the code we use to handle the click and double click events.
var clickPromise;
function myClickFunction() {
if (clickPromise === undefined)
clickPromise = WinJS.Promise.timeout(250).then(function() {
// Do Something Here
clickPromise = undefined;
});
}
function myDoubleClickFunction() {
if (clickPromise !== undefined) {
clickPromise.cancel();
clickPromise === undefined;
}
// Do Something Here
}
Let’s break it down. In the click handler, myClickFunction, we create a Promise and use the timeout method to build in a small delay before executing whatever action we want to have happen on a click. This gives us time to see if the click is actually the beginning of a double click. In my app, I have found that a 250 millisecond delay works well. You may want to play around with this number in your app. You just need to be careful to not reduce the time interval to such a small time period that you end up handling both click and double click actions. We assign the Promise we create to the clickPromise variable. We will use clickPromise later to determine if we are handling a click or double click, and take the appropriate action.
If the timeout expires, we perform our whatever action we want to occur on a click or tap. Once we are done, we set clickPromise back to undefined so we are ready to go for the next click event.
In the double click handler, we check clickPromise to see if there is a pending click action. If there is, we cancel it because it was created during the “click portion” of our double click event. We set clickPromise to undefined to be ready to handle the next iteration of click or click/doubleclick events. We then take our double click action confident that the original click action will not be taken because we cancelled the pending Promise.