2022-10-14 10:47:08 +00:00
function getMessageFromJsonData ( success , json ) {
let message = success ? "Success!" : "Error, please try again later" ;
let key = success ? "message" : "error" ;
if ( ! json || ! json [ key ] ) return message ;
message = json [ key ] ;
if ( ! success && json [ "details" ] ) {
message = json [ "details" ] ;
}
return message ;
}
function showToast ( success , message , isToastTwo = false ) {
let element = success ? "toast-post-success" : "toast-post-error" ;
2022-10-14 12:33:36 +00:00
let textElement = element + "-text" ;
2022-10-14 10:47:08 +00:00
if ( isToastTwo ) {
2022-10-14 12:33:36 +00:00
element = element + "2" ;
textElement = textElement + "2" ;
}
2022-10-14 09:49:58 +00:00
if ( ! message ) {
message = success ? "Success" : "Error, please try again later" ;
}
2022-10-14 10:47:08 +00:00
document . getElementById ( textElement ) . innerText = message ;
2022-10-14 09:49:58 +00:00
bootstrap . Toast . getOrCreateInstance ( document . getElementById ( element ) ) . show ( ) ;
2022-10-14 08:19:09 +00:00
}
2022-10-14 12:43:23 +00:00
function createXhrWithFormKey ( url , method = "POST" , form = new FormData ( ) ) {
2022-10-14 12:33:36 +00:00
const xhr = new XMLHttpRequest ( ) ;
xhr . open ( method , url ) ;
xhr . setRequestHeader ( 'xhr' , 'xhr' ) ;
2022-10-14 12:43:23 +00:00
if ( ! form ) form = new FormData ( ) ;
2022-10-14 12:33:36 +00:00
form . append ( "formkey" , formkey ( ) ) ;
return [ xhr , form ] ; // hacky but less stupid than what we were doing before
2022-10-14 11:31:02 +00:00
}
2022-10-14 07:58:05 +00:00
2022-11-06 12:04:00 +00:00
function postToast ( t , url , data , extraActionsOnSuccess , method = "POST" ) {
2022-11-07 05:41:57 +00:00
const isShopConfirm = t . id . startsWith ( 'buy1-' ) || t . id . startsWith ( 'buy2-' ) || t . id . startsWith ( 'giveaward' )
2022-11-03 19:07:08 +00:00
if ( ! isShopConfirm )
{
t . disabled = true ;
t . classList . add ( "disabled" ) ;
}
2022-10-14 07:58:05 +00:00
2022-10-14 12:33:36 +00:00
let form = new FormData ( ) ;
2022-10-14 07:58:05 +00:00
if ( typeof data === 'object' && data !== null ) {
for ( let k of Object . keys ( data ) ) {
form . append ( k , data [ k ] ) ;
}
}
2022-11-06 12:04:00 +00:00
const xhr = createXhrWithFormKey ( url , method , form ) ;
2022-10-14 12:01:11 +00:00
xhr [ 0 ] . onload = function ( ) {
2022-10-14 07:58:05 +00:00
let result
2022-10-14 12:33:36 +00:00
let message ;
let success = xhr [ 0 ] . status >= 200 && xhr [ 0 ] . status < 300 ;
2022-11-04 21:56:08 +00:00
if ( success && extraActionsOnSuccess ) result = extraActionsOnSuccess ( xhr [ 0 ] ) ;
2022-10-14 12:33:36 +00:00
if ( typeof result == "string" ) {
message = result ;
} else {
message = getMessageFromJsonData ( success , JSON . parse ( xhr [ 0 ] . response ) ) ;
}
let oldToast = bootstrap . Toast . getOrCreateInstance ( document . getElementById ( 'toast-post-' + ( success ? 'error' : 'success' ) ) ) ; // intentionally reversed here: this is the old toast
oldToast . hide ( ) ;
showToast ( success , message ) ;
2022-11-03 19:07:08 +00:00
if ( ! isShopConfirm ) {
t . disabled = false ;
t . classList . remove ( "disabled" ) ;
}
2022-10-14 12:33:36 +00:00
return success ;
2022-10-14 07:58:05 +00:00
} ;
2022-10-14 12:01:11 +00:00
xhr [ 0 ] . send ( xhr [ 1 ] ) ;
2022-11-03 19:07:08 +00:00
if ( ! isShopConfirm )
{
setTimeout ( ( ) => {
t . disabled = false ;
t . classList . remove ( "disabled" ) ;
} , 2000 ) ;
}
}
2022-11-06 12:04:00 +00:00
function postToastReload ( t , url , method = "POST" ) {
2022-11-04 21:44:37 +00:00
postToast ( t , url ,
{
} ,
( ) => {
location . reload ( )
}
2022-11-06 12:04:00 +00:00
, method ) ;
2022-11-04 21:44:37 +00:00
}
2022-11-06 12:04:00 +00:00
function postToastSwitch ( t , url , button1 , button2 , cls , extraActionsOnSuccess , method = "POST" ) {
2022-11-03 19:08:22 +00:00
postToast ( t , url ,
2022-11-03 19:07:08 +00:00
{
} ,
( xhr ) => {
2022-11-04 18:45:52 +00:00
if ( button1 )
{
if ( typeof ( button1 ) == 'boolean' ) {
location . reload ( )
} else {
2022-12-16 20:00:42 +00:00
try {
document . getElementById ( button1 ) . classList . toggle ( cls ) ;
2022-12-16 20:17:23 +00:00
}
catch ( e ) { }
try {
document . getElementById ( button2 ) . classList . toggle ( cls ) ;
2022-12-16 20:00:42 +00:00
}
catch ( e ) { }
2022-11-04 18:45:52 +00:00
}
}
2022-11-04 21:56:08 +00:00
if ( extraActionsOnSuccess ) extraActionsOnSuccess ( xhr ) ;
2022-11-03 19:07:08 +00:00
}
2022-11-06 12:04:00 +00:00
, method ) ;
2022-10-14 07:58:05 +00:00
}
if ( window . location . pathname != '/submit' )
{
document . addEventListener ( 'keydown' , ( e ) => {
if ( ! ( ( e . ctrlKey || e . metaKey ) && e . key === "Enter" ) ) return ;
const targetDOM = document . activeElement ;
if ( ! ( targetDOM instanceof HTMLTextAreaElement || targetDOM instanceof HTMLInputElement ) ) return ;
const formDOM = targetDOM . parentElement ;
const submitButtonDOMs = formDOM . querySelectorAll ( 'input[type=submit], .btn-primary' ) ;
if ( submitButtonDOMs . length === 0 )
throw new TypeError ( "I am unable to find the submit button :(. Contact the head custodian immediately." )
const btn = submitButtonDOMs [ 0 ]
btn . click ( ) ;
} ) ;
}
addEventListener ( 'show.bs.modal' , function ( e ) {
location . hash = "modal" ;
} ) ;
addEventListener ( 'hide.bs.modal' , function ( e ) {
if ( location . hash == "#modal" ) {
history . back ( ) ;
}
} ) ;
addEventListener ( 'hashchange' , function ( e ) {
if ( location . hash != "#modal" ) {
const curr _modal = bootstrap . Modal . getInstance ( document . getElementsByClassName ( 'show' ) [ 0 ] )
if ( curr _modal ) curr _modal . hide ( )
}
} ) ;
function disable ( t ) {
t . classList . add ( 'disabled' ) ;
setTimeout ( ( ) => {
t . classList . remove ( "disabled" ) ;
} , 2000 ) ;
}
2022-11-08 04:09:55 +00:00
function autoExpand ( field ) {
2022-10-14 07:58:05 +00:00
xpos = window . scrollX ;
ypos = window . scrollY ;
field . style . height = 'inherit' ;
2022-12-04 15:40:32 +00:00
let computed = window . getComputedStyle ( field ) ;
2022-10-14 07:58:05 +00:00
2022-12-04 15:40:32 +00:00
let height = parseInt ( computed . getPropertyValue ( 'border-top-width' ) , 10 )
2022-10-14 07:58:05 +00:00
+ parseInt ( computed . getPropertyValue ( 'padding-top' ) , 10 )
+ field . scrollHeight
+ parseInt ( computed . getPropertyValue ( 'padding-bottom' ) , 10 )
+ parseInt ( computed . getPropertyValue ( 'border-bottom-width' ) , 10 ) ;
field . style . height = height + 'px' ;
if ( Math . abs ( window . scrollX - xpos ) < 1 && Math . abs ( window . scrollY - ypos ) < 1 ) return ;
window . scrollTo ( xpos , ypos ) ;
} ;
document . addEventListener ( 'input' , function ( event ) {
if ( event . target . tagName . toLowerCase ( ) !== 'textarea' ) return ;
autoExpand ( event . target ) ;
} , false ) ;
function smoothScrollTop ( )
{
window . scrollTo ( { top : 0 , behavior : 'smooth' } ) ;
}
// Click navbar to scroll back to top
2022-11-26 05:34:50 +00:00
const nav = document . getElementsByTagName ( 'nav' )
2022-12-04 15:40:32 +00:00
if ( nav . length ) {
2022-11-26 05:34:50 +00:00
nav [ 0 ] . addEventListener ( 'click' , ( e ) => {
if ( e . target . id === "navbar" ||
e . target . classList . contains ( "container-fluid" ) ||
e . target . id == "navbarResponsive" ||
e . target . id == "logo-container" ||
e . target . classList . contains ( "srd" ) )
smoothScrollTop ( ) ;
} , false ) ;
}
2022-10-14 07:58:05 +00:00
// Dynamic shadow when the user scrolls
document . addEventListener ( 'scroll' , function ( event ) {
let nav = document . querySelector ( "nav" ) ;
let i = ( Math . min ( 20 , window . scrollY / 4 ) + 1 ) / 21 ;
nav . style . boxShadow = "0px 2px " + i * 21 + "px rgba(15,15,15," + i * . 3 + ")" ;
if ( window . scrollY <= 0 )
{
// nav.classList.remove("shadow");
nav . classList . remove ( "navbar-active" ) ;
nav . style . boxShadow = "unset" ;
}
else
{
// nav.classList.add("shadow");
nav . classList . add ( "navbar-active" ) ;
}
} , false ) ;
function formkey ( ) {
let formkey = document . getElementById ( "formkey" )
if ( formkey ) return formkey . innerHTML ;
else return null ;
}
function expandDesktopImage ( url ) {
const e = this . event
if ( e . ctrlKey || e . metaKey || e . shiftKey || e . altKey )
2022-11-07 10:49:49 +00:00
return ;
2022-10-14 07:58:05 +00:00
e . preventDefault ( ) ;
if ( ! url )
{
url = e . target . dataset . src
if ( ! url ) url = e . target . src
}
document . getElementById ( "desktop-expanded-image" ) . src = url . replace ( "200w_d.webp" , "giphy.webp" ) ;
document . getElementById ( "desktop-expanded-image-wrap-link" ) . href = url ;
bootstrap . Modal . getOrCreateInstance ( document . getElementById ( 'expandImageModal' ) ) . show ( ) ;
} ;
function bs _trigger ( e ) {
let tooltipTriggerList = [ ] . slice . call ( e . querySelectorAll ( '[data-bs-toggle="tooltip"]' ) ) ;
tooltipTriggerList . map ( function ( element ) {
return bootstrap . Tooltip . getOrCreateInstance ( element ) ;
} ) ;
const popoverTriggerList = [ ] . slice . call ( e . querySelectorAll ( '[data-bs-toggle="popover"]' ) ) ;
popoverTriggerList . map ( function ( popoverTriggerEl ) {
const popoverId = popoverTriggerEl . getAttribute ( 'data-content-id' ) ;
let contentEl ;
try { contentEl = e . getElementById ( popoverId ) ; }
catch ( t ) { contentEl = document . getElementById ( popoverId ) ; }
if ( contentEl ) {
return bootstrap . Popover . getOrCreateInstance ( popoverTriggerEl , {
content : contentEl . innerHTML ,
html : true ,
} ) ;
}
} )
2022-11-21 15:14:26 +00:00
if ( typeof update _speed _emoji _modal == 'function' ) {
2022-10-14 07:58:05 +00:00
let forms = e . querySelectorAll ( "textarea, .allow-emojis" ) ;
forms . forEach ( i => {
let pseudo _div = document . createElement ( "div" ) ;
pseudo _div . className = "ghostdiv" ;
pseudo _div . style . display = "none" ;
i . after ( pseudo _div ) ;
i . addEventListener ( 'input' , update _speed _emoji _modal , false ) ;
i . addEventListener ( 'keydown' , speed _carot _navigate , false ) ;
} ) ;
}
}
2022-12-04 15:40:32 +00:00
let bsTriggerOnReady = function ( ) {
2022-10-14 07:58:05 +00:00
bs _trigger ( document ) ;
}
if ( document . readyState === "complete" ||
( document . readyState !== "loading" && ! document . documentElement . doScroll ) ) {
bsTriggerOnReady ( ) ;
} else {
document . addEventListener ( "DOMContentLoaded" , bsTriggerOnReady ) ;
}
function escapeHTML ( unsafe ) {
return unsafe . replace ( /&/g , "&" ) . replace ( /</g , "<" ) . replace ( />/g , ">" ) . replace ( /"/g , """ ) . replace ( /'/g , "'" ) ;
}
function changename ( s1 , s2 ) {
const files = document . getElementById ( s2 ) . files ;
if ( files . length > 4 )
{
alert ( "You can't upload more than 4 files at one time!" )
2022-12-07 16:51:51 +00:00
document . getElementById ( s2 ) . value = null
2022-10-14 07:58:05 +00:00
return
}
let filename = '' ;
for ( const e of files ) {
2022-11-07 22:25:39 +00:00
filename += e . name . substr ( 0 , 22 ) + ', ' ;
2022-10-14 07:58:05 +00:00
}
document . getElementById ( s1 ) . innerHTML = escapeHTML ( filename . slice ( 0 , - 2 ) ) ;
}
function showmore ( ) {
const btn = this . event . target
const div = btn . parentElement . nextElementSibling
div . classList . toggle ( 'd-none' )
if ( div . classList . contains ( 'd-none' ) )
btn . innerHTML = 'SHOW MORE'
else
btn . innerHTML = 'SHOW LESS'
}
function formatDate ( d ) {
2022-12-04 15:40:32 +00:00
let year = d . getFullYear ( ) ;
let monthAbbr = d . toLocaleDateString ( 'en-us' , { month : 'short' } ) ;
let day = d . getDate ( ) ;
let hour = ( "0" + d . getHours ( ) ) . slice ( - 2 ) ;
let minute = ( "0" + d . getMinutes ( ) ) . slice ( - 2 ) ;
let second = ( "0" + d . getSeconds ( ) ) . slice ( - 2 ) ;
let tzAbbr = d . toLocaleTimeString ( 'en-us' , { timeZoneName : 'short' } ) . split ( ' ' ) [ 2 ] ;
2022-10-14 07:58:05 +00:00
return ( day + " " + monthAbbr + " " + year + " "
2022-10-14 09:49:58 +00:00
+ hour + ":" + minute + ":" + second + " " + tzAbbr ) ;
2022-10-14 07:58:05 +00:00
}
const timestamps = document . querySelectorAll ( '[data-time]' ) ;
for ( const e of timestamps ) {
2022-11-25 23:25:15 +00:00
e . innerHTML = formatDate ( new Date ( e . dataset . time * 1000 ) ) ;
2022-10-14 07:58:05 +00:00
} ;
function timestamp ( str , ti ) {
2022-11-25 23:25:15 +00:00
const date = formatDate ( new Date ( ti * 1000 ) ) ;
document . getElementById ( str ) . setAttribute ( "data-bs-original-title" , date ) ;
2022-10-14 07:58:05 +00:00
} ;
function areyousure ( t ) {
if ( t . value )
t . value = 'Are you sure?'
else
t . innerHTML = t . innerHTML . replace ( t . textContent , 'Are you sure?' )
2022-12-11 19:19:10 +00:00
t . setAttribute ( "onclick" , t . dataset . click ) ;
2022-10-14 07:58:05 +00:00
if ( t . dataset . dismiss )
2022-10-14 09:49:58 +00:00
t . setAttribute ( "data-bs-dismiss" , t . dataset . dismiss ) ;
2022-10-14 18:20:23 +00:00
}
2022-10-24 22:36:51 +00:00
function prepare _to _pause ( audio ) {
for ( const e of document . querySelectorAll ( 'video,audio' ) )
{
e . addEventListener ( 'play' , ( ) => {
if ( ! audio . paused ) audio . pause ( ) ;
} ) ;
}
2022-11-18 19:41:03 +00:00
window . addEventListener ( 'click' , ( e ) => {
if ( e . target . tagName . toLowerCase ( ) == "lite-youtube" && ! audio . paused ) audio . pause ( ) ;
} ) ;
2022-10-24 22:36:51 +00:00
}
2022-11-07 06:08:50 +00:00
function sendFormXHR ( e , extraActionsOnSuccess ) {
const form = e . target ;
const xhr = new XMLHttpRequest ( ) ;
e . preventDefault ( ) ;
formData = new FormData ( form ) ;
formData . append ( "formkey" , formkey ( ) ) ;
actionPath = form . getAttribute ( "action" ) ;
xhr . open ( "POST" , actionPath ) ;
xhr . setRequestHeader ( 'xhr' , 'xhr' ) ;
xhr . onload = function ( ) {
if ( xhr . status >= 200 && xhr . status < 300 ) {
let data = JSON . parse ( xhr . response ) ;
showToast ( true , getMessageFromJsonData ( true , data ) ) ;
if ( extraActionsOnSuccess ) extraActionsOnSuccess ( xhr ) ;
} else {
document . getElementById ( 'toast-post-error-text' ) . innerText = "Error, please try again later."
try {
let data = JSON . parse ( xhr . response ) ;
2022-12-04 15:40:32 +00:00
bootstrap . Toast . getOrCreateInstance ( document . getElementById ( 'toast-post-error' ) ) . show ( ) ;
2022-11-07 06:08:50 +00:00
document . getElementById ( 'toast-post-error-text' ) . innerText = data [ "error" ] ;
if ( data && data [ "details" ] ) document . getElementById ( 'toast-post-error-text' ) . innerText = data [ "details" ] ;
} catch ( e ) {
2022-12-04 15:40:32 +00:00
bootstrap . Toast . getOrCreateInstance ( document . getElementById ( 'toast-post-success' ) ) . hide ( ) ;
bootstrap . Toast . getOrCreateInstance ( document . getElementById ( 'toast-post-error' ) ) . show ( ) ;
2022-11-07 06:08:50 +00:00
}
}
} ;
xhr . send ( formData ) ;
}
2022-11-07 06:30:41 +00:00
function sendFormXHRSwitch ( e ) {
2022-11-07 06:08:50 +00:00
sendFormXHR ( e ,
( ) => {
2022-11-07 06:30:41 +00:00
e . target . previousElementSibling . classList . remove ( 'd-none' ) ;
e . target . classList . add ( 'd-none' ) ;
2022-11-07 06:08:50 +00:00
}
)
}
2022-12-10 10:40:34 +00:00
let sortAscending = { } ;
function sort _table ( t ) {
const n = Array . prototype . indexOf . call ( t . parentElement . children , t ) ;
const table = this . event . target . parentElement . parentElement . parentElement
const rows = table . rows ;
let items = [ ] ;
for ( let i = 1 ; i < rows . length ; i ++ ) {
const ele = rows [ i ] ;
let x = rows [ i ] . getElementsByTagName ( "TD" ) [ n ] ;
if ( ! ( 'sortKey' in x . dataset ) ) {
x = x . getElementsByTagName ( 'a' ) [ 0 ] || x ;
}
let attr ;
if ( 'sortKey' in x . dataset ) {
attr = x . dataset . sortKey ;
} else if ( 'time' in x . dataset ) {
attr = parseInt ( x . dataset . time ) ;
} else {
attr = x . innerText
2022-12-10 11:57:23 +00:00
if ( /^[\d-,]+$/ . test ( x . innerHTML ) ) {
2022-12-10 10:40:34 +00:00
attr = parseInt ( attr . replace ( /,/g , '' ) )
}
}
items . push ( { ele , attr } ) ;
}
if ( sortAscending [ n ] ) {
items . sort ( ( a , b ) => a . attr > b . attr ? 1 : - 1 ) ;
sortAscending [ n ] = false ;
} else {
items . sort ( ( a , b ) => a . attr < b . attr ? 1 : - 1 ) ;
sortAscending [ n ] = true ;
}
for ( let i = items . length - 1 ; i -- ; ) {
items [ i ] . ele . parentNode . insertBefore ( items [ i ] . ele , items [ i + 1 ] . ele ) ;
}
}
document . addEventListener ( "click" , function ( e ) {
const element = e . target
if ( element instanceof HTMLImageElement && element . alt . startsWith ( '![](' ) )
expandDesktopImage ( )
else if ( element . tagName == "TH" )
sort _table ( element )
} ) ;