From 19f377c31b6c1db550830d5492a05d5143392557 Mon Sep 17 00:00:00 2001 From: Vanessa Date: Sat, 13 Jan 2024 22:34:46 +0800 Subject: [PATCH] :art: https://github.com/siyuan-note/siyuan/issues/9867 --- app/appearance/langs/en_US.json | 1 + app/appearance/langs/es_ES.json | 1 + app/appearance/langs/fr_FR.json | 1 + app/appearance/langs/zh_CHT.json | 1 + app/appearance/langs/zh_CN.json | 1 + app/src/assets/scss/business/_av.scss | 16 +++++++ app/src/menus/protyle.ts | 5 +- app/src/protyle/gutter/index.ts | 5 +- app/src/protyle/render/av/action.ts | 5 +- app/src/protyle/render/av/cell.ts | 18 +++++++ app/src/protyle/wysiwyg/index.ts | 69 +++++++++++++++++++++++++-- 11 files changed, 114 insertions(+), 9 deletions(-) diff --git a/app/appearance/langs/en_US.json b/app/appearance/langs/en_US.json index 2fab29349..1628be966 100644 --- a/app/appearance/langs/en_US.json +++ b/app/appearance/langs/en_US.json @@ -1,4 +1,5 @@ { + "dragFill": "Drag vertically to fill value", "switchReadonly": "Switch read-only mode", "original": "Original", "selectRelation": "Please select the related column first", diff --git a/app/appearance/langs/es_ES.json b/app/appearance/langs/es_ES.json index 41bce7635..697c7a8cc 100644 --- a/app/appearance/langs/es_ES.json +++ b/app/appearance/langs/es_ES.json @@ -1,4 +1,5 @@ { + "dragFill": "Arrastra verticalmente para rellenar el valor", "switchReadonly": "Cambiar modo de sólo lectura", "original": "Original", "selectRelation": "Seleccione primero la columna relacionada", diff --git a/app/appearance/langs/fr_FR.json b/app/appearance/langs/fr_FR.json index 6099163b9..e2e75d275 100644 --- a/app/appearance/langs/fr_FR.json +++ b/app/appearance/langs/fr_FR.json @@ -1,4 +1,5 @@ { + "dragFill": "Arrastra verticalmente para rellenar el valor", "switchReadonly": "Changer de mode lecture seule", "original": "Originale", "selectRelation": "Veuillez d'abord sélectionner la colonne associée", diff --git a/app/appearance/langs/zh_CHT.json b/app/appearance/langs/zh_CHT.json index f7f7da567..d24e80774 100644 --- a/app/appearance/langs/zh_CHT.json +++ b/app/appearance/langs/zh_CHT.json @@ -1,4 +1,5 @@ { + "dragFill": "下拉填滿資料", "switchReadonly": "唯讀模式切換", "original": "原值", "selectRelation": "請先選擇關聯列", diff --git a/app/appearance/langs/zh_CN.json b/app/appearance/langs/zh_CN.json index 2343e1383..a17963734 100644 --- a/app/appearance/langs/zh_CN.json +++ b/app/appearance/langs/zh_CN.json @@ -1,4 +1,5 @@ { + "dragFill": "下拉填充数据", "switchReadonly": "只读模式切换", "original": "原值", "selectRelation": "请先选择关联列", diff --git a/app/src/assets/scss/business/_av.scss b/app/src/assets/scss/business/_av.scss index 53b9772dd..0eee48966 100644 --- a/app/src/assets/scss/business/_av.scss +++ b/app/src/assets/scss/business/_av.scss @@ -258,6 +258,10 @@ border-radius: var(--b3-border-radius); } + &--active { + background-color: var(--b3-menu-background); + } + .block__icon { position: absolute; right: 5px; @@ -275,6 +279,18 @@ } } + &__drag-fill { + position: absolute; + right: 0; + bottom: 0; + width: 9px; + height: 9px; + border: 2px solid var(--b3-theme-primary-lighter); + border-radius: 50%; + box-sizing: border-box; + cursor: ns-resize; + } + &__cellheader { padding: 5px; display: flex; diff --git a/app/src/menus/protyle.ts b/app/src/menus/protyle.ts index 3cc474be7..f17ab800b 100644 --- a/app/src/menus/protyle.ts +++ b/app/src/menus/protyle.ts @@ -1880,13 +1880,14 @@ export const setFold = (protyle: IProtyle, nodeElement: Element, isOpen?: boolea focusBlock(nodeElement, undefined, false); } } - nodeElement.querySelectorAll(".img--select, .av__cell--select, .av__row--select").forEach((item: HTMLElement) => { + nodeElement.querySelectorAll(".img--select, .av__cell--select, .av__cell--active, .av__row--select").forEach((item: HTMLElement) => { if (item.classList.contains("av__row--select")) { item.classList.remove("av__row--select"); item.querySelector(".av__firstcol use").setAttribute("xlink:href", "#iconUncheck"); updateHeader(item); } else { - item.classList.remove("img--select", "av__cell--select"); + item.querySelector(".av__drag-fill")?.remove(); + item.classList.remove("img--select", "av__cell--select", "av__cell--active"); } }); } diff --git a/app/src/protyle/gutter/index.ts b/app/src/protyle/gutter/index.ts index eda8c159c..a05a17c09 100644 --- a/app/src/protyle/gutter/index.ts +++ b/app/src/protyle/gutter/index.ts @@ -217,8 +217,9 @@ export class Gutter { return; } if (buttonElement.dataset.type === "NodeAttributeViewRow") { - blockElement.querySelectorAll(".av__cell--select").forEach((cellElement: HTMLElement) => { - cellElement.classList.remove("av__cell--select"); + blockElement.querySelectorAll(".av__cell--select, .av__cell--active").forEach((cellElement: HTMLElement) => { + cellElement.classList.remove("av__cell--select", "av__cell--active"); + cellElement.querySelector(".av__drag-fill")?.remove(); }); const avID = blockElement.getAttribute("data-av-id"); const srcIDs = [Lute.NewNodeID()]; diff --git a/app/src/protyle/render/av/action.ts b/app/src/protyle/render/av/action.ts index 40791e4d7..ab8b2fdc6 100644 --- a/app/src/protyle/render/av/action.ts +++ b/app/src/protyle/render/av/action.ts @@ -256,8 +256,9 @@ export const avContextmenu = (protyle: IProtyle, rowElement: HTMLElement, positi if (!blockElement) { return false; } - blockElement.querySelectorAll(".av__cell--select").forEach(item => { - item.classList.remove("av__cell--select"); + blockElement.querySelectorAll(".av__cell--select, .av__cell--active").forEach(item => { + item.classList.remove("av__cell--select", "av__cell--active"); + item.querySelector(".av__drag-fill")?.remove(); }); if (!rowElement.classList.contains("av__row--select")) { blockElement.querySelectorAll(".av__row--select").forEach(item => { diff --git a/app/src/protyle/render/av/cell.ts b/app/src/protyle/render/av/cell.ts index 1f53964a1..0c5be5c5c 100644 --- a/app/src/protyle/render/av/cell.ts +++ b/app/src/protyle/render/av/cell.ts @@ -647,3 +647,21 @@ export const updateHeaderCell = (cellElement: HTMLElement, headerValue: { } } }; + +export const getPositionByCellElement = (cellElement: HTMLElement) => { + let rowElement = hasClosestByClassName(cellElement, "av__row"); + if (!rowElement) { + return; + } + let rowIndex = -1; + while (rowElement) { + rowElement = rowElement.previousElementSibling as HTMLElement; + rowIndex++; + } + let celIndex = -2; + while (cellElement) { + cellElement = cellElement.previousElementSibling as HTMLElement; + celIndex++; + } + return {rowIndex, celIndex}; +} diff --git a/app/src/protyle/wysiwyg/index.ts b/app/src/protyle/wysiwyg/index.ts index 966e76c85..0b5d24f47 100644 --- a/app/src/protyle/wysiwyg/index.ts +++ b/app/src/protyle/wysiwyg/index.ts @@ -81,7 +81,7 @@ import {showColMenu} from "../render/av/col"; import {openViewMenu} from "../render/av/view"; import {avRender} from "../render/av/render"; import {checkFold} from "../../util/noRelyPCFunction"; -import {getCellText, updateCellsValue} from "../render/av/cell"; +import {getCellText, getPositionByCellElement, updateCellsValue} from "../render/av/cell"; export class WYSIWYG { public lastHTMLs: { [key: string]: string } = {}; @@ -89,6 +89,7 @@ export class WYSIWYG { public preventKeyup: boolean; private shiftStartElement: HTMLElement; + private preventClick: boolean; constructor(protyle: IProtyle) { this.element = document.createElement("div"); @@ -191,13 +192,14 @@ export class WYSIWYG { private setEmptyOutline(protyle: IProtyle, element: HTMLElement) { // 图片移除选择状态应放在前面,否则 https://github.com/siyuan-note/siyuan/issues/4173 - protyle.wysiwyg.element.querySelectorAll(".img--select, .av__cell--select, .av__row--select").forEach((item: HTMLElement) => { + protyle.wysiwyg.element.querySelectorAll(".img--select, .av__cell--select, .av__cell--active, .av__row--select").forEach((item: HTMLElement) => { if (item.classList.contains("av__row--select") && !hasClosestByClassName(element, "av")) { item.classList.remove("av__row--select"); item.querySelector(".av__firstcol use").setAttribute("xlink:href", "#iconUncheck"); updateHeader(item); } else { - item.classList.remove("img--select", "av__cell--select"); + item.classList.remove("img--select", "av__cell--select", "av__cell--active"); + item.querySelector(".av__drag-fill")?.remove(); } }); @@ -432,10 +434,67 @@ export class WYSIWYG { data: oldWidth + "px" }]); }; + this.preventClick = true; event.stopPropagation(); event.preventDefault(); return; } + // av cell select + const avCellElement = hasClosestByClassName(target, "av__cell"); + if (!protyle.disabled && avCellElement && avCellElement.dataset.id) { + const nodeElement = hasClosestBlock(avCellElement); + if (!nodeElement) { + return; + } + nodeElement.querySelectorAll(".av__cell--select").forEach(item => { + item.classList.remove("av__cell--select"); + }) + nodeElement.querySelectorAll(".av__drag-fill").forEach(item => { + item.remove(); + }) + avCellElement.classList.add("av__cell--select"); + const originIndex = getPositionByCellElement(avCellElement); + let moveCellElement: HTMLElement; + let lastCellElement: HTMLElement; + documentSelf.onmousemove = (moveEvent: MouseEvent) => { + const tempCellElement = hasClosestByClassName(moveEvent.target as HTMLElement, "av__cell") as HTMLElement; + if (moveCellElement && tempCellElement && tempCellElement.isSameNode(moveCellElement)) { + return; + } + moveCellElement = tempCellElement; + if (moveCellElement && moveCellElement.dataset.id && !avCellElement.isSameNode(moveCellElement)) { + const newIndex = getPositionByCellElement(moveCellElement); + nodeElement.querySelectorAll(".av__cell--active").forEach((item: HTMLElement) => { + item.classList.remove("av__cell--active"); + }) + nodeElement.querySelectorAll(".av__row").forEach((rowElement: HTMLElement, index: number) => { + if (index >= Math.min(originIndex.rowIndex, newIndex.rowIndex) && index <= Math.max(originIndex.rowIndex, newIndex.rowIndex)) { + rowElement.querySelectorAll(".av__cell").forEach((cellElement: HTMLElement, cellIndex: number) => { + if (cellIndex >= Math.min(originIndex.celIndex, newIndex.celIndex) && cellIndex <= Math.max(originIndex.celIndex, newIndex.celIndex)) { + cellElement.classList.add("av__cell--active"); + lastCellElement = cellElement; + } + }); + } + }) + } + }; + + documentSelf.onmouseup = () => { + documentSelf.onmousemove = null; + documentSelf.onmouseup = null; + documentSelf.ondragstart = null; + documentSelf.onselectstart = null; + documentSelf.onselect = null; + focusBlock(nodeElement); + lastCellElement.insertAdjacentHTML("beforeend", `
`) + return false; + }; + this.preventClick = true; + event.stopPropagation(); + event.preventDefault(); + return false; + } // 图片、iframe、video 缩放 if (!protyle.disabled && target.classList.contains("protyle-action__drag")) { const nodeElement = hasClosestBlock(target); @@ -1695,6 +1754,10 @@ export class WYSIWYG { }); this.element.addEventListener("click", (event: MouseEvent & { target: HTMLElement }) => { + if (this.preventClick) { + this.preventClick = false; + return; + } protyle.app.plugins.forEach(item => { item.eventBus.emit("click-editorcontent", { protyle,