Timer Concept

Here is a first draft of a timer concept I came up with, similar to what we had with Classic Apps. This uses some USC columns, javascript columns, HTML, and a Web Embed component to function without having to worry about the 10 second limit that we experience within Glide currently. It’s a little bit of setup, but not too terrible.

The old timer in classic apps used start time, current time, duration, and some javascript math to work. This follows very similar logic.

The buttons set various values in a table, which are used to build a small HTML page that shows the timer. To keep the times as accurate as possible and make it easy to calculate durations, I ended up using unix time. This made durations a whole lot easier to calculate.

The custom actions for the buttons may be a little overkill with a handful of Set Column actions strung together and some Wait conditions in between, but I wanted to make sure there weren’t any surprises with values getting set before they were calculated on the back end.

Let me know if anything doesn’t work correctly, or if you have any ideas to improve or simplify my logic. Also feel free to fork it and make improvements. Just be sure to share in this same thread if you do.

This should be a copyable template.
@Himaladin @Robert_Petitto

8 Likes

Visually, STUNNING!

This still doesn’t solve for to-the-second accuracy in the data editor though for visibility conditions, etc. correct?

I guess it depends on how its used. Clicking a button would give you to-the-millisecond accuracy, but no, I’m pretty sure it wouldn’t work to control visibility since the timer itself is contained in the web embed sandbox.

1 Like

Ya…that’s the rub :frowning:

Regardless, as always, you are the MAN.

I will definitely be bookmarking this app for when I need to display a timer, but until Glide gives us faster refresh in the data editor, I can’t use it for the QA app I’m currently building.

1 Like

You’re using setInterval, and I don’t see the use of delay. Do you mean they are the same? I’ve tested setInterval doesn’t work in Glide tables.

Thank you for sharing.

The setInterval is not running in a normal javascript column. It’s running on a small html page that contains the javascript inside of the web embed component. Every time a button is pressed, it rebuilds the html and the web embed reloads to run the javascript inside of that html page.

1 Like

It seems like a dead-end to work in the data editor unless accepting a delay time at the beginning.

I’m thinking the same. It becomes impractical to use the delay method.

I do remember a couple of years ago, there was a little bit of a hack where you could use a location component to continuously update your location, and as a side effect, it would cause computed columns in the same table to compute every 2 to 5 seconds instead of every 10 seconds. Not a very good solution and I’m not sure if it works like that anymore, but it was interesting to observe. But it does prove that it is possible if Glide allowed it. However, I imagine that it could start to use a lot of device resources, especially if a large table is continually updated and running code.

For now, I think the web embed method is the best option we have because it allows you to continuously run javascript in a loop and still see results as it runs.

It’s very interesting. I searched many posts here and saw @Uzo posts about timers and delays, but there is no way to contact or message him. Why?

@Jeff_Hager, I use the same technique for both the clock display and the countdown, all within the web embed component.

ScreenRecording2024-06-16at22.21.01-ezgif.com-video-to-webp-converter

1 Like

Hi! Could you share the template for the Countdown?
Thanks in advance

@Felipe_Andai are you asking me or @Himaladin for a template? Mine already is a template.

I should mention though, that since I posted this, we now have the ability to create custom components, which is probably a better way to achieve this. I’ve seen a couple demonstrations of this by others already.

1 Like

I already saw yours, it’s awesome. But I needed the countdown functionality.

1 Like

So you want to set a deadline, and the clock starts the countdown towards that deadline?

Exactly, I need to set 30 minutes and countdown to 0 showing seconds. I followed @Jeff_Hager Custom Component implementation and it’s incredible, but unstable, if the App loses focus it stops.

This is a modification of Jeff’s template script. Replace {{deadline}} with your deadline column.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Deadline Countdown</title>
    <style>
        html, body {
            height: 100vh;
            margin: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            font-family: Arial, sans-serif;
            background-color: #f0f0f0;
            flex-direction: column;
        }
        #deadline {
            font-size: 1em;
        }
        #countdown {
            font-size: 2em;
        }
    </style>
