Skip to content

Commit

Permalink
feat(selection): auto-scroll the viewport when dragging with selection
Browse files Browse the repository at this point in the history
- implements latest SlickGrid [PR #656](6pac/SlickGrid#656) to auto-scroll when making cell or row selection
  • Loading branch information
ghiscoding committed Dec 18, 2021
1 parent e89ba3e commit ecd9c57
Show file tree
Hide file tree
Showing 16 changed files with 979 additions and 61 deletions.
1 change: 1 addition & 0 deletions examples/webpack-demo-vanilla-bundle/src/app-routing.ts
Expand Up @@ -20,6 +20,7 @@ export class AppRouting {
{ route: 'example14', name: 'example14', title: 'Example14', moduleId: './examples/example14' },
{ route: 'example15', name: 'example15', title: 'Example15', moduleId: './examples/example15' },
{ route: 'example16', name: 'example16', title: 'Example16', moduleId: './examples/example16' },
{ route: 'example17', name: 'example17', title: 'Example17', moduleId: './examples/example17' },
{ route: 'icons', name: 'icons', title: 'icons', moduleId: './examples/icons' },
{ route: '', redirect: 'example01' },
{ route: '**', redirect: 'example01' }
Expand Down
5 changes: 4 additions & 1 deletion examples/webpack-demo-vanilla-bundle/src/app.html
Expand Up @@ -12,7 +12,7 @@ <h4 class="title is-4 has-text-white">Slickgrid-Universal</h4>
</div>

<a role="button" class="navbar-burger burger" aria-label="menu" aria-expanded="false"
data-target="navbarBasicExample">
data-target="navbarBasicExample">
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
Expand Down Expand Up @@ -75,6 +75,9 @@ <h4 class="title is-4 has-text-white">Slickgrid-Universal</h4>
<a class="navbar-item" onclick.delegate="loadRoute('example16')">
Example16 - Regular & Custom Tooltips
</a>
<a class="navbar-item" onclick.delegate="loadRoute('example17')">
Example17 - Auto-Scroll for Selector
</a>
</div>
</div>
</div>
Expand Down
50 changes: 50 additions & 0 deletions examples/webpack-demo-vanilla-bundle/src/examples/example17.html
@@ -0,0 +1,50 @@
<h3 class="title is-3">Example 17 - Auto-Scroll with Range Selector
<span class="subtitle">(with Salesforce Theme)</span>
<div class="subtitle" style="float: right; margin-top: -20px">
<a class="is-size-5" target="_blank"
href="https://github.com/ghiscoding/slickgrid-universal/blob/master/examples/webpack-demo-vanilla-bundle/src/examples/example01.ts">
<span class="mdi mdi-link mdi-v-align-sub"></span> code
</a>
</div>
</h3>

<div style="min-height: 750px">
<div class="row scroll-configs">
<span>
<label for="min-internal">MIN interval to show next cell (ms): </label>
<input id="min-internal" type="number" data-test="min-interval-input" value.bind="minInterval" />
<label for="max-internal" style="margin-left: 15px;">MAX delay to show next cell (ms): </label>
<input id="max-internal" type="number" data-test="max-interval-input" value.bind="maxInterval" />
<label for="delay-cursor" style="margin-left: 15px;">Delay when cursor outside 1px (ms): </label>
<input id="delay-cursor" type="number" data-test="delay-cursor-input" value.bind="delayCursor" />
</span>
</div>
<div class="row" style="margin-bottom: 15px;">
<label for="is-autoscroll">Auto Scroll: (need click Set Options): </label>
<input id="is-autoscroll" type="checkbox" data-test="is-autoscroll-chk" checked.bind="isAutoScroll" />

<span style="margin-left: 20px;">
<button class="btn btn-default btn-xs" data-test="default-options-btn" onclick.delegate="setOptions()">
Set Options
</button>
<button class="btn btn-default btn-xs" data-test="default-options-btn" onclick.delegate="setDefaultOptions()">
Set Default Options
</button>
<button class="btn btn-default btn-xs" data-test="set-clear-frozen-btn" onclick.delegate="toggleFrozen()">
Set/Clear Frozen
</button>
</span>
</div>

<h5 class="title is-5">Grid 1 - Using "SlickCellRangeSelector"</h5>
<div class="grid1">
</div>

<div class="column is-half">
<hr style="margin: 16px 0" />
</div>

<h5 class="title is-5">Grid 2 - Using "SlickRowSelectionModel"</h5>
<div class="grid2">
</div>
</div>
34 changes: 34 additions & 0 deletions examples/webpack-demo-vanilla-bundle/src/examples/example17.scss
@@ -0,0 +1,34 @@
$control-height: 2.4em;
@import 'bulma/bulma';

.scroll-configs input {
width: 50px;
}
.cell-effort-driven {
text-align: center;
}
.slick-group-title[level='0'] {
font-weight: bold;
}
.slick-group-title[level='1'] {
text-decoration: underline;
}
.slick-group-title[level='2'] {
font-style: italic;
}
.slick-row:not(.slick-group) >.cell-unselectable {
background: #efefef;
}
.slick-row .slick-cell.frozen:last-child,
.slick-header-column.frozen:last-child,
.slick-headerrow-column.frozen:last-child,
.slick-footerrow-column.frozen:last-child {
border-right: 1px solid red;
}

.slick-row.frozen:last-child .slick-cell {
border-bottom: 1px solid red;
}
.option-item {
padding: 6px;
}
156 changes: 156 additions & 0 deletions examples/webpack-demo-vanilla-bundle/src/examples/example17.ts
@@ -0,0 +1,156 @@
import { Column, Formatters, GridOption, SlickCellRangeSelector, SlickCellSelectionModel, SlickRowSelectionModel } from '@slickgrid-universal/common';
import { Slicker, SlickVanillaGridBundle } from '@slickgrid-universal/vanilla-bundle';
import { ExampleGridOptions } from './example-grid-options';

// use any of the Styling Theme
import '../material-styles.scss';
// import '../salesforce-styles.scss';
import './example17.scss';

const NB_ITEMS = 995;

export class Example17 {
gridOptions1: GridOption;
gridOptions2: GridOption;
columnDefinitions1: Column[];
columnDefinitions2: Column[];
dataset1: any[];
dataset2: any[];
sgb1: SlickVanillaGridBundle;
sgb2: SlickVanillaGridBundle;
isAutoScroll = true;
minInterval = 30;
maxInterval = 600;
delayCursor = 5;

attached() {
this.defineGrids();

// mock some data (different in each dataset)
this.dataset1 = this.mockData(NB_ITEMS);
this.dataset2 = this.mockData(NB_ITEMS);

this.sgb1 = new Slicker.GridBundle(document.querySelector<HTMLDivElement>(`.grid1`), this.columnDefinitions1, { ...ExampleGridOptions, ...this.gridOptions1 }, this.dataset1);
this.sgb2 = new Slicker.GridBundle(document.querySelector<HTMLDivElement>(`.grid2`), this.columnDefinitions2, { ...ExampleGridOptions, ...this.gridOptions2 }, this.dataset2);

this.setOptions();
}

dispose() {
this.sgb1?.dispose();
this.sgb2?.dispose();
}

/* Define grid Options and Columns */
defineGrids() {
this.columnDefinitions1 = [
{ id: 'title', name: 'Title', field: 'title', sortable: true, minWidth: 100, filterable: true },
{ id: 'duration', name: 'Duration', field: 'duration', sortable: true, minWidth: 100, filterable: true },
{ id: '%', name: '% Complete', field: 'percentComplete', sortable: true, minWidth: 100, filterable: true, formatter: Formatters.percentCompleteBar },
{ id: 'start', name: 'Start', field: 'start', formatter: Formatters.dateIso, minWidth: 120, exportWithFormatter: true, filterable: true },
{ id: 'finish', name: 'Finish', field: 'finish', formatter: Formatters.dateIso, minWidth: 120, exportWithFormatter: true, filterable: true },
{ id: 'cost', name: 'Cost', field: 'cost', formatter: Formatters.dollar, minWidth: 75, exportWithFormatter: true, filterable: true },
{ id: 'effort-driven', name: 'Effort Driven', field: 'effortDriven', formatter: Formatters.checkmarkMaterial, sortable: true, minWidth: 75, filterable: true }
];

for (let i = 0; i < 30; i++) {
this.columnDefinitions1.push({ id: `mock${i}`, name: `Mock${i}`, field: `mock${i}`, minWidth: 75 });
}

this.gridOptions1 = {
enableAutoResize: false,
enableCellNavigation: true,
gridHeight: 225,
gridWidth: 800,
rowHeight: 33,
// enableExcelCopyBuffer: true,
};

// copy the same Grid Options and Column Definitions to 2nd grid
this.columnDefinitions2 = this.columnDefinitions1;
this.gridOptions2 = {
...this.gridOptions1,
...{
enableCheckboxSelector: true,
// enableExcelCopyBuffer: false,
gridHeight: 255,
}
};
}

mockData(count: number) {
// mock a dataset
const mockDataset = [];
for (let i = 0; i < count; i++) {
const randomYear = 2000 + Math.floor(Math.random() * 10);
const randomMonth = Math.floor(Math.random() * 11);
const randomDay = Math.floor((Math.random() * 29));
const randomPercent = Math.round(Math.random() * 100);

mockDataset[i] = {
id: i,
title: 'Task ' + i,
duration: Math.round(Math.random() * 100) + '',
percentComplete: randomPercent,
start: new Date(randomYear, randomMonth + 1, randomDay),
finish: new Date(randomYear + 1, randomMonth + 1, randomDay),
cost: Math.round(Math.random() * 10000) / 100,
effortDriven: (i % 5 === 0)
};
for (let j = 0; j < 30; j++) {
mockDataset[i]['mock' + j] = j;
}
}

return mockDataset;
}

toggleFrozen() {
const option = this.sgb1.slickGrid.getOptions();
const frozenRow = option.frozenRow;
const frozenColumn = option.frozenColumn;
const newOption = {
frozenColumn: frozenColumn === -1 ? 1 : -1,
frozenRow: frozenRow === -1 ? 3 : -1
};
this.sgb1.slickGrid.setOptions(newOption);
this.sgb2.slickGrid.setOptions(newOption);
}

setDefaultOptions() {
this.isAutoScroll = true;
this.minInterval = 30;
this.maxInterval = 600;
this.delayCursor = 5;
this.setOptions();
}

setOptions() {
this.sgb1.slickGrid.setSelectionModel(new SlickCellSelectionModel({
selectActiveCell: true,
cellRangeSelector: new SlickCellRangeSelector({
selectionCss: {
border: '2px dashed #01b83b'
} as CSSStyleDeclaration,
autoScroll: this.isAutoScroll,
minIntervalToShowNextCell: +this.minInterval,
maxIntervalToShowNextCell: +this.maxInterval,
accelerateInterval: +this.delayCursor
})
}));

this.sgb2.slickGrid.setSelectionModel(new SlickRowSelectionModel({
cellRangeSelector: new SlickCellRangeSelector({
selectionCss: {
border: 'none'
} as CSSStyleDeclaration,
autoScroll: this.isAutoScroll,
minIntervalToShowNextCell: +this.minInterval,
maxIntervalToShowNextCell: +this.maxInterval,
accelerateInterval: +this.delayCursor
})
}));
this.sgb1.slickGrid.invalidate();
this.sgb2.slickGrid.invalidate();
}
}

0 comments on commit ecd9c57

Please sign in to comment.