Need help integrating code wrote on Edittext to the Discourse

I created this timer using the following code, it’s working locally but I having trouble integrating it on my forum. Can someone please help?

<!-- HTML (Add this to the Header section) -->
<style>
  button {
    padding: 5px;
    margin: 2px;
    cursor: pointer;
    border: none;
    color: white;
    width: 100px; /* Set the desired width for all buttons */
    border-radius: 5px;
  }

  #readTaskButton {
    background: #008000; /* Darker green for better visibility on dark background */
  }

  #enterRoomButton {
    background: #DAA520; /* Darker yellow */
  }

  #pauseButton {
    background: #A0522D; /* Darker orange */
  }

  #stopButton {
    background: #FF0000; /* Darker red */
  }
</style>

<div style="display: flex; align-items: center; justify-content: center;">
  <div style="display: flex; flex-direction: column; align-items: center; margin-right: 20px;">
    <button id="readTaskButton" onclick="startTimer(90)">Read Task</button>
    <button id="enterRoomButton" onclick="startTimer(480)">Enter Room</button>
  </div>
  <div id="timer" style="font-size: 2em; text-align: center; margin: 0 20px;" onclick="togglePauseResume()">00:00</div>
  <div style="display: flex; flex-direction: column; align-items: center; margin-left: 20px;">
    <button id="pauseButton" onclick="togglePauseResume()">Pause</button>
    <button id="stopButton" onclick="stopTimer()">Stop</button>
  </div>
</div>

<!-- JavaScript (Add this to the Footer section) -->
<script>
  let timer;
  let totalSeconds;
  let isShortTimer = true;
  let isPaused = false;

  function startTimer(duration) {
    resetTimer();
    totalSeconds = duration;
    timer = setInterval(updateTimer, 1000);
  }

  function togglePauseResume() {
    if (isPaused) {
      resumeTimer();
    } else {
      pauseTimer();
    }
    updateButtonLabel();
  }

  function updateButtonLabel() {
    const button = document.getElementById('pauseButton');
    button.innerText = isPaused ? 'Resume' : 'Pause';
  }

  function pauseTimer() {
    clearInterval(timer);
    isPaused = true;
  }

  function resumeTimer() {
    isPaused = false;
    timer = setInterval(updateTimer, 1000);
  }

  function stopTimer() {
    resetTimer();
    updateButtonLabel();
  }

  function updateTimer() {
    if (totalSeconds <= 0) {
      if (isShortTimer) {
        isShortTimer = false;
        startTimer(480); // Start the longer timer automatically after the initial timer
      } else {
        isShortTimer = true;
        startTimer(90); // Start the initial timer automatically after the longer timer
      }
    }

    const minutes = Math.floor(totalSeconds / 60);
    const seconds = totalSeconds % 60;

    const formattedTime = `${formatTime(minutes)}:${formatTime(seconds)}`;
    document.getElementById('timer').innerText = formattedTime;

    totalSeconds--;
  }

  function formatTime(time) {
    return time < 10 ? '0' + time : time;
  }

  function resetTimer() {
    clearInterval(timer);
    document.getElementById('timer').innerText = '00:00';
  }
</script>

Hi,

You would want to insert the JS in Head instead to make it work!
Also, be careful with the button CSS – you should make a specific selector to avoid overwriting the default CSS.

Ideally, you want to create a theme component, and use an outlet to handle HTML/logic. I can show you later!

2 Likes

Thank you so much for responding.

I tried that. I created a new theme component and then by using edit CSS/HTML option, I inserted that code in common>header section. I can see the timer on the website but the problem is that the timer doesn’t play. It has play and stop button, locally it works fine but on the website it only shows the timer but no functioning.


I also checked console, using inspect and this is the error that it shows.

Yes, your code is being blocked by CSP. (see security settings)
You could whitelist unsafe-inline in the settings, but that doesn’t sound like a good idea.
In your case, to make your code work with CSP enabled, i believe you need to handle the click differently.


On a side note, here is a theme component using your code: https://github.com/Arkshine/discourse-timer-component.
Feel free to fork it and install it on your Discourse.

Hopefully, my code is not too horrible, but this would be the preferred way as opposition adding plain JavaScript in this context.
It should work the same with extra reactivity stuff, settings, and locale.

It may be overwhelming, but it is an excellent opportunity to dig into theme component development! Do not hesitate to ask if you don’t understand something. :slight_smile:

I highly recommend using the Discourse Theme CLI if you want to work with it locally. It’s handy!

2 Likes

