From a50e3fe34be043e28a4ee0d107a5bd01c9a8cb18 Mon Sep 17 00:00:00 2001 From: mrfry Date: Tue, 18 May 2021 11:11:44 +0200 Subject: [PATCH] Script message window code refactor --- devel/testWrapper.js | 3 +- stable.user.js | 1114 +++++++++++++++--------------------------- 2 files changed, 406 insertions(+), 711 deletions(-) diff --git a/devel/testWrapper.js b/devel/testWrapper.js index 016f6cd..7e54981 100644 --- a/devel/testWrapper.js +++ b/devel/testWrapper.js @@ -23,8 +23,7 @@ // @version DEVEL // @description Online Moodle/Elearning/KMOOC test help // @author Yout -// @match https://elearning.uni-obuda.hu/main/* -// @match https://elearning.uni-obuda.hu/kmooc/* +// @match https://elearning.uni-obuda.hu/* // @match https://qmining.frylabs.net/* // @match http://qmining.frylabs.net/* // @match file:///* diff --git a/stable.user.js b/stable.user.js index 4f01ee6..160cd9e 100755 --- a/stable.user.js +++ b/stable.user.js @@ -46,7 +46,7 @@ // : Script header {{{ // ==UserScript== // @name Moodle/Elearning/KMOOC test help -// @version 2.1.1.1 +// @version 2.1.2.0 // @description Online Moodle/Elearning/KMOOC test help // @author MrFry // @match https://elearning.uni-obuda.hu/* @@ -74,7 +74,7 @@ // ==/UserScript== // : }}} -;(function() { +;(function () { // : ESLINT bs {{{ // eslint-disable-line @@ -110,29 +110,12 @@ // Devel vars // ------------------------------------------------------------------------------ // forcing pages for testing. unless you test, do not set these to true! -<<<<<<< Updated upstream - setVal('ISDEVEL', true) -||||||| constructed merge base const isDevel = false setVal('ISDEVEL', isDevel) -======= - const isDevel = true - setVal('ISDEVEL', isDevel) ->>>>>>> Stashed changes // only one of these should be true for testing -<<<<<<< Updated upstream - const forceTestPage = true - const forceResultPage = false - const forceDefaultPage = false -||||||| constructed merge base const forceTestPage = isDevel && false const forceResultPage = isDevel && false const forceDefaultPage = isDevel && false -======= - const forceTestPage = isDevel && true - const forceResultPage = isDevel && false - const forceDefaultPage = isDevel && false ->>>>>>> Stashed changes // ------------------------------------------------------------------------------ const logElementGetting = false @@ -169,29 +152,6 @@ ? 'https://elearning.uni-obuda.hu/' : location.href - const menuButtons = { - website: { - title: 'Weboldal', - onClick: () => { - openInTab(serverAdress + 'menuClick') - }, - }, - help: { - title: 'Help', - onClick: () => { - ShowHelp() - }, - }, - donate: { - title: 'Donate', - onClick: () => { - openInTab(serverAdress + 'donate?scriptMenu', { - active: true, - }) - }, - }, - } - // : Localisation {{{ const huTexts = { @@ -265,7 +225,7 @@ const select = elem.tagName ? elem.getElementsByTagName('select') : [] if (select.length > 0) { const question = [] - Array.from(elem.childNodes).forEach(cn => { + Array.from(elem.childNodes).forEach((cn) => { if (cn.nodeValue) { question.push(cn.nodeValue) } @@ -280,8 +240,8 @@ if (img.tagName === 'IMG') { promises.push( - new Promise(resolve => { - digestMessage(getBase64Image(img)).then(res => { + new Promise((resolve) => { + digestMessage(getBase64Image(img)).then((res) => { resolve({ type: 'img', val: res, @@ -327,7 +287,7 @@ function getLegacyImageID(imgArray) { try { - return imgArray.map(img => { + return imgArray.map((img) => { if (!img.src.includes('brokenfile')) { let filePart = img.src.split('/') filePart = filePart[filePart.length - 1] @@ -365,7 +325,7 @@ ) getQuizData() - .then(readQuestions => { + .then((readQuestions) => { if (readQuestions.length === 0) { ShowMessage( texts.unableToParseTestQuestion, @@ -380,7 +340,7 @@ return } - const questions = readQuestions.map(question => { + const questions = readQuestions.map((question) => { return { Q: question.question, possibleAnswers: question.possibleAnswers, @@ -399,7 +359,7 @@ log(sentData) - post('ask', sentData).then(results => { + post('ask', sentData).then((results) => { removeLoadingMessage() ShowAnswers( results.map((res, i) => { @@ -411,14 +371,14 @@ ) }) }) - .catch(err => { + .catch((err) => { warn(err) warn('Error in handleQuiz()') }) } function getQuizData() { - return new Promise(resolve => { + return new Promise((resolve) => { // TODO: dropdown in question // TODO: get possible answers too const promises = [] @@ -443,7 +403,7 @@ } Promise.all(promises) - .then(result => { + .then((result) => { const errorsRemoved = result.reduce((acc, res) => { if (res.success) { acc.push(res) @@ -452,7 +412,7 @@ }, []) resolve(errorsRemoved) }) - .catch(err => { + .catch((err) => { warn('Error in handleQuiz()') warn(err) }) @@ -481,7 +441,7 @@ const select = node.getElementsByTagName('select')[0] if (select) { const options = [] - Array.from(select).forEach(opt => { + Array.from(select).forEach((opt) => { if (!emptyOrWhiteSpace(opt.innerText)) { options.push([{ type: 'txt', val: opt.innerText }]) } @@ -492,7 +452,7 @@ } else if (answerRoot.tagName === 'DIV') { const answers = Array.from(answerRoot.childNodes) - answers.forEach(answer => { + answers.forEach((answer) => { if (answer.tagName) { promises.push(getTextPromisesFromNode(answer)) } @@ -502,7 +462,7 @@ } else if (answerRoot.tagName === 'TABLE') { const answers = Array.from(answerRoot.childNodes[0].childNodes) - answers.forEach(answer => { + answers.forEach((answer) => { if (answer.tagName) { promises.push( getTextPromisesFromNode(answer.getElementsByClassName('text')[0]) @@ -523,7 +483,7 @@ function getImgNodesFromArray(arr) { return arr.reduce((acc, x) => { if (Array.isArray(x)) { - x.forEach(y => { + x.forEach((y) => { if (y.type === 'img') { acc.push(y.node) } @@ -538,7 +498,7 @@ } function getQuestionPromiseForSingleQuestion(node) { - return new Promise(resolve => { + return new Promise((resolve) => { try { let qtextNode = node.getElementsByClassName('qtext')[0] if (!qtextNode) { @@ -550,7 +510,7 @@ const possibleAnswerPromises = getPossibleAnswersFromTest(node) const unflattenedPossibleAnswerPromises = possibleAnswerPromises - ? possibleAnswerPromises.map(x => { + ? possibleAnswerPromises.map((x) => { return Promise.all(x) }) : [] @@ -563,7 +523,7 @@ const questionText = removeUnnecesarySpaces( question.reduce(makeTextFromElements, []).join(' ') ) - const possibleAnswers = possibleAnswerArray.map(x => { + const possibleAnswers = possibleAnswerArray.map((x) => { return removeUnnecesarySpaces( x.reduce(makeTextFromElements, []).join(' ') ) @@ -582,13 +542,13 @@ resolve({ question: questionText, - possibleAnswers, - images, - data, + possibleAnswers: possibleAnswers, + images: images, + data: data, success: true, }) }) - .catch(err => { + .catch((err) => { warn('Error in getQuestionPromiseForSingleQuestion()') warn(err) resolve({ success: false }) @@ -605,7 +565,7 @@ if (hashedImages.length > 0) { return { type: 'image', - hashedImages: hashedImages.map(x => { + hashedImages: hashedImages.map((x) => { return x.val }), images: legacyImages, @@ -622,7 +582,7 @@ // : Result page processing functions {{{ function getQuiz() { - return new Promise(resolve => { + return new Promise((resolve) => { const promises = [] let questionNodes = Array.from( document.getElementsByTagName('form')[0].childNodes[0].childNodes @@ -640,7 +600,7 @@ } Promise.all(promises) - .then(result => { + .then((result) => { const errorsRemoved = result.reduce((acc, res) => { if (res.success) { acc.push(res) @@ -649,7 +609,7 @@ }, []) resolve(errorsRemoved) }) - .catch(err => { + .catch((err) => { warn('Error in getQuiz()') warn(err) }) @@ -658,7 +618,7 @@ function getPromisesThatMeetsRequirements(getters, node) { let res - Object.keys(getters).some(key => { + Object.keys(getters).some((key) => { const getter = getters[key] if (getter.requirement(node)) { try { @@ -676,7 +636,7 @@ } function getQuizFromNode(node) { - return new Promise(resolve => { + return new Promise((resolve) => { try { const questionPromises = getPromisesThatMeetsRequirements( questionGetters, @@ -713,7 +673,7 @@ result.data.possibleAnswers = possibleAnswers resolve(result) }) - .catch(err => { + .catch((err) => { warn('Error in getQuizFromNode()') warn(err) resolve({ success: false }) @@ -730,7 +690,7 @@ if (images && images.length > 0) { return { type: 'image', - hashedImages: images.map(x => { + hashedImages: images.map((x) => { return x.val }), } @@ -744,10 +704,10 @@ const questionGetters = { getSimpleQuestion: { description: 'Basic question getter', - requirement: node => { + requirement: (node) => { return node.getElementsByClassName('qtext').length > 0 }, - getterFunction: node => { + getterFunction: (node) => { const question = node.getElementsByClassName('qtext')[0] return getTextPromisesFromNode(question) }, @@ -757,23 +717,23 @@ const answerGetters = { getSimpleAnswer: { description: 'Basic answer getter', - requirement: node => { + requirement: (node) => { return node.getElementsByClassName('rightanswer').length > 0 }, - getterFunction: node => { + getterFunction: (node) => { const answer = node.getElementsByClassName('rightanswer')[0] return getTextPromisesFromNode(answer) }, }, noCorrect: { description: 'Gets correct answer, even if the correct is not shown', - requirement: node => { + requirement: (node) => { return ( node.getElementsByClassName('rightanswer').length === 0 && node.getElementsByClassName('answer').length > 0 ) }, - getterFunction: node => { + getterFunction: (node) => { const possibleAnswers = getPossibleAnswers(node) if (getIfSolutionIsCorrect(node)) { @@ -781,7 +741,7 @@ return [ { type: 'txt', - val: possibleAnswers.find(x => { + val: possibleAnswers.find((x) => { return x.selectedByUser === false }).text, }, @@ -796,7 +756,7 @@ return [ { type: 'txt', - val: possibleAnswers.find(x => { + val: possibleAnswers.find((x) => { return x.selectedByUser === true }).text, }, @@ -804,36 +764,36 @@ } }, }, - getDropdownAnswer: { + /* getDropdownAnswer: { description: 'Dropdown answer getter', - requirement: node => { + requirement: (node) => { return false }, - getterFunction: node => { + getterFunction: (node) => { // TODO dropdown kérdés.html return 'asd' }, }, getTextareaAnswer: { description: 'Get complex answer', - requirement: node => { + requirement: (node) => { return false }, - getterFunction: node => { + getterFunction: (node) => { // TODO Ugrás... bug.html return 'asd' }, }, getDragBoxAnswer: { description: 'Get complex answer', - requirement: node => { + requirement: (node) => { return false }, - getterFunction: node => { + getterFunction: (node) => { // TODO dragboxes return 'asd' - }, - }, + }, + },*/ } function getIfSolutionIsCorrect(node) { @@ -869,7 +829,7 @@ const select = node.getElementsByTagName('select')[0] if (select) { const options = [] - Array.from(select.childNodes).forEach(opt => { + Array.from(select.childNodes).forEach((opt) => { if (!emptyOrWhiteSpace(opt.innerText)) { options.push(opt.innerText) } @@ -885,10 +845,10 @@ } function digestMessage(message) { - return new Promise(resolve => { + return new Promise((resolve) => { const encoder = new TextEncoder() const data = encoder.encode(message) - crypto.subtle.digest('SHA-256', data).then(buf => { + crypto.subtle.digest('SHA-256', data).then((buf) => { let res = String.fromCharCode.apply(null, new Uint8Array(buf)) res = btoa(res) .replace(/=/g, '') @@ -901,12 +861,12 @@ function getBase64Image(img) { img.crossOrigin = 'Anonymous' - let canvas = document.createElement('canvas') + const canvas = document.createElement('canvas') canvas.width = img.width canvas.height = img.height - let ctx = canvas.getContext('2d') + const ctx = canvas.getContext('2d') ctx.drawImage(img, 0, 0) - let dataURL = canvas.toDataURL('image/png') + const dataURL = canvas.toDataURL('image/png') img.crossOrigin = undefined return dataURL.replace(/^data:image\/(png|jpg);base64,/, '') } @@ -976,8 +936,8 @@ }) const getHostHandler = { - apply: function() { - let result = apply(...arguments) + apply: function () { + const result = apply(...arguments) return result === shadowRootNewHost ? shadowRootHost : result }, } @@ -1035,7 +995,8 @@ if (elementUpdaterInterval === -1) { elementUpdaterInterval = setInterval(() => { updatableElements.forEach(({ elem, target }) => { - let { left, top, width, height } = target.getBoundingClientRect() + let { left, top } = target.getBoundingClientRect() + const { width, height } = target.getBoundingClientRect() left += window.scrollX top += window.scrollY @@ -1152,7 +1113,7 @@ if (!sideLinks) { return } - Array.from(sideLinks.childNodes).forEach(link => { + Array.from(sideLinks.childNodes).forEach((link) => { link.addEventListener('mousedown', () => { FillFeedbackCID(url, link) }) @@ -1194,13 +1155,13 @@ } try { - addEventListener = (function() { + addEventListener = (function () { if (document.addEventListener) { - return function(element, event, handler) { + return function (element, event, handler) { element.addEventListener(event, handler, false) } } else { - return function(element, event, handler) { + return function (element, event, handler) { element.attachEvent('on' + event, handler) } } @@ -1216,13 +1177,13 @@ } function Auth(pw) { - post('login', { pw: pw, script: true }).then(res => { + post('login', { pw: pw, script: true }).then((res) => { if (res.result === 'success') { ConnectToServer(AfterLoad) clearAllMessages() resetMenu() } else { - SafeGetElementById('infoMainDiv', elem => { + SafeGetElementById('infoMainDiv', (elem) => { elem.innerText = texts.invalidPW + pw }) } @@ -1230,16 +1191,16 @@ } function resetMenu() { - SafeGetElementById('scriptMenuDiv', elem => { + SafeGetElementById('scriptMenuDiv', (elem) => { elem.style.backgroundColor = '#262626' }) - SafeGetElementById('retryContainer', elem => { + SafeGetElementById('retryContainer', (elem) => { elem.style.display = 'none' }) - SafeGetElementById('loginDiv', elem => { + SafeGetElementById('loginDiv', (elem) => { elem.style.display = 'none' }) - SafeGetElementById('infoMainDiv', elem => { + SafeGetElementById('infoMainDiv', (elem) => { elem.innerText = texts.loading }) } @@ -1247,7 +1208,7 @@ function ConnectToServer(cwith) { clearAllMessages() GetXHRInfos() - .then(inf => { + .then((inf) => { if (inf.result === 'nouser') { NoUserAction() return @@ -1267,9 +1228,13 @@ : '📬' } - overlay.querySelector('#infoMainDiv').innerText = `${ - subjInfo.subjects - } tárgy, ${subjInfo.questions} kérdés. User ID: ${getUid()}` + overlay.querySelector( + '#infoMainDiv' + ).innerText = `${subjInfo.subjects.toLocaleString( + 'hu' + )} tárgy, ${subjInfo.questions.toLocaleString( + 'hu' + )} kérdés.\nUser ID: ${getUid()}` // FIXME: if cwith() throws an unhandled error it sais server is not avaible cwith() }) @@ -1279,25 +1244,25 @@ } function NoUserAction() { - SafeGetElementById('scriptMenuDiv', elem => { + SafeGetElementById('scriptMenuDiv', (elem) => { elem.style.backgroundColor = '#44cc00' }) - SafeGetElementById('infoMainDiv', elem => { + SafeGetElementById('infoMainDiv', (elem) => { elem.innerText = '' }) - SafeGetElementById('loginDiv', elem => { + SafeGetElementById('loginDiv', (elem) => { elem.style.display = 'flex' }) } function NoServerAction() { - SafeGetElementById('scriptMenuDiv', elem => { + SafeGetElementById('scriptMenuDiv', (elem) => { elem.style.backgroundColor = 'red' }) - SafeGetElementById('infoMainDiv', elem => { + SafeGetElementById('infoMainDiv', (elem) => { elem.innerText = texts.noServer }) - SafeGetElementById('retryContainer', elem => { + SafeGetElementById('retryContainer', (elem) => { elem.style.display = 'flex' }) log(texts.noServerConsoleMessage) @@ -1379,7 +1344,7 @@ function PrepareAnswers(result) { const { answers, question } = result if (answers.length > 0) { - return answers.map(answer => { + return answers.map((answer) => { const { Q, A, data } = answer.q let msg = Q + '\n' + A @@ -1442,7 +1407,7 @@ texts.noResult, undefined, - function() { + function () { OpenErrorPage({ message: 'No result found', question: Array.isArray(answers[0]) @@ -1459,7 +1424,7 @@ // : Quiz saving {{{ function HandleResults() { - getQuiz().then(res => { + getQuiz().then((res) => { SaveQuiz(res, ShowSaveQuizDialog) // saves the quiz questions and answers }) } @@ -1482,7 +1447,7 @@ msg, null, - function() { + function () { let towrite = '' try { towrite += '

