I am working on a simple web page that stores the start time, then displays the time when you click a button sort of like a timer. I came across this problem where when clicking a button in a form, it reloads the script overwriting the start time variable. Here is the code:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Work Tracker</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body {background-color: grey;}
.button {
border: none;
color: rgb(0, 0, 0);
padding: 15px 32px;
text-align: right;
text-decoration: none;
display: inline-block;
font-size: 25px;
margin: 4px 2px;
cursor: pointer;
border-radius: 10px;
}
.button2 {background-color: #ff0000;}
#text1 {
color: black;
text-align: center;
font: bold 24px sans-serif;
background: white;
padding: 10px;
border: solid black 2px;
border-radius: 10px;
}
</style>
</head>
<body>
<?php
date_default_timezone_set('America/Los_Angeles');
$startTime = date("h:i a");
echo "<h2>" . $startTime . "</h2>";
if (isset($_POST["btn-endtimer"])) {
$endtime = date("h:i a");
echo "<h2>" . $endtime . "</h2>";
}
?>
<script type="text/javascript">
if(starttime === undefined){
var starttime = "<?php echo "$startTime"; ?>";
console.log(starttime);
}
console.log(starttime);
</script>
<form method="post">
<input type="submit" value="End Timer" name="btn-endtimer" style="background-color:#ffb3b3; height:100px; width:250px; font-size:50px; border-radius: 15px; border-color: #fc9f9f">
</form>
</body>
</html>
Here is the webpage: it displays the time when the page was opened as well as a button. When this button is clicked, it runs a line of code that stores the current date, but it reloads the script, so the start time variable is overwritten to the current time. Is there a way to send the starttime variable somewhere so that it can not be changed? This is what is looks like after clicking the button a few minutes later:
CodePudding user response:
Perhaps the easiest way to interact between browser and server to do what you want ( log a time ) would be to use AJAX. Requests are sent without needing to reload the page and provide a better user experience.
The following would send a time
to the server (same page in this instance) - how you deal with that server-side is not specified but would, in most cases, involve writing to a database.
This demo will fire an ajax request but due to the sandbox will throw an error but inspecting network traffic in console should illustrate what happens.
// utility to format a Date into a minimal timestring - chose UK for locale
const gettime=()=>Intl.DateTimeFormat('en-GB', { timeStyle:'medium' } ).format( new Date() );
// utility to display, in the H2 element, the time at any particular moment
const displaytime=()=>{
let date=gettime();
let content=`<div>${date}</div>`;
document.querySelector('h2').insertAdjacentHTML('beforeend',content)
};
// the AJAX callback. This can be used to do what ever you need to do once you have logged
// the time on the server. DOM manipulation, inform user, open window etc
const callback=(r)=>{
alert(r)
};
// There is no need to actually send the time from the client ( it can be modified )
// - instead you could just send a beacon to say "log now" type thing but for example
// send the time to the same page.
const sendtime=()=>{
let url=location.href; // or /path/to/script.php etc
let fd=new FormData();
fd.set('time',gettime() );
fetch( url,{ method:'post',body:fd } )
.then(r=>r.text())
.then(callback)
.catch(alert)
};
// delegated event listener to respond to button clicks
document.addEventListener('click',e=>{
if( e.target instanceof HTMLInputElement && e.target.type=='button' && e.target.name=='btn-endtimer' ){
displaytime();
sendtime();
}
});
// how initial load time - this could be fetched from db rather than using current time!
displaytime();
body {
background-color: grey;
}
/*
other styles removed as they were not applicable
to the original code
*/
input[name="btn-endtimer"] {
background-color: #ffb3b3;
height: 100px;
width: 250px;
font-size: 50px;
border-radius: 15px;
border-color: #fc9f9f
}
<h2></h2>
<input type="button" value="End Timer" name="btn-endtimer" />
CodePudding user response:
The method post will always refresh the page since PHP code is sent to server and it needs to be loaded typically on new page.
You can avoid that by using JavaScript function
<body>
<?php
date_default_timezone_set('America/Los_Angeles');
$startTime = date("h:i a");
echo "<h2>" . $startTime . "</h2>";
?>
<script>
window.addEventListener("load", function() {
var endTime = "";
var startTime = "<?php echo $startTime; ?>";
console.log(startTime);
document.getElementById("end-timer-button").addEventListener("click", function() {
endTime = new Date().toLocaleTimeString();
document.getElementById("end-time").innerHTML = endTime;
});
});
</script>
<button id="end-timer-button"
style="background-color:#ffb3b3; height:100px; width:250px; font-size:50px; border-radius: 15px; border-color: #fc9f9f">End
Timer</button>
<h2 id="end-time"></h2>
</body>
The PHP code is used to create new variable $startTime
and store it. The JavaScript code is used to handle the button click and store var = EndTime
wich is an empty string that gets value from PHP $startTime
. Finally document.getElementById("end-time").innerHTML = endTime;
prints out the EndTime
variable into <h2 id="end-time"></h2>
if you want the time to be displayed above the button. you can simply put it between the PHP code And start of JavaScript like this
echo "<h2>" . $startTime . "</h2>";
?>
<h2 id="end-time"></h2>
<script>
Hope this helps / solves your problem