I have made a GUI which will record data remotely and store the data in a google sheet. I have been able to store the user inputs in google sheet but i am struggling with other values
My code (thanks to link)
```<!DOCTYPE html>
<html>
<head>
<title>Listening Test</title>
<!-- bootstrap & fontawesome css -->
<link href="http://cdn.jsdelivr.net/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet"/>
<link rel="stylesheet" href="http://cdn.jsdelivr.net/fontawesome/4.1.0/css/font-awesome.min.css" />
<!-- BootstrapValidator CSS -->
<link rel="stylesheet" href="http://cdn.jsdelivr.net/jquery.bootstrapvalidator/0.5.0/css/bootstrapValidator.min.css"/>
<!-- jQuery and Bootstrap JS -->
<script type="text/javascript" src="http://cdn.jsdelivr.net/jquery/1.11.1/jquery.min.js"></script>
<script type="text/javascript" src="http://cdn.jsdelivr.net/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<!-- BootstrapValidator JS -->
<script type="text/javascript" src="http://cdn.jsdelivr.net/jquery.bootstrapvalidator/0.5.0/js/bootstrapValidator.min.js"></script>
<!-- Animated Loading Icon -->
<style type="text/css">
.glyphicon-refresh-animate {
-animation: spin .7s infinite linear;
-webkit-animation: spin2 .7s infinite linear;
}
@-webkit-keyframes spin2 {
from { -webkit-transform: rotate(0deg);}
to { -webkit-transform: rotate(360deg);}
}
@keyframes spin {
from { transform: scale(1) rotate(0deg);}
to { transform: scale(1) rotate(360deg);}
}
</style>
</head>
<body>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-lg-12">
</div>
</div>
<hr>
<div class="row center">
<h5 class="header col s12 light brown-text">Step 1: Enter sentence you want to start from <br> Step 2: click start and listen to the fixed set of audio files <br> If you detect speaker change point, give your response in the form of 'YES/NO'</h5>
<p style="color:red">(Use earphones if available)</p>
</div>
<form class="row center" role="form" id="test-form">
<div class="form-group">
<label class="col-lg-3 control-label">Name</label>
<div class="col-lg-3 inputGroupContainer">
<div class="input-group">
<input type="text" class="form-control" name="firstName" placeholder="First Name"/>
</div>
</div>
</div>
<div class="form-group">
<label class="col-lg-3 control-label">Sentence Number</label>
<div class="col-lg-3 inputGroupContainer">
<div class="input-group">
<!-- <textarea type="text" class="form-control" name="notes" placeholder="Sentence Number"></textarea> -->
<input type="text" class="form-control" name="notes" placeholder="Sentence Number"/>
</div>
</div>
</div>
<div class="form-group">
<div class="col-lg-9 col-lg-offset-3">
<button type="submit" class="btn btn-default" id="postForm">Submit</button>
</div>
</div>
</form>
</div>
</body>
<footer>
<script src="validation-functions.js"></script>
</footer>
</html>```
Validate google sheet and taking the google ID
```$(document).ready(function() {
$('#test-form').bootstrapValidator({
//submitButtons: '#postForm',
// To use feedback icons, ensure that you use Bootstrap v3.1.0 or later
feedbackIcons: {
valid: 'glyphicon glyphicon-ok',
invalid: 'glyphicon glyphicon-remove',
validating: 'glyphicon glyphicon-refresh'
},
fields: {
firstName: {
message: 'The first name is not valid',
validators: {
notEmpty: {
message: 'The first name is required and cannot be empty'
},
stringLength: {
min: 1,
max: 30,
message: 'The first name must be more than 1 and less than 30 characters long'
},
regexp: {
regexp: /^[A-z]+$/,
message: 'The first name can only accept alphabetical input'
},
}
},
lastName: {
message: 'Last Name is not valid',
validators: {
notEmpty: {
message: 'Last Name is required and cannot be empty'
},
stringLength: {
min: 1,
max: 30,
message: 'Last Name must be more than 1 and less than 30 characters long'
},
regexp: {
// regexp: /^[A-z]+$/,
message: 'Last Names can only consist of alphabetical characters'
},
}
},
email: {
validators: {
notEmpty: {
message: 'The email address is required and cannot be empty'
},
emailAddress: {
message: 'The email address is not a valid'
}
}
},
address: {
message: 'Address is not valid',
validators: {
notEmpty: {
message: 'Address is required and cannot be empty'
}
}
},
}
})
.on('success.form.bv', function(e) {
// Prevent form submission
e.preventDefault();
// Get the form instance
var $form = $(e.target);
// Get the BootstrapValidator instance
var bv = $form.data('bootstrapValidator');
// Use Ajax to submit form data
var url = 'https://script.google.com/macros/s/AKfycbxdbjLtkrE7SlC1OKBvOLoj7KpfFhKpZMb7xI-vxf64ZNIYsEViZl6kTJJMkab0wgyM/exec';
var redirectUrl = 'recorder.html';
// show the loading
$('#postForm').prepend($('<span></span>').addClass('glyphicon glyphicon-refresh glyphicon-refresh-animate'));
var jqxhr = $.post(url, $form.serialize(), function(data) {
console.log("Success! Data: " + data.statusText);
$(location).attr('href',redirectUrl);
})
.fail(function(data) {
console.warn("Error! Data: " + data.statusText);
// HACK - check if browser is Safari - and redirect even if fail b/c we know the form submits.
if (navigator.userAgent.search("Safari") >= 0 && navigator.userAgent.search("Chrome") < 0) {
//alert("Browser is Safari -- we get an error, but the form still submits -- continue.");
$(location).attr('href',redirectUrl);
}
});
});
});```
My main javascript file where data will be loaded
```<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"
integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN"
crossorigin="anonymous"
/>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="music-container" id="music-container">
<div class="music-info" id="music-info">
<h4 id="title"></h4>
<span class="timestamp" id="timestamp">00:00 / 00:00</span>
<div class="progress-container" id="progress-container">
<div class="progress" id="progress"></div>
</div>
</div>
<audio src="music/1.wav" id="audio"></audio>
<div class="img-container">
<img src="images/1.png" alt="music-cover" id="cover" />
</div>
<div class="navigation">
<!-- <div class="col s6 input-field">
<input value="" id="number" min="1" max="150" step="1" type="number" class="validate">
<label for="number">Enter sentence no</label>
</div> -->
<!-- <button id="random" class="action-btn">
<i class="fa fa-random"></i>
</button> -->
<!-- <button id="prev" class="action-btn">
<i class="fa fa-backward"></i>
</button> -->
<button id="play" class="action-btn action-btn-big">
<i class="fa fa-play">Play</i>
</button>
<button id="next" class="action-btn">
<i class="fa fa-forward">Next audio</i>
</button>
<button id="repeat" class="action-btn">
<i class="fa fa-repeat">Repeat</i>
</button>
<br />
<button id="yes" class="action-btn">
<i class="fa fa-yes">Yes</i>
</button>
<button id="no" class="action-btn">
<i class="fa fa-no">No</i>
</button>
</div>
</div>
<!-- <p hidden>
<details class="order-container" id="order-container"></details>
</p> -->
<script>
const musicContainer = document.getElementById("music-container");
const musicInfo = document.getElementById("music-info");
const playBtn = document.getElementById("play");
// const prevBtn = document.getElementById('prev');
const nextBtn = document.getElementById("next");
const sentence = document.getElementById("number")
// const random = document.getElementById('random');
const repeat = document.getElementById("repeat");
const audio = document.getElementById("audio");
const progress = document.getElementById("progress");
const progressContainer = document.getElementById("progress-container");
const title = document.getElementById("title");
const cover = document.getElementById("cover");
const timestamp = document.getElementById("timestamp");
// const orderContainer = document.getElementById('order-container');
const yes = document.getElementById("yes");
const no = document.getElementById("no");
// Song titles
const initialSongs = [];
let songs = [...initialSongs];
const params = new Proxy(new URLSearchParams(window.location.search), {
get: (searchParams, prop) => searchParams.get(prop),
});
// Get the value of "sentence-number" --> "https://example.com/?sentence-number=1"
let value = params.sentence;
// Keep track of song
let songIndex = 1;
// Initially load song details info DOM
loadSong(songs[songIndex]);
// Update song details
function loadSong(song) {
title.innerText = song;
audio.src = `music/${song}.wav`;
cover.src = `images/${song}.png`;
}
var startTime;
// Play song
function playSong() {
updateTimestamp();
musicContainer.classList.add("play");
musicInfo.classList.add("show");
playBtn.querySelector("i.fa").classList.remove("fa-play");
playBtn.querySelector("i.fa").classList.add("fa-pause");
audio.play();
startTime = Date.now();
}
// Pause song
function pauseSong() {
musicContainer.classList.remove("play");
playBtn.querySelector("i.fa").classList.add("fa-play");
playBtn.querySelector("i.fa").classList.remove("fa-pause");
audio.pause();
}
// Previous song
function prevSong() {
songIndex--;
if (songIndex < 0) {
songIndex = song.length - 1;
}
loadSong(songs[songIndex]);
playSong();
}
// Calculate time
function stopButton() {
if (startTime) {
var endTime = Date.now();
var difference = endTime - startTime;
alert("Reaction time: " + difference + " ms");
startTime = null;
}
return difference
}
// Next song
function nextSong() {
songIndex++;
if (songIndex > songs.length - 1) {
songIndex = 0;
}
loadSong(songs[songIndex]);
playSong();
}
// Get song duration
function getSongDuration() {
let allMins = Math.floor(audio.duration / 60);
if (allMins < 10) {
allMins = "0" + String(allMins);
}
let allSecs = Math.floor(audio.duration % 60);
if (allSecs < 10) {
allSecs = "0" + String(allSecs);
}
if (allMins && allSecs) {
return `${allMins}:${allSecs}`;
} else {
return "00:00";
}
}
// Update timestamp
function updateTimestamp() {
// Get minutes
let mins = Math.floor(audio.currentTime / 60);
if (mins < 10) {
mins = "0" + String(mins);
}
// Get seconds
let secs = Math.floor(audio.currentTime % 60);
if (secs < 10) {
secs = "0" + String(secs);
}
if (mins && secs) {
timestamp.innerHTML = `${mins}:${secs} / ${getSongDuration()}`;
} else {
timestamp.innerHTML = "00:00 / 00:00";
}
}
// Update progress bar
function updateProgress(e) {
const { duration, currentTime } = e.srcElement;
const progressPercent = (currentTime / duration) * 100;
progress.style.width = `${progressPercent}%`;
updateTimestamp();
}
// Set progress bar & timestamp
function setProgress(e) {
const width = this.clientWidth;
const clickX = e.offsetX;
const duration = audio.duration;
audio.currentTime = (clickX / width) * duration;
updateTimestamp();
}
// Set song on repeat
function repeatSong() {
const isPlaying = musicContainer.classList.contains("play");
if (isPlaying) {
pauseSong();
} else {
playSong();
}
}
// Set song on repeat
function setRandomOrder() {
if (random.classList.contains("active")) {
random.classList.remove("active");
songs = [...initialSongs];
songIndex = songs.indexOf(title.innerText);
} else {
random.classList.add("active");
songs = shuffle(songs);
songIndex = songs.indexOf(title.innerText);
}
}
// Shuffle songs
function shuffle(songs) {
for (let i = songs.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[songs[i], songs[j]] = [songs[j], songs[i]];
}
return songs;
}
// Set song on click
function setSong(i) {
songIndex = i;
console.log("setSong -> songIndex", songIndex);
loadSong(songs[songIndex]);
playSong();
}
// Event listeners
playBtn.addEventListener("click", () => {
const isPlaying = musicContainer.classList.contains("play");
if (isPlaying) {
pauseSong();
} else {
playSong();
}
});
// Change song
nextBtn.addEventListener("click", nextSong);
// Time/song update
audio.addEventListener("timeupdate", updateProgress);
// Click on progress bar
progressContainer.addEventListener("click", setProgress);
// Song ends
audio.addEventListener("ended", pauseSong);
// Repeat song
repeat.addEventListener("click", repeatSong);
// Random songs order
// random.addEventListener('click', setRandomOrder);
yes.addEventListener("click", stopButton);
no.addEventListener("click", stopButton);
const download = function (data) {
// Creating a Blob for having a csv file format
// and passing the data with type
const blob = new Blob([data], { type: 'text/csv' });
// Creating an object for downloading url
const url = window.URL.createObjectURL(blob)
// Creating an anchor(a) tag of HTML
const a = document.createElement('a')
// Passing the blob downloading url
a.setAttribute('href', url)
// Setting the anchor tag attribute for downloading
// and passing the download file name
a.setAttribute('download', 'download.csv');
// Performing a download with click
a.click()
}
const csvmaker = function (data) {
// Empty array for storing the values
csvRows = [];
// Headers is basically a keys of an
// object which is id, name, and
// profession
const headers = Object.keys(data);
// As for making csv format, headers
// must be separated by comma and
// pushing it into array
csvRows.push(headers.join(','));
// Pushing Object values into array
// with comma separation
const values = Object.values(data).join(',');
csvRows.push(values)
// Returning the array joining with new line
return csvRows.join('\n')
}
const get = async function () {
// JavaScript object
const data = {
id: 1,
name: `${stopButton}`,
profession: "developer"
}
const csvdata = csvmaker(data);
download(csvdata);
}
// Getting element by id and adding
// eventlistener to listen everytime
// button get pressed
const btn = document.getElementById('action');
btn.addEventListener('click', get);
</script>
</body>
</html>
```
[![enter image description here][2]][2]
[1]: https://gist.github.com/willpatera/ee41ae374d3c9839c2d6
[2]: https://i.stack.imgur.com/sWmF7.png
As can be seen from the picture
i want to add the value of button output from repeat, Yes and No to the google sheet.
That means every time the user presses 'Yes' the google sheet should update it as yes in that specific column. Same goes for the No and no. of repeatations.
Any kind of help would be greatly appreciated
Thank you