OXIESEC PANEL
- Current Dir:
/
/
var
/
www
/
reader
/
_backup
/
tinymce
/
tinymce
/
src
/
core
/
main
/
ts
/
keyboard
Server IP: 139.59.38.164
Upload:
Create Dir:
Name
Size
Modified
Perms
📁
..
-
02/20/2020 05:44:43 AM
rwxr-xr-x
📄
ArrowKeys.ts
2.28 KB
02/20/2020 05:43:50 AM
rw-r--r--
📄
BoundaryCaret.ts
2.59 KB
02/20/2020 05:43:50 AM
rw-r--r--
📄
BoundaryLocation.ts
6.56 KB
02/20/2020 05:43:51 AM
rw-r--r--
📄
BoundarySelection.ts
4.54 KB
02/20/2020 05:43:52 AM
rw-r--r--
📄
CefNavigation.ts
9.07 KB
02/20/2020 05:43:52 AM
rw-r--r--
📄
CefUtils.ts
2.54 KB
02/20/2020 05:43:53 AM
rw-r--r--
📄
ContentEndpointNavigation.ts
2.99 KB
02/20/2020 05:43:54 AM
rw-r--r--
📄
DeleteBackspaceKeys.ts
3.49 KB
02/20/2020 05:43:54 AM
rw-r--r--
📄
EnterKey.ts
1.29 KB
02/20/2020 05:43:55 AM
rw-r--r--
📄
FormatShortcuts.ts
886 bytes
02/20/2020 05:43:55 AM
rw-r--r--
📄
HomeEndKeys.ts
980 bytes
02/20/2020 05:43:56 AM
rw-r--r--
📄
InlineUtils.ts
3.26 KB
02/20/2020 05:43:56 AM
rw-r--r--
📄
InputKeys.ts
1.55 KB
02/20/2020 05:43:57 AM
rw-r--r--
📄
InsertSpace.ts
2.3 KB
02/20/2020 05:43:57 AM
rw-r--r--
📄
KeyboardOverrides.ts
1011 bytes
02/20/2020 05:43:58 AM
rw-r--r--
📄
MatchKeys.ts
1.64 KB
02/20/2020 05:43:58 AM
rw-r--r--
📄
Nbsps.ts
5.95 KB
02/20/2020 05:43:59 AM
rw-r--r--
📄
SpaceKey.ts
1 KB
02/20/2020 05:43:59 AM
rw-r--r--
📄
TableNavigation.ts
6.86 KB
02/20/2020 05:44:00 AM
rw-r--r--
Editing: TableNavigation.ts
Close
/** * Copyright (c) Tiny Technologies, Inc. All rights reserved. * Licensed under the LGPL or a commercial license. * For LGPL see License.txt in the project root for license information. * For commercial licenses see https://www.tiny.cloud/ */ import { HTMLElement, Range, Element } from '@ephox/dom-globals'; import { Arr, Option, Fun } from '@ephox/katamari'; import { Element as SugarElement, Attr, Insert } from '@ephox/sugar'; import CaretFinder from '../caret/CaretFinder'; import CaretPosition from '../caret/CaretPosition'; import * as CefUtils from './CefUtils'; import { getPositionsAbove, findClosestHorizontalPositionFromPoint, getPositionsBelow, getPositionsUntilPreviousLine, getPositionsUntilNextLine, BreakType, LineInfo } from '../caret/LineReader'; import { findClosestPositionInAboveCell, findClosestPositionInBelowCell } from '../caret/TableCells'; import ScrollIntoView from '../dom/ScrollIntoView'; import Editor from '../api/Editor'; import NodeType from '../dom/NodeType'; import Settings from '../api/Settings'; import { isFakeCaretTableBrowser } from '../caret/FakeCaret'; const moveToRange = (editor: Editor, rng: Range) => { editor.selection.setRng(rng); ScrollIntoView.scrollRangeIntoView(editor, rng); }; const hasNextBreak = (getPositionsUntil, scope: HTMLElement, lineInfo: LineInfo): boolean => { return lineInfo.breakAt.map((breakPos) => getPositionsUntil(scope, breakPos).breakAt.isSome()).getOr(false); }; const startsWithWrapBreak = (lineInfo: LineInfo) => lineInfo.breakType === BreakType.Wrap && lineInfo.positions.length === 0; const startsWithBrBreak = (lineInfo: LineInfo) => lineInfo.breakType === BreakType.Br && lineInfo.positions.length === 1; const isAtTableCellLine = (getPositionsUntil, scope: HTMLElement, pos: CaretPosition) => { const lineInfo = getPositionsUntil(scope, pos); // Since we can't determine if the caret is on the above or below line in a word wrap break we asume it's always // on the below/above line based on direction. This will make the caret jump one line if you are at the end of the last // line and moving down or at the beginning of the second line moving up. if (startsWithWrapBreak(lineInfo) || (!NodeType.isBr(pos.getNode()) && startsWithBrBreak(lineInfo))) { return !hasNextBreak(getPositionsUntil, scope, lineInfo); } else { return lineInfo.breakAt.isNone(); } }; const isAtFirstTableCellLine = Fun.curry(isAtTableCellLine, getPositionsUntilPreviousLine) as (scope: HTMLElement, pos: CaretPosition) => boolean; const isAtLastTableCellLine = Fun.curry(isAtTableCellLine, getPositionsUntilNextLine) as (scope: HTMLElement, pos: CaretPosition) => boolean; const isCaretAtStartOrEndOfTable = (forward: boolean, rng: Range, table: Element): boolean => { const caretPos = CaretPosition.fromRangeStart(rng); return CaretFinder.positionIn(!forward, table).map((pos) => pos.isEqual(caretPos)).getOr(false); }; const navigateHorizontally = (editor, forward: boolean, table: HTMLElement, td: HTMLElement): boolean => { const rng = editor.selection.getRng(); const direction = forward ? 1 : -1; if (isFakeCaretTableBrowser() && isCaretAtStartOrEndOfTable(forward, rng, table)) { const newRng = CefUtils.showCaret(direction, editor, table, !forward, true); moveToRange(editor, newRng); return true; } return false; }; const getClosestAbovePosition = (root: HTMLElement, table: HTMLElement, start: CaretPosition): CaretPosition => { return findClosestPositionInAboveCell(table, start).orThunk( () => { return Arr.head(start.getClientRects()).bind((rect) => { return findClosestHorizontalPositionFromPoint(getPositionsAbove(root, CaretPosition.before(table)), rect.left); }); } ).getOr(CaretPosition.before(table)); }; const getClosestBelowPosition = (root: HTMLElement, table: HTMLElement, start: CaretPosition): CaretPosition => { return findClosestPositionInBelowCell(table, start).orThunk( () => { return Arr.head(start.getClientRects()).bind((rect) => { return findClosestHorizontalPositionFromPoint(getPositionsBelow(root, CaretPosition.after(table)), rect.left); }); } ).getOr(CaretPosition.after(table)); }; const getTable = (previous: boolean, pos: CaretPosition): Option<HTMLElement> => { const node = pos.getNode(previous); return NodeType.isElement(node) && node.nodeName === 'TABLE' ? Option.some(node as HTMLElement) : Option.none(); }; const renderBlock = (down: boolean, editor: Editor, table: HTMLElement, pos: CaretPosition) => { const forcedRootBlock = Settings.getForcedRootBlock(editor); if (forcedRootBlock) { editor.undoManager.transact(() => { const element = SugarElement.fromTag(forcedRootBlock); Attr.setAll(element, Settings.getForcedRootBlockAttrs(editor)); Insert.append(element, SugarElement.fromTag('br')); if (down) { Insert.after(SugarElement.fromDom(table), element); } else { Insert.before(SugarElement.fromDom(table), element); } const rng = editor.dom.createRng(); rng.setStart(element.dom(), 0); rng.setEnd(element.dom(), 0); moveToRange(editor, rng); }); } else { moveToRange(editor, pos.toRange()); } }; const moveCaret = (editor: Editor, down: boolean, pos: CaretPosition) => { const table = down ? getTable(true, pos) : getTable(false, pos); const last = down === false; table.fold( () => moveToRange(editor, pos.toRange()), (table) => { return CaretFinder.positionIn(last, editor.getBody()).filter((lastPos) => lastPos.isEqual(pos)).fold( () => moveToRange(editor, pos.toRange()), (_) => renderBlock(down, editor, table, pos) ); } ); }; const navigateVertically = (editor, down: boolean, table: HTMLElement, td: HTMLElement): boolean => { const rng = editor.selection.getRng(); const pos = CaretPosition.fromRangeStart(rng); const root = editor.getBody(); if (!down && isAtFirstTableCellLine(td, pos)) { const newPos = getClosestAbovePosition(root, table, pos); moveCaret(editor, down, newPos); return true; } else if (down && isAtLastTableCellLine(td, pos)) { const newPos = getClosestBelowPosition(root, table, pos); moveCaret(editor, down, newPos); return true; } else { return false; } }; const moveH = (editor, forward: boolean) => () => { return Option.from(editor.dom.getParent(editor.selection.getNode(), 'td,th')).bind((td) => { return Option.from(editor.dom.getParent(td, 'table')).map((table) => { return navigateHorizontally(editor, forward, table, td); }); }).getOr(false); }; const moveV = (editor, forward: boolean) => () => { return Option.from(editor.dom.getParent(editor.selection.getNode(), 'td,th')).bind((td) => { return Option.from(editor.dom.getParent(td, 'table')).map((table) => { return navigateVertically(editor, forward, table, td); }); }).getOr(false); }; export { isFakeCaretTableBrowser, moveH, moveV };