Why do mouseup events sometimes fire if the mouse is not released?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • markszlazak@gmail.com

    Why do mouseup events sometimes fire if the mouse is not released?

    In the following script, a control displays (black box) in each table
    cell once you mouse over the cell. Mouse down on the control to change
    the mode of the table. Drag the mouse over cells in the same column
    then mouseup anywhere in a cell. The mouseup event sometimres fires
    before the selection of table cells by dragging is complete. It's
    important that I stop these "false" mouseup's from firing or
    distinguish them from when I let go of the mouse button.

    <html>
    <head>
    <title></title>
    <style>
    #calendar {
    position:relati ve;
    top:10;
    left:10;
    background-color:white;
    width:700;
    }
    .calendarHeader {
    background-color:lightgree n;
    text-align:center;
    font-family:sans-serif;
    width:347;
    }
    .calendarRow {
    height:30;
    }
    #book {
    position:absolu te;
    width:400;
    height:200;
    color:grey;
    background-color:lightyell ow;
    border:3px grey solid;
    font-weight:bold;
    font-family:sans-serif;
    visibility:hidd en;
    }
    #output {
    position:relati ve;
    top:30;
    left:10
    }
    #clear {
    position:relati ve;
    top:40;
    left:10;
    width:80;
    background-color:lightgrey ;
    border:2px black solid;
    color:black;
    text-align:center;
    font-weight:bold;
    font-family:sans-serif;
    }
    </style>
    </head>
    <body>
    <table id='calendar' border='1' cellpadding='0' cellspacing='0' >
    <tr>
    <td class="calendar Header">Mark</td>
    <td class="calendar Header">Jennie</td>
    </tr>
    <tr class='calendar Row'>
    <td id='1|Mark'></td>
    <td id='1|Jennie'></td>
    </tr>
    <tr class='calendar Row'>
    <td id='2|Mark'></td>
    <td id='2|Jennie'></td>
    </tr>
    <tr class='calendar Row'>
    <td id='3|Mark'></td>
    <td id='3|Jennie'></td>
    </tr>
    <tr class='calendar Row'>
    <td id='4|Mark'></td>
    <td id='4|Jennie'></td>
    </tr>
    <tr class='calendar Row'>
    <td id='5|Mark'></td>
    <td id='5|Jennie'></td>
    </tr>
    <tr class='calendar Row'>
    <td id='6|Mark'></td>
    <td id='6|Jennie'></td>
    </tr>
    <tr class='calendar Row'>
    <td id='7|Mark'></td>
    <td id='7|Jennie'></td>
    </tr>
    </table>

    <div id="output"><te xtarea cols=50 rows=10></textarea></div>
    <div id="clear"
    onclick="docume nt.getElementBy Id('output').fi rstChild.value =
    '';">CLEAR</div>
    <div id="book" onclick="this.s tyle.visibility = 'hidden';">&nbs p;</
    div>

    <script>
    var calendar = document.getEle mentById('calen dar'),
    slots = calendar.getEle mentsByTagName( 'td'),
    rows = calendar.getEle mentsByTagName( 'tr'),
    /*debug*/ output = document.getEle mentById('outpu t').firstChild;
    /*debug*/ output.value = '';

    var apt = document.getEle mentById('book' );
    apt.appendChild (document.creat eTextNode(''));

    function addWebControl(e l) {
    var wc = document.create Element('div');
    wc.setAttribute ('style',
    'position:relat ive; ' +
    'background-color:lightgrey ;' +
    'border-width:1px;' +
    'border-color:black; ' +
    'border-style:solid; ' +
    'margin:0px; ' +
    'padding:0px; ' +
    'visibility:hid den; ' +
    'top:0; ' +
    'left:312; ' +
    'height:10; ' +
    'width:30;');
    el.appendChild( wc);
    }

    var firstSlotSelect ed = null,
    firstInitialSta te,
    drag = false,
    columnSelected,
    firstRowSelecte d,
    lastRowSelected ;

    function mousedownHandle r(e) { // Handler only on web access control
    button inside slot.
    var target = getEventTarget( e);

    drag = true;
    firstInitialSta te = target.style.ba ckgroundColor;
    firstSlotSelect ed = target.parentNo de;
    columnSelected = firstSlotSelect ed.cellIndex;
    firstRowSelecte d = firstSlotSelect ed.parentNode.r owIndex;

    var wcs, bgC = (firstInitialSt ate == 'lightgrey')?
    'lightgrey':'wh ite';
    target.parentNo de.style.backgr oundColor = bgC;
    (wcs = target.parentNo de.firstChild.s tyle).backgroun dColor =
    (firstInitialSt ate == 'lightgrey')? 'white':'lightg rey';
    wcs.visibility = 'hidden';

    return false;
    }

    var highlightedSlot = null;

    function mouseoverHandle r(e) {
    var target = getEventTarget( e);
    if (target.nodeNam e != 'TD') return; // Mouse did not move into
    table cell.

    /** Find the element the mouse moved from **/

    var relTarget = (!e)? null:(e.related Target)?
    e.relatedTarget :e.fromElement; // Get the element the mouse comes
    from.
    if (!relTarget) return;

    while (relTarget != target && relTarget.nodeN ame != 'BODY') { // Move
    through ancestors until target or BODY found.
    relTarget = relTarget.paren tNode;
    }

    if (relTarget == target) return; // Mouse moves from a child
    (related target) over the target element.

    /** Mouse actually entered TD. Handle event. **/

    if (!drag) {
    if (highlightedSlo t) { // Corrects for mouseout failing to
    register with rapid cursor movement.
    highlightedSlot .style.backgrou ndColor =
    (highlightedSlo t.firstChild.st yle.backgroundC olor == 'lightgrey')?
    'white':'lightg rey';
    highlightedSlot .firstChild.sty le.visibility = "hidden";
    }
    highlightedSlot = target;
    target.style.ba ckgroundColor =
    (target.firstCh ild.style.backg roundColor == 'lightgrey')?
    'lightyellow':' lightgrey';
    target.firstChi ld.style.visibi lity = "visible";
    }
    else {
    if (target.cellInd ex == columnSelected) {
    lastRowSelected = target.parentNo de.rowIndex;
    var wcs, bgC = (firstInitialSt ate == 'lightgrey')?
    'lightgrey':'wh ite';
    target.style.ba ckgroundColor = bgC;
    (wcs = target.firstChi ld.style).backg roundColor =
    (firstInitialSt ate == 'lightgrey')? 'white':'lightg rey';
    wcs.visibility = 'hidden';
    }
    else {
    firstSlotSelect ed = null;
    firstInitialSta te = null;
    firstRowSelecte d = null;
    lastRowSelected = null;
    columnSelected = null;
    }
    }
    }

    function mouseoutHandler (e) {
    var target = getEventTarget( e);
    if (target.nodeNam e != 'TD') return; // Mouse did not move out of
    table cell.

    /** Find the element the mouse moved to. **/

    var relTarget = (!e)? null:(e.related Target)?
    e.relatedTarget :e.toElement; // Get the element the mouse goes to.
    if (!relTarget) return;

    while (relTarget != target && relTarget.nodeN ame != 'BODY') { // Move
    through ancestors until target or BODY found.
    relTarget = relTarget.paren tNode;
    }

    if (relTarget == target) return; // Mouse moves to a child (related
    target) out of the target element.

    /** Mouse actually left TD. Handle event. **/

    if (drag) {
    target.style.ba ckgroundColor =
    (target.firstCh ild.style.backg roundColor == 'lightgrey')?
    'white':'lightg rey';
    }
    else {
    highlightedSlot = null;
    target.style.ba ckgroundColor =
    (target.firstCh ild.style.backg roundColor == 'lightgrey')?
    'white':'lightg rey';
    target.firstChi ld.style.visibi lity = "hidden";
    }
    }

    function mouseupHandler( e) {
    var target = getEventTarget( e);
    if (target.nodeNam e == 'DIV') target = target.parentNo de;

    /*debug*/ output.value += 'mouseUp\t';

    if (drag) {
    firstSlotSelect ed = null;
    firstInitialSta te = null;
    firstRowSelecte d = null;
    lastRowSelected = null;
    columnSelected = null;
    drag = false;
    }
    else if (target.style.b ackgroundColor != 'lightgrey' &&
    getEventCoordin ateX(e) - getElementCoord inateX(target) < 310) {
    apt.firstChild. replaceData(1,1 0,target.id);
    apt.style.left = e.clientX + window.pageXOff set;
    apt.style.top = e.clientY + window.pageYOff set;
    apt.style.visib ility = 'visible';
    }
    }

    function getElementCoord inateX(el) {
    var x = 0;
    while (el) {
    x += el.offsetLeft;
    el = el.offsetParent ;
    }
    return x;
    }

    function getEventCoordin ateX(e) {
    return (typeof e.offsetX != 'undefined')? e.offsetX:e.cli entX +
    window.pageXOff set;
    }

    function addEvent(el, evtType, listener, captures) {
    if (el.addEventLis tener) {
    el.addEventList ener(evtType, listener, captures);
    return true;
    }
    else if (el.attachEvent ) {
    return el.attachEvent( 'on' + evtType, listener);
    }
    else {
    el['on' + evtType] = listener;
    }
    }

    function getEventTarget( e) {
    return (window.event)? window.event.sr cElement:(e)? e.target:null;
    }

    for (var i=0; i < slots.length; i++) {
    if (slots[i].id.length 0) {
    addWebControl(s lots[i]); // Add web control DIV element as second
    child;
    addEvent(slots[i], 'mouseout', mouseoutHandler , false);
    addEvent(slots[i], 'mouseover', mouseoverHandle r, false);
    addEvent(slots[i], 'mouseup', mouseupHandler, false);
    addEvent(slots[i].firstChild, 'mousedown', mousedownHandle r, false);
    }
    }
    </script>
    </body>
    </html>
  • Stevo

    #2
    Re: Why do mouseup events sometimes fire if the mouse is not released?

    markszlazak@gma il.com wrote:
    In the following script, a control displays (black box) in each table
    cell once you mouse over the cell. Mouse down on the control to change
    the mode of the table. Drag the mouse over cells in the same column
    then mouseup anywhere in a cell. The mouseup event sometimres fires
    before the selection of table cells by dragging is complete. It's
    important that I stop these "false" mouseup's from firing or
    distinguish them from when I let go of the mouse button.
    You might be suffering from key bounce. It happens with switches all the
    time. You push a button and think you're making contact once and keeping
    the button down you'd expect no mouse up. But, the nature of switches is
    that you often get a bounce like a dropped ball doesn't just hit the
    ground and stay there, it bounces a few times before settling. Same deal
    with switches. I had to build debounce logic into a keyboard driver I
    wrote once, although that was in assembler and had a lot more control
    over timing than JavaScript would have. The basic principle is that you
    ignore up events for a certain amount of time because you know they're
    just the bounces. Then after that "blocking" time (we're talking a very
    short time here), you look at the state, wait a bit more, check it
    again, and then you can be sure of the final state and re-enable
    (unblock) the up events. If you see the state is up, then you can
    generate an up event (or call your up event handler) because you've
    detected a genuine up event.

    Now whether all this is coming into play in your situation, and whether
    even if it is, you have the level of control that would be needed is a
    different story. It's possible of course that Windows already takes care
    of such issues. I'm throwing it out there though, and it was fun to
    reminisce about the old days of Assembler to myself :-)

    Comment

    • markszlazak@gmail.com

      #3
      Re: Why do mouseup events sometimes fire if the mouse is notreleased?

      On May 6, 11:51 am, Stevo <n...@mail.inva lidwrote:
      markszla...@gma il.com wrote:
      In the following script, a control displays (black box) in each table
      cell once you mouse over the cell. Mouse down on the control to change
      the mode of the table. Drag the mouse over cells in the same column
      then mouseup anywhere in a cell. The mouseup event sometimres fires
      before the selection of table cells by dragging is complete. It's
      important that I stop these "false" mouseup's from firing or
      distinguish them from when I let go of the mouse button.
      >
      You might be suffering from key bounce. It happens with switches all the
      time. You push a button and think you're making contact once and keeping
      the button down you'd expect no mouse up. But, the nature of switches is
      that you often get a bounce like a dropped ball doesn't just hit the
      ground and stay there, it bounces a few times before settling. Same deal
      with switches. I had to build debounce logic into a keyboard driver I
      wrote once, although that was in assembler and had a lot more control
      over timing than JavaScript would have. The basic principle is that you
      ignore up events for a certain amount of time because you know they're
      just the bounces. Then after that "blocking" time (we're talking a very
      short time here), you look at the state, wait a bit more, check it
      again, and then you can be sure of the final state and re-enable
      (unblock) the up events. If you see the state is up, then you can
      generate an up event (or call your up event handler) because you've
      detected a genuine up event.
      >
      Now whether all this is coming into play in your situation, and whether
      even if it is, you have the level of control that would be needed is a
      different story. It's possible of course that Windows already takes care
      of such issues. I'm throwing it out there though, and it was fun to
      reminisce about the old days of Assembler to myself :-)
      OK thanks, that is something to look at. So I take it that you don't
      see an obvious problem with the code.

      Comment

      Working...