</head>
<body>
    <div id="deadline">Deadline: </div>
    <div id="countdown"></div>

    <script>
        function updateCountdown(deadline) {
            const now = new Date();
            if (!deadline || deadline === 0) {
                document.getElementById('deadline').textContent = 'Deadline: Not Set';
                document.getElementById('countdown').textContent = '00:00:00';
            } else {
                const remainingTime = deadline - now.getTime();
                if (remainingTime <= 0) {
                    document.getElementById('countdown').textContent = '00:00:00';
                    document.getElementById('deadline').textContent = 'Time\'s up!';
                } else {
                    const remainingHours = String(Math.floor(remainingTime / (1000 * 60 * 60))).padStart(2, '0');
                    const remainingMinutes = String(Math.floor((remainingTime % (1000 * 60 * 60)) / (1000 * 60))).padStart(2, '0');
                    const remainingSeconds = String(Math.floor((remainingTime % (1000 * 60)) / 1000)).padStart(2, '0');
                    document.getElementById('countdown').textContent = `${remainingHours}:${remainingMinutes}:${remainingSeconds}`;
                }
            }
        }

        const deadlineString = '{{deadline}}'.replace(' at', ''); 
        const deadline = new Date(deadlineString).getTime(); 
        document.getElementById('deadline').textContent += deadlineString;
        updateCountdown(deadline);

        setInterval(() => updateCountdown(deadline), 1000);
    </script>
</body>
</html>

6 Likes

Thanks a lot!

1 Like

How were you able to reduce the space below the countdown? I made a slight adjustment to the script and got rid of the space above. But I can’t seem to find how to edit the space below:

Here’s my code:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width">
    <title>Deadline Countdown</title>
    <style>
        html, body {
            justify-content: center;
            align-items: center;
            font-family: Arial, sans-serif;
            color: red; /* Change text color to red */
            padding: 10px 0;
        }
        #countdown {
            font-size: 1.5em;
            font-weight: bold;
            text-align: center;
            box-sizing: border-box; /* Ensure padding is included in the element's total width */
        }
        .unit {
            font-size: 0.3em;
            margin-left: 0.1em;
        }
        .segment {
            margin: 0 1em; 
        }
    </style>
</head>
<body>
    <div id="countdown"></div>

    <script>
        function updateCountdown(deadline) {
            const now = new Date();
            const remainingTime = deadline - now.getTime();
            
            if (remainingTime <= 0) {
                document.getElementById('countdown').innerHTML = '00<span class="unit">D</span> | 00<span class="unit">H</span> | 00<span class="unit">M</span> | 00<span class="unit">S</span>';
            } else {
                const remainingDays = String(Math.floor(remainingTime / (1000 * 60 * 60 * 24))).padStart(2, '0');
                const remainingHours = String(Math.floor((remainingTime % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60))).padStart(2, '0');
                const remainingMinutes = String(Math.floor((remainingTime % (1000 * 60 * 60)) / (1000 * 60))).padStart(2, '0');
                const remainingSeconds = String(Math.floor((remainingTime % (1000 * 60)) / 1000)).padStart(2, '0');
                document.getElementById('countdown').innerHTML = `${remainingDays}<span class="unit">D</span>` +
                    `<span class="segment">|</span>${remainingHours}<span class="unit">H</span>` +
                    `<span class="segment">|</span>${remainingMinutes}<span class="unit">M</span>` +
                    `<span class="segment">|</span>${remainingSeconds}<span class="unit">S</span>`;
            }
        }

        const deadlineString = '{{deadline}}'.replace(' at', ''); 
        const deadline = new Date(deadlineString).getTime(); 
        updateCountdown(deadline);

        setInterval(() => updateCountdown(deadline), 1000);
    </script>
</body>
</html>

Oh yes, the cause is the smallest height size of the web embed component, not the javascript code. To make it smaller, I added a container to set it with custom CSS (class name: iframeSize).

.iframeSize iframe.size-small {
    height: 100px;
}
2 Likes

Hi. I replaced the code as you suggested, but I cannot make it work properly. It displays “Deadline: not set”. Probably it’s just a minor adjustment but I just can’t.