0

I want to prevent that a dropdown menu is opened when selecting a range of cells. I know, I can add an onmousedown event and call event.preventDefault()

The problem is that this will disable the dropdown for a single click event too. Is there a way to distinguish between the selection of a range (the mouse is pressed and not immediately released) and the click on a single cell (mouse is pressed and released)? I have also tried with onselectstart but it doesn't help me in this case.

Here a small demo: https://jsfiddle.net/vqsv99t4/2/

Neo
  • 1,171
  • 3
  • 17
  • 42
  • **[Check the answer here](http://stackoverflow.com/a/4139860/2065039)** – Guruprasad J Rao Nov 08 '16 at 08:12
  • Thx, but my real case is a little more complex. The selection can start in any cell of a table. This cell could be a combobox, but also a date input picker, or a text input. So it would be complex to implement the solution you suggested (I hope there is an easier way ;) – Neo Nov 08 '16 at 08:38
  • @Zardo can you please share your code? so that we can understand what you have achieved. Then maybe we can help you better. – sam Nov 08 '16 at 08:50
  • Well, in that case it would be easier if you provide some `demo` for it to help you.. :) – Guruprasad J Rao Nov 08 '16 at 09:32
  • Here the demo: https://jsfiddle.net/vqsv99t4/ – Neo Nov 08 '16 at 10:42

1 Answers1

1

I have updated your code to work according to your need.

  1. Disable text selection: Removed from Javascript to CSS

    .noselect {
      -webkit-touch-callout: none; /* iOS Safari */
        -webkit-user-select: none; /* Chrome/Safari/Opera */
         -khtml-user-select: none; /* Konqueror */
           -moz-user-select: none; /* Firefox */
            -ms-user-select: none; /* Internet Explorer/Edge */
                user-select: none; /* Non-prefixed version, currently
                                      not supported by any browser */
    }
    

    Source: https://stackoverflow.com/a/4407335/1957036

  2. Stopping event bubble from <td> to document: event.stopPropagation() will stop bubbling up the event to document mousemove() and mouseup() listener

  3. Logic: Storing the first cell from which the selection has started (mousedown() event on the cell). Then, checking the cell where the selection has stopped(mouseup() event).

  4. Modified HTML for better usage.

  5. Added data- attribute on cells for storing row-column information

Updated-2016-11-11

  1. Added jQuery-UI Selectmenu to replace <select>.

    Reason: <select> dropdown can't be triggered using JavaScript/JQuery.

//console.clear();

var BUTTON_LEFT = 1,
  BUTTON_RIGHT = 2;

var startCell = null;


(function() {

  $("#select").selectmenu();

  $(".mouse-event-cell")
    .on('mousedown', onMouseDown)
    .on('mouseup', onMouseUp)
    .on('mousemove', onMouseOver);
  $(document)
    .on('mousemove', onDocMouseOver)
    .on('mouseup', onDocMouseUp);
})();

function onDocMouseOver(e) {
  if (e.buttons !== BUTTON_LEFT) {
    startCell = null;
    clearFill();
  }
}

function onDocMouseUp(e) {
  if (e.buttons !== BUTTON_LEFT) {
    startCell = null;
    clearFill();
  }
}

function onMouseDown(e) {
  isInsideCell = true;

  if (startCell === null)
    startCell = e.currentTarget;
};

function onMouseOver(e) {
  if (startCell !== null) {
    fill(startCell, e.currentTarget, 'region');
  }
  e.stopPropagation();
}

function onMouseUp(e) {
  var endCell = e.currentTarget;

  if (startCell !== null) {
    fill(startCell, endCell, 'selected');
  }

  startCell = null;
  e.stopPropagation()
}

function fill(startCell, endCell, classToAdd) {
  var col0 = startCell.dataset['column'],
    row0 = startCell.dataset['row'],
    col1 = endCell.dataset['column'],
    row1 = endCell.dataset['row'],
    colMin = Math.min(col0, col1),
    colMax = Math.max(col0, col1),
    rowMin = Math.min(row0, row1),
    rowMax = Math.max(row0, row1);

  clearFill();

  if (startCell === endCell) {
    console.log('same-cell');
  } else {
    console.log('range-of-cell');
  }

  //console.log(startCell, endCell);


  for (var itCol = colMin; itCol <= colMax; itCol++) {
    for (var itRow = rowMin; itRow <= rowMax; itRow++) {
      $('#codexpl .mouse-event-cell#cell_' + itRow + '_' + itCol).addClass(classToAdd);
    }
  }
}

function clearFill() {
  $('#codexpl .mouse-event-cell').removeClass('selected').removeClass('region');
}
.ui-selectmenu-button.ui-button {
  width: 5em;
}
select {
  width: auto;
}
table {
  border-collapse: separate;
}
td.mouse-event-cell {
  border: 1px solid #ddd;
  padding: 2px 10px;
  height: 30px;
  /*To disable the text selection*/
  -webkit-touch-callout: none;
  /* iOS Safari */
  -webkit-user-select: none;
  /* Chrome/Safari/Opera */
  -khtml-user-select: none;
  /* Konqueror */
  -moz-user-select: none;
  /* Firefox */
  -ms-user-select: none;
  /* Internet Explorer/Edge */
  user-select: none;
  /* Non-prefixed version, currently
                                  not supported by any browser */
}
td.selected {
  background-color: goldenrod;
  color: white;
}
td.region {
  border-style: dashed;
  border-color: #BBB;
}
<!DOCTYPE html>
<html>

