/* mulsu.js, part of nitpo, by Thomas Krichel */ const html_ns = 'http://www.w3.org/1999/xhtml'; const fields = ['emad']; const labins = ['label', 'input']; /* STATE VARIABLES */ /* subscriber email address if set as an emad */ var set_emad = null; /* the potential emad input by the user */ var emad_input = null; /* the current repcode */ var set_repcode = null; /* the signup text without decoration, usually 'Sign up' */ var bare_signup_text = null; /* the current emad set on the signup elements */ var emad_signup = null; /* the label on the emad input, before entry */ var label_emfal = null; /* CONF variables, read with read_conf() */ /* the nitpo_url, found in the HTML id="nitpo_url" */ /* this is the king of configs. When it is zero, all the configs are read */ var nitpo_url = null; /* the nitpo path start, found in the HTML id="nitpo_pathstart" */ //var nitpo_pathstart = null; /* nitpo timeout, in miliseconds found in the HTML id="nitpo_timeout" */ //var nitpo_timeout = null; /* mulsu wait phrase, displayed while the fetch is is progress found in the HTML id="mulsu_wait_start" */ //var mulsu_wait_start = null; /* mulsu wait success phrase, displayed when the signup is successful found in the HTML id="mulsu_wait_success" */ // var mulsu_wait_success = null; /* mulsu wait failure phrase, displayed when the signup has failed found in the HTML id="mulsu_wait_failure" */ // var mulsu_wait_success = null; /* label for the input when succesfully entered */ //var label_emcor = null; var mulsu_conf = {}; // /* Phrase variables, read from the HTML file as text contents */ // function read_conf() { // /* conf variables, set to null at the start, set with read_conf */ // /* the nitpo address, found in the HTML id="nitpo_url" // if this is null, invoque read_conf */ // nitpo_url = read_a_conf('nitpo_url'); // mulsu_wait_start = read_a_conf('mulsu_wait_start'); // nitpo_wait_success = read_a_conf('mulsu_wait_success'); // mulsu_wait_failure = read_a_conf('mulsu_wait_failure'); // label_emcor = read_a_conf('label_emcor'); // } // // */ function read_conf() { /* conf variables, set to null at the start, set with read_conf */ /* the nitpo address, found in the HTML id="nitpo_url" if this is null, invoque read_conf */ conf_ele = document.getElementById('mulsu_conf'); divs = conf_ele.getElementsByTagName('div'); for (const div of divs) { mulsu_conf[div.getAttribute('id')] = div.textContent; } // console.log('conf ' + mulsu_conf); } function read_a_conf(elid) { let ele = document.getElementById(elid); if(ele === null) { return null; } out = ele.textContent; return out; } /* called by HTML */ async function on_signup(button_ele) { /* must have id of form nitpo_REPCODE_signup */ /* read the configuration if the nitpo address is not set */ if(mulsu_conf['nitpo_url'] === undefined) { read_conf(); } elid = button_ele.getAttribute('id'); set_bare_text_on_former_selection(); clear_feedback(); /* if the email input on the current element has focus, we should */ /* do nothing here, but this is not (yet) implemented */ /* this is for setting at the start, should be onload= */ if(bare_signup_text === null) { bare_signup_text = button_ele.textContent; } const old_repcode = set_repcode; /* when the emad is not set, close the form there */ set_repcode = get_repcode_from_elid(elid); /* open the emad_input_form at start, or emad_input is not an emad */ if(set_emad === null) { if(old_repcode !== null) { close_emad_input_form(old_repcode); } /* special function to activate return */ const emad_input_id = 'nitpo_' + set_repcode + '_emad_input'; const emad_input_ele = document.getElementById(emad_input_id); if(emad_input_ele !== null) { add_char_treatment(emad_input_ele); // console.log("I add char treatment to " + emad_input_id); } else { // console.log("I can't find " + emad_input_id); } open_emad_input(button_ele); return false; } focus_on_signup(set_repcode); /* only redecorate if emad_signup is not up-to-date */ if((emad_signup !== null) && (emad_signup !== set_emad)) { /* remove the fidba */ // console.log('remove feeback'); const fidba_elid = 'nitpo_' + set_repcode + '_emad_fidba'; const fidba_ele = document.getElementById(fidba_elid); if(fidba_ele !== null) { fidba_ele.textContent = ''; fidba_ele.style.display = 'none'; } else { alert('no fidba'); } decorate_signups(emad_input); focus_on_signup(set_repcode); } const url = form_url(); console.log('CALL ' + url); button_ele.oldText = button_ele.textContents; button_ele.textContent = mulsu_conf['wait_start'] + ' ' + set_emad + "…"; const response = await fetchWithTimeout(url, button_ele, options = {}); let end = ''; if(! response.ok) { catastrophic(); } else { end = mulsu_conf['wait_success']; } const json_data = await response.json(); // Get JSON value from the response body const message = json_data['message']; const fidba_elid = 'nitpo_' + set_repcode + '_emad_fidba'; const fidba_ele = document.getElementById(fidba_elid); if(button_ele !== null) { fidba_ele.textContent = message; fidba_ele.style.display = 'initial'; } console.log('result ' + message); console.log('CALLed ' + url); button_ele.textContent += ' ' + end; button_ele.disable = true; button_ele.style.display = 'none'; return true; } /* called by HTML */ function on_emad_input(ele) { /* must have id of form nitpo_REPCODE_emad_input */ const elid = ele.getAttribute('id'); emad_input = ele.value.trim(); const is_emad = is_it_emad(emad_input); if(emad_input !== null) { ele.value = emad_input; } if(is_emad === false) { cant_signup(set_repcode, emad_input); set_emad = null; decorate_signups(); when_decosi('show'); return; } // console.log('* dig for emad' + elid); // set_emad = dig_for_emad(emad_input); set_emad = emad_input; // console.log('* docorate ' + elid); decorate_signups(); relabel_emad_input(); console.log('clear feedback'); clear_feedback(); when_decosi('clear'); /* move current decosi into viewport */ const decosi_elid = 'nitpo_' + set_repcode + '_decosi'; decois_ele = document.getElementById(decosi_elid); if(! is_it_in_viewport(decosi_ele)) { decosi_ele.scrollIntoView(); } } /* function called to disable further signup attempt after a non-200 response */ function catastrophic() { button_eles = document.getElementsByTagNameNS(html_ns, 'button'); for (const button_ele of button_eles) { button_ele.style.display = 'none'; } const label_elid = 'nitpo_' + set_repcode + '_emad_label'; label_ele = document.getElementById(label_elid) if(label_ele !== null) { label_ele.style.display = 'none'; } const emad_input_elid = 'nitpo_' + set_repcode + '_emad_input'; const emad_input_ele = document.getElementById(emad_input_elid); if(emad_input_ele !== null) { emad_input_ele.style.display = 'none'; } const emad_label_elid = 'nitpo_' + set_repcode + '_emad_label'; const emad_label_ele = document.getElementById(emad_label_elid); if(emad_label_ele !== null) { console.log('hidden'); emad_label_ele.style.visibilty = 'hidden'; } const fidba_elid = 'nitpo_' + set_repcode + '_emad_fidba'; const ele = document.getElementById(fidba_elid); ele.textContent = mulsu_conf['catastrophic']; ele.style.display = 'initial'; } function clear_feedback() { fidba_eles = document.getElementsByClassName('fidba'); for (const fidba_ele of fidba_eles) { const elid = fidba_ele.getAttribute('id'); // console.log('clear_feedback ' + elid); fidba_ele.style.display = 'none'; } } function set_bare_text_on_former_selection() { /* happens of we don't have a valid email on it, before it is changed */ if(set_emad !== null) { return false; } if(set_repcode === null) { return false; } if(bare_signup_text === null) { return false; } relabel_emad_input(); const elid = 'nitpo_' + set_repcode + '_emad_input' let signup_button_ele = document.getElementById(elid); if(signup_button_ele === null) { // console.log('g 4'); return false; } // console.log('reset ' + set_repcode); signup_button_ele.textContent = bare_signup_text; // console.log('done reset ' + set_repcode + ' ' + bare_signup_text); return true; } // keep this for the moment // function dig_for_emad(string) { // /* look for the email in something like */ // /* Thomas Krichel */ // const words = string.split(" "); // let found = null; // for (const word of words) { // if(! is_it_emad(word)) { // continue; // } // found = word; // } // if(found === null) { // return null; // } // found = found.replace('<',''); // found = found.replace('>',''); // // console.log('dug emad "' + found + '"'); // return found; // } function form_url() { if(nitpo_url === null) { read_conf(); } nitpo_url = mulsu_conf['nitpo_url']; url = nitpo_url + '/' + set_repcode + '/' + set_emad; return url; } function open_emad_input(signup_ele) { let is_focus_set = false; for (const labin of labins) { for (const field of fields) { const elid = 'nitpo_' + set_repcode + '_' + field + '_' + labin const size_elid = 'nitpo_' + set_repcode + '_hezel'; // console.log("looking for " + elid); const target_ele = document.getElementById(elid); if(target_ele === null) { continue; } /* use inline-block so we can fix the width */ target_ele.style.display = 'inline-block'; if(labin !== 'input') { continue; } // console.log('set focus in target_form ' + elid); // bad target here set_width(size_elid, elid); target_ele.focus(); is_focus_set = true; if(emad_input !== null) { target_ele.value = emad_input; } } } /* close_other_forms(set_repcode);*/ if(set_emad !== null && ! is_focus_set) { console.log('focus on ' + set_repcode); focus_on_signup(set_repcode); } } function relabel_emad_input() { label_elid = 'nitpo_' + set_repcode + '_emad_label'; label_ele = document.getElementById(label_elid); if(label_ele === null) { console.log('no ' + label_elid); return false; } /* save old contents */ if(label_emfal === null) { label_emfal = label_ele.textContent; } /* no email set ... revert to early stage */ /* emcor means email correct */ /* emfal means email false */ if(set_emad === null) { label_ele.classList.add('label_emfal'); label_ele.classList.remove('label_emcor'); label_ele.textContent = label_emfal; return; } console.log('emcor ' + label_elid + ' ' + mulsu_conf['label_emcor']); label_ele.classList.add('label_emcor'); label_ele.classList.remove('label_emfal'); // console.log('add ' + mulsu_conf['label_emcor']); label_ele.textContent = mulsu_conf['label_emcor']; return false; } function cant_signup(repcode, string) { const signup_elid = 'nitpo_' + repcode + '_signup'; const fidba_elid = 'nitpo_' + repcode + '_emad_fidba'; const input_elid = 'nitpo_' + repcode + '_emad_input'; const input_ele = document.getElementById(input_elid); /* set input length if(input_ele !== null) { const input_length = input_ele.value.length; // multiply by 1.25 for extra space const show_input = 1.25 * input_length; console.log('show_input' + show_input); input_ele.style.width = show_input + 'ch'; } */ /* if we have the fidba element, print fidba there */ const signup_ele = document.getElementById(signup_elid); const fidba_ele = document.getElementById(fidba_elid); if(signup_ele === null && fidba_ele === null) { return; } let target_ele = signup_ele; if(fidba_ele !== null) { target_ele = fidba_ele; target_ele.style.display = 'initial'; } if(string === '') { /* just show the default */ signup_ele.textContent = bare_signup_text; } else { target_ele.textContent = "I can’t sign up “" + string + "”"; } if(repcode === set_repcode) { console.log('in cant, set focus on ' + input_elid); input_ele.focus(); } return false; } function focus_on_signup(repcode) { elid = 'nitpo_' + repcode + '_signup'; let signup_ele = document.getElementById(elid); if(signup_ele === null) { console.log("I can't see the element " + elid); return false; } signup_ele.focus(); signup_ele.value = emad_input; return false; } function close_emad_input_form(repcode) { if(set_repcode === null) { console.log("With no set repcode, I keep the input open."); return false; } for (const field of fields) { for (const labin of labins) { const elid = 'nitpo_' + repcode + '_' + field + '_' + labin; const target_ele = document.getElementById(elid); if(target_ele === null) { continue; } target_ele.style.display = 'none'; } } return true; } function when_decosi(string) { console.log('start when_decosi'); if(string == 'clear') { eles = document.getElementsByClassName('clear_when_decosi'); for (const ele of eles) { ele.style.display = 'none'; } return true; } if(string == 'show') { eles = document.getElementsByClassName('clear_when_decosi'); for (const ele of eles) { ele.style.display = 'initial'; } return true; } return false; } function decorate_signups() { relabel_emad_input(); // console.log('start of decorate at ' + set_repcode); button_eles = document.getElementsByTagNameNS(html_ns, 'button'); /* don't overwrite the current signup button */ const current_signup_elid = 'nitpo_' + set_repcode + '_signup'; /* decorated signup, if different */ const current_decosi_elid = 'nitpo_' + set_repcode + '_decosi'; const have_i_decosi = have_i(current_decosi_elid); for (const button_ele of button_eles) { if(button_ele.disabled) { continue; } const button_id = button_ele.getAttribute('id'); // console.log(button_id + ' ' + have_i_decosi); if(button_id.substr(0,6) !== 'nitpo_') { continue; } button_type = decosi_or_signup(button_ele); if(! ( button_type == 'signup' || button_type == 'decosi')) { console.log('bad button ' + button_id + ' ' + button_type); continue; } const repcode = get_repcode_from_elid(button_id); if(set_emad === null) { if(button_type === 'signup') { if(have_i_decosi) { button_ele.style.display = 'initial'; button_ele.textContent = bare_signup_text; } else if(button_ele.getAttribute('id') != current_signup_elid) { button_ele.textContent = bare_signup_text; } } if(button_type === 'decosi') { button_ele.style.display = 'none'; } } else { /* set the focus */ // console.log('set_emad'); button_ele.textContent = bare_signup_text + " " + set_emad; if(button_type === 'decosi') { // console.log('decosi ' + button_id); button_ele.style.display = 'initial'; if(repcode == set_repcode) { console.log('set focus in decorate ' + set_repcode + ' ' + button_id); //console.log(signup_button_ele); button_ele.focus(); } } if(button_type === 'signup') { button_ele.textContent = bare_signup_text + " " + set_emad; if(have_i_decosi) { button_ele.style.display = 'none'; } else { /* just in case */ button_ele.style.display = 'initial'; } // repcode = get_repcode_from_elid(button_id); } } } emad_signup = set_emad; return true; } function have_i(elid) { const out = document.getElementById(elid); console.log("have i " + elid); if(out === null) { return false; } return true; } /* decosi or signup ? */ function decosi_or_signup(ele) { elid = ele.getAttribute('id'); return elid.substr(-6); } function is_it_emad(string) { /* this is the same check as used server-side, don't change */ const is_emad = /([^@]+@[^@]+\.[^@]+)/.test(string); return is_emad; } /* function has_emad(string) { const last_part = last_word(string); if(is_it_emad(last_part)) { return last_part; } return null; } function last_word(anchor_string) { const words = anchor_string.split(" "); return words[words.length - 1]; } */ function get_repcode_from_elid(elid) { // starts with nitpo_ const from_repcode_start = elid.substring(6); const end_of_repcode = from_repcode_start.indexOf('_') const repcode = from_repcode_start.substring(0, end_of_repcode) return repcode; } async function call_fetch(url) { try { let res = await fetch(url); return await res; } catch (error) { console.log(error); } } /* from https://dmitripavlutin.com/timeout-fetch-reqpuest/ */ async function fetchWithTimeout(url, button_ele, options = {}) { const { timeout = mulsu_conf['nitpo_timeout'] } = options; const controller = new AbortController(); const timeout_id = setTimeout(() => controller.abort(), timeout); const response = await call_fetch(url, { signal: controller.signal }); clearTimeout(timeout_id); return response; } function add_char_treatment(ele) { ele.addEventListener('keyup', function(event) { const code = event.keyCode; if(! (code == 13 || code == 32)) { /* if(code != 13) { */ return; } const on_ele = document.activeElement; const on_elid = on_ele.getAttribute('id'); const to_elid = 'nitpo_' + set_repcode + '_signup'; const to_ele = document.getElementById(to_elid); on_ele.blur(); to_ele.focus(); }); return false; } function set_width(elid_from, elid_to) { const from = document.getElementById(elid_from); const to = document.getElementById(elid_to); if(from === null) { console.log("I can't see " + elid_from); return; } style = window.getComputedStyle(from); width = style.getPropertyValue('width'); console.log('width set to ' + width + ' of ' + elid_from); to.style.width = width; } function is_it_in_viewport(ele) { var top = ele.offsetTop; var left = ele.offsetLeft; var width = ele.offsetWidth; var height = ele.offsetHeight; while(ele.offsetParent) { ele = ele.offsetParent; top += ele.offsetTop; left += ele.offsetLeft; } return ( top < (window.pageYOffset + window.innerHeight) && left < (window.pageXOffset + window.innerWidth) && (top + height) > window.pageYOffset && (left + width) > window.pageXOffset ); }