- save & load

- key navigation
- ui improvements
This commit is contained in:
bkfox
2022-12-11 00:29:53 +01:00
parent cfc0e45439
commit 61af53eecb
10 changed files with 250 additions and 95 deletions

View File

@ -1,21 +1,22 @@
<template>
<tr>
<slot name="head" :item="item" :row="index"/>
<slot name="head" :item="item" :row="row"/>
<template v-for="(attr,col) in columns" :key="col">
<td :class="['cell', 'cell-' + attr]" :data-index="col"
<td :class="['cell', 'cell-' + attr]" :data-col="col"
:draggable="orderable"
@dragstart="onDragStart" @dragover="onDragOver" @drop="onDrop">
<slot :name="attr" :item="item" :row="index" :col="col"
<slot :name="attr" :item="item" :cell="cells[col]"
:data="itemData" :attr="attr" :emit="cellEmit"
:value="itemData && itemData[attr]">
{{ itemData && itemData[attr] }}
</slot>
</td>
</template>
<slot name="tail" :item="item" :row="index"/>
<slot name="tail" :item="item" :row="cell.row"/>
</tr>
</template>
<script>
import {isReactive, toRefs} from 'vue'
import Model from '../model'
export default {
@ -23,35 +24,48 @@ export default {
props: {
item: Object,
index: Number,
columns: Array,
cell: Object,
orderable: {type: Boolean, default: false},
},
computed: {
row() { return this.cell.row || 0 },
columns() { return this.cell.columns },
itemData() {
return this.item instanceof Model ? this.item.data : this.item;
},
cells() {
const cell = isReactive(this.cell) && toRefs(this.cell) || this.cell
const cells = []
for(var col in this.columns)
cells.push({...cell, col: Number(col)})
return cells
},
cellEls() {
return [...this.$el.querySelectorAll('td')].filter(x => x.dataset.col)
},
},
methods: {
/// Emit a 'cell' event.
/// Event data: `{index, name, data, item, attr}`
/// Event data: `{name, data, item, attr}`
///
/// @param {Number} col: cell column's index
/// @param {String} name: cell's event name
/// @param {} data: cell's event data
cellEmit(name, col, data) {
cellEmit(name, cell, data) {
this.$emit('cell', {
name, col, data,
name, cell, data,
item: this.item,
attr: this.columns[col],
})
},
onDragStart(ev) {
const dataset = ev.target.dataset;
const data = `cell:${dataset.index}`
const data = `cell:${dataset.col}`
ev.dataTransfer.setData("text/cell", data)
ev.dataTransfer.dropEffect = 'move'
},
@ -69,9 +83,27 @@ export default {
ev.preventDefault()
this.$emit('move', {
from: Number(data.slice(5)),
to: Number(ev.target.dataset.index),
to: Number(ev.target.dataset.col),
})
},
focus(col, from) {
if(from)
col += from.col
const target = this.cellEls[col]
if(!target)
return
const control = target.querySelector('input') ||
target.querySelector('button') ||
target.querySelector('select') ||
target.querySelector('a');
control && control.focus()
}
},
mounted() {
this.$el.__row = this
},
}