Fixed bug and added atto handler
This commit is contained in:
@@ -58,7 +58,7 @@ function setUpMoodleGpt(config: Config) {
|
||||
const inputTypeQuery = ['checkbox', 'radio', 'text', 'number']
|
||||
.map(e => `input[type="${e}"]`)
|
||||
.join(',');
|
||||
const inputQuery = inputTypeQuery + ', textarea, select, [contenteditable]';
|
||||
const inputQuery = inputTypeQuery + ', textarea, select, [contenteditable], .qtype_essay_editor';
|
||||
const forms = document.querySelectorAll('.formulation');
|
||||
|
||||
// For each form we inject a function on the queqtion
|
||||
|
||||
@@ -16,6 +16,10 @@ function createAndNormalizeQuestion(questionContainer: HTMLElement) {
|
||||
for (const useless of accesshideElements) {
|
||||
question = question.replace(useless.innerText, '');
|
||||
}
|
||||
const attoText = questionContainer.querySelector('.qtype_essay_editor');
|
||||
if (attoText) {
|
||||
question = question.replace((attoText as HTMLElement).innerText, '');
|
||||
}
|
||||
|
||||
// Make tables more readable for chat-gpt
|
||||
const tables: NodeListOf<HTMLTableElement> = questionContainer.querySelectorAll('.qtext table');
|
||||
|
||||
@@ -7,6 +7,7 @@ import handleRadio from '@core/questions/radio';
|
||||
import handleCheckbox from '@core/questions/checkbox';
|
||||
import handleSelect from '@core/questions/select';
|
||||
import handleTextbox from '@core/questions/textbox';
|
||||
import handleAtto from '@core/questions/atto';
|
||||
|
||||
type Props = {
|
||||
config: Config;
|
||||
@@ -26,6 +27,7 @@ function autoCompleteMode(props: Props) {
|
||||
if (!props.config.infinite) props.removeListener();
|
||||
|
||||
const handlers = [
|
||||
handleAtto,
|
||||
handleContentEditable,
|
||||
handleTextbox,
|
||||
handleNumber,
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
import type Config from '@typing/config';
|
||||
import type GPTAnswer from '@typing/gpt-answer';
|
||||
|
||||
/**
|
||||
* Hanlde atto editor
|
||||
* See: https://docs.moodle.org/404/en/Atto_editor#Atto_accessibility
|
||||
* @param config
|
||||
* @param inputList
|
||||
* @param gptAnswer
|
||||
* @returns
|
||||
*/
|
||||
function handleAtto(
|
||||
config: Config,
|
||||
inputList: NodeListOf<HTMLElement>,
|
||||
gptAnswer: GPTAnswer
|
||||
): boolean {
|
||||
const input = inputList[0];
|
||||
|
||||
if (!input.classList.contains('qtype_essay_editor')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const iframe = input.querySelector('iframe');
|
||||
if (!iframe || !iframe.contentDocument || !iframe.contentDocument.body || !iframe.contentWindow) {
|
||||
return false;
|
||||
}
|
||||
const iframeBody = iframe.contentDocument.body;
|
||||
|
||||
const textContainer = iframeBody.querySelector('p');
|
||||
if (!textContainer) return false;
|
||||
|
||||
if (config.typing) {
|
||||
let index = 0;
|
||||
const eventHandler = function (event: KeyboardEvent) {
|
||||
event.preventDefault();
|
||||
|
||||
if (event.key === 'Backspace' || index >= gptAnswer.response.length) {
|
||||
iframe.contentWindow!.removeEventListener('keydown', eventHandler);
|
||||
return;
|
||||
}
|
||||
|
||||
// Append text one character at a time
|
||||
const textNode = document.createTextNode(gptAnswer.response.charAt(index++));
|
||||
textContainer.appendChild(textNode);
|
||||
|
||||
// Move the cursor after the last character
|
||||
const range = iframe.contentDocument!.createRange();
|
||||
range.selectNodeContents(textContainer);
|
||||
range.collapse(false); // Collapse the range to the end point
|
||||
const selection = iframe.contentWindow!.getSelection();
|
||||
if (selection) {
|
||||
selection.removeAllRanges();
|
||||
selection.addRange(range);
|
||||
}
|
||||
|
||||
iframe.contentWindow!.focus(); // Focus the iframe window to see cursor
|
||||
};
|
||||
|
||||
iframe.contentWindow.addEventListener('keydown', eventHandler);
|
||||
} else {
|
||||
textContainer.textContent += gptAnswer.response;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export default handleAtto;
|
||||
@@ -1,6 +1,11 @@
|
||||
import type Config from '@typing/config';
|
||||
import type GPTAnswer from '@typing/gpt-answer';
|
||||
|
||||
function isContentEditable(element: HTMLElement) {
|
||||
const contenteditable = element.getAttribute('contenteditable');
|
||||
return typeof contenteditable === 'string' && contenteditable !== 'false';
|
||||
}
|
||||
|
||||
/**
|
||||
* Hanlde contenteditable elements
|
||||
* @param config
|
||||
@@ -17,7 +22,7 @@ function handleContentEditable(
|
||||
|
||||
if (
|
||||
inputList.length !== 1 || // for now we don't handle many input for editable textcontent
|
||||
typeof input.getAttribute('contenteditable') !== 'string'
|
||||
!isContentEditable(input)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
@@ -28,7 +33,7 @@ function handleContentEditable(
|
||||
const eventHandler = function (event: KeyboardEvent) {
|
||||
event.preventDefault();
|
||||
|
||||
if (event.key === 'Backspace' || index > gptAnswer.response.length) {
|
||||
if (event.key === 'Backspace' || index >= gptAnswer.response.length) {
|
||||
input.removeEventListener('keydown', eventHandler);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ function handleNumber(
|
||||
|
||||
const eventHanlder = function (event: Event) {
|
||||
event.preventDefault();
|
||||
if ((<KeyboardEvent>event).key === 'Backspace' || index > number.length) {
|
||||
if ((<KeyboardEvent>event).key === 'Backspace' || index >= number.length) {
|
||||
input.removeEventListener('keydown', eventHanlder);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ function handleTextbox(
|
||||
const eventHandler = function (event: Event) {
|
||||
event.preventDefault();
|
||||
|
||||
if ((<KeyboardEvent>event).key === 'Backspace' || index > gptAnswer.response.length) {
|
||||
if ((<KeyboardEvent>event).key === 'Backspace' || index >= gptAnswer.response.length) {
|
||||
input.removeEventListener('keydown', eventHandler);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -104,6 +104,16 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Textbox -->
|
||||
<section class="formulation">
|
||||
<div class="qtext">
|
||||
<p>What is the name of the USA president ?</p>
|
||||
</div>
|
||||
<div>
|
||||
<input type="text" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Select -->
|
||||
<section class="formulation">
|
||||
<div class="qtext">
|
||||
|
||||
Reference in New Issue
Block a user