x-data-spreadsheet
Version:
a javascript xpreadsheet
408 lines (367 loc) • 10.5 kB
JavaScript
import { h } from './element';
import { cssPrefix } from '../config';
import { CellRange } from '../core/cell_range';
const selectorHeightBorderWidth = 2 * 2 - 1;
let startZIndex = 10;
class SelectorElement {
constructor(useHideInput = false) {
this.useHideInput = useHideInput;
this.inputChange = () => {};
this.cornerEl = h('div', `${cssPrefix}-selector-corner`);
this.areaEl = h('div', `${cssPrefix}-selector-area`)
.child(this.cornerEl).hide();
this.clipboardEl = h('div', `${cssPrefix}-selector-clipboard`).hide();
this.autofillEl = h('div', `${cssPrefix}-selector-autofill`).hide();
this.el = h('div', `${cssPrefix}-selector`)
.css('z-index', `${startZIndex}`)
.children(this.areaEl, this.clipboardEl, this.autofillEl)
.hide();
if (useHideInput) {
this.hideInput = h('input', '')
.on('compositionend', (evt) => {
this.inputChange(evt.target.value);
});
this.el.child(this.hideInputDiv = h('div', 'hide-input').child(this.hideInput));
this.el.child(this.hideInputDiv = h('div', 'hide-input').child(this.hideInput));
}
startZIndex += 1;
}
setOffset(v) {
this.el.offset(v).show();
return this;
}
hide() {
this.el.hide();
return this;
}
setAreaOffset(v) {
const {
left, top, width, height,
} = v;
const of = {
width: width - selectorHeightBorderWidth + 0.8,
height: height - selectorHeightBorderWidth + 0.8,
left: left - 0.8,
top: top - 0.8,
};
this.areaEl.offset(of).show();
if (this.useHideInput) {
this.hideInputDiv.offset(of);
this.hideInput.val('').focus();
}
}
setClipboardOffset(v) {
const {
left, top, width, height,
} = v;
this.clipboardEl.offset({
left,
top,
width: width - 5,
height: height - 5,
});
}
showAutofill(v) {
const {
left, top, width, height,
} = v;
this.autofillEl.offset({
width: width - selectorHeightBorderWidth,
height: height - selectorHeightBorderWidth,
left,
top,
}).show();
}
hideAutofill() {
this.autofillEl.hide();
}
showClipboard() {
this.clipboardEl.show();
}
hideClipboard() {
this.clipboardEl.hide();
}
}
function calBRAreaOffset(offset) {
const { data } = this;
const {
left, top, width, height, scroll, l, t,
} = offset;
const ftwidth = data.freezeTotalWidth();
const ftheight = data.freezeTotalHeight();
let left0 = left - ftwidth;
if (ftwidth > l) left0 -= scroll.x;
let top0 = top - ftheight;
if (ftheight > t) top0 -= scroll.y;
return {
left: left0,
top: top0,
width,
height,
};
}
function calTAreaOffset(offset) {
const { data } = this;
const {
left, width, height, l, t, scroll,
} = offset;
const ftwidth = data.freezeTotalWidth();
let left0 = left - ftwidth;
if (ftwidth > l) left0 -= scroll.x;
return {
left: left0, top: t, width, height,
};
}
function calLAreaOffset(offset) {
const { data } = this;
const {
top, width, height, l, t, scroll,
} = offset;
const ftheight = data.freezeTotalHeight();
let top0 = top - ftheight;
// console.log('ftheight:', ftheight, ', t:', t);
if (ftheight > t) top0 -= scroll.y;
return {
left: l, top: top0, width, height,
};
}
function setBRAreaOffset(offset) {
const { br } = this;
br.setAreaOffset(calBRAreaOffset.call(this, offset));
}
function setTLAreaOffset(offset) {
const { tl } = this;
tl.setAreaOffset(offset);
}
function setTAreaOffset(offset) {
const { t } = this;
t.setAreaOffset(calTAreaOffset.call(this, offset));
}
function setLAreaOffset(offset) {
const { l } = this;
l.setAreaOffset(calLAreaOffset.call(this, offset));
}
function setLClipboardOffset(offset) {
const { l } = this;
l.setClipboardOffset(calLAreaOffset.call(this, offset));
}
function setBRClipboardOffset(offset) {
const { br } = this;
br.setClipboardOffset(calBRAreaOffset.call(this, offset));
}
function setTLClipboardOffset(offset) {
const { tl } = this;
tl.setClipboardOffset(offset);
}
function setTClipboardOffset(offset) {
const { t } = this;
t.setClipboardOffset(calTAreaOffset.call(this, offset));
}
function setAllAreaOffset(offset) {
setBRAreaOffset.call(this, offset);
setTLAreaOffset.call(this, offset);
setTAreaOffset.call(this, offset);
setLAreaOffset.call(this, offset);
}
function setAllClipboardOffset(offset) {
setBRClipboardOffset.call(this, offset);
setTLClipboardOffset.call(this, offset);
setTClipboardOffset.call(this, offset);
setLClipboardOffset.call(this, offset);
}
export default class Selector {
constructor(data) {
this.inputChange = () => {};
this.data = data;
this.br = new SelectorElement(true);
this.t = new SelectorElement();
this.l = new SelectorElement();
this.tl = new SelectorElement();
this.br.inputChange = (v) => {
this.inputChange(v);
};
this.br.el.show();
this.offset = null;
this.areaOffset = null;
this.indexes = null;
this.range = null;
this.arange = null;
this.el = h('div', `${cssPrefix}-selectors`)
.children(
this.tl.el,
this.t.el,
this.l.el,
this.br.el,
).hide();
// for performance
this.lastri = -1;
this.lastci = -1;
startZIndex += 1;
}
resetData(data) {
this.data = data;
this.range = data.selector.range;
this.resetAreaOffset();
}
hide() {
this.el.hide();
}
resetOffset() {
const {
data, tl, t, l, br,
} = this;
const freezeHeight = data.freezeTotalHeight();
const freezeWidth = data.freezeTotalWidth();
if (freezeHeight > 0 || freezeWidth > 0) {
tl.setOffset({ width: freezeWidth, height: freezeHeight });
t.setOffset({ left: freezeWidth, height: freezeHeight });
l.setOffset({ top: freezeHeight, width: freezeWidth });
br.setOffset({ left: freezeWidth, top: freezeHeight });
} else {
tl.hide();
t.hide();
l.hide();
br.setOffset({ left: 0, top: 0 });
}
}
resetAreaOffset() {
// console.log('offset:', offset);
const offset = this.data.getSelectedRect();
const coffset = this.data.getClipboardRect();
setAllAreaOffset.call(this, offset);
setAllClipboardOffset.call(this, coffset);
this.resetOffset();
}
resetBRTAreaOffset() {
const offset = this.data.getSelectedRect();
const coffset = this.data.getClipboardRect();
setBRAreaOffset.call(this, offset);
setTAreaOffset.call(this, offset);
setBRClipboardOffset.call(this, coffset);
setTClipboardOffset.call(this, coffset);
this.resetOffset();
}
resetBRLAreaOffset() {
const offset = this.data.getSelectedRect();
const coffset = this.data.getClipboardRect();
setBRAreaOffset.call(this, offset);
setLAreaOffset.call(this, offset);
setBRClipboardOffset.call(this, coffset);
setLClipboardOffset.call(this, coffset);
this.resetOffset();
}
set(ri, ci, indexesUpdated = true) {
const { data } = this;
const cellRange = data.calSelectedRangeByStart(ri, ci);
const { sri, sci } = cellRange;
if (indexesUpdated) {
let [cri, cci] = [ri, ci];
if (ri < 0) cri = 0;
if (ci < 0) cci = 0;
data.selector.setIndexes(cri, cci);
this.indexes = [cri, cci];
}
this.moveIndexes = [sri, sci];
// this.sIndexes = sIndexes;
// this.eIndexes = eIndexes;
this.range = cellRange;
this.resetAreaOffset();
this.el.show();
}
setEnd(ri, ci, moving = true) {
const { data, lastri, lastci } = this;
if (moving) {
if (ri === lastri && ci === lastci) return;
this.lastri = ri;
this.lastci = ci;
}
this.range = data.calSelectedRangeByEnd(ri, ci);
setAllAreaOffset.call(this, this.data.getSelectedRect());
}
reset() {
// console.log('::::', this.data);
const { eri, eci } = this.data.selector.range;
this.setEnd(eri, eci);
}
showAutofill(ri, ci) {
if (ri === -1 && ci === -1) return;
// console.log('ri:', ri, ', ci:', ci);
// const [sri, sci] = this.sIndexes;
// const [eri, eci] = this.eIndexes;
const {
sri, sci, eri, eci,
} = this.range;
const [nri, nci] = [ri, ci];
// const rn = eri - sri;
// const cn = eci - sci;
const srn = sri - ri;
const scn = sci - ci;
const ern = eri - ri;
const ecn = eci - ci;
if (scn > 0) {
// left
// console.log('left');
this.arange = new CellRange(sri, nci, eri, sci - 1);
// this.saIndexes = [sri, nci];
// this.eaIndexes = [eri, sci - 1];
// data.calRangeIndexes2(
} else if (srn > 0) {
// top
// console.log('top');
// nri = sri;
this.arange = new CellRange(nri, sci, sri - 1, eci);
// this.saIndexes = [nri, sci];
// this.eaIndexes = [sri - 1, eci];
} else if (ecn < 0) {
// right
// console.log('right');
// nci = eci;
this.arange = new CellRange(sri, eci + 1, eri, nci);
// this.saIndexes = [sri, eci + 1];
// this.eaIndexes = [eri, nci];
} else if (ern < 0) {
// bottom
// console.log('bottom');
// nri = eri;
this.arange = new CellRange(eri + 1, sci, nri, eci);
// this.saIndexes = [eri + 1, sci];
// this.eaIndexes = [nri, eci];
} else {
// console.log('else:');
this.arange = null;
// this.saIndexes = null;
// this.eaIndexes = null;
return;
}
if (this.arange !== null) {
// console.log(this.saIndexes, ':', this.eaIndexes);
const offset = this.data.getRect(this.arange);
offset.width += 2;
offset.height += 2;
const {
br, l, t, tl,
} = this;
br.showAutofill(calBRAreaOffset.call(this, offset));
l.showAutofill(calLAreaOffset.call(this, offset));
t.showAutofill(calTAreaOffset.call(this, offset));
tl.showAutofill(offset);
}
}
hideAutofill() {
['br', 'l', 't', 'tl'].forEach((property) => {
this[property].hideAutofill();
});
}
showClipboard() {
const coffset = this.data.getClipboardRect();
setAllClipboardOffset.call(this, coffset);
['br', 'l', 't', 'tl'].forEach((property) => {
this[property].showClipboard();
});
}
hideClipboard() {
['br', 'l', 't', 'tl'].forEach((property) => {
this[property].hideClipboard();
});
}
}