Added selection calculating

Todo: Move listeners from scroller (handlers)
This commit is contained in:
Eugene 2023-07-21 11:07:03 +03:00
parent 6df6413838
commit b4aa4a4b67
6 changed files with 76 additions and 12 deletions

View File

@ -12,6 +12,8 @@ export class Scroller {
private verticalScroller: HTMLDivElement private verticalScroller: HTMLDivElement
private horizontalScroller: HTMLDivElement private horizontalScroller: HTMLDivElement
private root: Spreadsheet private root: Spreadsheet
private isSelecting = false
constructor(root: Spreadsheet) { constructor(root: Spreadsheet) {
this.root = root this.root = root
@ -26,16 +28,45 @@ export class Scroller {
this.updateScrollerSize() //* Init size set this.updateScrollerSize() //* Init size set
this.element.addEventListener('scroll', this.handleScroll) this.element.addEventListener('scroll', this.handleScroll)
this.element.addEventListener('mousedown', this.handleClick)
this.element.addEventListener('mousemove', event => {
if(!this.isSelecting) return;
const {offsetX, offsetY} = event
const lastSelectedCell = this.root.getCellByCoords(offsetX, offsetY)
if(this.root.selection.selectedRange) {
this.root.selection.selectedRange.to = lastSelectedCell
}
})
this.element.addEventListener('mouseup', () => {
this.isSelecting = false
console.log(this.root.selection)
})
} }
handleScroll = () => { private handleClick = (event: MouseEvent) => {
const {offsetX, offsetY} = event
const clickedCell = this.root.getCellByCoords(offsetX, offsetY)
this.isSelecting = true
this.root.selection.selectedRange = {
from: clickedCell,
to: clickedCell
}
this.root.selection.selectedCell = clickedCell
this.root.renderSheet()
}
private handleScroll = () => {
const rect = this.getViewportBoundlingRect() const rect = this.getViewportBoundlingRect()
this.root.viewport.updateValues(rect) this.root.viewport.updateValues(rect)
this.root.renderSheet() this.root.renderSheet()
} }
getViewportBoundlingRect(): ViewportRect { public getViewportBoundlingRect(): ViewportRect {
const { scrollTop, scrollLeft } = this.element const { scrollTop, scrollLeft } = this.element
const { height, width } = this.element.getBoundingClientRect() const { height, width } = this.element.getBoundingClientRect()
const bottom = scrollTop + height const bottom = scrollTop + height
@ -49,7 +80,7 @@ export class Scroller {
} }
} }
buildComponent() { private buildComponent() {
const scroller = document.createElement('div') const scroller = document.createElement('div')
const verticalScroller = document.createElement('div') const verticalScroller = document.createElement('div')
const horizontalScroller = document.createElement('div') const horizontalScroller = document.createElement('div')
@ -74,14 +105,14 @@ export class Scroller {
return { scroller, verticalScroller, horizontalScroller } return { scroller, verticalScroller, horizontalScroller }
} }
getActualHeight() { private getActualHeight() {
return this.root.config.rows.reduce((acc, curr) => { return this.root.config.rows.reduce((acc, curr) => {
acc += curr.height acc += curr.height
return acc return acc
}, 0) }, 0)
} }
getActualWidth() { private getActualWidth() {
return this.root.config.columns.reduce((acc, curr) => { return this.root.config.columns.reduce((acc, curr) => {
acc += curr.width acc += curr.width
return acc return acc
@ -96,11 +127,11 @@ export class Scroller {
this.setScrollerWidth(totalWidth) this.setScrollerWidth(totalWidth)
} }
setScrollerHeight(height: number) { private setScrollerHeight(height: number) {
this.verticalScroller.style.height = height + 'px' this.verticalScroller.style.height = height + 'px'
} }
setScrollerWidth(width: number) { private setScrollerWidth(width: number) {
this.horizontalScroller.style.width = width + 'px' this.horizontalScroller.style.width = width + 'px'
} }
} }

View File

@ -27,6 +27,26 @@ export class Sheet {
} }
getCellByCoords(x: number, y: number): Position {
let row = 0;
let height = 0
while(height <= y) {
height += this.root.config.rows[row].height
if(height >= y) break;
row++;
}
let col = 0;
let width = 0;
while(width <= x) {
width += this.root.config.columns[col].width
if(width >= x) break;
col++;
}
return new Position(row, col)
}
renderCell(position: Position) { renderCell(position: Position) {
const {column, row} = position const {column, row} = position
this.root.data[row][column].render(this.root) this.root.data[row][column].render(this.root)

View File

@ -6,6 +6,7 @@ import { Table } from "./components/table";
import { Toolbar } from "./components/toolbar"; import { Toolbar } from "./components/toolbar";
import { Cell } from "./modules/cell"; import { Cell } from "./modules/cell";
import { Config, ViewProperties } from "./modules/config"; import { Config, ViewProperties } from "./modules/config";
import { Selection } from "./modules/selection";
import { Styles } from "./modules/styles"; import { Styles } from "./modules/styles";
import { Viewport } from "./modules/viewport"; import { Viewport } from "./modules/viewport";
import './scss/main.scss' import './scss/main.scss'
@ -39,6 +40,7 @@ export class Spreadsheet {
public config: Config public config: Config
public data: Cell[][] public data: Cell[][]
public viewport: Viewport public viewport: Viewport
public selection: Selection
constructor(target: string | HTMLElement, props?: SpreadsheetConstructorProperties) { constructor(target: string | HTMLElement, props?: SpreadsheetConstructorProperties) {
const config = createSampleConfig(750, 750) const config = createSampleConfig(750, 750)
@ -55,6 +57,7 @@ export class Spreadsheet {
this.header = new Header(this) this.header = new Header(this)
this.editor = new Editor(this) this.editor = new Editor(this)
this.viewport = new Viewport(this, this.scroller.getViewportBoundlingRect()) this.viewport = new Viewport(this, this.scroller.getViewportBoundlingRect())
this.selection = new Selection()
this.data = data this.data = data
@ -94,6 +97,10 @@ export class Spreadsheet {
return this.config.view return this.config.view
} }
getCellByCoords(x: number, y: number) {
return this.sheet.getCellByCoords(x, y)
}
renderSheet() { renderSheet() {
this.sheet.renderSheet() this.sheet.renderSheet()
} }

View File

@ -34,18 +34,19 @@ export class Cell {
let {height, width, x, y} = new RenderBox(root.config, this.position) let {height, width, x, y} = new RenderBox(root.config, this.position)
const { ctx } = root const { ctx } = root
const isCellSelected = (root.selection.selectedCell?.row === this.position.row && root.selection.selectedCell.column === this.position.column)
y -= root.viewport.top y -= root.viewport.top
x -= root.viewport.left x -= root.viewport.left
ctx.clearRect(x, y, width, height) ctx.clearRect(x, y, width, height)
ctx.fillStyle = 'white' ctx.fillStyle = isCellSelected ? 'red' : 'white'
ctx.strokeStyle = 'black' ctx.strokeStyle = 'black'
ctx.fillRect(x + 1, y + 1, width - 1, height - 1) ctx.fillRect(x, y, width - 1, height - 1)
ctx.strokeRect(x, y, width, height) ctx.strokeRect(x, y, width, height)
ctx.fillStyle = 'black' ctx.fillStyle = 'black'
ctx.textAlign = 'left' ctx.textAlign = 'left'
ctx.font = '16px Arial' ctx.font = `16px Arial`
ctx.textBaseline = 'middle' ctx.textBaseline = 'middle'
ctx.fillText(this.displayValue, x + 2, y + height / 2, width) ctx.fillText(this.displayValue, x + 2, y + height / 2, width)
} }

View File

@ -7,6 +7,7 @@ export class RenderBox {
width: number width: number
height: number height: number
constructor(config: Config, cellPosition: Position) { constructor(config: Config, cellPosition: Position) {
this.x = this.getXCoord(cellPosition.column, config) this.x = this.getXCoord(cellPosition.column, config)
this.y = this.getYCoord(cellPosition.row, config) this.y = this.getYCoord(cellPosition.row, config)
this.width = config.columns[cellPosition.column].width this.width = config.columns[cellPosition.column].width
@ -16,7 +17,7 @@ export class RenderBox {
private getXCoord(column: number, config: Config): number { private getXCoord(column: number, config: Config): number {
let x = 0; let x = 0;
for(let i = 0; i < column; i++) { for (let i = 0; i < column; i++) {
x += config.columns[i].width x += config.columns[i].width
} }
@ -25,7 +26,7 @@ export class RenderBox {
private getYCoord(row: number, config: Config): number { private getYCoord(row: number, config: Config): number {
let y = 0 let y = 0
for(let i = 0; i < row; i++) { for (let i = 0; i < row; i++) {
y += config.rows[i].height y += config.rows[i].height
} }
return y return y

View File

@ -1,3 +1,5 @@
.content { .content {
position: absolute; position: absolute;
top: 0; top: 0;
@ -5,7 +7,9 @@
} }
.spreadsheet_container { .spreadsheet_container {
position: relative;
isolation: isolate; isolation: isolate;
border: 2px solid black;
} }
.sheet{ .sheet{