<head>
  <meta name="description" content="selecting multiple cells">
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>

  <script src="https://code.jquery.com/jquery-3.1.0.js"></script>
  <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

  <link href="https://code.jquery.com/ui/1.12.1/themes/smoothness/jquery-ui.css" rel="stylesheet" type="text/css" />
  <link href="https://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet" type="text/css" />
  <script src="https://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>

</head>

<body>
  <table id="codexpl">
    <tr>
      <th>#</th>
      <th>Columna</th>
      <th>Relative</th>
      <th>Isso</th>
    </tr>
    <tr>
      <td id="cell_0_0" data-row="0" data-column="0" class='mouse-event-cell'>
        <select id="select">
          <option value="volvo">Volvo</option>
          <option value="saab">Saab</option>
          <option value="mercedes">Mercedes</option>
          <option value="audi">Audi</option>
        </select>
      </td>
      <td id="cell_0_1" data-row="0" data-column="1" class='mouse-event-cell'>cell[0][1]</td>
      <td id="cell_0_2" data-row="0" data-column="2" class='mouse-event-cell'>cell[0][2]</td>
      <td id="cell_0_3" data-row="0" data-column="3" class='mouse-event-cell'>cell[0][3]</td>
      <td id="cell_0_4" data-row="0" data-column="4" class='mouse-event-cell'>cell[0][4]</td>
    </tr>
    <tr>
      <td id="cell_1_0" data-row="1" data-column="0" class='mouse-event-cell'>cell[1][0]</td>
      <td id="cell_1_1" data-row="1" data-column="1" class='mouse-event-cell'>cell[1][1]</td>
      <td id="cell_1_2" data-row="1" data-column="2" class='mouse-event-cell'>cell[1][2]</td>
      <td id="cell_1_3" data-row="1" data-column="3" class='mouse-event-cell'>cell[1][3]</td>
      <td id="cell_1_4" data-row="1" data-column="4" class='mouse-event-cell'>cell[1][4]</td>
    </tr>
    <tr>
      <td id="cell_2_0" data-row="2" data-column="0" class='mouse-event-cell'>cell[2][0]</td>
      <td id="cell_2_1" data-row="2" data-column="1" class='mouse-event-cell'>cell[2][1]</td>
      <td id="cell_2_2" data-row="2" data-column="2" class='mouse-event-cell'>cell[2][2]</td>
      <td id="cell_2_3" data-row="2" data-column="3" class='mouse-event-cell'>cell[2][3]</td>
      <td id="cell_2_4" data-row="2" data-column="4" class='mouse-event-cell'>cell[2][4]</td>
    </tr>
    <tr>
      <td id="cell_3_0" data-row="3" data-column="0" class='mouse-event-cell'>cell[3][0]</td>
      <td id="cell_3_1" data-row="3" data-column="1" class='mouse-event-cell'>cell[3][1]</td>
      <td id="cell_3_2" data-row="3" data-column="2" class='mouse-event-cell'>cell[3][2]</td>
      <td id="cell_3_3" data-row="3" data-column="3" class='mouse-event-cell'>cell[3][3]</td>
      <td id="cell_3_4" data-row="3" data-column="4" class='mouse-event-cell'>cell[3][4]</td>
    </tr>
    <tr>
      <td id="cell_4_0" data-row="4" data-column="0" class='mouse-event-cell'>cell[4][0]</td>
      <td id="cell_4_1" data-row="4" data-column="1" class='mouse-event-cell'>cell[4][1]</td>
      <td id="cell_4_2" data-row="4" data-column="2" class='mouse-event-cell'>cell[4][2]</td>
      <td id="cell_4_3" data-row="4" data-column="3" class='mouse-event-cell'>cell[4][3]</td>
      <td id="cell_4_4" data-row="4" data-column="4" class='mouse-event-cell'>cell[4][4]</td>
    </tr>
  </table>
</body>

</html>
Community
  • 1
  • 1
sam
  • 811
  • 2
  • 10
  • 25
  • I really appreciated the time you have invested for me. Very nice solution, but this doesn't solve my problem: if I add the mouse-cell-event class even to the combobox and I start the selection from this cell, the dropdown menu is displayed and the selection of a range become difficult. – Neo Nov 11 '16 at 15:09
  • Ohh. I think I now got the issue. I will update soon. – sam Nov 11 '16 at 15:17
  • Btw a solution could be to make the combobox not editable, but this has the drawback that I should do a selection-mode and a non-selection-mode. It would be nice if I could avoid this.... – Neo Nov 11 '16 at 15:38
  • @Zardo Don't fear...I am here. I will resolve this. :) – sam Nov 11 '16 at 15:41
  • @Zardo I have updated the code as ` – sam Nov 11 '16 at 17:51
  • Wow, cool! Now it's working exactly as i wish! Thank you very much! :-) – Neo Nov 14 '16 at 12:37
  • Its awesome if it really helped you. :) – sam Nov 14 '16 at 14:35
  • can I ask another question? You have marked with the css class "mouse-event-cell" all cell that have listeners for mouse events and than with a javascript function you set the real listeners. Is this approach better than setting onMouseOver, onMouseDown,... on every cell? I understand it keeps the xhtml page more compact... can this influence the performance of loading the page as well? – Neo Nov 16 '16 at 08:33
  • @Zardo Unfortunately, yes, it will affect the performance as we are attaching listener to each cell. – sam Nov 16 '16 at 08:52
  • @Zardo Refer to this SO Ques http://stackoverflow.com/questions/28627606/does-adding-too-many-event-listeners-affect-performance – sam Nov 16 '16 at 09:04