Created
October 8, 2024 08:20
-
-
Save stefanseeger/42e1e47d0c975e2982acebdcb6ce367c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** Utils to be used in the User-Scripts */ | |
'use strict'; | |
class TmUtils { | |
/** @returns `Promise` which resolves when ``HTMLElement` for selector was found */ | |
async waitForElement(selector, base = document) { | |
return new Promise((resolve) => { | |
if (this.$(selector, base)) { | |
return resolve(this.$(selector)); | |
} | |
const observer = new MutationObserver(() => { | |
if (this.$(selector, base)) { | |
resolve(this.$(selector, base)); | |
observer.disconnect(); | |
} | |
}); | |
observer.observe(document.body, { | |
childList: true, | |
subtree: true, | |
}); | |
}); | |
} | |
/** | |
* Sets value for `HTMLInput` for selector | |
* @param force override previous value | |
*/ | |
async setValue(selectorOrElement, value, base = document, force = false) { | |
const element = this.$(selectorOrElement, base); | |
// Only set value if not set already or disabled | |
if ( | |
element && | |
(force || !this.hasValue(element)) && | |
!this.isTampermonkeyChange(element) && | |
!this.isDisabled(element) | |
) { | |
this.setTampermonkeyChange(element); | |
element.value = value; | |
element.dispatchEvent(new Event('input')); | |
element.dispatchEvent(new Event('change')); | |
element.dispatchEvent(new Event('blur')); | |
} | |
} | |
/** @returns value of `HTMLInput` for selector */ | |
getValue(selectorOrElement, base = document) { | |
const element = this.$(selectorOrElement, base); | |
return element?.value; | |
} | |
/** @returns `true` when `HTMLInput` for selector has a value. */ | |
hasValue(selectorOrElement, base = document) { | |
const value = this.getValue(selectorOrElement, base); | |
return value !== '0: null' && value !== '1: undefined' && value; | |
} | |
/** Clicks `HTMLElement` for selector */ | |
click(selectorOrElement, base = document) { | |
const element = this.$(selectorOrElement, base); | |
if ( | |
element && | |
!this.isTampermonkeyChange(element) && | |
!this.isDisabled(element) | |
) { | |
this.setTampermonkeyChange(element); | |
element.click(); | |
} | |
} | |
/** checks checkbox for selector */ | |
check(selectorOrElement, value = true, base = document) { | |
const input = this.$(selectorOrElement, base); | |
if ( | |
input && | |
input.checked != value && | |
!this.isTampermonkeyChange(input) && | |
!this.isDisabled(input) | |
) { | |
this.setTampermonkeyChange(input); | |
input.click(); | |
} | |
} | |
/** | |
* Selects `mat-option` in `mat-select` | |
* @param index of the option to select | |
*/ | |
async matSelect(selector, base = document, index = 0) { | |
const matSelect = this.$(`mat-select${selector}.ng-pristine`, base); | |
if (matSelect) { | |
matSelect.click(); | |
this.setTampermonkeyChange(matSelect); | |
await this.waitForElement('mat-option'); | |
this.$$('mat-option')[index].click(); | |
} | |
} | |
/** | |
* @returns first `HTMLELement` for the provided selector | |
* @param selectorOrElement will directly be returned if it is not a string. Otherwise `querySelector` is used. | |
*/ | |
$(selectorOrElement, base = document) { | |
if (typeof selectorOrElement === 'string') { | |
return base.querySelector(selectorOrElement); | |
} | |
return selectorOrElement; | |
} | |
/** @returns all `HTMLElements` for the provided selector */ | |
$$(selector, base = document) { | |
return base.querySelectorAll(selector); | |
} | |
/** @returns `true` when element is diabled */ | |
isDisabled(selectorOrElement, base = document) { | |
const element = this.$(selectorOrElement, base); | |
return element?.disabled; | |
} | |
/** @returns date `string` for provided `Date` object */ | |
dateString(date = new Date()) { | |
return ( | |
'' + | |
(date.getDate() + '').padStart(2, 0) + | |
'.' + | |
(date.getMonth() + 1 + '').padStart(2, 0) + | |
'.' + | |
date.getFullYear() | |
); | |
} | |
/** @returns date `string` which is accepted by the email pattern for provided `Date` object */ | |
emailFriendlyDate(date = new Date()) { | |
const year = this.dateString(date); | |
const time = | |
'' + | |
date.getHours() + | |
'-' + | |
date.getMinutes() + | |
'-' + | |
date.getSeconds(); | |
return year + '_' + time; | |
} | |
/** Resolves Promise after given timeout */ | |
async wait(timeout) { | |
if (!timeout) return; | |
return new Promise((resolve) => { | |
setTimeout(() => { | |
resolve(); | |
}, timeout); | |
}); | |
} | |
/** Searches for attribute which marks Tampermonkey changes */ | |
isTampermonkeyChange(selectorOrElement, base) { | |
const element = this.$(selectorOrElement, base); | |
return !!element?.hasAttribute('data-tampermonkey'); | |
} | |
// Set Tampermonkey change attribute | |
setTampermonkeyChange(selectorOrElement, base) { | |
const element = this.$(selectorOrElement, base); | |
element.setAttribute('data-tampermonkey', true); | |
} | |
/** Opens prompt to set a Tampermonkey value */ | |
promptValue(text, variableName, defaultValue) { | |
let value = window.GM_getValue(variableName); | |
if (!value) { | |
value = prompt(text, defaultValue ?? ''); | |
window.GM_setValue(variableName, value); | |
} | |
return value; | |
} | |
/** Checks URL for `resetTampermonkey=true` and resets all Tampermonkey values when found */ | |
resetTampermonkey() { | |
if (window.location.href.includes('resetTampermonkey=true')) { | |
const keys = window.GM_listValues(); | |
keys.forEach((key) => { | |
window.GM_deleteValue(key); | |
}); | |
alert('Tampermonkey was resetted'); | |
} | |
} | |
} | |
window.TM_Utils = new TmUtils(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment