Search code examples
javascriptpolymeriron-elements

How to select multiple elements in iron-selector by mouse drag


How can I select multiple items inside an iron-selector by clicking, holding and dragging the mouse, or even by drawing a rectangle with the mouse, and selecting all the items under it?

I use Polymer 1.11.3 and iron-selector 2.1.0, and reading the documentation provided no obvious solution.

This is my actual element in which I want to enable the drag-selection:

enter image description here

My goal is to be able to click e.g. on Sunday 7, drag the mouse to 15, release the click, and have 7-15 selected.


Solution

  • To be able to select my mouse click and drag, do the following:

    1. Set the css property user-select: none; to the element which holds your selectable items.

    2. Add on-track="handleTrack" to the element which holds your selectable items.

    3. Put this div somewhere in your element: <div id="selectionBox" style="position:absolute; top:0; left:0; height:0; width:0; border:2px solid #000; background-color:rgba(128, 128, 128, 0.3); z-index:999;"></div>

    Then, add these functions to your element:

    handleTrack: function(e) {
        switch(e.detail.state) {
            case "start":
                this.x1 = e.detail.x;
                this.y1 = e.detail.y;
                this.drawRectangle(this.x1, this.y1, this.x2, this.y2);
                break;
            case "track":
                this.x2 = e.detail.x;
                this.y2 = e.detail.y;
                this.drawRectangle(this.x1, this.y1, this.x2, this.y2);
                break;
            case "end":
                this.x2 = e.detail.x;
                this.y2 = e.detail.y;
                this.drawRectangle(0, 0, 0, 0);
                this.selectRectangle(e);
            break;
        }
    },
    drawRectangle: function(x1, y1, x2, y2) {
        this.$.selectionBox.style.left = x1 + 'px';
        this.$.selectionBox.style.top = y1 + 'px';
        this.$.selectionBox.style.width = (x2 - x1) + 'px';
        this.$.selectionBox.style.height = (y2 - y1) + 'px';
    },
    selectRectangle: function(e) {
        var tol = 20;
        var ironSelectors = Polymer.dom(e.currentTarget).querySelectorAll("iron-selector");
        ironSelectors.forEach(function(selector) {
            selector.items.forEach(function(i) {
                var el = i.getBoundingClientRect();
                if ((el.left+tol >= this.x1) && (el.top+tol >= this.y1) && (el.right-tol <= this.x2) && (el.bottom-tol <= this.y2)) {
                    selector.select(i.value);
                }
            }.bind(this));
        }.bind(this));
    }
    

    This code also works if you have multiple iron-selector.