From 8816035310d5875bf47413583593067cca8d5bc9 Mon Sep 17 00:00:00 2001 From: vascocc Date: Mon, 11 Nov 2019 14:05:28 +0000 Subject: [PATCH 1/3] feat(lib): add additive behavior This commit adds additive behavior, mimicking the behavior when holding the Shift key. Updated app to be able to select addictive behavior. Updated Cypress tests. Updated documentation. --- README.md | 4 ++- cypress/integration/dragging.spec.ts | 31 +++++++++++++++++++ cypress/support/utils.ts | 4 +++ .../src/lib/select-container.component.ts | 9 +++--- src/app/app.component.html | 2 ++ src/app/app.component.ts | 1 + 6 files changed, 46 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index aa24cdd..2e67be4 100644 --- a/README.md +++ b/README.md @@ -250,6 +250,7 @@ shortcuts: { | selectMode | Boolean | `false` | If set to `true`, a _toggle_ mode is activated similar to the `toggleSingleItem` shortcut. Useful for mobile. | | custom | Boolean | `false` | If set to `true`, all default styles for selected items will not be applied. | | selectWithShortcut | Boolean | `false` | If set to `true`, items can only be selected when single clicking and applying a keyboard shortcut | +| additive | Boolean | `false` | If set to `true`, will add items to selection the same way as holding the `shift` key. | Here's an example of all inputs in action: @@ -261,7 +262,8 @@ Here's an example of all inputs in action: [disableDrag]="true" [selectMode]="true" [custom]="true" - [selectWithShortcut]="false"> + [selectWithShortcut]="false" + [additive]="true"> ... ``` diff --git a/cypress/integration/dragging.spec.ts b/cypress/integration/dragging.spec.ts index 70f1b45..c4bc6cd 100644 --- a/cypress/integration/dragging.spec.ts +++ b/cypress/integration/dragging.spec.ts @@ -4,6 +4,7 @@ import { disableSelection, disableSelectOnDrag, enableSelectMode, + enableAdditive, getDesktopExample, shouldBeInvisible, shouldBeVisible, @@ -372,6 +373,36 @@ describe('Dragging', () => { }); }); + describe('Additive', () => { + beforeEach(() => { + enableAdditive(); + }); + + it('should extend selection after mouseup', () => { + getDesktopExample().within(() => { + cy.getSelectItem(0) + .dispatch('mousedown', { button: 0 }) + .getSelectItem(5) + .dispatch('mousemove') + .dispatch('mouseup') + .shouldSelect([1, 2, 5, 6]) + .getSelectItem(2) + .dispatch('mousedown', { button: 0 }) + .getSelectItem(7) + .as('end') + .dispatch('mousemove') + .shouldSelect([1, 2, 5, 6]) + .get(`.${SELECTED_CLASS}`) + .should('have.length', 8) + .get('@end') + .dispatch('mouseup') + .shouldSelect([1, 2, 3, 4, 5, 6, 7, 8]) + .get(`.${SELECTED_CLASS}`) + .should('have.length', 8); + }); + }); + }); + describe('Shortcuts', () => { it('should toggle single items', () => { getDesktopExample().within(() => { diff --git a/cypress/support/utils.ts b/cypress/support/utils.ts index 1b7ee73..a0e6c5b 100644 --- a/cypress/support/utils.ts +++ b/cypress/support/utils.ts @@ -68,6 +68,10 @@ export const enableSelectWithShortcut = () => { return cy.get('[data-cy="selectWithShortcut"]').click(); }; +export const enableAdditive = () => { + return cy.get('[data-cy="additive"]').click(); +}; + export const selectAll = () => { return getSelectAllButton().click(); }; diff --git a/projects/ngx-drag-to-select/src/lib/select-container.component.ts b/projects/ngx-drag-to-select/src/lib/select-container.component.ts index 7f8ee81..a727752 100644 --- a/projects/ngx-drag-to-select/src/lib/select-container.component.ts +++ b/projects/ngx-drag-to-select/src/lib/select-container.component.ts @@ -103,6 +103,7 @@ export class SelectContainerComponent implements AfterViewInit, OnDestroy, After @Input() disableRangeSelection = false; @Input() selectMode = false; @Input() selectWithShortcut = false; + @Input() additive = false; @Input() @HostBinding('class.dts-custom') @@ -466,7 +467,7 @@ export class SelectContainerComponent implements AfterViewInit, OnDestroy, After const itemRect = item.getBoundingClientRect(); const withinBoundingBox = inBoundingBox(mousePoint, itemRect); - if (this.shortcuts.extendedSelectionShortcut(event) && this.disableRangeSelection) { + if ((this.shortcuts.extendedSelectionShortcut(event) && this.disableRangeSelection) || this.additive) { return; } @@ -494,7 +495,7 @@ export class SelectContainerComponent implements AfterViewInit, OnDestroy, After (!withinBoundingBox && !this.shortcuts.toggleSingleItem(event) && !this.selectMode && - !this.shortcuts.extendedSelectionShortcut(event) && + (!this.shortcuts.extendedSelectionShortcut(event) || this.additive) && !this.selectWithShortcut) || (this.shortcuts.extendedSelectionShortcut(event) && currentIndex > -1) || (!withinBoundingBox && this.shortcuts.toggleSingleItem(event) && !item.selected) || @@ -540,7 +541,7 @@ export class SelectContainerComponent implements AfterViewInit, OnDestroy, After } private _isExtendedSelection(event: Event) { - return this.shortcuts.extendedSelectionShortcut(event) && this.selectOnDrag; + return (this.shortcuts.extendedSelectionShortcut(event) && this.selectOnDrag) || this.additive; } private _normalSelectionMode(selectBox: BoundingBox, item: SelectItemDirective, event: Event) { @@ -575,7 +576,7 @@ export class SelectContainerComponent implements AfterViewInit, OnDestroy, After const action = this.shortcuts.removeFromSelection(event) ? Action.Delete - : this.shortcuts.addToSelection(event) + : this.shortcuts.addToSelection(event) || this.additive ? Action.Add : Action.None; diff --git a/src/app/app.component.html b/src/app/app.component.html index 70c95fe..9f46247 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -26,6 +26,7 @@

> Select Mode Select with Shortcut + Additive
@@ -44,6 +45,7 @@

[disableRangeSelection]="disableRangeSelection" [selectOnDrag]="selectOnDrag" [selectWithShortcut]="selectWithShortcut" + [additive]="additive" > diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 1a4ee2f..9b85740 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -19,6 +19,7 @@ export class AppComponent implements OnInit { disableRangeSelection = false; isDesktop = false; selectWithShortcut = false; + additive = false; constructor( private titleService: Title, From d19e31fa24fb6d951bddf5bb0d157ca4f004a07a Mon Sep 17 00:00:00 2001 From: vascocc Date: Sun, 1 Dec 2019 21:45:14 +0000 Subject: [PATCH 2/3] feat(lib): add additive behavior This commit adds additive behavior, mimicking the behavior when holding the Shift key. Fixed Additive implementation; Updated tests and documentation; --- README.md | 2 +- cypress/integration/clicking.spec.ts | 35 +++++++++++++++++++ cypress/integration/dragging.spec.ts | 5 --- .../src/lib/select-container.component.ts | 27 ++++++++------ 4 files changed, 52 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 2e67be4..bac5654 100644 --- a/README.md +++ b/README.md @@ -250,7 +250,7 @@ shortcuts: { | selectMode | Boolean | `false` | If set to `true`, a _toggle_ mode is activated similar to the `toggleSingleItem` shortcut. Useful for mobile. | | custom | Boolean | `false` | If set to `true`, all default styles for selected items will not be applied. | | selectWithShortcut | Boolean | `false` | If set to `true`, items can only be selected when single clicking and applying a keyboard shortcut | -| additive | Boolean | `false` | If set to `true`, will add items to selection the same way as holding the `shift` key. | +| additive | Boolean | `false` | If set to `true`, will add items to selection when clicking and dragging. | Here's an example of all inputs in action: diff --git a/cypress/integration/clicking.spec.ts b/cypress/integration/clicking.spec.ts index 472b82a..62a287b 100644 --- a/cypress/integration/clicking.spec.ts +++ b/cypress/integration/clicking.spec.ts @@ -3,6 +3,7 @@ import { DEFAULT_CONFIG } from '../../projects/ngx-drag-to-select/src/lib/config import { disableRangeSelection, disableSelectOnDrag, + enableAdditive, enableSelectWithShortcut, getDesktopExample, toggleItem @@ -233,4 +234,38 @@ describe('Clicking', () => { }); }); }); + + describe('Select with Additive', () => { + beforeEach(() => { + enableAdditive(); + }); + + it('should add item to selection if clicked', () => { + getDesktopExample().within(() => { + cy.getSelectItem(0) + .dispatch('mousedown', { button: 0 }) + .dispatch('mouseup') + .getSelectItem(1) + .dispatch('mousedown', { button: 0 }) + .dispatch('mouseup') + .shouldSelect([1, 2]); + }); + }); + + it('should remove the item if clicked', () => { + getDesktopExample().within(() => { + cy.getSelectItem(0) + .dispatch('mousedown', { button: 0 }) + .dispatch('mouseup') + .getSelectItem(1) + .dispatch('mousedown', { button: 0 }) + .dispatch('mouseup') + .shouldSelect([1, 2]) + .getSelectItem(0) + .dispatch('mousedown', { button: 0 }) + .dispatch('mouseup') + .shouldSelect([2]); + }); + }); + }); }); diff --git a/cypress/integration/dragging.spec.ts b/cypress/integration/dragging.spec.ts index c4bc6cd..2875d95 100644 --- a/cypress/integration/dragging.spec.ts +++ b/cypress/integration/dragging.spec.ts @@ -389,12 +389,7 @@ describe('Dragging', () => { .getSelectItem(2) .dispatch('mousedown', { button: 0 }) .getSelectItem(7) - .as('end') .dispatch('mousemove') - .shouldSelect([1, 2, 5, 6]) - .get(`.${SELECTED_CLASS}`) - .should('have.length', 8) - .get('@end') .dispatch('mouseup') .shouldSelect([1, 2, 3, 4, 5, 6, 7, 8]) .get(`.${SELECTED_CLASS}`) diff --git a/projects/ngx-drag-to-select/src/lib/select-container.component.ts b/projects/ngx-drag-to-select/src/lib/select-container.component.ts index a727752..43de814 100644 --- a/projects/ngx-drag-to-select/src/lib/select-container.component.ts +++ b/projects/ngx-drag-to-select/src/lib/select-container.component.ts @@ -467,7 +467,7 @@ export class SelectContainerComponent implements AfterViewInit, OnDestroy, After const itemRect = item.getBoundingClientRect(); const withinBoundingBox = inBoundingBox(mousePoint, itemRect); - if ((this.shortcuts.extendedSelectionShortcut(event) && this.disableRangeSelection) || this.additive) { + if (this.shortcuts.extendedSelectionShortcut(event) && this.disableRangeSelection /* || this.additive*/) { return; } @@ -483,25 +483,27 @@ export class SelectContainerComponent implements AfterViewInit, OnDestroy, After (withinBoundingBox && !this.shortcuts.toggleSingleItem(event) && !this.selectMode && + !this.additive && !this.selectWithShortcut) || (this.shortcuts.extendedSelectionShortcut(event) && item.selected && !this._lastRangeSelection.get(item)) || withinRange || (withinBoundingBox && this.shortcuts.toggleSingleItem(event) && !item.selected) || (!withinBoundingBox && this.shortcuts.toggleSingleItem(event) && item.selected) || - (withinBoundingBox && !item.selected && this.selectMode) || - (!withinBoundingBox && item.selected && this.selectMode); + (withinBoundingBox && !item.selected && (this.selectMode || this.additive)) || + (!withinBoundingBox && item.selected && (this.selectMode || this.additive)); const shouldRemove = (!withinBoundingBox && !this.shortcuts.toggleSingleItem(event) && !this.selectMode && - (!this.shortcuts.extendedSelectionShortcut(event) || this.additive) && + !this.additive && + !this.shortcuts.extendedSelectionShortcut(event) && !this.selectWithShortcut) || (this.shortcuts.extendedSelectionShortcut(event) && currentIndex > -1) || (!withinBoundingBox && this.shortcuts.toggleSingleItem(event) && !item.selected) || (withinBoundingBox && this.shortcuts.toggleSingleItem(event) && item.selected) || - (!withinBoundingBox && !item.selected && this.selectMode) || - (withinBoundingBox && item.selected && this.selectMode); + (!withinBoundingBox && !item.selected && (this.selectMode || this.additive)) || + (withinBoundingBox && item.selected && (this.selectMode || this.additive)); if (shouldAdd) { this._selectItem(item); @@ -541,17 +543,20 @@ export class SelectContainerComponent implements AfterViewInit, OnDestroy, After } private _isExtendedSelection(event: Event) { - return (this.shortcuts.extendedSelectionShortcut(event) && this.selectOnDrag) || this.additive; + return this.shortcuts.extendedSelectionShortcut(event) && this.selectOnDrag; } private _normalSelectionMode(selectBox: BoundingBox, item: SelectItemDirective, event: Event) { const inSelection = boxIntersects(selectBox, item.getBoundingClientRect()); - const shouldAdd = inSelection && !item.selected && !this.shortcuts.removeFromSelection(event); + const shouldAdd = + (inSelection && !item.selected && !this.shortcuts.removeFromSelection(event)) || + (this.additive && ((inSelection && !item.selected) || (!inSelection && item.selected))); const shouldRemove = (!inSelection && item.selected && !this.shortcuts.addToSelection(event)) || - (inSelection && item.selected && this.shortcuts.removeFromSelection(event)); + (inSelection && item.selected && this.shortcuts.removeFromSelection(event)) || + (this.additive && !inSelection && !item.selected); if (shouldAdd) { this._selectItem(item); @@ -563,7 +568,7 @@ export class SelectContainerComponent implements AfterViewInit, OnDestroy, After private _extendedSelectionMode(selectBox, item: SelectItemDirective, event: Event) { const inSelection = boxIntersects(selectBox, item.getBoundingClientRect()); - const shoudlAdd = + const shouldAdd = (inSelection && !item.selected && !this.shortcuts.removeFromSelection(event) && !this._tmpItems.has(item)) || (inSelection && item.selected && this.shortcuts.removeFromSelection(event) && !this._tmpItems.has(item)); @@ -571,7 +576,7 @@ export class SelectContainerComponent implements AfterViewInit, OnDestroy, After (!inSelection && item.selected && this.shortcuts.addToSelection(event) && this._tmpItems.has(item)) || (!inSelection && !item.selected && this.shortcuts.removeFromSelection(event) && this._tmpItems.has(item)); - if (shoudlAdd) { + if (shouldAdd) { item.selected ? item._deselect() : item._select(); const action = this.shortcuts.removeFromSelection(event) From 97e1cffa7be3433539a5e783a7f22cb65c86389c Mon Sep 17 00:00:00 2001 From: vascocc Date: Sun, 1 Dec 2019 22:07:16 +0000 Subject: [PATCH 3/3] feat(lib): add additive behavior Code cleaning. --- .../ngx-drag-to-select/src/lib/select-container.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/ngx-drag-to-select/src/lib/select-container.component.ts b/projects/ngx-drag-to-select/src/lib/select-container.component.ts index 43de814..3c46f27 100644 --- a/projects/ngx-drag-to-select/src/lib/select-container.component.ts +++ b/projects/ngx-drag-to-select/src/lib/select-container.component.ts @@ -467,7 +467,7 @@ export class SelectContainerComponent implements AfterViewInit, OnDestroy, After const itemRect = item.getBoundingClientRect(); const withinBoundingBox = inBoundingBox(mousePoint, itemRect); - if (this.shortcuts.extendedSelectionShortcut(event) && this.disableRangeSelection /* || this.additive*/) { + if (this.shortcuts.extendedSelectionShortcut(event) && this.disableRangeSelection) { return; }