I can’t thank you enough for helping me with this. This is amazing!!
You have inspired me to learn this. :heart:

There are few changes and queries I have regarding the timer. Can I share with you?

Queries:

  1. What’s the purpose of waiting button?

Critical Immediate Changes:

  1. It’s a continuous timer, first starts with 1:30 sec then shift to 8:00 min then shift to 1:30 and so on, never ends.

  2. When the timer is playing, users need to have the ability to bypass directly to 8:00 min by clicking on enter room button or shift to 1:30 timer by clicking on the read task timer. therefore disabling the pause and stop button when the timer is not playing makes sense but when the timer is playing and disabling the read task and enter room button will unable users to bypass the timer.

Future Changes:

  1. Adding a voice note at start 1:30 sec timer, start of 8:00 min timer, at remaining 2:00 min of 8:00 min timer and finally end of 8:00 min timer, which is basically the start of 1:30 sec. So in total three voice notes,
  2. Adding a pop up alert for at each voice note, which appears and disappears, shouldn’t occupy the full screen, instead the area where timer is located.

I definitively did not understand everything in your code; it would seem :smile:

It doesn’t make sense to be able to click on those pause/stop buttons if a timer has not started. Same as showing “pause” or “resume”, so it’s like in the waiting you have an active timer. Actually, I would hide the button instead. But I guess it’s fine to use “pause” label as default.

It alternates between both, alright. I thought it was a loop with one of those timers.
I’m not sure to understand the context, it looks pretty weird to me, I can change it. :smile:

I see.

Let me fix that before doing anything else. :slight_smile:

Hey,

For me it’s amazing seeing this timer come to life. You’re amazing and inspiring.

This is a timer for a exam given by doctors, I am a doctor as well trying to help other doctors.

The exam consists of 16 rooms, containing 16 different patients that we need to diagnose and manage. Before entering any room a task is kept outside that you can read in 1 min 30 sec and then you enter the room, you have 8 minutes to perform the task and manage the patients, the cycle continues for 16 other rooms. that takes in total 3 hours to complete.

I unfortunately failed this exam, because of misinformation and misguidance related to this, which has inspired me to create this forum to help guide other doctors.

Hope this gives the context. :innocent:

1 Like

I’ve pushed an update. It should loop short/long timer, and you can switch to any timer now. I’ve also removed the “waiting…” usage. Let me know if it works better.

Thanks for explaining the context, I understand now! :+1:

2 Likes

I found a bug, if I click on the read task button the timer goes from 1:30 min to 8:00 min and then keeps looping on 1:30 min. If I click on enter room button, the timer goes from 8:00 to 1:30 and then keeps looping on the 8:00 min timer.

My bad. It’s fixed. I checked only the first loop because I was in a hurry, and I did not notice the switch did not happen after. :smile:

2 Likes

That’s okay!

I’ll also start learning from the material you shared earlier. I’ll get back to you, if I have any queries.

Now, the issue is that when you click the “Read Task” button, the timer starts at 1:30 and loops on 8:00.

1:30 > 8:00 > 8:00 > 8:00 …

If you click the “Enter Room” button, the timer starts at 8:00 and loops on 1:30.

8:00 > 1:30 > 1:30 > 1:30 …

Ideally, there should be a smooth, continuous loop alternating between 1:30 and 8:00, with the starting point determined by the button you click first.

For instance, if you click the “Read Task” button, the timer should start at 1:30 and then proceed in an alternating loop between 8:00 and 1:30:

1:30 > 8:00 > 1:30 > 8:00…

If you click the “Enter Room” button, the timer should start from 8:00 and follow an alternating loop between 1:30 and 8:00:

8:00 > 1:30 > 8:00 > 1:30…

Are you sure you did update and refresh the page? You describe the bug before the fix, and I can’t reproduce it now. I tested again, and it loops as expected.

1 Like

I just checked, it’s working as expected. :innocent::heart:

I think now I would like to learn how I can myself make changes to the timer. So, I stop bugging you. :joy:

I want to give myself a small task, with this existing project of the timer, which will help me learn.

The task is to add a name “PLAB 2 Timer” just above the actual timer, like that:

Can you guide me from where should I start?

The first time step is to install Discourse for development. It will be easier to test.

Then, you can fork my component, clone it somewhere, and use Discourse Theme CLI.

Look at the <template>... </template> code. You can add your text there.
The CSS is located in common/common.scss file.

You can localize your text by adding an entry in locales/en.yml – then you can use {{I18n.t(themePrefix("my_translation_key"))}}

2 Likes