view src/site.js @ 27:176a182c02cf

add view_course
author Franklin Schmidt <fschmidt@gmail.com>
date Fri, 01 Aug 2025 20:08:13 -0600
parents f5425a3c1898
children 99b71a377f2c
line wrap: on
line source

'use strict';

function ajax(url,postData) {
	let request = new XMLHttpRequest();
	let method = postData ? "POST" : "GET";
	request.open( method, url );
	if( typeof(postData)==='string' )
		request.setRequestHeader( "Content-Type", "application/x-www-form-urlencoded" );
	request.onload = function() {
		if( request.status !== 200 ) {
			let err = 'sr_ajax failed: ' + request.status;
			if( request.responseText ) {
				err += '\n' + request.responseText;
				document.write('<pre>'+request.responseText+'</pre>');
			}
			err += '\npage = ' + window.location;
			ajax( '/error_log.js', 'err='+encodeURIComponent(err) );
			return;
		}
		try {
			//console.log(request.responseText);
			eval( request.responseText );
		} catch(e) {
			window.sr_err = '\najax-url = ' + url;
			//window.sr_err += '\n'+('ajax-response =\n' + request.responseText).trim();
			throw e;
		}
	};
	request.send(postData);
}

window.onerror = function(msg, url, line, col, error) {
	if( !url )
		return;
	let err = msg;
	err += '\nurl = ' + url;
	if( url != window.location )
		err += '\npage = ' + window.location;
	err += '\nline = '+line;
	if( col )
		err += '\ncolumn = ' + col;
	if( error ) {
		if( error.stack )
			err += '\nstack = ' + error.stack;
		if( error.cause )
			err += '\ncause= ' + error.cause;
		if( error.fileName )
			err += '\nfileName= ' + error.fileName;
	}
	if( window.err ) {
		err += window.err;
		window.err = null;
	}
	ajax( '/error_log.js', 'err='+encodeURIComponent(err) );
};

function ajaxForm(url,form) {
	let post = '';
	for( let i=0; i<form.length; i++ ) {
		let input = form[i];
		let name = input.name;
		if( name === '' )
			continue;
		let type = input.type;
		if( (type==='radio' || type==='checkbox') && !input.checked )
			continue;
		post += name + '=' + encodeURIComponent(input.value) + '&';
	}
	ajax(url,post,{form:form});
}


let currentPulldown = null;
let newPulldown = null;

function clickMenu(clicked,display) {
	//console.log('clickMenu');
	let pulldown = clicked.parentNode.querySelector('div');
	if( pulldown !== currentPulldown ) {
		pulldown.style.display = display || 'block';
		newPulldown = pulldown;
		window.onclick = function() {
			//console.log('window.onclick');
			if( currentPulldown ) {
				currentPulldown.style.display = 'none';
				if( !newPulldown )
					window.onclick = null;
			}
			currentPulldown = newPulldown;
			newPulldown = null;
		};
		pulldown.scrollIntoViewIfNeeded(false);
	}
}

function getEnclosingDialog(el) {
	while( el.nodeName !== 'DIALOG' )
		el = el.parentNode;
	return el;
}

function closeModal(el) {
	getEnclosingDialog(el).close();
}

let lastY = 0;

function scrollToTop() {
	lastY = window.scrollY;
	window.scrollTo( 0, 0 );
}

function scrollToBottom() {
	lastY = window.scrollY;
	window.scrollTo( 0, document.body.scrollHeight );
}

function scrollBack() {
	window.scrollTo( 0, lastY );
}


// requires markdown-it

let mdDiv = document.createElement('div');

function handleMarkdown() {
	let converter = window.markdownit({html: true});
	let divs = document.querySelectorAll('[markdown]');
	for( let div of divs ) {
		let text = div.textContent;
		text = text.replace(/\{([^|}]+)\|([^|}]+)\}/g, '<ruby>$1<rt>$2</rt></ruby>');
		text = converter.render(text);
		if( div.getAttribute('role')==='assistant' ) {
			mdDiv.innerHTML = text;
			let rts = mdDiv.querySelectorAll('rt');
			for( let rt of rts ) {
				rt.remove();
			}
			//console.log(mdDiv.textContent);
			let lang = div.getAttribute('lang');
			text += `\n<p><audio controls preload=none src="/tts.mp3?lang=${lang}&text=${encodeURIComponent(mdDiv.textContent)}"></p>\n`;
		}
		div.innerHTML = text;
		div.removeAttribute('markdown');
	}
}