Skip to content

Commit

Permalink
[#12455] Limit word and character count for text editor. (#12503)
Browse files Browse the repository at this point in the history
* Limit word and character count in text editor

* Fix snapshot testing and remove character limit

* Quick fix on word limit

* Fix snapshot test

* Change Word Count to Character Count

* Fix linting

* Update Snapshot test

* Change Character Count Limit

* Fix select all + paste bug

* Trauncate text and set cursor to end of pasted text

* Fix lint

---------

Co-authored-by: Dominic Lim <46486515+domlimm@users.noreply.github.com>
Co-authored-by: Wei Qing <48304907+weiquu@users.noreply.github.com>
  • Loading branch information
3 people committed Aug 3, 2023
1 parent 0a7f8aa commit 0976824
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,7 @@
[init]="init" [disabled]="isDisabled"
[ngModel]="richText" (ngModelChange)="richTextChange.emit($event)" [attr.placeholder]="placeholderText">
</editor>
<div *ngIf="hasCharacterLimit">
{{ RICH_TEXT_EDITOR_MAX_CHARACTER_LENGTH > characterCount ? RICH_TEXT_EDITOR_MAX_CHARACTER_LENGTH - characterCount : 0}} characters left
</div>
</div>
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { TINYMCE_BASE_URL } from './tinymce';

const RICH_TEXT_EDITOR_MAX_CHARACTER_LENGTH = 2000;

/**
* A rich text editor.
*/
Expand All @@ -11,9 +13,15 @@ import { TINYMCE_BASE_URL } from './tinymce';
})
export class RichTextEditorComponent implements OnInit {

// const
RICH_TEXT_EDITOR_MAX_CHARACTER_LENGTH: number = RICH_TEXT_EDITOR_MAX_CHARACTER_LENGTH;

@Input()
isDisabled: boolean = false;

@Input()
hasCharacterLimit: boolean = false;

@Input()
minHeightInPx: number = 150;

Expand All @@ -26,6 +34,8 @@ export class RichTextEditorComponent implements OnInit {
@Output()
richTextChange: EventEmitter<string> = new EventEmitter();

characterCount: number = 0;

// the argument passed to tinymce.init() in native JavaScript
init: any = {};

Expand Down Expand Up @@ -63,9 +73,64 @@ export class RichTextEditorComponent implements OnInit {
autoresize_bottom_margin: 50,

toolbar1: this.defaultToolbar,
setup: (editor:any) => {
if (this.hasCharacterLimit) {
editor.on('GetContent', () => {
setTimeout(() => {
this.characterCount = this.getCurrentCharacterCount(editor);
}, 0);
});
editor.on('keypress', (event:any) => {
const currentCharacterCount = this.getCurrentCharacterCount(editor);
if (currentCharacterCount >= RICH_TEXT_EDITOR_MAX_CHARACTER_LENGTH) {
event.preventDefault();
}
});
editor.on('paste', (event: any) => {
const contentBeforePasteEvent = editor.getContent({ format: 'text' });
setTimeout(() => {
const currentCharacterCount = this.getCurrentCharacterCount(editor);
if (currentCharacterCount >= RICH_TEXT_EDITOR_MAX_CHARACTER_LENGTH) {
event.preventDefault();
const contentAfterPasteEvent = editor.getContent({ format: 'text' });
let firstDifferentIndex = 0;
while (contentBeforePasteEvent[firstDifferentIndex] === contentAfterPasteEvent[firstDifferentIndex]) {
firstDifferentIndex += 1;
}
const contentBeforeFirstDifferentIndex = contentBeforePasteEvent.substring(0, firstDifferentIndex);
const contentAfterFirstDifferentIndex = contentBeforePasteEvent.substring(firstDifferentIndex);
const lengthExceed = currentCharacterCount - RICH_TEXT_EDITOR_MAX_CHARACTER_LENGTH;
const pasteContentLength = contentAfterPasteEvent.length - contentBeforePasteEvent.length;
const pasteContent = contentAfterPasteEvent.substring(
firstDifferentIndex,
firstDifferentIndex + pasteContentLength,
);
const truncatedPastedText = pasteContent.substring(0, pasteContentLength - lengthExceed);
const finalContent = contentBeforeFirstDifferentIndex + truncatedPastedText
+ contentAfterFirstDifferentIndex;
editor.setContent(finalContent);

// This sets the cursor to the end of the text.
const selection = editor.selection.getRng();
const newCursorPosition = firstDifferentIndex + truncatedPastedText.length;
const newRange = editor.dom.createRng();
newRange.setStart(selection.startContainer, newCursorPosition);
newRange.collapse(true);
editor.selection.setRng(newRange);
}
}, 0);
});
}
},
};
}

getCurrentCharacterCount(editor: any): number {
const wordCountApi = editor.plugins.wordcount;
const currentCharacterCount = wordCountApi.body.getCharacterCount();
return currentCharacterCount;
}

renderEditor(event: any): void {
// If the editor has not been rendered before, render it once it gets into the viewport
// However, do not destroy it when it gets out of the viewport
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ <h5>Or</h5>
<span class="ngb-tooltip-class" ngbTooltip="Will be displayed at the top of the page when users respond to the session.">Instructions</span>
</div>
<div class="col-md-10 text-md-start">
<tm-rich-text-editor id="instructions" [richText]="model.instructions" (richTextChange)="triggerModelChange('instructions', $event)" [isDisabled]="!model.isEditable"></tm-rich-text-editor>
<tm-rich-text-editor id="instructions" [richText]="model.instructions" (richTextChange)="triggerModelChange('instructions', $event)" [isDisabled]="!model.isEditable" [hasCharacterLimit]="true"></tm-rich-text-editor>
</div>
</div>
<br/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,9 @@ exports[`InstructorSessionEditPageComponent should snap with feedback session qu
<div
inviewport=""
>
<div>
2000 characters left
</div>
</div>
</tm-rich-text-editor>
</div>
Expand Down Expand Up @@ -3330,6 +3333,9 @@ exports[`InstructorSessionEditPageComponent should snap with new question added
<div
inviewport=""
>
<div>
2000 characters left
</div>
</div>
</tm-rich-text-editor>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,9 @@ exports[`InstructorSessionsPageComponent should snap when new session form is ex
<div
inviewport=""
>
<div>
2000 characters left
</div>
</div>
</tm-rich-text-editor>
</div>
Expand Down

0 comments on commit 0976824

Please sign in to comment.