In modern web applications, it is essential to provide users with a seamless experience where their progress is saved across sessions. One of the most common use cases for this is tracking how much of a video a user has watched, so they can pick up where they left off. This tutorial will walk you through how to implement such a system using JavaScript, localStorage, and event listeners, while also integrating server-side communication to store watched time.
**
Overview of the Code
**
The provided solution allows for tracking the watched time of multiple videos on a webpage. It stores the watch progress in the browser’s localStorage and, if a user exceeds the last watched time, updates the progress in a server-side database using a POST request. The goal is to offer a generic, scalable method that works for all videos with minimal effort.
<video class="videoCourse" controls data-idvideo="123">
<source src="path/to/video.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
<video class="videoCourse" controls data-idvideo="123">
: This element embeds a video player on the page.
The class="videoCourse" is used to select all videos on the page via JavaScript.
The data-idvideo="123" is a custom attribute that holds a unique identifier for each video. This ID allows us to track and store the watch progress for individual videos.
// Function to update the watched time
function updateWatchedTime(video, videoId) {
var timeInSeconds = video.currentTime; // Time watched in seconds
var minutes = Math.floor(timeInSeconds / 60); // Whole part (minutes)
var seconds = timeInSeconds % 60; // Remaining seconds
var decimalTime = minutes + (seconds / 60); // Converts seconds into a fractional minute
// Get the last recorded time for the video (saved in localStorage or a global variable)
var lastRecordedTime = localStorage.getItem("lastRecordedTime_" + videoId);
if (lastRecordedTime === null) {
lastRecordedTime = 0; // Default value if no previous time is found
} else {
lastRecordedTime = parseFloat(lastRecordedTime);
}
// Check if the current time is greater than the last recorded time
if (decimalTime > lastRecordedTime) {
// If the current time is greater, save the new time
var requestData = "VIDEO_ID=" + videoId + "&WATCHED_TIME=" + decimalTime.toFixed(4);
console.log("Sending: " + requestData); // Shows the watched time in decimal (4 decimal places)
// Send the data to the server (replace with actual URL)
$.post("path/to/api", requestData, function(response) {
// Handle server response if needed
console.log("Server response: " + response);
// After saving, update the localStorage with the new watched time
localStorage.setItem("lastRecordedTime_" + videoId, decimalTime.toFixed(4));
});
} else {
console.log("Watched time is less than the last recorded time. No update sent.");
}
}
// Add an event listener for the 'timeupdate' event to all video elements
document.querySelectorAll('.videoCourse').forEach(function(video) {
// Get the video ID (should be uniquely assigned to each video element)
var videoId = video.getAttribute('data-idvideo');
// Add the 'timeupdate' event listener
video.addEventListener('timeupdate', function(event) {
updateWatchedTime(video, videoId); // Pass the video and its ID directly
});
});
**
Explanation of the Code
- Update Watched Time Function** The core of this solution is the updateWatchedTime() function. This function is responsible for:
Calculating the Watch Progress: The function first retrieves the currentTime of the video (in seconds) and converts this into minutes and seconds. The time is then converted to a decimal format (e.g., 3 minutes 30 seconds becomes 3.50).
Checking the Last Recorded Time: Using the localStorage.getItem() method, we retrieve the last recorded time for the video. If no time has been recorded yet (i.e., the first time the user watches the video), it defaults to 0. This ensures that progress tracking starts from zero.
Storing the Time: If the current time is greater than the last recorded time, it means the user has watched more of the video since the last update. The function sends the updated time to the server using a POST request. After the data is successfully sent, the localStorage is updated with the new time.
2. Handling Multiple Videos
The script adds an event listener to all videos on the page with the class="videoCourse". It uses the data-idvideo attribute to get the unique video ID and tracks the progress for each individual video.
Event Listener: Every time the video’s time is updated (i.e., as the user watches the video), the timeupdate event is triggered. This event fires continuously as the video plays, providing an opportunity to track the progress.
querySelectorAll(): This method selects all video elements on the page, making the script adaptable for any number of videos. It loops through each video, attaching the timeupdate listener, ensuring that the watch progress is tracked for each video independently.
**
How This Works: A Step-by-Step Flow
**
User Watches Video: As the user watches the video, the timeupdate event continuously triggers.
Watch Progress Calculated: The script calculates how much of the video has been watched in minutes and seconds, then converts it to a decimal format.
Last Recorded Time: The script compares the current watch time to the last recorded time saved in localStorage.
Update if Necessary: If the current watch time is greater than the previously saved time, the new time is sent to the server. Afterward, the new time is saved in localStorage.
Next Visit: The next time the user visits the page, the script checks localStorage for the last saved time. If available, it starts tracking from where the user left off.
**
Benefits and Use Cases
**
Scalability: This approach works for any number of videos on a page. It uses the data-idvideo attribute to uniquely identify each video, making the system scalable without modification.
Persistence: Using localStorage, the user’s progress is saved across sessions. Even if the page is reloaded or if the user leaves and returns, their progress is retained.
Seamless Integration: The solution integrates smoothly with existing video players, making it easy to implement on websites that already use the HTML5
Top comments (1)
Great post! This is a useful technique for tracking video watch progress in JavaScript—definitely going to try this in my projects.