mirror of
https://gitlab.com/MrFry/moodle-test-userscript
synced 2025-04-01 20:22:48 +02:00
Handling questions with select element
This commit is contained in:
parent
3f641f07cc
commit
a437f8f98d
2 changed files with 326 additions and 411 deletions
18
.eslintrc.js
18
.eslintrc.js
|
@ -5,16 +5,18 @@ module.exports = {
|
||||||
node: true,
|
node: true,
|
||||||
jest: true,
|
jest: true,
|
||||||
},
|
},
|
||||||
extends: ["eslint:recommended"],
|
extends: ['eslint:recommended'],
|
||||||
globals: {
|
globals: {
|
||||||
Atomics: "readonly",
|
Atomics: 'readonly',
|
||||||
SharedArrayBuffer: "readonly",
|
SharedArrayBuffer: 'readonly',
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
"no-extra-semi": "off",
|
'no-extra-semi': 'off',
|
||||||
"no-undef": ["warn"],
|
'no-undef': ['error'],
|
||||||
eqeqeq: ["warn", "smart"],
|
eqeqeq: ['warn', 'smart'],
|
||||||
"no-unused-vars": "off",
|
'no-unused-vars': 'warn',
|
||||||
"no-prototype-builtins": "off",
|
'no-prototype-builtins': 'off',
|
||||||
|
'object-shorthand': ['warn', 'never'],
|
||||||
|
'prefer-const': 'warn',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
531
stable.user.js
531
stable.user.js
|
@ -90,8 +90,8 @@
|
||||||
function delVal(name) {
|
function delVal(name) {
|
||||||
return GM_deleteValue(name)
|
return GM_deleteValue(name)
|
||||||
}
|
}
|
||||||
function openInTab(address, options) {
|
function openInTab(address) {
|
||||||
GM_openInTab(address, options)
|
GM_openInTab(address, false)
|
||||||
}
|
}
|
||||||
function xmlhttpRequest(opts) {
|
function xmlhttpRequest(opts) {
|
||||||
GM_xmlhttpRequest(opts)
|
GM_xmlhttpRequest(opts)
|
||||||
|
@ -105,22 +105,25 @@
|
||||||
|
|
||||||
// : Constants and global variables {{{
|
// : Constants and global variables {{{
|
||||||
|
|
||||||
const logElementGetting = false
|
// ------------------------------------------------------------------------------
|
||||||
const logEnabled = true
|
// Devel vars
|
||||||
const showErrors = true
|
// ------------------------------------------------------------------------------
|
||||||
// forcing pages for testing. unless you test, do not set these to true!
|
// forcing pages for testing. unless you test, do not set these to true!
|
||||||
setVal('ISDEVEL', false)
|
setVal('ISDEVEL', false)
|
||||||
// only one of these should be true for testing
|
// only one of these should be true for testing
|
||||||
const forceTestPage = false
|
const forceTestPage = false
|
||||||
const forceResultPage = false
|
const forceResultPage = false
|
||||||
const forceDefaultPage = false
|
const forceDefaultPage = false
|
||||||
|
// ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
const logElementGetting = false
|
||||||
|
const logEnabled = true
|
||||||
|
const showErrors = true
|
||||||
|
|
||||||
var addEventListener // add event listener function
|
var addEventListener // add event listener function
|
||||||
let serverAdress = 'https://qmining.frylabs.net/'
|
let serverAdress = 'https://qmining.frylabs.net/'
|
||||||
let apiAdress = 'https://api.frylabs.net/'
|
let apiAdress = 'https://api.frylabs.net/'
|
||||||
const ircAddress = 'https://kiwiirc.com/nextclient/irc.sub.fm/#qmining'
|
// const ircAddress = 'https://kiwiirc.com/nextclient/irc.sub.fm/#qmining'
|
||||||
const correctSource =
|
|
||||||
'https://qmining.frylabs.net/moodle-test-userscript/stable.user.js?up'
|
|
||||||
|
|
||||||
const motdShowCount = 3 /* Ammount of times to show motd */
|
const motdShowCount = 3 /* Ammount of times to show motd */
|
||||||
const messageOpacityDelta = 0.1
|
const messageOpacityDelta = 0.1
|
||||||
|
@ -147,6 +150,29 @@
|
||||||
? 'https://elearning.uni-obuda.hu/'
|
? 'https://elearning.uni-obuda.hu/'
|
||||||
: location.href
|
: 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 {{{
|
// : Localisation {{{
|
||||||
|
|
||||||
const huTexts = {
|
const huTexts = {
|
||||||
|
@ -172,8 +198,6 @@
|
||||||
retry: 'Újrapróbálás',
|
retry: 'Újrapróbálás',
|
||||||
dataEditor: 'Data editor',
|
dataEditor: 'Data editor',
|
||||||
dataEditorTitle: 'Adatbázisban lévő kérdések szerkesztése',
|
dataEditorTitle: 'Adatbázisban lévő kérdések szerkesztése',
|
||||||
ircButton: 'IRC chat',
|
|
||||||
ircButtonTitle: 'IRC chat',
|
|
||||||
invalidPW: 'Hibás jelszó: ',
|
invalidPW: 'Hibás jelszó: ',
|
||||||
search: 'Keresés ...',
|
search: 'Keresés ...',
|
||||||
loading: 'Betöltés ...',
|
loading: 'Betöltés ...',
|
||||||
|
@ -181,7 +205,7 @@
|
||||||
newPWTitle: 'Új jelszó új felhasználónak',
|
newPWTitle: 'Új jelszó új felhasználónak',
|
||||||
pwRequest: 'Jelszó új felhasználónak',
|
pwRequest: 'Jelszó új felhasználónak',
|
||||||
noServer: 'Nem elérhető a szerver!',
|
noServer: 'Nem elérhető a szerver!',
|
||||||
noUser: 'Nem vagy bejelentkezve!',
|
pwHere: 'Jelszó ...',
|
||||||
noServerConsoleMessage: `Nem elérhető a szerver, vagy kis eséllyel kezeletlen hiba történt! Ha elérhető a weboldal, akkor ott meg bírod nézni a kérdéseket itt: ${serverAdress}legacy`,
|
noServerConsoleMessage: `Nem elérhető a szerver, vagy kis eséllyel kezeletlen hiba történt! Ha elérhető a weboldal, akkor ott meg bírod nézni a kérdéseket itt: ${serverAdress}legacy`,
|
||||||
noParseableQuestionResult:
|
noParseableQuestionResult:
|
||||||
'A tesztben nem találhatók kérdések, amit fel lehet dolgozni, vagy hiba történt feldolgozásuk közben',
|
'A tesztben nem találhatók kérdések, amit fel lehet dolgozni, vagy hiba történt feldolgozásuk közben',
|
||||||
|
@ -219,9 +243,19 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let select = elem.tagName ? elem.getElementsByTagName('select') : []
|
const select = elem.tagName ? elem.getElementsByTagName('select') : []
|
||||||
if (select.length > 0) {
|
if (select.length > 0) {
|
||||||
promises.push({ type: 'txt', val: '...', node: select[0] })
|
const question = []
|
||||||
|
Array.from(elem.childNodes).forEach(cn => {
|
||||||
|
if (cn.nodeValue) {
|
||||||
|
question.push(cn.nodeValue)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
promises.push({
|
||||||
|
type: 'txt',
|
||||||
|
val: question.join('...'),
|
||||||
|
node: select[0],
|
||||||
|
})
|
||||||
return promises
|
return promises
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,10 +336,6 @@
|
||||||
return document.getElementById('page-header').innerText.split('\n')[0] || ''
|
return document.getElementById('page-header').innerText.split('\n')[0] || ''
|
||||||
}
|
}
|
||||||
|
|
||||||
function uniq(a) {
|
|
||||||
return [...new Set(a)]
|
|
||||||
}
|
|
||||||
|
|
||||||
// : }}}
|
// : }}}
|
||||||
|
|
||||||
// : Test page processing functions {{{
|
// : Test page processing functions {{{
|
||||||
|
@ -405,20 +435,35 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPossibleAnswersFromTest(node) {
|
function getPossibleAnswersFromTest(node) {
|
||||||
|
try {
|
||||||
const promises = []
|
const promises = []
|
||||||
let answerRoot = node.getElementsByClassName('answer')[0]
|
let answerRoot = node.getElementsByClassName('answer')[0]
|
||||||
|
|
||||||
if (!answerRoot) {
|
if (!answerRoot) {
|
||||||
answerRoot = node.getElementsByClassName('subquestion')[0]
|
answerRoot = node.getElementsByClassName('subquestion')[0]
|
||||||
|
if (answerRoot) {
|
||||||
|
// FIXME: is this needed, what is this lol
|
||||||
const options = Array.from(answerRoot.getElementsByTagName('option'))
|
const options = Array.from(answerRoot.getElementsByTagName('option'))
|
||||||
const possibleAnswers = options.reduce((acc, option) => {
|
const possibleAnswers = options.reduce((acc, option) => {
|
||||||
if (!emptyOrWhiteSpace(option.innerText)) {
|
if (!emptyOrWhiteSpace(option.innerText)) {
|
||||||
acc.push(option.innerText)
|
acc.push([{ type: 'txt', val: option.innerText }])
|
||||||
}
|
}
|
||||||
return acc
|
return acc
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return possibleAnswers
|
return possibleAnswers
|
||||||
|
} else {
|
||||||
|
const select = node.getElementsByTagName('select')[0]
|
||||||
|
if (select) {
|
||||||
|
const options = []
|
||||||
|
Array.from(select).forEach(opt => {
|
||||||
|
if (!emptyOrWhiteSpace(opt.innerText)) {
|
||||||
|
options.push([{ type: 'txt', val: opt.innerText }])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return options
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (answerRoot.tagName === 'DIV') {
|
} else if (answerRoot.tagName === 'DIV') {
|
||||||
const answers = Array.from(answerRoot.childNodes)
|
const answers = Array.from(answerRoot.childNodes)
|
||||||
|
|
||||||
|
@ -444,6 +489,10 @@
|
||||||
|
|
||||||
return promises
|
return promises
|
||||||
}
|
}
|
||||||
|
} catch (e) {
|
||||||
|
warn('Error in getPossibleAnswersFromTest()!')
|
||||||
|
warn(e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getImgNodesFromArray(arr) {
|
function getImgNodesFromArray(arr) {
|
||||||
|
@ -494,7 +543,7 @@
|
||||||
x.reduce(makeTextFromElements, []).join(' ')
|
x.reduce(makeTextFromElements, []).join(' ')
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
let images = getImagesFromElements([
|
const images = getImagesFromElements([
|
||||||
...question,
|
...question,
|
||||||
...possibleAnswerArray.reduce((acc, x) => {
|
...possibleAnswerArray.reduce((acc, x) => {
|
||||||
return [...acc, ...x]
|
return [...acc, ...x]
|
||||||
|
@ -598,6 +647,7 @@
|
||||||
|
|
||||||
function getQuizFromNode(node) {
|
function getQuizFromNode(node) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
|
try {
|
||||||
const questionPromises = getPromisesThatMeetsRequirements(
|
const questionPromises = getPromisesThatMeetsRequirements(
|
||||||
questionGetters,
|
questionGetters,
|
||||||
node
|
node
|
||||||
|
@ -613,13 +663,16 @@
|
||||||
resolve({ success: false })
|
resolve({ success: false })
|
||||||
}
|
}
|
||||||
|
|
||||||
Promise.all([Promise.all(questionPromises), Promise.all(answerPromises)])
|
Promise.all([
|
||||||
|
Promise.all(questionPromises),
|
||||||
|
Promise.all(answerPromises),
|
||||||
|
])
|
||||||
.then(([question, answer]) => {
|
.then(([question, answer]) => {
|
||||||
const questionText = question
|
const questionText = question
|
||||||
.reduce(makeTextFromElements, [])
|
.reduce(makeTextFromElements, [])
|
||||||
.join(' ')
|
.join(' ')
|
||||||
const answerText = answer.reduce(makeTextFromElements, []).join(' ')
|
const answerText = answer.reduce(makeTextFromElements, []).join(' ')
|
||||||
let images = getImagesFromElements([...question, ...answer])
|
const images = getImagesFromElements([...question, ...answer])
|
||||||
|
|
||||||
const result = {
|
const result = {
|
||||||
Q: removeUnnecesarySpaces(questionText),
|
Q: removeUnnecesarySpaces(questionText),
|
||||||
|
@ -635,6 +688,11 @@
|
||||||
warn(err)
|
warn(err)
|
||||||
resolve({ success: false })
|
resolve({ success: false })
|
||||||
})
|
})
|
||||||
|
} catch (e) {
|
||||||
|
warn('Error in getQuizFromNode()!')
|
||||||
|
warn(e)
|
||||||
|
warn(node)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -660,7 +718,7 @@
|
||||||
return node.getElementsByClassName('qtext').length > 0
|
return node.getElementsByClassName('qtext').length > 0
|
||||||
},
|
},
|
||||||
getterFunction: node => {
|
getterFunction: node => {
|
||||||
let question = node.getElementsByClassName('qtext')[0]
|
const question = node.getElementsByClassName('qtext')[0]
|
||||||
return getTextPromisesFromNode(question)
|
return getTextPromisesFromNode(question)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -673,7 +731,7 @@
|
||||||
return node.getElementsByClassName('rightanswer').length > 0
|
return node.getElementsByClassName('rightanswer').length > 0
|
||||||
},
|
},
|
||||||
getterFunction: node => {
|
getterFunction: node => {
|
||||||
let answer = node.getElementsByClassName('rightanswer')[0]
|
const answer = node.getElementsByClassName('rightanswer')[0]
|
||||||
return getTextPromisesFromNode(answer)
|
return getTextPromisesFromNode(answer)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -755,6 +813,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPossibleAnswers(node) {
|
function getPossibleAnswers(node) {
|
||||||
|
try {
|
||||||
|
if (node.getElementsByClassName('answer').length > 0) {
|
||||||
const answerNodes = Array.from(
|
const answerNodes = Array.from(
|
||||||
node.getElementsByClassName('answer')[0].childNodes
|
node.getElementsByClassName('answer')[0].childNodes
|
||||||
)
|
)
|
||||||
|
@ -775,13 +835,30 @@
|
||||||
}
|
}
|
||||||
return acc
|
return acc
|
||||||
}, [])
|
}, [])
|
||||||
|
} else {
|
||||||
|
const select = node.getElementsByTagName('select')[0]
|
||||||
|
if (select) {
|
||||||
|
const options = []
|
||||||
|
Array.from(select.childNodes).forEach(opt => {
|
||||||
|
if (!emptyOrWhiteSpace(opt.innerText)) {
|
||||||
|
options.push(opt.innerText)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return options
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
warn('Error in getPossibleAnswers()!')
|
||||||
|
warn(e)
|
||||||
|
warn(node)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function digestMessage(message) {
|
function digestMessage(message) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
const encoder = new TextEncoder()
|
const encoder = new TextEncoder()
|
||||||
const data = encoder.encode(message)
|
const data = encoder.encode(message)
|
||||||
const hash = 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))
|
let res = String.fromCharCode.apply(null, new Uint8Array(buf))
|
||||||
res = btoa(res)
|
res = btoa(res)
|
||||||
.replace(/=/g, '')
|
.replace(/=/g, '')
|
||||||
|
@ -928,7 +1005,6 @@
|
||||||
if (elementUpdaterInterval === -1) {
|
if (elementUpdaterInterval === -1) {
|
||||||
elementUpdaterInterval = setInterval(() => {
|
elementUpdaterInterval = setInterval(() => {
|
||||||
updatableElements.forEach(({ elem, target }) => {
|
updatableElements.forEach(({ elem, target }) => {
|
||||||
let currX, currY, currWidth, currHeight
|
|
||||||
let { left, top, width, height } = target.getBoundingClientRect()
|
let { left, top, width, height } = target.getBoundingClientRect()
|
||||||
left += window.scrollX
|
left += window.scrollX
|
||||||
top += window.scrollY
|
top += window.scrollY
|
||||||
|
@ -1124,13 +1200,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetMenu() {
|
function resetMenu() {
|
||||||
SafeGetElementById('menuButtonDiv', elem => {
|
SafeGetElementById('scriptMenuDiv', elem => {
|
||||||
elem.style.backgroundColor = '#262626'
|
elem.style.backgroundColor = '#262626'
|
||||||
})
|
})
|
||||||
SafeGetElementById('ircButton', elem => {
|
SafeGetElementById('retryContainer', elem => {
|
||||||
elem.style.display = 'none'
|
|
||||||
})
|
|
||||||
SafeGetElementById('retryButton', elem => {
|
|
||||||
elem.style.display = 'none'
|
elem.style.display = 'none'
|
||||||
})
|
})
|
||||||
SafeGetElementById('loginDiv', elem => {
|
SafeGetElementById('loginDiv', elem => {
|
||||||
|
@ -1176,32 +1249,26 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function NoUserAction() {
|
function NoUserAction() {
|
||||||
SafeGetElementById('menuButtonDiv', elem => {
|
SafeGetElementById('scriptMenuDiv', elem => {
|
||||||
elem.style.backgroundColor = '#44cc00'
|
elem.style.backgroundColor = '#44cc00'
|
||||||
})
|
})
|
||||||
SafeGetElementById('infoMainDiv', elem => {
|
SafeGetElementById('infoMainDiv', elem => {
|
||||||
elem.innerText = texts.noUser
|
elem.innerText = ''
|
||||||
if (getCid()) {
|
|
||||||
elem.innerText += ` (${getCid()})`
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
SafeGetElementById('loginDiv', elem => {
|
SafeGetElementById('loginDiv', elem => {
|
||||||
elem.style.display = ''
|
elem.style.display = 'flex'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function NoServerAction() {
|
function NoServerAction() {
|
||||||
SafeGetElementById('menuButtonDiv', elem => {
|
SafeGetElementById('scriptMenuDiv', elem => {
|
||||||
elem.style.backgroundColor = 'red'
|
elem.style.backgroundColor = 'red'
|
||||||
})
|
})
|
||||||
SafeGetElementById('infoMainDiv', elem => {
|
SafeGetElementById('infoMainDiv', elem => {
|
||||||
elem.innerText = texts.noServer
|
elem.innerText = texts.noServer
|
||||||
})
|
})
|
||||||
SafeGetElementById('ircButton', elem => {
|
SafeGetElementById('retryContainer', elem => {
|
||||||
elem.style.display = ''
|
elem.style.display = 'flex'
|
||||||
})
|
|
||||||
SafeGetElementById('retryButton', elem => {
|
|
||||||
elem.style.display = ''
|
|
||||||
})
|
})
|
||||||
log(texts.noServerConsoleMessage)
|
log(texts.noServerConsoleMessage)
|
||||||
}
|
}
|
||||||
|
@ -1237,7 +1304,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function HandleUI(url) {
|
function HandleUI() {
|
||||||
const newVersion = info().script.version !== getVal('lastVerson')
|
const newVersion = info().script.version !== getVal('lastVerson')
|
||||||
const showMOTD = shouldShowMotd()
|
const showMOTD = shouldShowMotd()
|
||||||
const isNewVersionAvaible =
|
const isNewVersionAvaible =
|
||||||
|
@ -1263,10 +1330,6 @@
|
||||||
greetMsg.push(texts.versionUpdated + info().script.version)
|
greetMsg.push(texts.versionUpdated + info().script.version)
|
||||||
setVal('lastVerson', info().script.version) // setting lastVersion
|
setVal('lastVerson', info().script.version) // setting lastVersion
|
||||||
}
|
}
|
||||||
if (!installedFromCorrectSource(correctSource)) {
|
|
||||||
greetMsg.push(texts.reinstallFromCorrectSource)
|
|
||||||
log(`update url:${info().script.updateURL}`)
|
|
||||||
}
|
|
||||||
if (showMOTD) {
|
if (showMOTD) {
|
||||||
greetMsg.push(texts.motd + motd)
|
greetMsg.push(texts.motd + motd)
|
||||||
timeout = null
|
timeout = null
|
||||||
|
@ -1359,7 +1422,7 @@
|
||||||
|
|
||||||
// : Quiz saving {{{
|
// : Quiz saving {{{
|
||||||
|
|
||||||
function HandleResults(url) {
|
function HandleResults() {
|
||||||
getQuiz().then(res => {
|
getQuiz().then(res => {
|
||||||
SaveQuiz(res, ShowSaveQuizDialog) // saves the quiz questions and answers
|
SaveQuiz(res, ShowSaveQuizDialog) // saves the quiz questions and answers
|
||||||
})
|
})
|
||||||
|
@ -1433,15 +1496,6 @@
|
||||||
|
|
||||||
// : Misc {{{
|
// : Misc {{{
|
||||||
|
|
||||||
// : Install source checker {{{
|
|
||||||
|
|
||||||
function installedFromCorrectSource(source) {
|
|
||||||
// https://qmining.frylabs.net/moodle-test-userscript/stable.user.js?up
|
|
||||||
return info().script.updateURL === correctSource
|
|
||||||
}
|
|
||||||
|
|
||||||
// : }}}
|
|
||||||
|
|
||||||
// : Version action functions {{{
|
// : Version action functions {{{
|
||||||
|
|
||||||
function FreshStart() {
|
function FreshStart() {
|
||||||
|
@ -1494,7 +1548,7 @@
|
||||||
// : Video hotkey stuff {{{
|
// : Video hotkey stuff {{{
|
||||||
|
|
||||||
// this function adds basic hotkeys for video controll.
|
// this function adds basic hotkeys for video controll.
|
||||||
function AddVideoHotkeys(url) {
|
function AddVideoHotkeys() {
|
||||||
var seekTime = 20
|
var seekTime = 20
|
||||||
document.addEventListener('keydown', function(e) {
|
document.addEventListener('keydown', function(e) {
|
||||||
try {
|
try {
|
||||||
|
@ -1666,7 +1720,7 @@
|
||||||
mainDiv.offsetTop - e.clientY,
|
mainDiv.offsetTop - e.clientY,
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
mainDiv.addEventListener('mouseup', e => {
|
mainDiv.addEventListener('mouseup', () => {
|
||||||
isMouseDown = false
|
isMouseDown = false
|
||||||
})
|
})
|
||||||
mainDiv.addEventListener('mousemove', e => {
|
mainDiv.addEventListener('mousemove', e => {
|
||||||
|
@ -1848,13 +1902,12 @@
|
||||||
const buttonStyle = {
|
const buttonStyle = {
|
||||||
color: 'white',
|
color: 'white',
|
||||||
backgroundColor: 'transparent',
|
backgroundColor: 'transparent',
|
||||||
margin: buttonMargin,
|
margin: '2px',
|
||||||
border: 'none',
|
border: 'none',
|
||||||
fontSize: '30px',
|
fontSize: '30px',
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
userSelect: 'none',
|
userSelect: 'none',
|
||||||
}
|
}
|
||||||
var buttonMargin = '2px 2px 2px 2px' // uniform button margin
|
|
||||||
if (msgItem[currItem].length > 1) {
|
if (msgItem[currItem].length > 1) {
|
||||||
// PREV SUGG BUTTON ------------------------------------------------------------------------------------------------------------
|
// PREV SUGG BUTTON ------------------------------------------------------------------------------------------------------------
|
||||||
var prevSuggButton = CreateNodeWithText(
|
var prevSuggButton = CreateNodeWithText(
|
||||||
|
@ -1952,53 +2005,59 @@
|
||||||
// shows a fancy menu
|
// shows a fancy menu
|
||||||
function ShowMenu() {
|
function ShowMenu() {
|
||||||
try {
|
try {
|
||||||
const appedtTo = overlay // will be appended here
|
// Script menu -----------------------------------------------------------------
|
||||||
const menuButtonDiv = document.createElement('div')
|
const scriptMenuDiv = document.createElement('div')
|
||||||
const id = 'menuButtonDiv'
|
const id = 'scriptMenuDiv'
|
||||||
menuButtonDiv.setAttribute('id', id)
|
scriptMenuDiv.setAttribute('id', id)
|
||||||
SetStyle(menuButtonDiv, {
|
SetStyle(scriptMenuDiv, {
|
||||||
width: '600px',
|
width: '300px',
|
||||||
// height: buttonHeight + 'px',
|
height: '90px',
|
||||||
top: window.innerHeight - 160 + 'px',
|
position: 'fixed',
|
||||||
|
bottom: '10px',
|
||||||
left: '10px',
|
left: '10px',
|
||||||
zIndex: 999999,
|
zIndex: 999999,
|
||||||
position: 'fixed',
|
|
||||||
textAlign: 'center',
|
|
||||||
padding: '0px',
|
|
||||||
margin: '0px',
|
|
||||||
background: '#262626',
|
background: '#262626',
|
||||||
border: '3px solid #99f',
|
border: '3px solid #99f',
|
||||||
borderRadius: '5px',
|
borderRadius: '5px',
|
||||||
opacity: getVal(`${id}_opacity`),
|
opacity: getVal(`${id}_opacity`),
|
||||||
|
fontSize: '14px',
|
||||||
})
|
})
|
||||||
// ------------------------------------------------------------------
|
|
||||||
// transparencity
|
|
||||||
// ------------------------------------------------------------------
|
|
||||||
addOpacityChangeEvent(menuButtonDiv)
|
|
||||||
|
|
||||||
const xButton = CreateNodeWithText(menuButtonDiv, '❌', 'div')
|
addEventListener(scriptMenuDiv, 'mousedown', function(e) {
|
||||||
SetStyle(xButton, {
|
if (e.which === 2) {
|
||||||
cursor: 'pointer',
|
scriptMenuDiv.parentNode.removeChild(scriptMenuDiv)
|
||||||
position: 'absolute',
|
}
|
||||||
right: '0px',
|
|
||||||
display: 'inline',
|
|
||||||
margin: '5px',
|
|
||||||
})
|
})
|
||||||
|
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 => {
|
xButton.addEventListener('mousedown', e => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
menuButtonDiv.parentNode.removeChild(menuButtonDiv)
|
scriptMenuDiv.parentNode.removeChild(scriptMenuDiv)
|
||||||
})
|
})
|
||||||
|
|
||||||
const mailButton = CreateNodeWithText(menuButtonDiv, '📭', 'div')
|
// Mail button -----------------------------------------------------------------
|
||||||
|
const mailButton = CreateNodeWithText(scriptMenuDiv, '📭', 'div')
|
||||||
mailButton.setAttribute('id', 'mailButton')
|
mailButton.setAttribute('id', 'mailButton')
|
||||||
SetStyle(mailButton, {
|
SetStyle(mailButton, {
|
||||||
fontSize: '30px',
|
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
|
display: 'inline',
|
||||||
left: '0px',
|
left: '0px',
|
||||||
bottom: '0px',
|
bottom: '0px',
|
||||||
display: 'inline',
|
|
||||||
margin: '5px',
|
margin: '5px',
|
||||||
|
fontSize: '30px',
|
||||||
})
|
})
|
||||||
|
|
||||||
mailButton.addEventListener('mousedown', e => {
|
mailButton.addEventListener('mousedown', e => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
if (userSpecificMotd && !userSpecificMotd.seen) {
|
if (userSpecificMotd && !userSpecificMotd.seen) {
|
||||||
|
@ -2016,215 +2075,111 @@
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
var tbl = document.createElement('table')
|
// -----------------------------------------------------------------------------
|
||||||
tbl.style.margin = '5px 5px 5px 5px'
|
// BUTTONS
|
||||||
tbl.style.textAlign = 'left'
|
// -----------------------------------------------------------------------------
|
||||||
tbl.style.width = '98%'
|
const buttonContainer = document.createElement('div')
|
||||||
menuButtonDiv.appendChild(tbl)
|
SetStyle(buttonContainer, {
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
})
|
||||||
|
|
||||||
var buttonRow = tbl.insertRow()
|
scriptMenuDiv.appendChild(buttonContainer)
|
||||||
var buttonCell = buttonRow.insertCell()
|
|
||||||
buttonCell.style.textAlign = 'center'
|
|
||||||
|
|
||||||
var buttonRow2 = tbl.insertRow()
|
const buttonStyle = {
|
||||||
var buttonCell2 = buttonRow2.insertCell()
|
|
||||||
buttonCell2.style.textAlign = 'center'
|
|
||||||
|
|
||||||
let buttonStyle = {
|
|
||||||
position: '',
|
position: '',
|
||||||
margin: '5px 5px 5px 5px',
|
margin: '3px',
|
||||||
border: 'none',
|
padding: '4px 8px',
|
||||||
backgroundColor: '#333333',
|
border: '1px solid #333',
|
||||||
padding: '4px',
|
|
||||||
borderRadius: '2px',
|
borderRadius: '2px',
|
||||||
color: '#ffffff',
|
color: '#ffffff',
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
}
|
}
|
||||||
// site link ----------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
let siteLink = CreateNodeWithText(
|
Object.keys(menuButtons).forEach(key => {
|
||||||
buttonCell,
|
const buttonData = menuButtons[key]
|
||||||
texts.websiteBugreport,
|
const button = CreateNodeWithText(
|
||||||
'button'
|
buttonContainer,
|
||||||
|
buttonData.title,
|
||||||
|
'div'
|
||||||
)
|
)
|
||||||
SetStyle(siteLink, buttonStyle)
|
SetStyle(button, buttonStyle)
|
||||||
|
if (buttonData.onClick) {
|
||||||
siteLink.addEventListener('click', function() {
|
button.addEventListener('click', function() {
|
||||||
openInTab(serverAdress + 'menuClick', {
|
buttonData.onClick()
|
||||||
active: true,
|
|
||||||
})
|
})
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// help button ----------------------------------------------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
let helpButton = CreateNodeWithText(buttonCell, texts.help, 'button')
|
// Info text
|
||||||
SetStyle(helpButton, buttonStyle)
|
// -----------------------------------------------------------------------------
|
||||||
|
const infoDiv = CreateNodeWithText(scriptMenuDiv, texts.loading, 'div')
|
||||||
helpButton.addEventListener('click', function() {
|
|
||||||
ShowHelp()
|
|
||||||
}) // adding clicktextNode
|
|
||||||
|
|
||||||
// site link ----------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
let contributeLink = CreateNodeWithText(
|
|
||||||
buttonCell,
|
|
||||||
texts.contribute,
|
|
||||||
'button'
|
|
||||||
)
|
|
||||||
SetStyle(contributeLink, buttonStyle)
|
|
||||||
|
|
||||||
contributeLink.addEventListener('click', function() {
|
|
||||||
openInTab(serverAdress + 'contribute?scriptMenu', {
|
|
||||||
active: true,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
// pw request ----------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
let pwRequest = CreateNodeWithText(buttonCell2, texts.pwRequest, 'button')
|
|
||||||
pwRequest.title = texts.newPWTitle
|
|
||||||
SetStyle(pwRequest, buttonStyle)
|
|
||||||
|
|
||||||
pwRequest.addEventListener('click', function() {
|
|
||||||
openInTab(serverAdress + 'pwRequest?scriptMenu', {
|
|
||||||
active: true,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
// IRC ----------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
let ircButton2 = CreateNodeWithText(
|
|
||||||
buttonCell2,
|
|
||||||
texts.ircButton,
|
|
||||||
'button'
|
|
||||||
)
|
|
||||||
ircButton2.title = texts.ircButtonTitle
|
|
||||||
SetStyle(ircButton2, buttonStyle)
|
|
||||||
ircButton2.addEventListener('click', function() {
|
|
||||||
openInTab(serverAdress + 'irc?scriptMenu', {
|
|
||||||
active: true,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
// Dataeditor ----------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
let ranklistButton = CreateNodeWithText(
|
|
||||||
buttonCell2,
|
|
||||||
texts.ranklist,
|
|
||||||
'button'
|
|
||||||
)
|
|
||||||
SetStyle(ranklistButton, buttonStyle)
|
|
||||||
ranklistButton.addEventListener('click', function() {
|
|
||||||
openInTab(serverAdress + 'ranklist?scriptMenu', {
|
|
||||||
active: true,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
// Dataeditor ----------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
let dataEditorButton = CreateNodeWithText(
|
|
||||||
buttonCell2,
|
|
||||||
texts.dataEditor,
|
|
||||||
'button'
|
|
||||||
)
|
|
||||||
dataEditorButton.title = texts.dataEditorTitle
|
|
||||||
SetStyle(dataEditorButton, buttonStyle)
|
|
||||||
dataEditorButton.addEventListener('click', function() {
|
|
||||||
openInTab(serverAdress + 'dataeditor?scriptMenu', {
|
|
||||||
active: true,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
// donate link ----------------------------------------------------------------------------------------------------------------
|
|
||||||
let donateLink = CreateNodeWithText(buttonCell, texts.donate, 'button')
|
|
||||||
SetStyle(donateLink, buttonStyle)
|
|
||||||
|
|
||||||
donateLink.addEventListener('click', function() {
|
|
||||||
openInTab(serverAdress + 'donate?scriptMenu', {
|
|
||||||
active: true,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
addEventListener(window, 'resize', function() {
|
|
||||||
menuButtonDiv.style.top = window.innerHeight - 70 + 'px'
|
|
||||||
})
|
|
||||||
|
|
||||||
// INFO TABEL --------------------------------------------------------------------
|
|
||||||
var itbl = document.createElement('table')
|
|
||||||
SetStyle(itbl, {
|
|
||||||
margin: '5px 5px 5px 5px',
|
|
||||||
textAlign: 'left',
|
|
||||||
width: '98%',
|
|
||||||
})
|
|
||||||
menuButtonDiv.appendChild(itbl)
|
|
||||||
var ibuttonRow = tbl.insertRow()
|
|
||||||
var ibuttonCell = ibuttonRow.insertCell()
|
|
||||||
ibuttonCell.style.textAlign = 'center'
|
|
||||||
|
|
||||||
// INFO DIV ---------------------------------------------------------------------------------
|
|
||||||
let infoDiv = CreateNodeWithText(ibuttonCell, texts.loading, 'span')
|
|
||||||
infoDiv.setAttribute('id', 'infoMainDiv')
|
infoDiv.setAttribute('id', 'infoMainDiv')
|
||||||
SetStyle(infoDiv, {
|
SetStyle(infoDiv, {
|
||||||
color: '#ffffff',
|
color: '#ffffff',
|
||||||
margin: '5px',
|
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',
|
||||||
})
|
})
|
||||||
|
|
||||||
// login div ----------------------------------------------------------------------------------------------------------------
|
|
||||||
const loginDiv = document.createElement('div')
|
|
||||||
loginDiv.style.display = 'none'
|
|
||||||
loginDiv.setAttribute('id', 'loginDiv')
|
|
||||||
const loginButton = document.createElement('button')
|
|
||||||
loginButton.innerText = texts.login
|
|
||||||
const loginInput = document.createElement('input')
|
const loginInput = document.createElement('input')
|
||||||
|
loginContainer.appendChild(loginInput)
|
||||||
loginInput.type = 'text'
|
loginInput.type = 'text'
|
||||||
loginInput.style.width = '400px'
|
loginInput.placeholder = texts.pwHere
|
||||||
loginInput.style.textAlign = 'center'
|
SetStyle(loginInput, {
|
||||||
loginDiv.appendChild(loginInput)
|
width: '100%',
|
||||||
loginDiv.appendChild(loginButton)
|
textAlign: 'center',
|
||||||
|
})
|
||||||
|
|
||||||
|
const loginButton = document.createElement('div')
|
||||||
|
loginContainer.appendChild(loginButton)
|
||||||
|
loginButton.innerText = texts.login
|
||||||
SetStyle(loginButton, buttonStyle)
|
SetStyle(loginButton, buttonStyle)
|
||||||
|
|
||||||
loginButton.addEventListener('click', function() {
|
loginButton.addEventListener('click', function() {
|
||||||
Auth(loginInput.value)
|
Auth(loginInput.value)
|
||||||
})
|
})
|
||||||
|
|
||||||
ibuttonCell.appendChild(loginDiv)
|
// -----------------------------------------------------------------------------
|
||||||
|
// Retry connection button (if server is not available)
|
||||||
// irc button ----------------------------------------------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
let ircButton = CreateNodeWithText(ibuttonCell, texts.ircButton, 'button')
|
const retryContainer = CreateNodeWithText(scriptMenuDiv, '', 'div')
|
||||||
SetStyle(ircButton, buttonStyle)
|
SetStyle(retryContainer, {
|
||||||
ircButton.style.display = 'none'
|
display: 'hidden',
|
||||||
ircButton.setAttribute('id', 'ircButton')
|
justifyContent: 'center',
|
||||||
|
|
||||||
ircButton.addEventListener('click', function() {
|
|
||||||
openInTab(ircAddress, {
|
|
||||||
active: true,
|
|
||||||
})
|
})
|
||||||
|
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',
|
||||||
})
|
})
|
||||||
|
|
||||||
// retry button ----------------------------------------------------------------------------------------------------------------
|
|
||||||
let retryButton = CreateNodeWithText(ibuttonCell, texts.retry, 'button')
|
|
||||||
SetStyle(retryButton, buttonStyle)
|
|
||||||
retryButton.style.display = 'none'
|
|
||||||
retryButton.setAttribute('id', 'retryButton')
|
|
||||||
|
|
||||||
retryButton.addEventListener('click', function() {
|
retryButton.addEventListener('click', function() {
|
||||||
menuButtonDiv.style.background = '#262626'
|
scriptMenuDiv.style.background = '#262626'
|
||||||
infoDiv.innerText = texts.loading
|
infoDiv.innerText = texts.loading
|
||||||
retryButton.style.display = 'none'
|
retryContainer.style.display = 'none'
|
||||||
ircButton.style.display = 'none'
|
|
||||||
ConnectToServer(AfterLoad)
|
ConnectToServer(AfterLoad)
|
||||||
})
|
})
|
||||||
|
|
||||||
// window resize event listener ---------------------------------------
|
|
||||||
addEventListener(window, 'resize', function() {
|
|
||||||
menuButtonDiv.style.top = window.innerHeight - 70 + 'px'
|
|
||||||
})
|
|
||||||
|
|
||||||
// APPEND EVERYTHING
|
// APPEND EVERYTHING
|
||||||
appedtTo.appendChild(menuButtonDiv)
|
overlay.appendChild(scriptMenuDiv)
|
||||||
|
|
||||||
addEventListener(menuButtonDiv, 'mousedown', function(e) {
|
|
||||||
if (e.which === 2) {
|
|
||||||
menuButtonDiv.parentNode.removeChild(menuButtonDiv)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Exception(e, 'script error at showing menu:')
|
Exception(e, 'script error at showing menu:')
|
||||||
}
|
}
|
||||||
|
@ -2264,17 +2219,15 @@
|
||||||
|
|
||||||
return (
|
return (
|
||||||
value
|
value
|
||||||
.replace(/\n/g, '')
|
.replace(/\s/g, '')
|
||||||
.replace(/\t/g, '')
|
.replace(/\t/g, '')
|
||||||
.replace(/ /g, '')
|
.replace(/ /g, '')
|
||||||
.replace(/\s/g, ' ') === ''
|
.replace(/\n/g, ' ') === ''
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// : }}}
|
// : }}}
|
||||||
|
|
||||||
const specialChars = ['&', '\\+']
|
|
||||||
|
|
||||||
const assert = val => {
|
const assert = val => {
|
||||||
if (!val) {
|
if (!val) {
|
||||||
throw new Error('Assertion failed')
|
throw new Error('Assertion failed')
|
||||||
|
@ -2324,7 +2277,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function SafeGetElementById(id, next) {
|
function SafeGetElementById(id, next) {
|
||||||
let element = overlay.querySelector('#' + id)
|
const element = overlay.querySelector('#' + id)
|
||||||
if (element) {
|
if (element) {
|
||||||
next(element)
|
next(element)
|
||||||
} else {
|
} else {
|
||||||
|
@ -2419,46 +2372,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function GetXHRQuestionAnswer(question) {
|
|
||||||
log('QUESTIONS', question)
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
let url = apiAdress + 'ask?'
|
|
||||||
let params = []
|
|
||||||
Object.keys(question).forEach(key => {
|
|
||||||
let val = question[key]
|
|
||||||
if (typeof val !== 'string') {
|
|
||||||
val = JSON.stringify(val)
|
|
||||||
}
|
|
||||||
params.push(key + '=' + encodeURIComponent(val))
|
|
||||||
})
|
|
||||||
url +=
|
|
||||||
params.join('&') +
|
|
||||||
'&cversion=' +
|
|
||||||
info().script.version +
|
|
||||||
'&cid=' +
|
|
||||||
getCid()
|
|
||||||
|
|
||||||
xmlhttpRequest({
|
|
||||||
method: 'GET',
|
|
||||||
url: url,
|
|
||||||
onload: function(response) {
|
|
||||||
try {
|
|
||||||
let res = JSON.parse(response.responseText)
|
|
||||||
resolve(res.result)
|
|
||||||
} catch (e) {
|
|
||||||
reject(e)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onerror: e => {
|
|
||||||
log('Errro paring JSON in GetXHRQuestionAnswer')
|
|
||||||
log(e)
|
|
||||||
reject(e)
|
|
||||||
reject(e)
|
|
||||||
},
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function post(path, message) {
|
function post(path, message) {
|
||||||
if (typeof message === 'object') {
|
if (typeof message === 'object') {
|
||||||
message = JSON.stringify(message)
|
message = JSON.stringify(message)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue