2022-11-20 12:55:35 +00:00
|
|
|
|
|
|
|
// Just to make the console a bit queer.
|
|
|
|
console.info('%c \n Be yourself! \n\n', `
|
|
|
|
font-family: Ubuntu, sans-serif;
|
|
|
|
font-size: 5rem;
|
|
|
|
font-weight: bold;
|
|
|
|
color: white;
|
|
|
|
text-shadow:
|
|
|
|
1px 1px #ff69b5,
|
|
|
|
2px 2px #ff0000,
|
|
|
|
3px 3px #ff8f00,
|
|
|
|
4px 4px #ffff00,
|
|
|
|
5px 5px #008f00,
|
|
|
|
6px 6px #00c1c1,
|
|
|
|
7px 7px #3e0099,
|
|
|
|
8px 8px #8f008f;
|
|
|
|
`)
|
2022-11-20 14:27:44 +00:00
|
|
|
|
2022-11-22 11:48:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
// GET HTML ELEMENTS ONCE
|
|
|
|
|
|
|
|
const body = document.getElementsByTagName('body')[0]
|
|
|
|
const websiteTitle = document.getElementById('websiteTitle')
|
|
|
|
const languageChooserSelect = document.getElementById('languageChooserSelect')
|
|
|
|
const metadataIsFirstCompletion = document.getElementById('metadataIsFirstCompletion')
|
|
|
|
const inputs = document.getElementById('inputs')
|
|
|
|
const submitButton = document.getElementById('submitButton')
|
|
|
|
const buttons_to_page = document.querySelectorAll('button[to-page]')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TEAMS
|
|
|
|
|
2022-11-21 15:40:44 +00:00
|
|
|
let teams = []
|
|
|
|
let teams_selected = new Set()
|
2022-11-20 14:27:44 +00:00
|
|
|
|
2022-11-21 15:40:44 +00:00
|
|
|
function selectTeam(team) {
|
|
|
|
teams_selected.add(team)
|
|
|
|
renderTeamSuggestions()
|
|
|
|
renderTeamSelected()
|
|
|
|
renderTeamSelectedAutomatically()
|
|
|
|
}
|
2022-11-22 11:48:34 +00:00
|
|
|
|
2022-11-21 15:40:44 +00:00
|
|
|
function deselectTeam(team) {
|
|
|
|
teams_selected = new Set([...teams_selected].filter(team_selected => team_selected.id !== team))
|
|
|
|
renderTeamSuggestions()
|
|
|
|
renderTeamSelected()
|
|
|
|
renderTeamSelectedAutomatically()
|
|
|
|
}
|
2022-11-22 11:48:34 +00:00
|
|
|
|
2022-11-21 15:40:44 +00:00
|
|
|
function renderTeamSuggestions() {
|
|
|
|
const team_suggestions_input = document.getElementById('team_suggestions_input')
|
|
|
|
const team_suggestions = document.getElementById('team_suggestions')
|
|
|
|
team_suggestions.innerHTML = ''
|
2022-11-20 14:27:44 +00:00
|
|
|
|
2022-11-21 15:40:44 +00:00
|
|
|
const team_suggestions_input_value = team_suggestions_input.value.toLowerCase()
|
2022-11-20 14:27:44 +00:00
|
|
|
|
2022-11-21 16:00:08 +00:00
|
|
|
if (team_suggestions_input_value.length > 0) {
|
|
|
|
// filter out parent_teams that are in the teams array
|
|
|
|
const teams_selected_ids = [...teams_selected]
|
|
|
|
.flatMap(team => [
|
|
|
|
team.id,
|
|
|
|
// ...team.parent_team_ids,
|
|
|
|
])
|
|
|
|
|
|
|
|
const filtered_teams = teams
|
|
|
|
.filter(team => !teams_selected_ids.includes(team.id))
|
|
|
|
.filter(team => team.name.toLowerCase().includes(team_suggestions_input_value))
|
|
|
|
.sort((a, b) => a.name.toLowerCase() > b.name.toLowerCase() ? 1 : -1)
|
|
|
|
|
|
|
|
for (const team of filtered_teams) {
|
|
|
|
const team_chip = document.createElement('div')
|
|
|
|
team_chip.classList.add('chip')
|
|
|
|
team_chip.classList.add('add')
|
|
|
|
team_chip.innerHTML = team.name
|
|
|
|
team_chip.addEventListener('click', () => {
|
|
|
|
selectTeam(team)
|
|
|
|
})
|
|
|
|
team_suggestions.appendChild(team_chip)
|
|
|
|
}
|
2022-11-21 15:40:44 +00:00
|
|
|
}
|
|
|
|
}
|
2022-11-22 11:48:34 +00:00
|
|
|
|
2022-11-21 15:40:44 +00:00
|
|
|
function renderTeamSelected() {
|
|
|
|
const teams_selected_node = document.getElementById('teams_selected')
|
|
|
|
teams_selected_node.innerHTML = ''
|
|
|
|
|
|
|
|
const filtered_teams = [...teams_selected]
|
|
|
|
.sort((a, b) => {
|
|
|
|
return a.name.toLowerCase() > b.name.toLowerCase() ? 1 : -1
|
|
|
|
})
|
|
|
|
|
2022-11-21 16:00:08 +00:00
|
|
|
const selected_teams_wrapper_node = document.getElementById('selected_teams_wrapper')
|
|
|
|
if (filtered_teams.length === 0) {
|
|
|
|
selected_teams_wrapper_node.style.display = 'none'
|
|
|
|
} else {
|
|
|
|
selected_teams_wrapper_node.style.display = 'block'
|
|
|
|
}
|
|
|
|
|
2022-11-21 15:40:44 +00:00
|
|
|
for (const team of filtered_teams) {
|
|
|
|
const team_chip = document.createElement('div')
|
|
|
|
team_chip.classList.add('chip')
|
|
|
|
team_chip.classList.add('remove')
|
|
|
|
team_chip.innerHTML = team.name
|
|
|
|
team_chip.addEventListener('click', () => {
|
|
|
|
deselectTeam(team.id)
|
|
|
|
})
|
|
|
|
teams_selected_node.appendChild(team_chip)
|
|
|
|
}
|
|
|
|
}
|
2022-11-22 11:48:34 +00:00
|
|
|
|
2022-11-21 15:40:44 +00:00
|
|
|
function getParentTeams(parent_team_ids) {
|
|
|
|
let parent_teams = []
|
|
|
|
|
|
|
|
for (const parent_team_id of parent_team_ids) {
|
|
|
|
const team = teams.find(team => team.id === parent_team_id)
|
|
|
|
if (team) {
|
|
|
|
parent_teams.push(team)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// filter out parent_teams that are in the teams array
|
|
|
|
const teams_selected_ids = [...teams_selected].map(team => team.id)
|
|
|
|
parent_teams = parent_teams.filter(parent_team => !teams_selected_ids.includes(parent_team.id))
|
|
|
|
|
|
|
|
return parent_teams
|
|
|
|
}
|
2022-11-22 11:48:34 +00:00
|
|
|
|
2022-11-21 15:40:44 +00:00
|
|
|
function renderTeamSelectedAutomatically() {
|
|
|
|
const teams_selected_node = document.getElementById('teams_selected_automatically')
|
|
|
|
teams_selected_node.innerHTML = ''
|
|
|
|
|
|
|
|
const parent_teams = getParentTeams([...new Set([...teams_selected].flatMap(team => team.parent_team_ids))])
|
|
|
|
.sort((a, b) => {
|
|
|
|
return a.name.toLowerCase() > b.name.toLowerCase() ? 1 : -1
|
|
|
|
})
|
|
|
|
|
|
|
|
for (const team of parent_teams) {
|
|
|
|
const team_chip = document.createElement('div')
|
|
|
|
team_chip.classList.add('chip')
|
|
|
|
team_chip.classList.add('automatic')
|
|
|
|
team_chip.innerHTML = team.name
|
|
|
|
teams_selected_node.appendChild(team_chip)
|
|
|
|
}
|
|
|
|
}
|
2022-11-22 11:48:34 +00:00
|
|
|
|
2022-11-21 15:40:44 +00:00
|
|
|
function loadTeams() {
|
2022-11-22 11:47:12 +00:00
|
|
|
// load teams from ./api/teams.json
|
|
|
|
fetch('./api/teams.json')
|
2022-11-21 15:40:44 +00:00
|
|
|
.then(response => response.json())
|
|
|
|
.then(data => {
|
|
|
|
teams = data.teams
|
|
|
|
renderTeamSuggestions()
|
|
|
|
})
|
|
|
|
.catch(error => {
|
|
|
|
console.error(error)
|
|
|
|
})
|
|
|
|
}
|
2022-11-22 11:48:34 +00:00
|
|
|
|
2022-11-21 16:00:08 +00:00
|
|
|
function initTeams() {
|
|
|
|
loadTeams()
|
|
|
|
renderTeamSuggestions()
|
|
|
|
renderTeamSelected()
|
|
|
|
renderTeamSelectedAutomatically()
|
|
|
|
}
|
2022-11-21 15:40:44 +00:00
|
|
|
|
2022-11-20 12:54:10 +00:00
|
|
|
|
|
|
|
|
2022-11-22 11:48:34 +00:00
|
|
|
// SUBMIT ANSWERS
|
2022-11-20 12:54:10 +00:00
|
|
|
|
2022-11-22 11:48:34 +00:00
|
|
|
|
|
|
|
function getIdentifier() {
|
|
|
|
// a got a few things from https://github.com/Valve/fingerprintjs2/blob/master/fingerprint2.js
|
|
|
|
|
|
|
|
// var getDoNotTrack = function() {
|
|
|
|
// if (navigator.doNotTrack) {
|
|
|
|
// return navigator.doNotTrack
|
|
|
|
// } else if (navigator.msDoNotTrack) {
|
|
|
|
// return navigator.msDoNotTrack
|
|
|
|
// } else if (window.doNotTrack) {
|
|
|
|
// return window.doNotTrack
|
|
|
|
// } else {
|
|
|
|
// return false
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
var getTouchSupport = function () {
|
|
|
|
var maxTouchPoints = 0
|
|
|
|
var touchEvent;
|
|
|
|
if (typeof navigator.maxTouchPoints !== 'undefined') {
|
|
|
|
maxTouchPoints = navigator.maxTouchPoints
|
|
|
|
} else if (typeof navigator.msMaxTouchPoints !== 'undefined') {
|
|
|
|
maxTouchPoints = navigator.msMaxTouchPoints
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
document.createEvent('TouchEvent')
|
|
|
|
touchEvent = true
|
|
|
|
} catch (_) {
|
|
|
|
touchEvent = false
|
|
|
|
}
|
|
|
|
var touchStart = 'ontouchstart' in window
|
|
|
|
return [maxTouchPoints, touchEvent, touchStart]
|
|
|
|
}
|
|
|
|
var timezone = function () {
|
|
|
|
if (window.Intl && window.Intl.DateTimeFormat) {
|
|
|
|
return new window.Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
var relativly_unique_information = {
|
|
|
|
browserPlatform: navigator.platform,
|
|
|
|
javaEnabled: navigator.javaEnabled(),
|
|
|
|
dataCookiesEnabled: navigator.cookieEnabled,
|
|
|
|
|
|
|
|
sizeScreenAvailWidth: screen.availWidth,
|
|
|
|
sizeScreenAvailHeight: screen.availHeight,
|
|
|
|
sizeScreenWidth: screen.width,
|
|
|
|
sizeScreenHeight: screen.height,
|
|
|
|
scrColorDepth: screen.colorDepth,
|
|
|
|
scrPixelDepth: screen.pixelDepth,
|
|
|
|
|
|
|
|
hardwareConcurrency: navigator.hardwareConcurrency,
|
|
|
|
// doNotTrack: getDoNotTrack(),
|
|
|
|
|
|
|
|
isTouchCapable: getTouchSupport().join('|'),
|
|
|
|
// isTouchCapable: 'ontouchstart' in window || window.DocumentTouch && document instanceof window.DocumentTouch || navigator.maxTouchPoints > 0 || window.navigator.msMaxTouchPoints > 0,
|
|
|
|
|
|
|
|
timezoneOffset: new Date().getTimezoneOffset(),
|
|
|
|
timezone: timezone(),
|
|
|
|
|
|
|
|
browserLanguage: (navigator.language || navigator.userLanguage || navigator.browserLanguage || navigator.systemLanguage),
|
|
|
|
languages: [...(navigator.languages || [])].sort().join('|'),
|
|
|
|
}
|
|
|
|
|
|
|
|
return Object.values(relativly_unique_information).join('|')
|
2022-11-20 12:54:10 +00:00
|
|
|
}
|
|
|
|
|
2022-11-22 11:48:34 +00:00
|
|
|
function getTimelessButAnonymousTrackingCode(questionKey) {
|
|
|
|
// tatc = Timeless but Anonymous Tracking Code
|
|
|
|
|
|
|
|
const shaObj = new jsSHA('SHA3-512', 'TEXT')
|
|
|
|
shaObj.update(window.pre_tatc + '' + questionKey) // +' '+answerKey
|
|
|
|
|
|
|
|
return shaObj.getHash('HEX')
|
|
|
|
}
|
2022-11-20 12:54:10 +00:00
|
|
|
|
2022-11-22 11:49:04 +00:00
|
|
|
function submitData(questionKey, answerKey) {
|
|
|
|
|
|
|
|
let team = [...teams_selected]
|
|
|
|
if (team.length > 0) {
|
|
|
|
team = team[0]
|
|
|
|
|
|
|
|
const data = {
|
|
|
|
questionKey,
|
|
|
|
answerKey,
|
|
|
|
metadata: {
|
|
|
|
team: window.volt_team,
|
|
|
|
timestamp: new Date() * 1,
|
|
|
|
tact: getTimelessButAnonymousTrackingCode({
|
|
|
|
identifier: getIdentifier(),
|
|
|
|
team,
|
|
|
|
questionKey,
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// send data to post: /api/submit_data using fetch
|
|
|
|
fetch('/api/submit_data', {
|
|
|
|
method: 'POST',
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
},
|
|
|
|
body: JSON.stringify(data)
|
|
|
|
}).then(response => {
|
|
|
|
if (response.status === 200) {
|
|
|
|
return response.json()
|
|
|
|
} else {
|
|
|
|
throw new Error('Something went wrong on api server!');
|
|
|
|
}
|
|
|
|
}).then(response => {
|
|
|
|
console.debug(response);
|
|
|
|
}).catch(error => {
|
|
|
|
console.error(error);
|
|
|
|
})
|
2022-11-20 12:54:10 +00:00
|
|
|
}
|
2022-11-22 11:49:04 +00:00
|
|
|
}
|
2022-11-20 12:54:10 +00:00
|
|
|
|
2022-11-22 11:48:34 +00:00
|
|
|
function clearForm() {
|
|
|
|
for (const ele of inputs.querySelectorAll('input[type="text"]')) {
|
|
|
|
ele.value = ''
|
|
|
|
}
|
|
|
|
for (const ele of inputs.querySelectorAll('input[type="number"]')) {
|
|
|
|
ele.value = ''
|
|
|
|
}
|
|
|
|
for (const ele of inputs.querySelectorAll('input[type="checkbox"]')) {
|
|
|
|
ele.checked = false
|
|
|
|
}
|
|
|
|
for (const ele of inputs.querySelectorAll('option')) {
|
|
|
|
ele.selected = false
|
|
|
|
}
|
|
|
|
}
|
2022-11-20 12:54:10 +00:00
|
|
|
|
2022-11-22 11:48:34 +00:00
|
|
|
function initSubmit() {
|
|
|
|
submitButton.addEventListener('click', () => {
|
|
|
|
submitForm()
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
function getTimelessButAnonymousTrackingCode(questionKey, answerKey) {
|
|
|
|
// tatc = Timeless but Anonymous Tracking Code
|
|
|
|
|
|
|
|
const shaObj = new jsSHA('SHA3-512', 'TEXT')
|
|
|
|
shaObj.update(window.pre_tatc + '' + questionKey) // +' '+answerKey
|
|
|
|
|
|
|
|
return shaObj.getHash('HEX')
|
|
|
|
}
|
|
|
|
function submitForm() {
|
|
|
|
if (navigator.onLine) {
|
|
|
|
|
|
|
|
var answers = []
|
|
|
|
|
|
|
|
const elements = [
|
|
|
|
...inputs.querySelectorAll('input[type="text"]'),
|
|
|
|
...inputs.querySelectorAll('textarea'),
|
|
|
|
...inputs.querySelectorAll('input[type="number"]'),
|
|
|
|
]
|
|
|
|
for (const ele of elements) {
|
|
|
|
const questionKey = ele.getAttribute('name')
|
|
|
|
const value = ele.value
|
|
|
|
if (value != '' && questionKey != '') {
|
|
|
|
answers.push({
|
|
|
|
questionKey: questionKey,
|
|
|
|
answerKey: null,
|
|
|
|
value: value,
|
|
|
|
// metadata: metadata,
|
|
|
|
// tatc: getTimelessButAnonymousTrackingCode(questionKey, null),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const ele of inputs.querySelectorAll('option')) {
|
|
|
|
const questionKey = ele.getAttribute('name')
|
|
|
|
const answerKey = ele.value
|
|
|
|
if (ele.selected && questionKey != '' && answerKey != '') {
|
|
|
|
answers.push({
|
|
|
|
questionKey: questionKey,
|
|
|
|
answerKey: answerKey,
|
|
|
|
value: true, // (ele.selected ? true : false),
|
|
|
|
// metadata: metadata,
|
|
|
|
// tatc: getTimelessButAnonymousTrackingCode(questionKey, null),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const ele of inputs.querySelectorAll('input[type="checkbox"]')) {
|
|
|
|
const questionKey = ele.getAttribute('name')
|
|
|
|
const answerKey = ele.value
|
|
|
|
if (ele.checked && questionKey != '' && answerKey != '') {
|
|
|
|
answers.push({
|
|
|
|
questionKey: questionKey,
|
|
|
|
answerKey: answerKey,
|
|
|
|
value: true, // (ele.checked ? true : false),
|
|
|
|
// metadata: metadata,
|
|
|
|
// tatc: getTimelessButAnonymousTrackingCode(questionKey, answerKey),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const ele of inputs.querySelectorAll('input[type="radio"]')) {
|
|
|
|
const questionKey = ele.getAttribute('name')
|
|
|
|
const answerKey = ele.value
|
|
|
|
if (ele.checked && questionKey != '' && answerKey != '') {
|
|
|
|
answers.push({
|
|
|
|
questionKey: questionKey,
|
|
|
|
answerKey: answerKey,
|
|
|
|
value: true, // (ele.checked ? true : false),
|
|
|
|
// metadata: metadata,
|
|
|
|
// tatc: getTimelessButAnonymousTrackingCode(questionKey, answerKey),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (answers.length > 0) {
|
|
|
|
body.classList.add('saving')
|
|
|
|
|
|
|
|
// add the metadata
|
|
|
|
const metadata_country_value = answers.filter(a => a.questionKey == 'metadata_country').map(a => a.answerKey)[0] || ''
|
|
|
|
const metadata_city_value = answers.filter(a => a.questionKey == 'metadata_city').map(a => a.value)[0] || ''
|
|
|
|
|
|
|
|
const metadata = {}
|
|
|
|
answers = answers.filter(answer => answer.questionKey != 'metadata_country' && answer.questionKey != 'metadata_city')
|
|
|
|
// answers = answers.map(answer=> ({
|
|
|
|
// ...answer,
|
|
|
|
// metadata: metadata,
|
|
|
|
// tatc: getTimelessButAnonymousTrackingCode(answer.questionKey, answer.answerKey),
|
|
|
|
// }) )
|
|
|
|
answers = answers.map(answer => Object.assign({}, answer, {
|
|
|
|
metadata: metadata,
|
|
|
|
tatc: getTimelessButAnonymousTrackingCode(answer.questionKey, answer.answerKey),
|
|
|
|
}))
|
|
|
|
|
|
|
|
console.log('answers:', answers)
|
|
|
|
|
|
|
|
|
|
|
|
let startTS = new Date() * 1
|
|
|
|
console.info('START', 0)
|
|
|
|
|
|
|
|
async.each(answers, (answer, callback) => {
|
|
|
|
const xmlReq = new XMLHttpRequest()
|
|
|
|
xmlReq.addEventListener('load', event => {
|
|
|
|
const json_res = JSON.parse(event.target.responseText)
|
|
|
|
if (!!json_res && !json_res.error) {
|
|
|
|
callback()
|
|
|
|
} else {
|
|
|
|
callback('error')
|
|
|
|
}
|
|
|
|
})
|
|
|
|
xmlReq.open('GET', CloudFunctionsPrefix + '?data=' + encodeURIComponent(JSON.stringify({ answers: [answer] })))
|
|
|
|
xmlReq.send()
|
|
|
|
}, error => {
|
|
|
|
console.info('END', (new Date() * 1) - startTS)
|
|
|
|
if (!!error) {
|
|
|
|
body.classList.add('error')
|
|
|
|
body.classList.remove('saving')
|
|
|
|
} else {
|
|
|
|
body.classList.add('success')
|
|
|
|
body.classList.remove('saving')
|
|
|
|
clearForm()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-11-22 12:51:04 +00:00
|
|
|
// CONTRASTING COLORS (for the question form)
|
|
|
|
|
|
|
|
function hexToRGBArray(color) {
|
|
|
|
if (color.startsWith('#')) {
|
|
|
|
color = color.substring(1)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (color.length === 3) {
|
|
|
|
color = color.charAt(0) + color.charAt(0) + color.charAt(1) + color.charAt(1) + color.charAt(2) + color.charAt(2);
|
|
|
|
} else if (color.length !== 6) {
|
|
|
|
throw (new Error('Invalid hex color: ' + color));
|
|
|
|
}
|
|
|
|
|
|
|
|
let rgb = [];
|
|
|
|
for (var i = 0; i <= 2; i++) {
|
|
|
|
rgb[i] = parseInt(color.substr(i * 2, 2), 16);
|
|
|
|
}
|
|
|
|
|
|
|
|
return rgb;
|
|
|
|
}
|
|
|
|
|
|
|
|
function luma(color) {
|
|
|
|
// color can be a hex string or an array of RGB values 0-255
|
|
|
|
const rgb = (typeof color === 'string') ? hexToRGBArray(color) : color;
|
|
|
|
return (0.2126 * rgb[0]) + (0.7152 * rgb[1]) + (0.0722 * rgb[2]); // SMPTE C, Rec. 709 weightings
|
|
|
|
}
|
|
|
|
|
|
|
|
function getContrastingColor(color) {
|
|
|
|
// source: https://stackoverflow.com/questions/635022/calculating-contrasting-colours-in-javascript
|
|
|
|
// exact answer: https://stackoverflow.com/a/6511606/2387277
|
|
|
|
// example: https://jsfiddle.net/thomasrosen/9njo6t7s/20/
|
|
|
|
|
|
|
|
return (luma(color) >= 165) ? '000' : 'fff';
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-11-22 11:48:34 +00:00
|
|
|
// GENERATE QUESTION FORM
|
|
|
|
|
|
|
|
function resetBodyClasses() {
|
|
|
|
body.classList.remove('error')
|
|
|
|
body.classList.remove('success')
|
|
|
|
body.classList.remove('saving')
|
2022-11-20 12:54:10 +00:00
|
|
|
}
|
2022-11-22 11:48:34 +00:00
|
|
|
|
2022-11-20 12:54:10 +00:00
|
|
|
function generateForm(data) {
|
|
|
|
// websiteTitle.innerHTML = 'Volt — '+getByLanguage(_DATA_.translation_texts.website_title).replace(/\n+/g, ' ')
|
|
|
|
|
2022-11-22 12:51:04 +00:00
|
|
|
inputs.innerHTML = ''
|
|
|
|
|
2022-11-20 12:54:10 +00:00
|
|
|
for (const section of _DATA_.sections) {
|
|
|
|
|
|
|
|
var sectionEle = document.createElement('section')
|
|
|
|
|
2022-11-22 12:51:04 +00:00
|
|
|
if (!!section.color) {
|
|
|
|
sectionEle.style.setProperty('--section-color', section.color)
|
|
|
|
sectionEle.style.setProperty('--on-section-color', '#'+getContrastingColor(section.color))
|
|
|
|
}
|
|
|
|
|
2022-11-20 12:54:10 +00:00
|
|
|
if (!!section.heading) {
|
|
|
|
var sectionHeading = document.createElement('h2')
|
|
|
|
sectionHeading.innerHTML = getByLanguage(section.heading)
|
|
|
|
sectionEle.appendChild(sectionHeading)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!!section.intro) {
|
|
|
|
var sectionIntro = document.createElement('p')
|
|
|
|
sectionIntro.classList.add('intro')
|
|
|
|
sectionIntro.innerHTML = getByLanguage(section.intro)
|
|
|
|
sectionEle.appendChild(sectionIntro)
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-11-22 12:51:04 +00:00
|
|
|
var questionsWrapperEle = document.createElement('div')
|
|
|
|
questionsWrapperEle.classList.add('questions')
|
|
|
|
|
2022-11-20 12:54:10 +00:00
|
|
|
// display questions
|
|
|
|
for (const questionKey of Object.keys(section.questions)) {
|
|
|
|
const question = section.questions[questionKey]
|
|
|
|
|
|
|
|
var questionEle = document.createElement('div')
|
|
|
|
questionEle.classList.add('question')
|
|
|
|
|
|
|
|
if (!!question.question) {
|
|
|
|
var questionHeading = document.createElement('h3')
|
|
|
|
questionHeading.innerHTML = getByLanguage(question.question)
|
|
|
|
questionEle.appendChild(questionHeading)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!!question.why) {
|
|
|
|
var question_why_text = document.createElement('p')
|
|
|
|
question_why_text.classList.add('why_text')
|
|
|
|
if (!question.info) {
|
|
|
|
question_why_text.classList.add('no_info_text')
|
|
|
|
}
|
|
|
|
question_why_text.innerHTML = getByLanguage(question.why)
|
|
|
|
questionEle.appendChild(question_why_text)
|
|
|
|
}
|
|
|
|
if (!!question.info) {
|
|
|
|
var question_info_text = document.createElement('p')
|
|
|
|
// question_info_text.classList.add('info_text')
|
|
|
|
question_info_text.innerHTML = getByLanguage(question.info)
|
|
|
|
questionEle.appendChild(question_info_text)
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (question.type == 'number') {
|
|
|
|
let newInput = document.createElement('input')
|
|
|
|
newInput.addEventListener('click', resetBodyClasses)
|
|
|
|
newInput.setAttribute('name', questionKey)
|
|
|
|
newInput.setAttribute('type', 'number')
|
|
|
|
newInput.setAttribute('placeholder', '…')
|
|
|
|
newInput.addEventListener('click', resetBodyClasses)
|
|
|
|
// newInput.value = '123'
|
|
|
|
questionEle.appendChild(newInput)
|
|
|
|
} else if (question.type == 'checkbox') {
|
|
|
|
for (const key of Object.keys(question.options)) {
|
|
|
|
|
|
|
|
let labelEle = document.createElement('label')
|
|
|
|
labelEle.classList.add('radio_or_checkbox_label')
|
|
|
|
labelEle.addEventListener('click', resetBodyClasses)
|
|
|
|
|
|
|
|
let checkboxEle = document.createElement('input')
|
|
|
|
checkboxEle.setAttribute('type', 'checkbox')
|
|
|
|
checkboxEle.setAttribute('name', questionKey)
|
|
|
|
checkboxEle.setAttribute('value', key)
|
|
|
|
labelEle.appendChild(checkboxEle)
|
|
|
|
|
|
|
|
let spanEle = document.createElement('span')
|
|
|
|
spanEle.innerHTML = getByLanguage(question.options[key])
|
|
|
|
labelEle.appendChild(spanEle)
|
|
|
|
|
|
|
|
questionEle.appendChild(labelEle)
|
|
|
|
}
|
|
|
|
} else if (question.type == 'radio') {
|
|
|
|
for (const key of Object.keys(question.options)) {
|
|
|
|
|
|
|
|
let labelEle = document.createElement('label')
|
|
|
|
labelEle.classList.add('radio_or_checkbox_label')
|
|
|
|
labelEle.addEventListener('click', resetBodyClasses)
|
|
|
|
|
|
|
|
let checkboxEle = document.createElement('input')
|
|
|
|
checkboxEle.setAttribute('type', 'radio')
|
|
|
|
checkboxEle.setAttribute('name', questionKey)
|
|
|
|
checkboxEle.setAttribute('value', key)
|
|
|
|
labelEle.appendChild(checkboxEle)
|
|
|
|
|
|
|
|
let spanEle = document.createElement('span')
|
|
|
|
spanEle.innerHTML = getByLanguage(question.options[key])
|
|
|
|
labelEle.appendChild(spanEle)
|
|
|
|
|
|
|
|
questionEle.appendChild(labelEle)
|
|
|
|
}
|
|
|
|
} else if (question.type == 'chooser') {
|
|
|
|
let newInput = document.createElement('select')
|
|
|
|
newInput.addEventListener('click', resetBodyClasses)
|
|
|
|
|
|
|
|
if (questionKey == 'metadata_country') {
|
|
|
|
newInput.setAttribute('selectedValue', window.volt_country_party)
|
|
|
|
for (const country_data of _DATA_.countries) {
|
|
|
|
const disabled = country_data.disabled
|
|
|
|
const value = (country_data.value ? country_data.value : '')
|
|
|
|
|
|
|
|
let title = ''
|
|
|
|
if (country_data.title) {
|
|
|
|
title = country_data.title
|
|
|
|
} else if (country_data.en && country_data.local_name && country_data.en != country_data.local_name) {
|
|
|
|
title = country_data.en + ' (' + country_data.local_name + ')'
|
|
|
|
} else if (country_data.en) {
|
|
|
|
title = country_data.en
|
|
|
|
} else if (country_data.local_name) {
|
|
|
|
title = country_data.local_name
|
|
|
|
}
|
|
|
|
|
|
|
|
const optionEle = document.createElement('option')
|
|
|
|
optionEle.setAttribute('name', questionKey)
|
|
|
|
optionEle.setAttribute('value', value)
|
|
|
|
optionEle.innerHTML = title
|
|
|
|
if (window.volt_country_party == value) {
|
|
|
|
optionEle.selected = true
|
|
|
|
}
|
|
|
|
if (disabled == true) {
|
|
|
|
optionEle.disabled = true
|
|
|
|
}
|
|
|
|
newInput.appendChild(optionEle)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// question.options = {
|
|
|
|
// '': {de:'…'},
|
|
|
|
// ...question.options
|
|
|
|
// }
|
|
|
|
question.options = Object.assign({}, { '': { de: '…' } }, question.options)
|
|
|
|
|
|
|
|
newInput.setAttribute('selectedValue', '')
|
|
|
|
|
|
|
|
// let optionEle = document.createElement('option')
|
|
|
|
// optionEle.setAttribute('value', '')
|
|
|
|
// optionEle.innerHTML = '…'
|
|
|
|
// newInput.appendChild(optionEle)
|
|
|
|
|
|
|
|
// var c = 0
|
|
|
|
for (const key of Object.keys(question.options)) {
|
|
|
|
let optionEle = document.createElement('option')
|
|
|
|
optionEle.setAttribute('name', questionKey)
|
|
|
|
optionEle.setAttribute('value', key)
|
|
|
|
optionEle.innerHTML = getByLanguage(question.options[key])
|
|
|
|
// if (c == 1) {
|
|
|
|
// optionEle.selected = true
|
|
|
|
// }
|
|
|
|
newInput.appendChild(optionEle)
|
|
|
|
// c += 1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
newInput.addEventListener('change', e => {
|
|
|
|
const optionEles = e.target.querySelectorAll('option')
|
|
|
|
for (let optionEle of optionEles) {
|
|
|
|
if (optionEle.selected) {
|
|
|
|
newInput.setAttribute('selectedValue', optionEle.value)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
if (question.multiSelect) {
|
|
|
|
newInput.setAttribute('multiple', 'multiple')
|
|
|
|
question.showAllOptions = true
|
|
|
|
}
|
|
|
|
if (question.showAllOptions) {
|
|
|
|
newInput.classList.add('showingAllOptions')
|
|
|
|
newInput.setAttribute('size', Object.keys(question.options).length)
|
|
|
|
} else {
|
|
|
|
newInput.classList.add('not_showingAllOptions')
|
|
|
|
}
|
|
|
|
|
|
|
|
questionEle.appendChild(newInput)
|
|
|
|
} else if (question.type == 'one_line_text') {
|
|
|
|
let newInput = document.createElement('input')
|
|
|
|
newInput.addEventListener('click', resetBodyClasses)
|
|
|
|
newInput.setAttribute('name', questionKey)
|
|
|
|
newInput.setAttribute('type', 'text')
|
|
|
|
newInput.setAttribute('placeholder', '…')
|
|
|
|
// newInput.value = 'some text'
|
|
|
|
questionEle.appendChild(newInput)
|
|
|
|
|
|
|
|
if (questionKey == 'metadata_city') {
|
|
|
|
newInput.value = window.volt_city
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
let newInput = document.createElement('textarea')
|
|
|
|
newInput.addEventListener('click', resetBodyClasses)
|
|
|
|
newInput.setAttribute('name', questionKey)
|
|
|
|
// newInput.setAttribute('type', 'text')
|
|
|
|
newInput.setAttribute('placeholder', '…')
|
|
|
|
// newInput.innerHTML = 'some text'
|
|
|
|
questionEle.appendChild(newInput)
|
|
|
|
}
|
|
|
|
|
2022-11-22 12:51:04 +00:00
|
|
|
questionsWrapperEle.appendChild(questionEle)
|
2022-11-20 12:54:10 +00:00
|
|
|
}
|
|
|
|
|
2022-11-22 12:51:04 +00:00
|
|
|
sectionEle.appendChild(questionsWrapperEle)
|
2022-11-20 12:54:10 +00:00
|
|
|
inputs.appendChild(sectionEle)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-11-22 11:48:34 +00:00
|
|
|
// TRANSLATION
|
2022-11-20 12:54:10 +00:00
|
|
|
|
|
|
|
function parseQuery(queryString) {
|
|
|
|
var query = {}
|
|
|
|
var pairs = (queryString[0] === '?' ? queryString.substr(1) : queryString).split('&')
|
|
|
|
for (var i = 0; i < pairs.length; i++) {
|
|
|
|
var pair = pairs[i].split('=')
|
|
|
|
if (pair[0] != '') {
|
|
|
|
query[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1] || '')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return query
|
|
|
|
}
|
2022-11-22 11:48:34 +00:00
|
|
|
|
2022-11-20 12:54:10 +00:00
|
|
|
function obj2searchQuery(obj) {
|
|
|
|
var query_parts = []
|
|
|
|
for (const key of Object.keys(obj)) {
|
|
|
|
query_parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]))
|
|
|
|
}
|
|
|
|
return '?' + query_parts.join('&')
|
|
|
|
}
|
|
|
|
|
2022-11-22 11:48:34 +00:00
|
|
|
function getByLanguage(objectWithValuesByLanguage) {
|
|
|
|
let value = '[NO TRANSLATION FOUND!]'
|
2022-11-20 12:54:10 +00:00
|
|
|
|
2022-11-22 11:48:34 +00:00
|
|
|
if (objectWithValuesByLanguage) {
|
|
|
|
if (objectWithValuesByLanguage[_language_]) {
|
|
|
|
value = objectWithValuesByLanguage[_language_]
|
|
|
|
} else if (objectWithValuesByLanguage['en']) {
|
|
|
|
value = objectWithValuesByLanguage['en']
|
|
|
|
} else if (objectWithValuesByLanguage['de']) {
|
|
|
|
value = objectWithValuesByLanguage['de']
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// if (value.indexOf(' ') > -1) {
|
|
|
|
// value = value.substr(0,value.lastIndexOf(' '))+' '+value.substr(value.lastIndexOf(' ')+1)
|
|
|
|
// }
|
|
|
|
|
|
|
|
return value
|
2022-11-20 12:54:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function updateLanguageTexts() {
|
|
|
|
const translationNodes = document.querySelectorAll('[data-translation-key]')
|
|
|
|
|
|
|
|
for (let translationNode of translationNodes) {
|
|
|
|
const translationKey = translationNode.getAttribute('data-translation-key')
|
|
|
|
if (_DATA_.translation_texts[translationKey]) {
|
|
|
|
let text = ''
|
|
|
|
if (_DATA_.translation_texts[translationKey].use_instead && _DATA_.translation_texts[_DATA_.translation_texts[translationKey].use_instead]) {
|
|
|
|
text = getByLanguage(_DATA_.translation_texts[_DATA_.translation_texts[translationKey].use_instead])
|
|
|
|
} else {
|
|
|
|
text = getByLanguage(_DATA_.translation_texts[translationKey])
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_DATA_.translation_texts[translationKey].prefix) {
|
|
|
|
text = _DATA_.translation_texts[translationKey].prefix + text
|
|
|
|
}
|
|
|
|
|
|
|
|
let translationDestination = ''
|
|
|
|
if (translationNode.hasAttribute('data-translation-dest')) {
|
|
|
|
translationDestination = translationNode.getAttribute('data-translation-dest')
|
|
|
|
}
|
|
|
|
|
|
|
|
if (translationDestination == 'attr-content') {
|
|
|
|
const temp_node = document.createElement("div")
|
|
|
|
temp_node.innerHTML = text
|
|
|
|
translationNode.setAttribute('content', temp_node.textContent || temp_node.innerText || "")
|
|
|
|
delete temp_node
|
|
|
|
} else {
|
|
|
|
text = text.replace(/\t+/g, '')
|
|
|
|
text = text.replace(/(^\n+|\n+$)/g, '')
|
|
|
|
if (!_DATA_.translation_texts[translationKey].is_plain) {
|
|
|
|
text = text.replace(/\n/g, '<br>')
|
|
|
|
}
|
|
|
|
translationNode.innerHTML = text
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-11-22 11:48:34 +00:00
|
|
|
// NAVIGATION
|
2022-11-20 12:54:10 +00:00
|
|
|
|
2022-11-22 11:48:34 +00:00
|
|
|
function initNavigationButtons() {
|
|
|
|
for (const button of buttons_to_page) {
|
|
|
|
button.addEventListener('click', () => {
|
|
|
|
const toPage = button.getAttribute('to-page')
|
|
|
|
if (!['', 'intro', 'privacy', 'metadata', 'questions'].includes(toPage)) {
|
|
|
|
toPage = ''
|
|
|
|
}
|
|
|
|
body.setAttribute('show', toPage)
|
|
|
|
window.scrollTo(0, 0)
|
|
|
|
history.pushState(null, websiteTitle.innerText, '#' + toPage)
|
|
|
|
})
|
|
|
|
}
|
2022-11-20 12:54:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-11-22 11:48:34 +00:00
|
|
|
// LANGUAGE CHOOSER
|
2022-11-20 12:54:10 +00:00
|
|
|
|
2022-11-21 18:16:00 +00:00
|
|
|
function selectLanguageInSelector() {
|
2022-11-22 00:30:39 +00:00
|
|
|
const html_node = document.querySelector('html')
|
2022-11-22 00:20:59 +00:00
|
|
|
html_node.setAttribute('lang', window._language_)
|
|
|
|
|
2022-11-21 18:16:00 +00:00
|
|
|
const optionEles = languageChooserSelect.querySelectorAll('option')
|
|
|
|
for (let optionEle of optionEles) {
|
|
|
|
if (optionEle.value === window._language_) {
|
|
|
|
optionEle.selected = true
|
|
|
|
} else {
|
|
|
|
optionEle.selected = false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-11-22 11:48:34 +00:00
|
|
|
|
2022-11-20 12:54:10 +00:00
|
|
|
function checkUrl() {
|
|
|
|
|
|
|
|
// check hash
|
|
|
|
|
|
|
|
let hash = document.location.hash
|
|
|
|
if (hash.charAt(0) === '#') {
|
|
|
|
hash = hash.slice(1)
|
|
|
|
}
|
|
|
|
body.setAttribute('show', hash)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// check search
|
|
|
|
|
|
|
|
const locationSearchObj = parseQuery(window.location.search)
|
|
|
|
|
|
|
|
// set language
|
2022-11-21 18:16:00 +00:00
|
|
|
window._language_ = locationSearchObj.lang || 'en'
|
|
|
|
selectLanguageInSelector()
|
2022-11-20 12:54:10 +00:00
|
|
|
updateLanguageTexts()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2022-11-22 11:48:34 +00:00
|
|
|
function initLanguageChooser() {
|
|
|
|
languageChooserSelect.addEventListener('change', e => {
|
|
|
|
const optionEles = e.target.querySelectorAll('option')
|
|
|
|
for (let optionEle of optionEles) {
|
|
|
|
if (optionEle.selected) {
|
|
|
|
window._language_ = optionEle.value
|
|
|
|
updateLanguageTexts()
|
2022-11-20 12:54:10 +00:00
|
|
|
|
2022-11-22 11:48:34 +00:00
|
|
|
var locationSearchObj = parseQuery(window.location.search)
|
|
|
|
locationSearchObj.lang = optionEle.value
|
|
|
|
history.pushState(null, websiteTitle.innerText, window.location.protocol + '//' + window.location.host + window.location.pathname + obj2searchQuery(locationSearchObj) + window.location.hash)
|
2022-11-20 12:54:10 +00:00
|
|
|
|
2022-11-22 11:48:34 +00:00
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
window.addEventListener('popstate', checkUrl)
|
|
|
|
}
|
2022-11-20 12:54:10 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2022-11-22 11:48:34 +00:00
|
|
|
// INIT WEBSITE
|
2022-11-20 12:54:10 +00:00
|
|
|
|
|
|
|
function _DATA_GOT_LOADED() {
|
|
|
|
if (typeof _DATA_ !== 'undefined') {
|
|
|
|
checkUrl()
|
|
|
|
generateForm(_DATA_)
|
|
|
|
}
|
|
|
|
}
|
2022-11-22 00:33:10 +00:00
|
|
|
|
|
|
|
window.addEventListener('load', () => {
|
|
|
|
_DATA_GOT_LOADED()
|
|
|
|
initTeams()
|
2022-11-22 11:48:34 +00:00
|
|
|
initLanguageChooser()
|
|
|
|
initNavigationButtons()
|
|
|
|
initSubmit()
|
2022-11-22 00:33:36 +00:00
|
|
|
})
|