Elküldött adatok:

' + JSON.stringify(sentData) @@ -1517,7 +1482,7 @@ log('unable to get subject name :c') } log('SENT DATA', sentData) - post('isAdding', sentData).then(res => { + post('isAdding', sentData).then((res) => { next(res.success, sentData, res.totalNewQuestions) }) } catch (e) { @@ -1586,7 +1551,7 @@ // this function adds basic hotkeys for video controll. function AddVideoHotkeys() { var seekTime = 20 - document.addEventListener('keydown', function(e) { + document.addEventListener('keydown', function (e) { try { var video = getVideo() var keyCode = e.keyCode // getting keycode @@ -1626,36 +1591,7 @@ // : Show message, and script menu stuff {{{ function clearAllMessages() { - overlay.querySelectorAll('#scriptMessage').forEach(x => x.remove()) - } - - function getConvertedMessageNode(message) { - const messageNode = document.createElement('p') - const resultNode = document.createElement('p') - messageNode.innerHTML = message.replace(/\n/g, '
') - - Array.from(messageNode.childNodes).forEach(node => { - if (node.tagName === 'A') { - let linkNode = document.createElement('span') - SetStyle(linkNode, { - color: 'lightblue', - textDecoration: 'underline', - cursor: 'pointer', - }) - linkNode.innerText = node.innerText - linkNode.addEventListener('mousedown', e => { - e.stopPropagation() - openInTab(node.href, { - active: true, - }) - }) - resultNode.appendChild(linkNode) - } else { - resultNode.appendChild(node) - } - }) - - return resultNode + overlay.querySelectorAll('#scriptMessage').forEach((x) => x.remove()) } function addOpacityChangeEvent(elem) { @@ -1665,7 +1601,7 @@ } let currOpacity = getVal(`${elem.id}_opacity`) || 1 - elem.addEventListener('wheel', e => { + elem.addEventListener('wheel', (e) => { e.preventDefault() const isUp = e.deltaY < 0 if (isUp) { @@ -1686,14 +1622,14 @@ let isMouseDown = false let offset = [0, 0] let mousePosition - elem.addEventListener('mousedown', e => { + elem.addEventListener('mousedown', (e) => { isMouseDown = true offset = [elem.offsetLeft - e.clientX, elem.offsetTop - e.clientY] }) elem.addEventListener('mouseup', () => { isMouseDown = false }) - elem.addEventListener('mousemove', e => { + elem.addEventListener('mousemove', (e) => { if (isMouseDown) { mousePosition = { x: e.clientX, @@ -1727,22 +1663,24 @@ // ------------------------------------------------------------------------- const id = 'scriptMessage' - let width = window.innerWidth - window.innerWidth / 6 // with of the box const messageElem = document.createElement('div') messageElem.setAttribute('id', id) addOpacityChangeEvent(messageElem) + let width = window.innerWidth - window.innerWidth / 6 // with of the box + if (width > 900) { + width = 900 + } SetStyle(messageElem, { position: 'fixed', zIndex: 999999, + color: '#fff', textAlign: 'center', - width: width + 'px', - padding: '0px', - background: '#222d32', - color: '#ffffff', - border: '3px solid #99f', - borderRadius: '5px', + border: '2px solid #f2cb05', + borderRadius: '0px', + backgroundColor: '#222426', top: '30px', left: (window.innerWidth - width) / 2 + 'px', + width: width + 'px', opacity: getVal(`${id}_opacity`), cursor: funct ? 'pointer' : 'move', }) @@ -1752,6 +1690,25 @@ if (movingEnabled) { addMoveEventListener(messageElem) } + addEventListener(window, 'resize', function () { + messageElem.style.left = (window.innerWidth - width) / 2 + 'px' + }) + + let timeOut + if (timeout && timeout > 0) { + timeOut = setTimeout(function () { + messageElem.parentNode.removeChild(messageElem) + }, timeout * 1000) + } + + addEventListener(messageElem, 'mousedown', function (e) { + if (e.which === 2) { + messageElem.parentNode.removeChild(messageElem) + if (timeOut) { + clearTimeout(timeOut) + } + } + }) // ------------------------------------------------------------------------- @@ -1763,7 +1720,7 @@ display: 'inline', margin: '3px', }) - xButton.addEventListener('mousedown', e => { + xButton.addEventListener('mousedown', (e) => { e.stopPropagation() messageElem.parentNode.removeChild(messageElem) }) @@ -1780,38 +1737,65 @@ // ------------------------------------------------------------------------- const sidesWidth = '10%' + const arrowStyle = { + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + fontSize: '22px', + userSelect: 'none', + flex: 1, + } + const infoTextStyle = { + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + flex: 1, + } + const childrenTree = { header: { style: { display: getCurrMsg().header ? '' : 'none', + padding: '5px 0px', }, }, msgContainer: { style: { display: 'flex', width: '100%', - padding: '10px 0px', + padding: '5px 0px', }, children: { leftSideDiv: { style: { + display: isSimpleMessage ? 'none' : 'flex', + flexFlow: 'column', width: sidesWidth, - display: isSimpleMessage ? 'none' : '', }, children: { questionIndex: { - style: { - backgroundColor: 'red', - }, + title: 'Kérdés sorszáma / talált válasz sorszáma', + style: infoTextStyle, }, matchPercent: { - style: { - backgroundColor: 'green', - }, + title: 'Talált kérdés egyezés', + style: infoTextStyle, }, prevPossible: { - style: { - backgroundColor: 'blue', + title: 'Előző lehetséges válasz', + style: Object.assign( + { + cursor: 'pointer', + }, + arrowStyle + ), + innerText: msgItem[currQuestionIndex].length > 1 ? '⬅️' : '', + onClick: (e) => { + e.stopPropagation() + if (currPossibleAnswerIndex > 0) { + currPossibleAnswerIndex-- + updateMessageText() + } }, }, }, @@ -1825,23 +1809,67 @@ }, rightSideDiv: { style: { + display: isSimpleMessage ? 'none' : 'flex', + flexFlow: 'column', width: sidesWidth, - display: isSimpleMessage ? 'none' : '', }, children: { prevQuestion: { - style: { - backgroundColor: 'red', + title: 'Előző kérdés', + style: Object.assign( + { + cursor: msgItem.length > 1 ? 'pointer' : '', + }, + arrowStyle + ), + innerText: msgItem.length > 1 ? '⬆️' : '', + onClick: (e) => { + if (msgItem.length > 1) { + e.stopPropagation() + if (currQuestionIndex > 0) { + currQuestionIndex-- + updateMessageText() + } + } }, }, nextQuestion: { - style: { - backgroundColor: 'green', + title: 'Következő kérdés', + style: Object.assign( + { + cursor: msgItem.length > 1 ? 'pointer' : '', + }, + arrowStyle + ), + innerText: msgItem.length > 1 ? '⬇️' : '', + onClick: (e) => { + if (msgItem.length > 1) { + e.stopPropagation() + if (currQuestionIndex < msgItem.length - 1) { + currQuestionIndex++ + updateMessageText() + } + } }, }, nextPossible: { - style: { - backgroundColor: 'blue', + title: 'Következő lehetséges válasz', + style: Object.assign( + { + cursor: 'pointer', + }, + arrowStyle + ), + innerText: msgItem[currQuestionIndex].length > 1 ? '➡️' : '', + onClick: (e) => { + e.stopPropagation() + if ( + currPossibleAnswerIndex < + msgItem[currQuestionIndex].length - 1 + ) { + currPossibleAnswerIndex++ + updateMessageText() + } }, }, }, @@ -1855,14 +1883,9 @@ // ------------------------------------------------------------------------- - try { - result.msgContainer.child.msgDiv.elem.addEventListener('mousedown', e => { - e.stopPropagation() - }) - } catch (e) { - console.warn('Error setting up msg') - console.warn(e) - } + result.msgContainer.child.msgDiv.elem.addEventListener('mousedown', (e) => { + e.stopPropagation() + }) // ------------------------------------------------------------------------- @@ -1871,18 +1894,16 @@ result.header.elem.innerText = getCurrMsg().header result.msgContainer.child.msgDiv.elem.innerText = getCurrMsg().m - result.msgContainer.child.leftSideDiv.child.questionIndex.elem.innerText = - (currQuestionIndex + 1).toString() + '.' - result.msgContainer.child.leftSideDiv.child.matchPercent.elem.innerText = getCurrMsg().p - result.msgContainer.child.leftSideDiv.child.prevPossible.elem.innerText = - '<' + if (msgItem.length !== 1 || msgItem[0].length !== 1) { + result.msgContainer.child.leftSideDiv.child.questionIndex.elem.innerText = + (currQuestionIndex + 1).toString() + + './' + + (currPossibleAnswerIndex + 1) + + '.' + } - result.msgContainer.child.rightSideDiv.child.prevQuestion.elem.innerText = - '^' - result.msgContainer.child.rightSideDiv.child.nextQuestion.elem.innerText = - '˘' - result.msgContainer.child.rightSideDiv.child.nextPossible.elem.innerText = - '>' + result.msgContainer.child.leftSideDiv.child.matchPercent.elem.innerText = + getCurrMsg().p + '%' result.msgContainer.child.msgDiv.elem.innerText = getCurrMsg().m } catch (e) { @@ -1904,365 +1925,6 @@ } } - function ShowMessageOld(msgItem, timeout, funct) { - // msgItem help: - // [ [ {}{}{}{} ] [ {}{}{} ] ] - // msgItem[] <- a questions stuff - // msgItem[][] <- a questions relevant answers array - // msgItem[][].p <- a questions precent - // msgItem[][].m <- a questions message - try { - let defMargin = '0px 5px' - let isSimpleMessage = false - let simpleMessageText = '' - if (typeof msgItem === 'string') { - simpleMessageText = msgItem - if (simpleMessageText === '') { - // if msg is empty - return - } - msgItem = [ - [ - { - m: simpleMessageText, - }, - ], - ] - isSimpleMessage = true - } - - const appedtTo = overlay // will be appended here - const startFromTop = 25 // top distance - let width = window.innerWidth - window.innerWidth / 6 // with of the box - - const mainDiv = document.createElement('div') // the main divider, wich items will be attached to - const id = 'scriptMessage' - mainDiv.setAttribute('id', id) - if (funct) { - addEventListener(mainDiv, 'click', funct) - } - // lotsa crap style - SetStyle(mainDiv, { - position: 'fixed', - zIndex: 999999, - textAlign: 'center', - width: width + 'px', - padding: '0px', - color: '#ffffff', - border: '2px solid #f2cb05', - borderRadius: '0px', - backgroundColor: '#222426', - top: startFromTop + 'px', - left: (window.innerWidth - width) / 2 + 'px', - opacity: getVal(`${id}_opacity`), - cursor: funct ? 'pointer' : 'move', - }) - - // ------------------------------------------------------------------ - // transparencity - // ------------------------------------------------------------------ - addOpacityChangeEvent(mainDiv) - // ------------------------------------------------------------------ - // moving msg - // ------------------------------------------------------------------ - const movingEnabled = !funct - let isMouseDown = false - let offset = [0, 0] - let mousePosition - if (movingEnabled) { - mainDiv.addEventListener('mousedown', e => { - isMouseDown = true - offset = [ - mainDiv.offsetLeft - e.clientX, - mainDiv.offsetTop - e.clientY, - ] - }) - mainDiv.addEventListener('mouseup', () => { - isMouseDown = false - }) - mainDiv.addEventListener('mousemove', e => { - if (isMouseDown) { - mousePosition = { - x: e.clientX, - y: e.clientY, - } - mainDiv.style.left = mousePosition.x + offset[0] + 'px' - mainDiv.style.top = mousePosition.y + offset[1] + 'px' - } - }) - } - - const xButton = CreateNodeWithText(null, '❌', 'div') - SetStyle(xButton, { - cursor: 'pointer', - position: 'absolute', - right: '0px', - display: 'inline', - margin: '3px', - }) - xButton.addEventListener('mousedown', e => { - e.stopPropagation() - mainDiv.parentNode.removeChild(mainDiv) - }) - - // ------------------------------------------------------------------ - var matchPercent = msgItem[0][0].p - if (isSimpleMessage) { - mainDiv.appendChild(xButton) - var simpleMessageParagrapg = document.createElement('p') // new paragraph - simpleMessageParagrapg.style.margin = defMargin // fancy margin - - const mesageNode = getConvertedMessageNode(simpleMessageText) - - simpleMessageParagrapg.appendChild(mesageNode) - mesageNode.addEventListener('mousedown', e => { - e.stopPropagation() - }) - SetStyle(mesageNode, { - margin: '10px 100px', - cursor: funct ? 'pointer' : 'auto', - }) - - Array.from(mesageNode.getElementsByTagName('a')).forEach(anchorElem => { - anchorElem.style.color = 'lightblue' - }) - - mainDiv.appendChild(simpleMessageParagrapg) // adding text box to main div - } else { - const headerRow = document.createElement('div') - headerRow.setAttribute('id', 'msgHeader') - SetStyle(headerRow, { - height: '20px', - userSelect: 'none', - }) - mainDiv.appendChild(headerRow) - - const headerText = CreateNodeWithText(headerRow, '', 'div') - headerText.title = 'Talált kérdés tárgy neve' - SetStyle(headerText, { - padding: '2px 5px', - textAlign: 'center', - display: 'inline', - }) - - headerRow.appendChild(xButton) - // if its a fucking complicated message - // TABLE SETUP ------------------------------------------------------------------------------------------------------------ - var table = document.createElement('table') - table.style.width = '100%' - // ROWS ----------------------------------------------------------------------------------------------------- - var rowOne = table.insertRow() // previous suggestion, question text, and prev question - var rowTwo = table.insertRow() // next question button - var rowThree = table.insertRow() // next suggetsion button - // CELLS ----------------------------------------------------------------------------------------------------- - // row one - const sideCellWidth = 30 - var numberTextCell = rowOne.insertCell() - SetStyle(numberTextCell, { - width: sideCellWidth + 'px', - }) - var questionCell = rowOne.insertCell() // QUESTION CELL - questionCell.setAttribute('id', 'questionCell') - questionCell.rowSpan = 3 - var prevQuestionCell = rowOne.insertCell() - SetStyle(prevQuestionCell, { - width: sideCellWidth + 'px', - }) - // row two - var percentTextCell = rowTwo.insertCell() - SetStyle(percentTextCell, { - width: sideCellWidth + 'px', - }) - var nextQuestionCell = rowTwo.insertCell() - SetStyle(nextQuestionCell, { - width: sideCellWidth + 'px', - }) - // row three - var prevSuggestionCell = rowThree.insertCell() - var nextSuggestionCell = rowThree.insertCell() - // adding finally - mainDiv.appendChild(table) - // PERCENT TEXT SETUP ----------------------------------------------------------------------------------------------------- - var percentTextBox = CreateNodeWithText(percentTextCell, '') - percentTextBox.setAttribute('id', 'percentTextBox') - percentTextBox.title = 'Egyezés %' - - if (matchPercent) { - // if match percent param is not null - percentTextBox.innerText = matchPercent + '%' - } - // NUMBER SETUP ----------------------------------------------------------------------------------------------------- - var numberTextBox = CreateNodeWithText(numberTextCell, '1.') - numberTextBox.setAttribute('id', 'numberTextBox') - numberTextBox.title = 'Lehetséges válasz index' - - // ANSWER NODE SETUP ------------------------------------------------------------------------------------------------------------- - var questionTextElement = CreateNodeWithText( - questionCell, - 'ur question goes here, mister OwO' - ) - - questionTextElement.addEventListener('mousedown', e => { - e.stopPropagation() - }) - - SetStyle(questionTextElement, { - cursor: funct ? 'pointer' : 'auto', - }) - - questionTextElement.setAttribute('id', 'questionTextElement') - - // BUTTON SETUP ----------------------------------------------------------------------------------------------------------- - var currItem = 0 - var currRelevantQuestion = 0 - - const GetRelevantQuestion = () => { - // returns the currItemth questions currRelevantQuestionth relevant question - return msgItem[currItem][currRelevantQuestion] - } - - const ChangeCurrItemIndex = to => { - currItem += to - if (currItem < 0) { - currItem = 0 - } - if (currItem > msgItem.length - 1) { - currItem = msgItem.length - 1 - } - currRelevantQuestion = 0 - } - - const ChangeCurrRelevantQuestionIndex = to => { - currRelevantQuestion += to - if (currRelevantQuestion < 0) { - currRelevantQuestion = 0 - } - if (currRelevantQuestion > msgItem[currItem].length - 1) { - currRelevantQuestion = msgItem[currItem].length - 1 - } - } - - const SetQuestionText = () => { - const relevantQuestion = GetRelevantQuestion() - if (relevantQuestion.header) { - headerText.innerText = relevantQuestion.header - } - questionTextElement.innerText = relevantQuestion.m - - if (currItem === 0 && currRelevantQuestion === 0) { - numberTextBox.innerText = currRelevantQuestion + 1 + '.' - } else { - numberTextBox.innerText = - currItem + 1 + './' + (currRelevantQuestion + 1) + '.' - } - if (relevantQuestion.p) { - percentTextBox.innerText = relevantQuestion.p + '%' - } - } - - const buttonStyle = { - color: 'white', - backgroundColor: 'transparent', - margin: '2px', - border: 'none', - fontSize: '30px', - cursor: 'pointer', - userSelect: 'none', - } - if (msgItem[currItem].length > 1) { - // PREV SUGG BUTTON ------------------------------------------------------------------------------------------------------------ - var prevSuggButton = CreateNodeWithText( - prevSuggestionCell, - '⬅️', - 'div' - ) - prevSuggButton.title = 'Előző lehetséges válasz' - SetStyle(prevSuggButton, buttonStyle) - - prevSuggButton.addEventListener('mousedown', function(e) { - e.stopPropagation() - ChangeCurrRelevantQuestionIndex(-1) - SetQuestionText() - }) - // NEXT SUGG BUTTON ------------------------------------------------------------------------------------------------------------ - var nextSuggButton = CreateNodeWithText( - nextSuggestionCell, - '➡️', - 'div' - ) - nextSuggButton.title = 'Következő lehetséges válasz' - SetStyle(nextSuggButton, buttonStyle) - - nextSuggButton.addEventListener('mousedown', function(e) { - e.stopPropagation() - ChangeCurrRelevantQuestionIndex(1) - SetQuestionText() - }) - } - // deciding if has multiple questions ------------------------------------------------------------------------------------------------ - if (msgItem.length === 1) { - SetQuestionText() - } else { - // if there are multiple items to display - // PREV QUESTION BUTTON ------------------------------------------------------------------------------------------------------------ - var prevButton = CreateNodeWithText(prevQuestionCell, '⬆️', 'div') - SetStyle(prevButton, buttonStyle) - prevButton.title = 'Előző kérdés' - - // event listener - prevButton.addEventListener('click', function() { - ChangeCurrItemIndex(-1) - SetQuestionText() - }) - // NEXT QUESTION BUTTON ------------------------------------------------------------------------------------------------------------ - var nextButton = CreateNodeWithText(nextQuestionCell, '⬇️', 'div') - SetStyle(nextButton, buttonStyle) - nextButton.title = 'Előző kérdés' - - // event listener - nextButton.addEventListener('click', function() { - ChangeCurrItemIndex(1) - SetQuestionText() - }) - SetQuestionText() - } - } - appedtTo.appendChild(mainDiv) // THE FINAL APPEND - - // setting some events - // addEventListener(window, 'scroll', function () { - // mainDiv.style.top = (pageYOffset + startFromTop) + 'px'; - // }) - addEventListener(window, 'resize', function() { - mainDiv.style.left = (window.innerWidth - width) / 2 + 'px' - }) - var timeOut - if (timeout && timeout > 0) { - // setting timeout if not zero or null - timeOut = setTimeout(function() { - mainDiv.parentNode.removeChild(mainDiv) - }, timeout * 1000) - } - // middle click close event listener - addEventListener(mainDiv, 'mousedown', function(e) { - if (e.which === 2) { - mainDiv.parentNode.removeChild(mainDiv) - if (timeOut) { - clearTimeout(timeOut) - } - } - }) - return { - messageElement: mainDiv, - removeMessage: () => { - mainDiv.parentNode.removeChild(mainDiv) - }, - } - } catch (e) { - Exception(e, 'script error at showing message:') - } - } - // shows a fancy menu function ShowMenu() { try { @@ -2274,6 +1936,7 @@ width: '300px', height: '90px', position: 'fixed', + padding: '3px 0px', bottom: '30px', left: '10px', zIndex: 999999, @@ -2284,69 +1947,13 @@ fontSize: '14px', }) - addEventListener(scriptMenuDiv, 'mousedown', function(e) { + addEventListener(scriptMenuDiv, 'mousedown', function (e) { if (e.which === 2) { scriptMenuDiv.parentNode.removeChild(scriptMenuDiv) } }) addOpacityChangeEvent(scriptMenuDiv) - // X button -------------------------------------------------------------------- - const xButton = CreateNodeWithText(scriptMenuDiv, '❌', 'div') - SetStyle(xButton, { - position: 'absolute', - display: 'inline', - right: '0px', - margin: '5px', - cursor: 'pointer', - fontSize: '18px', - }) - - xButton.addEventListener('mousedown', e => { - e.stopPropagation() - scriptMenuDiv.parentNode.removeChild(scriptMenuDiv) - }) - - // Mail button ----------------------------------------------------------------- - const mailButton = CreateNodeWithText(scriptMenuDiv, '📭', 'div') - mailButton.setAttribute('id', 'mailButton') - SetStyle(mailButton, { - position: 'absolute', - display: 'inline', - left: '0px', - bottom: '0px', - margin: '5px', - fontSize: '30px', - }) - - mailButton.addEventListener('mousedown', e => { - e.stopPropagation() - if (userSpecificMotd && !userSpecificMotd.seen) { - mailButton.innerText = '📭' - post('infos', { - userSpecificMotdSeen: true, - }) - } - if (!userSpecificMotd) { - return - } - clearAllMessages() - ShowMessage( - 'Üzenet oldal készítéjétől (csak te látod):\n' + userSpecificMotd.msg - ) - }) - - // ----------------------------------------------------------------------------- - // BUTTONS - // ----------------------------------------------------------------------------- - const buttonContainer = document.createElement('div') - SetStyle(buttonContainer, { - display: 'flex', - justifyContent: 'center', - }) - - scriptMenuDiv.appendChild(buttonContainer) - const buttonStyle = { position: '', margin: '3px', @@ -2357,89 +1964,158 @@ cursor: 'pointer', } - Object.keys(menuButtons).forEach(key => { - const buttonData = menuButtons[key] - const button = CreateNodeWithText( - buttonContainer, - buttonData.title, - 'div' - ) - SetStyle(button, buttonStyle) - if (buttonData.onClick) { - button.addEventListener('click', function() { - buttonData.onClick() - }) - } - }) - // ----------------------------------------------------------------------------- - // Info text - // ----------------------------------------------------------------------------- - const infoDiv = CreateNodeWithText(scriptMenuDiv, texts.loading, 'div') - infoDiv.setAttribute('id', 'infoMainDiv') - SetStyle(infoDiv, { - color: '#ffffff', - margin: '0px 50px', - textAlign: 'center', - }) - // ----------------------------------------------------------------------------- - // Login stuff (if user is not logged in) - // ----------------------------------------------------------------------------- - const loginContainer = document.createElement('div') - scriptMenuDiv.appendChild(loginContainer) - loginContainer.setAttribute('id', 'loginDiv') - SetStyle(loginContainer, { - display: 'none', - margin: '0px 50px', - }) + const childrenTree = { + xButton: { + innerText: '❌', + style: { + position: 'absolute', + display: 'inline', + right: '0px', + margin: '5px', + cursor: 'pointer', + fontSize: '18px', + }, + onClick: () => { + scriptMenuDiv.parentNode.removeChild(scriptMenuDiv) + }, + }, + mailButton: { + id: 'mailButton', + innerText: '📭', + style: { + position: 'absolute', + display: 'inline', + left: '5px', + bottom: '15px', + margin: '5px', + fontSize: '30px', + }, + onClick: () => { + if (userSpecificMotd && !userSpecificMotd.seen) { + SafeGetElementById('mailButton', (elem) => { + elem.innerText = '📭' + }) + post('infos', { + userSpecificMotdSeen: true, + }) + } + if (!userSpecificMotd) { + return + } + clearAllMessages() + ShowMessage( + 'Üzenet oldal készítéjétől (csak te látod):\n' + + userSpecificMotd.msg + ) + }, + }, + buttonContainer: { + style: { + display: 'flex', + justifyContent: 'center', + }, + children: { + website: { + innerText: 'Weboldal', + style: buttonStyle, + onClick: () => { + openInTab(serverAdress + '?menuClick') + }, + }, + help: { + innerText: 'Help', + style: buttonStyle, + onClick: () => { + ShowHelp() + }, + }, + donate: { + innerText: 'Donate', + style: buttonStyle, + onClick: () => { + openInTab(serverAdress + 'donate?scriptMenu', { + active: true, + }) + }, + }, + }, + }, + infoContainer: { + id: 'infoMainDiv', + innerText: texts.loading, + style: { + color: '#ffffff', + margin: '5px 50px', + textAlign: 'center', + }, + }, + loginContainer: { + id: 'loginDiv', + style: { + display: 'none', + margin: '0px 50px', + }, + children: { + loginInput: { + customElem: () => { + const loginInput = document.createElement('input') + loginInput.setAttribute('id', 'pwInput') + loginInput.type = 'text' + loginInput.placeholder = texts.pwHere + SetStyle(loginInput, { + width: '100%', + textAlign: 'center', + }) + return loginInput + }, + }, + loginButton: { + innerText: texts.login, + style: buttonStyle, + onClick: () => { + SafeGetElementById('pwInput', (elem) => { + Auth(elem.value) + }) + }, + }, + }, + }, + retryContainer: { + id: 'retryContainer', + style: { + display: 'none', + justifyContent: 'center', + }, + children: { + retryButton: { + innerText: texts.retry, + style: { + position: '', + padding: '0px 8px', + border: '1px solid #333', + borderRadius: '2px', + color: '#ffffff', + cursor: 'pointer', + }, + onClick: () => { + scriptMenuDiv.style.background = '#262626' + SafeGetElementById('infoMainDiv', (elem) => { + elem.innerText = texts.loading + }) + SafeGetElementById('retryContainer', (elem) => { + elem.style.display = 'none' + }) + ConnectToServer(AfterLoad) + }, + }, + }, + }, + } - const loginInput = document.createElement('input') - loginContainer.appendChild(loginInput) - loginInput.type = 'text' - loginInput.placeholder = texts.pwHere - SetStyle(loginInput, { - width: '100%', - textAlign: 'center', - }) - - const loginButton = document.createElement('div') - loginContainer.appendChild(loginButton) - loginButton.innerText = texts.login - SetStyle(loginButton, buttonStyle) - loginButton.addEventListener('click', function() { - Auth(loginInput.value) - }) - - // ----------------------------------------------------------------------------- - // Retry connection button (if server is not available) - // ----------------------------------------------------------------------------- - const retryContainer = CreateNodeWithText(scriptMenuDiv, '', 'div') - SetStyle(retryContainer, { - display: 'hidden', - justifyContent: 'center', - }) - retryContainer.style.display = 'none' - retryContainer.setAttribute('id', 'retryContainer') - - const retryButton = CreateNodeWithText(retryContainer, texts.retry, 'div') - retryContainer.appendChild(retryButton) - SetStyle(retryButton, { - position: '', - padding: '0px 8px', - border: '1px solid #333', - borderRadius: '2px', - color: '#ffffff', - cursor: 'pointer', - }) - retryButton.addEventListener('click', function() { - scriptMenuDiv.style.background = '#262626' - infoDiv.innerText = texts.loading - retryContainer.style.display = 'none' - ConnectToServer(AfterLoad) - }) - - // APPEND EVERYTHING + const result = {} + createHtml(childrenTree, scriptMenuDiv, result) overlay.appendChild(scriptMenuDiv) } catch (e) { Exception(e, 'script error at showing menu:') @@ -2489,7 +2165,7 @@ // : }}} - const assert = val => { + const assert = (val) => { if (!val) { throw new Error('Assertion failed') } @@ -2549,24 +2225,44 @@ function SetStyle(target, style) { Object.keys(style) .sort() - .forEach(key => { + .forEach((key) => { target.style[key] = style[key] }) } function createHtml(children, appendTo, result) { try { - Object.keys(children).forEach(key => { + Object.keys(children).forEach((key) => { const currElem = children[key] - const elem = document.createElement('div') + const elem = currElem.customElem + ? currElem.customElem() + : document.createElement('div') appendTo.appendChild(elem) result[key] = { elem: elem, child: {}, } - if (currElem.style) { - SetStyle(elem, currElem.style) + + if (!currElem.customElem) { + if (currElem.id) { + elem.setAttribute('id', currElem.id) + } + if (currElem.title) { + elem.title = currElem.title + } + if (currElem.innerText) { + elem.innerText = currElem.innerText + } + if (currElem.onClick) { + elem.addEventListener('mousedown', (e) => { + currElem.onClick(e) + }) + } + if (currElem.style) { + SetStyle(elem, currElem.style) + } } + if (currElem.children) { createHtml(currElem.children, elem, result[key].child) } @@ -2624,7 +2320,7 @@ headers: { 'Content-Type': 'application/json', }, - onload: function(response) { + onload: function (response) { try { setVal('lastInfoCheckTime', now) const res = JSON.parse(response.responseText) @@ -2637,7 +2333,7 @@ reject(e) } }, - onerror: e => { + onerror: (e) => { log('Info get Error', e) reject(e) }, @@ -2671,11 +2367,11 @@ headers: { 'Content-Type': 'application/json', }, - onerror: function(e) { + onerror: function (e) { log('Data send error', e) reject(e) }, - onload: resp => { + onload: (resp) => { try { const res = JSON.parse(resp.responseText) resolve(res) @@ -2693,7 +2389,7 @@ function OpenErrorPage(e) { const queries = [] try { - Object.keys(e).forEach(key => { + Object.keys(e).forEach((key) => { if (e[key]) { queries.push(`${key}=${encodeURIComponent(e[key])}`) } @@ -2719,7 +2415,7 @@ if (query) { q = query } - openInTab(serverAdress + `manual?${q}`, { + openInTab(serverAdress + `faq${q ? '?' + q : ''}`, { active: true, }) }