0

I would like to have different handlers for mouseDown, single click and double click events inside a html svg. Now when I click the svg, both mouseDown and click handlers are triggered, and similarly, when double clicking, both click and double click handlers are triggered. Is there a way to solve this problem? Thanks

Update: I would like to use these handlers on svg shapes, specifically mouseDown/Up for drag-and-drop, single click to change shapes, and double click to remove a shape.

Xiaofan Mu
  • 17
  • 2
  • 6

4 Answers4

1

Double click (obviously) consists of two single clicks. When the first click is performed no one knows will there be any second click or not. That's why the first click of a double click produces a "single click event". So there is no way to fix this problem.

The recommended solution is not to use both (single and double click) events on the same control.

olvin
  • 31
  • 4
  • "The recommended solution is not to use both (single and double click) events on the same control." Sometimes it's needed. E.g. if you're building a Windows File Explorer-like frontend, you want to select files on single click, and open on double. – Zoldszemesostoros Jun 21 '20 at 15:34
  • Yes but in this case the first click of a double click also leads to a file selection even if we usually don't notice it. So even in Windows Explorer this problem isn't solved because it cannot be. – olvin Jun 21 '20 at 15:41
  • so what do you recommend for a web-based file manager frontend? – Zoldszemesostoros Jun 21 '20 at 17:16
  • As @mashi said in his reply "There is no harm in selecting the same file multiple times". So there is no need to do anything special in case of a file manager. Just let that double selection happen =) – olvin Jun 21 '20 at 21:35
1

you may use event.detail to detect simple or double click

const clickSwitcher = (function()
  {
  const cDelay = 600                   // a large one...  
  let   refTO  = setTimeout(()=>{},0) // init for clear

  function sd_click( e, f_simpleClick, f_doubleClick ) // simple or double click shunt
    {
    clearTimeout( refTO )
    if (e.detail === 2)
      f_doubleClick(e) 
    else                    //  (e.detail === 1)              
      refTO = setTimeout( f_simpleClick, cDelay, e )    
    }
  return sd_click
  })()

document.querySelectorAll('#my-rect, span').forEach(el=>
  {
  el.onclick = e => clickSwitcher(e, simpleClick, doubleClick )
  })


// change to your own code for simpleClick and doubleClick event action

function simpleClick(e)
  {
  console.log('simple click on', e.target.textContent || 'svg element'   )
  }
function doubleClick(e)
  {
  console.log('double click on', e.target.textContent || 'svg element'   )
  }
.as-console-wrapper { max-height:100% !important; top:0; left:50% !important; width:50%; }
.as-console-row     { background-color: yellow; }
.as-console-row::after  { display:none !important; }

#my-paragraph, rect      { cursor: pointer;}
#my-paragraph span:hover { background-color:yellow }
#my-rect:hover           { fill: orange; }
<p id="my-paragraph">
  <span>Paul</span>
  <span>John</span>
</p>

<svg width="150" height="100" viewBox="0 0 3 2">
  <rect id="my-rect" width="1" height="2" x="2" fill="#d2232c" />
</svg>

see also -> What is the max delay between two clicks to trigger a double-click event?

[edit] updated answer:
improved code to make it easier to read, and make it more easily transposable

Mister Jojo
  • 20,093
  • 6
  • 21
  • 40
1

dblclick event fires after two click events and after two pairs of mousedown and mouseup events.

Usually, we see such a case when for example selecting/focusing a file by a single click and then executing a file by double click. There is no harm in selecting the same file multiple times.

If you need to distinguish these two events, you can postpone single click handling until you are sure it is not part of the double click, but this will add a delay in handling.

let clicks = 0;
let clickTimer = 0;
const dblClickTimeSpan = 300;

const clickHandler = (e) => {
    clicks++;
    if(clicks === 1) {
    clickTimer = setTimeout(()=>{
        clicks = 0;
        // handle single click, now we are sure it is not a bouble click
        console.log('Single Click.')
    }, dblClickTimeSpan);
    }
    if(clicks === 2) {
        // it is the second click in double-click event
        clearTimeout(clickTimer);
        clicks = 0;
    }
}

myButton.addEventListener('click', clickHandler);
myButton.addEventListener('dblclick', (e) => console.log('Double Click.'));
<button id="myButton">Button</button>
mashi
  • 532
  • 3
  • 6
0

You can create the click method and using timeout differentiate if there is single click or double click event happening. and in timeout set the difference of 1 or 2 seconds.

asfandyar24
  • 78
  • 2
  • 8