Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Algorithm for 'Shift + Clicking' items in a collection to select them

I am trying to mimic the file selecting from Windows Explorer in Javascript. I notice Windows Explorer has two types of "selecting". One is the normal selection which highlights the file and the other one is a dotted line which means that file is currently focussed on. So I am using "selected" and "focus" as css classes.

Here you can find an example of my code working in a webpage.

In my code it just finds the rows between the focussed item and the current item and select those.

select: function (e) {
    if (e.ctrlKey) {
        rs.removeFocus();
        $(this).toggleClass("selected");
        $(this).addClass("focus");
    }
    else if (e.shiftKey) {
        var focusItem = $("#Items p.focus");
        var currentItem = $(this);
        var betweenItems = rs.betweenItems(currentItem, focusItem);

        rs.unSelectAll();
        rs.removefocus();

        $(betweenItems).each(function () {
            this.addClass("selected");
        });

        focusItem.addClass("selected");
        $(this).addClass("focus");
        $(this).addClass("selected");
    }
    else {
        rs.unSelectAll();
        rs.removeFocus();
        $(this).addClass("selected");
        $(this).addClass("focus");
    }
}

This works "okay" but it's not exactly as advanced as the Windows Explorer selecting. In Windows Explorer they don't always select the rows between last focussed item and the current one. If there are no "gaps" in the selection they will add those items to the selection. But if there is a gap it will start from the focussed item.

I am not sure how I should do this. It seems the algorithm they use in Windows is a little to complex for me. So if anybody can help me or push me into the right direction I would appreciate it.

like image 681
Pickels Avatar asked Jun 02 '10 17:06

Pickels


3 Answers

The shift-click algorithm for Windows (at least Windows 7, which is what I'm running) is: Track the last item selected not by a shift-click. On a shift-click, select all items between that item and the current click inclusive.

Examples:

1) If you have just item 5 selected, and shift-click 8, it will select 5-8.

2) If you have item 5 selected, then ctrl-click 3, then shift-click 8, then it will select 3-8. But if you have item 3 selected, then ctrl-click 5, then shift-click 8, it will select 5-8 instead. So the history matters.

3) If you have item 5 selected, then shift-click 8, it will select 5-8; if you follow that with shift-click 3, it will unselect 5-8 and select 3-5. Even though the last item selected was 8, it uses 5 as the anchor, since it was the last item that was not selected with a shift-click. So items selected with shift-click are excluded from the history.

This means to emulate Windows shift-click, you can't just know what is selected, you need to know how it was selected as well.

Mac OS behaves differently from Windows in two ways. First, if you shift-click outside the bounds of the currently selected items, it always expands. For example, if you have item 5 selected, then shift-click 8, it will select 5-8. If you then shift-click 3, it will expand the selection to 3-8, not unselect 5-8 and select 3-5 as Windows would. Second, if you click inside the bounds of the current selection, it will fill in from the topmost selected item to the item you clicked on. If you have items 3 and 8 selected, and shift-click 5, it will select 3-5, regardless of whether you clicked 3 or 8 more recently. So to emulate Mac OS, you don't need to track the history.

like image 51
Brian Davies Avatar answered Nov 07 '22 03:11

Brian Davies


On macOS the rules are a bit subtle / nuanced. I documented them and created an implementation in javascript here: https://github.com/ibash/better-multiselect

Basically it's:

  1. Click

    1. move anchor and selection to the element clicked
    2. selection is the element clicked
  2. Command click

    1. if the element is not selected

      1. move anchor and selection to the element clicked
      2. add it to the selection
    2. if the element is selected

      1. remove it from the selection
      2. anchor / focus move to: the next greatest selected, or the least index (backwards) from click point
  3. shift click

    1. remove everything between anchor and focus
    2. move focus to where clicked
    3. add everything between focus and anchor
like image 32
ibash Avatar answered Nov 07 '22 01:11

ibash


Try this plugin: https://github.com/luckyseven/jquery-multiselector

An easy way to make page elements selectable using Shift and Ctrl/Command keys with left mouse click.

like image 30
Alberto Fecchi Avatar answered Nov 07 '22 03:11

Alberto Fecchi