0

Issue

I want to be able to touch my screen and drag my finger across the surface and select multiple boxes. I want to do the same thing with my mouse, where I hold down the mouse and drag it across whatever I want to select. Because of this, I am thinking that I would like to implement this in something like JQuery/JQuery mobile so that I have this behavior out of the box?

Code

Here is my working sample of what I have working so far.

  • Built a table and able to select specific elements by color (and ignore another)
  • Able to select by row or colum. Also able to unselect.
  • Able to select entire table or unselect (by color).

Attempts

I tried using JQuery UI. Specifically, the JQuery selectable api, but it breaks my existing code and is buggy. I also took a look at something I found here, but it is completely dependent on the desktop approach using shift and control. I also tried add select as an attribute to my <td> elements and use multiple select. I didn't think that hack would work, but I at least wanted to try it. Finally, looked at stackoverflow and it seems everyone wants to do this for checkboxes or with a keyboard.

Again, what I need is a way to be able to select multiple boxes/grids aka the elements in my grid by touching screen and dragging it across whatever I wish to select or do the same with my mouse.

Edit This is a good question, it is similar but not what I need. Same use case, but applied to both mouse event + touch events.

Any suggestions, clues, hints, or more would be deeply appreciated as I have thrown everything and the kitchen sink at this. I feel like this.

Community
  • 1
  • 1
hlyates
  • 1,279
  • 3
  • 22
  • 44

1 Answers1

2

I combined this answer with this one and it seems to work both on desktop and on mobile (code is a bit ugly, sorry for that).

How it works

Every <td> on the table listens both to normal mouse events (up/down/move) and to touch events (start/end/move).

On mousedown/touchstart the motion becomes "active", selection is reset (removing .highlight class) and current event element is selected.

The trick is in the touchmove event: since $(this) always refers to the element where the touch event started, we have to see what the user is actually touching passing the event coordinates to highlightHoveredObject, which will select the right element.

JSFiddle

JavaScript

function highlightHoveredObject(x, y) {
    $('td').each(function() {
      // check if is inside boundaries
      if (!(
          x <= $(this).offset().left || x >= $(this).offset().left + $(this).outerWidth() ||
          y <= $(this).offset().top  || y >= $(this).offset().top + $(this).outerHeight()
      )) {

        $(this).addClass('highlight');
      }
    });
}

// if you are using jQuery Mobile replace the next line with
// $("#yourpage").on("pagecreate", function() {

$(document).ready(function() {  

    var active = false;

    $("td").on("mousedown", function(ev) {
        active = true;
        $(".highlight").removeClass("highlight"); // clear previous selection
        ev.preventDefault(); // this prevents text selection from happening
        $(this).addClass("highlight");
    });

    $("td").on("mousemove", function(ev) {
        if (active) {
            $(this).addClass("highlight");
        }
    });

    $(document).on("mouseup", function(ev) {
        active = false;
    });

    $("td").on("touchstart", function(ev) {
        active = true;
        $(".highlight").removeClass("highlight"); // clear previous selection
        ev.preventDefault(); // this prevents text selection from happening
        $(this).addClass("highlight");
    });

    $("td").on("touchmove", function(ev) {
        if (active) {
            var touch = ev.originalEvent.touches[0];
            highlightHoveredObject(touch.clientX, touch.clientY);
        }
    });

    $(document).on("touchend", function(ev) {
        active = false;
    });

});

HTML

<table border="1" width="100%">
    <tbody><tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
    </tr>
    <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
    </tr>
    <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
    </tr>
</tbody></table>

CSS

.highlight { background-color:#ccffcc; }
Community
  • 1
  • 1
Sga
  • 3,608
  • 2
  • 36
  • 47
  • It works for my mouse, but I am only getting one td element to select at a time with touch. In other words, no drag select with mobile. Are you experiencing that? – hlyates Apr 22 '15 at 20:22
  • 1
    JSFiddle works fine for me both on my Android device (Moto G) and on emulation in Chrome browser – Sga Apr 22 '15 at 20:23
  • I am on a Microsoft Surface and tested on IE explorer 11 (because of enterprise requirements). Let me check on Firefox. :-( – hlyates Apr 22 '15 at 20:26
  • Okay, it works on firefox(yay!), but not IE11. What might be the reason for that? I gave you an upvote. :) – hlyates Apr 22 '15 at 20:31
  • It's buggy on IE11, but it works. You have to hold your finger down much, much, longer. Thank you. If you don't mind, because I am a learner. Could you please edit your answer to include a basic summary of how this code works and the idea behind it? I am super humbled, but also want to learn how to be a better developer. I'll mark your contribution as the answer soon. – hlyates Apr 22 '15 at 20:37
  • 1
    Thanks. Can you also try adding `-ms-touch-action: none;"` to your CSS? – Sga Apr 22 '15 at 20:38
  • I'll fork your code and do that shortly. I'll report back. Like this? See: https://jsfiddle.net/hf2008/5k1Lf88f/2/ – hlyates Apr 22 '15 at 20:39
  • Thank you sir. I'll research into what that is doing. Teaching me a lot today. If possible, could you please briefly explain what the boundary portion of the code is doing? The even listener stuff makes sense. :D – hlyates Apr 22 '15 at 21:52
  • 1
    Yes! thanks a lot, it is just what I was looking for. – juanram0n Dec 31 '21 at 11:09