Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Announce Plugin, add features to current plugin #2119

Merged
merged 35 commits into from
Oct 5, 2023
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
2bb535a
init
BryanValverdeU Sep 27, 2023
4e4a184
remove
BryanValverdeU Sep 27, 2023
0636a21
Merge branch 'master' of https://github.com/microsoft/roosterjs into …
BryanValverdeU Sep 27, 2023
3b80697
Fix type issues
BryanValverdeU Sep 27, 2023
8d9776a
add tests
BryanValverdeU Sep 27, 2023
509fe96
Fix build
BryanValverdeU Sep 27, 2023
3f8310a
Move logic from Editor to Plugin
BryanValverdeU Sep 28, 2023
d74c113
Add type to param
BryanValverdeU Sep 28, 2023
6d906c7
Merge branch 'master' into u/bvalverde/announceInRooster
BryanValverdeU Sep 28, 2023
4c63b7d
DefaultAnnounceString to KnownAnnounceStrings
BryanValverdeU Sep 28, 2023
282fe30
merge classes
BryanValverdeU Sep 29, 2023
5bde70a
Add more details in comments
BryanValverdeU Sep 29, 2023
a70eed0
Merge branch 'u/bvalverde/announceInRooster' of https://github.com/mi…
BryanValverdeU Sep 29, 2023
49639ab
Fix build
BryanValverdeU Sep 29, 2023
dd768ff
const enum
BryanValverdeU Sep 29, 2023
e074fb6
Merge branch 'master' into u/bvalverde/announceInRooster
BryanValverdeU Sep 29, 2023
609c097
fix
BryanValverdeU Sep 29, 2023
be5c532
Merge branch 'u/bvalverde/announceInRooster' of https://github.com/mi…
BryanValverdeU Sep 29, 2023
77e4259
init
BryanValverdeU Sep 29, 2023
b4e5d07
Add callback that returns string
BryanValverdeU Sep 29, 2023
9a58331
init2
BryanValverdeU Sep 29, 2023
fc4163a
Merge branch 'u/bvalverde/announceInRooster' of https://github.com/mi…
BryanValverdeU Sep 29, 2023
d4a8201
Merge branch 'u/bvalverde/announceInRooster' of https://github.com/mi…
BryanValverdeU Sep 29, 2023
99cb624
Merge branch 'u/bvalverde/announceInRooster1' of https://github.com/m…
BryanValverdeU Sep 29, 2023
9c076d3
Merge branch 'master' of https://github.com/microsoft/roosterjs into …
BryanValverdeU Oct 2, 2023
ae5d67c
Fix test after merge
BryanValverdeU Oct 2, 2023
3970517
Refactor
BryanValverdeU Oct 2, 2023
a036879
refactor
BryanValverdeU Oct 2, 2023
0fde998
Fix
BryanValverdeU Oct 2, 2023
b9010e1
Dispose editor
BryanValverdeU Oct 2, 2023
3c0da76
Move util from dom to plugin pkg & fix
BryanValverdeU Oct 5, 2023
8b426d2
Merge branch 'master' of https://github.com/microsoft/roosterjs into …
BryanValverdeU Oct 5, 2023
0e2f7c2
Merge branch 'master' into u/bvalverde/announceInRooster1
BryanValverdeU Oct 5, 2023
f3b1877
remove unneeded if
BryanValverdeU Oct 5, 2023
ac149ea
remove unneeded test
BryanValverdeU Oct 5, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions demo/scripts/controls/getToggleablePlugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,11 @@ export default function getToggleablePlugins(initState: BuildInPluginState) {

function getDefaultStringsMap(): Map<KnownAnnounceStrings, string> {
return new Map<KnownAnnounceStrings, string>([
[KnownAnnounceStrings.AnnounceListItemBulletIndentation, 'Autocorrected Bullet'],
[KnownAnnounceStrings.AnnounceListItemNumberingIndentation, 'Autocorrected {0}'],
[KnownAnnounceStrings.AnnounceListItemBullet, 'Autocorrected Bullet'],
[KnownAnnounceStrings.AnnounceListItemNumbering, 'Autocorrected {0}'],
[
KnownAnnounceStrings.AnnounceOnFocusLastCell,
'Warning, pressing tab here adds an extra row.',
],
]);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import convertDecimalsToAlpha from '../list/convertDecimalsToAlpha';
import convertDecimalsToRoman from '../list/convertDecimalsToRomans';
import safeInstanceOf from '../utils/safeInstanceOf';
import VList from '../list/VList';
import { KnownAnnounceStrings } from 'roosterjs-editor-types';
import type { AnnounceData } from 'roosterjs-editor-types';

/**
* Get the announce data for the current List
* @returns announce data for list or undefined.
*/
export default function getAnnounceDataForList(
list: HTMLElement | null,
li: HTMLElement | null
): AnnounceData | undefined {
if (!safeInstanceOf(li, 'HTMLLIElement')) {
return undefined;
}

if (li && safeInstanceOf(list, 'HTMLOListElement')) {
const vList = new VList(list);
const listItemIndex = vList.getListItemIndex(li);
let stringToAnnounce = listItemIndex == -1 ? '' : listItemIndex.toString();
switch (list.style.listStyleType) {
case 'lower-alpha':
case 'lower-latin':
case 'upper-alpha':
case 'upper-latin':
stringToAnnounce = convertDecimalsToAlpha(listItemIndex - 1);
break;
case 'lower-roman':
case 'upper-roman':
stringToAnnounce = convertDecimalsToRoman(listItemIndex);
break;
}

return {
defaultStrings: KnownAnnounceStrings.AnnounceListItemNumbering,
formatStrings: [stringToAnnounce],
};
} else if (safeInstanceOf(list, 'HTMLUListElement')) {
return {
defaultStrings: KnownAnnounceStrings.AnnounceListItemBullet,
};
}
return undefined;
}
4 changes: 2 additions & 2 deletions packages/roosterjs-editor-dom/lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export { default as getAnnounceDataForList } from './announceData/getAnnounceDataForList';

export { default as getBlockElementAtNode } from './blockElements/getBlockElementAtNode';
export { default as getFirstLastBlockElement } from './blockElements/getFirstLastBlockElement';

Expand Down Expand Up @@ -71,8 +73,6 @@ export { default as VList } from './list/VList';
export { default as VListItem } from './list/VListItem';
export { default as createVListFromRegion } from './list/createVListFromRegion';
export { default as VListChain } from './list/VListChain';
export { default as convertDecimalsToAlpha } from './list/convertDecimalsToAlpha';
export { default as convertDecimalsToRoman } from './list/convertDecimalsToRomans';
export { default as setListItemStyle } from './list/setListItemStyle';
export { getTableFormatInfo } from './table/tableFormatInfo';
export { saveTableCellMetadata } from './table/tableCellInfo';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import getAnnounceDataForList from '../../lib/announceData/getAnnounceDataForList';
import { createElement } from 'roosterjs-editor-dom';
import { KnownAnnounceStrings } from 'roosterjs-editor-types';

describe('getAnnounceDataForList', () => {
it('should return announce data for numbered list item | OL', () => {
const el = createElement(
{
tag: 'OL',
children: [
{
tag: 'LI',
children: ['asd'],
},
],
},
document
) as any;

el && document.body.appendChild(el);

const announceData = getAnnounceDataForList(el, el?.firstChild);
expect(announceData).toEqual({
defaultStrings: KnownAnnounceStrings.AnnounceListItemNumbering,
formatStrings: ['1'],
});
});

it('should return announce data for numbered list item | UL', () => {
const el = createElement(
{
tag: 'UL',
children: [
{
tag: 'LI',
children: ['asd'],
},
],
},
document
) as any;

el && document.body.appendChild(el);

const announceData = getAnnounceDataForList(el, el?.firstChild);
expect(announceData).toEqual({
defaultStrings: KnownAnnounceStrings.AnnounceListItemBullet,
});
});

it('should return announce data for bullet list item | undefined', () => {
const announceData = getAnnounceDataForList(null, null);
expect(announceData).toEqual(undefined);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { IEditor, AnnounceData } from 'roosterjs-editor-types';

/**
* Represents a Announce feature used in Announce Plugin.
* If the Should Handle Callback returns announce data, it will be announced by using a aria-live region.
*/
export interface AnnounceFeature {
/**
* Whether to handle this feature, if returns Announce Data, will be announced, otherwise will do nothing.
* @returns
*/
shouldHandle: (editor: IEditor, lastFocusedElement: HTMLElement | null) => AnnounceData | false;
/**
* Keys handled in the current event
*/
keys: number[];
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { createElement } from 'roosterjs-editor-dom';
import { AnnounceFeatures } from './features/AnnounceFeatures';
import { createElement, getObjectKeys } from 'roosterjs-editor-dom';
import { PluginEventType } from 'roosterjs-editor-types';
import type { AnnounceFeatureKey } from './features/AnnounceFeatures';
import type { AnnounceFeature } from './AnnounceFeature';
import type { CompatibleKnownAnnounceStrings } from 'roosterjs-editor-types/lib/compatibleTypes';
import type {
EditorPlugin,
IEditor,
PluginEvent,
AnnounceData,
PluginKeyDownEvent,
KnownAnnounceStrings,
} from 'roosterjs-editor-types';

Expand Down Expand Up @@ -36,13 +40,28 @@ const createAriaLiveElement = (document: Document): HTMLDivElement => {
export default class Announce implements EditorPlugin {
private ariaLiveElement: HTMLDivElement | undefined;
private editor: IEditor | undefined;
private features: AnnounceFeature[];
private lastFocusedElement: HTMLElement | null = null;

constructor(
private stringsMapOrGetter?:
| Map<CompatibleKnownAnnounceStrings | KnownAnnounceStrings, string>
| ((key: CompatibleKnownAnnounceStrings | KnownAnnounceStrings) => string)
| undefined
) {}
| Map<KnownAnnounceStrings | CompatibleKnownAnnounceStrings, string>
| ((key: KnownAnnounceStrings | CompatibleKnownAnnounceStrings) => string)
| undefined,
skipAnnounceFeatures: AnnounceFeatureKey[] = [],
additionalFeatures?: AnnounceFeature[]
) {
this.features = getObjectKeys(AnnounceFeatures)
.map(key => {
if (skipAnnounceFeatures.indexOf(key) == -1) {
return AnnounceFeatures[key];
}

return undefined;
})
.filter(feature => !!feature)
.concat(additionalFeatures || []) as AnnounceFeature[];
}

/**
* Get a friendly name of this plugin
Expand All @@ -65,23 +84,49 @@ export default class Announce implements EditorPlugin {
dispose() {
this.ariaLiveElement?.parentElement?.removeChild(this.ariaLiveElement);
this.ariaLiveElement = undefined;
this.stringsMapOrGetter = undefined;
this.lastFocusedElement = null;
while (this.features.length > 0) {
this.features.pop();
}
this.editor = undefined;
}

/**
* Handle events triggered from editor
* @param event PluginEvent object
*/
onPluginEvent(event: PluginEvent) {
onPluginEvent(ev: PluginEvent) {
if (
this.editor &&
event.eventType == PluginEventType.ContentChanged &&
event.additionalData?.getAnnounceData
ev.eventType == PluginEventType.ContentChanged &&
ev.additionalData?.getAnnounceData
) {
const data = event.additionalData.getAnnounceData();
const data = ev.additionalData.getAnnounceData();
if (data) {
this.announce(data, this.editor);
}
}

if (ev.eventType == PluginEventType.KeyDown && this.editor) {
this.handleFeatures(ev, this.editor);
}
}

private handleFeatures(event: PluginKeyDownEvent, editor: IEditor) {
editor.runAsync(() => {
this.features
.filter(feature => feature.keys.indexOf(event.rawEvent.which) > -1)
BryanValverdeU marked this conversation as resolved.
Show resolved Hide resolved
.some(feature => {
const announceData = feature.shouldHandle(editor, this.lastFocusedElement);
if (announceData) {
this.announce(announceData, editor);
}
return !!announceData;
});

this.lastFocusedElement = editor.getElementAtCursor();
});
}

protected announce(announceData: AnnounceData, editor: IEditor) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import announceNewListItemNumber from './announceNewListItem';
import announceWarningOnLastCell from './announceWarningOnLastTableCell';
import type { AnnounceFeature } from '../AnnounceFeature';

/**
* Announce feature keys
*/
export type AnnounceFeatureKey = 'announceNewListItem' | 'announceWarningOnLastTableCell';
/**
* @internal
*/
export const AnnounceFeatures: Record<AnnounceFeatureKey, AnnounceFeature> = {
announceNewListItem: announceNewListItemNumber,
announceWarningOnLastTableCell: announceWarningOnLastCell,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { getAnnounceDataForList } from 'roosterjs-editor-dom';
import { Keys } from 'roosterjs-editor-types';
import type { AnnounceFeature } from '../AnnounceFeature';

const LIST_SELECTOR = 'OL,UL';
const LIST_ITEM_SELECTOR = 'LI';

const announceNewListItemNumber: AnnounceFeature = {
keys: [Keys.ENTER],
shouldHandle: editor => {
const li = editor.getElementAtCursor(LIST_ITEM_SELECTOR);
const list = editor.getElementAtCursor(LIST_SELECTOR);
return (!!(list && li) && getAnnounceDataForList(list, li)) || false;
},
};

export default announceNewListItemNumber;
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { contains, safeInstanceOf } from 'roosterjs-editor-dom';
import { Keys, KnownAnnounceStrings, SelectionRangeTypes } from 'roosterjs-editor-types';
import type { AnnounceFeature } from '../AnnounceFeature';

const TABLE_CELL_SELECTOR = 'td,th';
const TABLE_SELECTOR = 'table';

const announceWarningOnLastCell: AnnounceFeature = {
shouldHandle: (editor, lastFocusedElement) => {
const selection = editor.getSelectionRangeEx();

return (
selection?.type == SelectionRangeTypes.Normal &&
selection.areAllCollapsed &&
selection.ranges.length === 1 &&
!contains(
lastFocusedElement,
selection.ranges[0].startContainer,
true /*treatSameNodeAsContain*/
) &&
isLastCell() && {
defaultStrings: KnownAnnounceStrings.AnnounceOnFocusLastCell,
}
);
function isLastCell(): boolean {
const table = editor.getElementAtCursor(TABLE_SELECTOR);

if (safeInstanceOf(table, 'HTMLTableElement')) {
const allCells = table.querySelectorAll(TABLE_CELL_SELECTOR);
const focusedCell = editor.getElementAtCursor(TABLE_CELL_SELECTOR);

return focusedCell == allCells.item(allCells.length - 1);
}
return false;
}
},
keys: [Keys.TAB, Keys.UP, Keys.DOWN, Keys.LEFT, Keys.RIGHT],
};

export default announceWarningOnLastCell;
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export { default as AnnouncePlugin } from './AnnouncePlugin';
export { AnnounceFeatureKey } from './features/AnnounceFeatures';
export { AnnounceFeature } from './AnnounceFeature';
Loading
Loading