SushiCode
SushiCode

Reputation: 97

How to associate Object with DOM element in plain Javascript?

I am trying to create an app where each click of a button will create a new stopwatch, which consist of an h1 and a div element:

const addButton = document.querySelector('.add-button')!;
addButton.addEventListener('click', createTimer);

function createTimer() {
    var divTimer = document.createElement('div');
    var divHeader = document.createElement('h1');

    divHeader.textContent = 'Timer';
    divTimer.textContent = '00:00:00';

    document.body.appendChild(divHeader);
    document.body.appendChild(divTimer);
}

However, I want to associate each stopwatch's DOM elements created from the button press above, with a stopwatch object. The idea is that each stopwatch should have its own seconds, minutes, hours.

const testTimerDisplay = document.getElementById('timerA')!;

//Class based objects ES6
class Stopwatch {
    seconds: number;
    minutes: number;
    hours: number;

    constructor() {
        this.seconds = 0;
        this.minutes = 0;
        this.hours = 0;
    }

    tick() {
        setInterval(() => {
            this.seconds++
            testTimerDisplay.textContent = this.seconds.toString(); //NOT A GOOD IMPLEMENTATION
        }, 1000)
    }
}

const timerA = new Timer();

As you can see, when I call tick(), it'll only modify testTimerDisplay which of course is not what I ultimately want. Is there a way for me to click the button and associate a new stopwatch object with the DOM that it creates?

Upvotes: 0

Views: 534

Answers (1)

Arthur Borba
Arthur Borba

Reputation: 463

Well you could work with IDs in your Stopwatch structure:

// remove this:
// const testTimerDisplay = document.getElementById('timerA')!;

//Class based objects ES6
class Stopwatch {
    // add the id prop
    id: string,
    seconds: number;
    minutes: number;
    hours: number;

    // add id as a parameter for the constructor
    constructor(id) {
        this.id = id; // set the id
        this.seconds = 0;
        this.minutes = 0;
        this.hours = 0;
    }

    tick() {
        setInterval(() => {
            this.seconds++;
            // at tick method you increment display based on the id
            const timerId = `timer${this.id}`;
            const testTimerDisplay = document.getElementById(timerId);
            testTimerDisplay.textContent = this.seconds.toString();
        }, 1000)
    }
}

Now you have to set this ID string as you tag id at your createTimer function:

const addButton = document.querySelector('.add-button')!;
addButton.addEventListener('click', createTimer);

function createTimer() {
    // first define this timer id, you could make it based on your list indexes
    var id = document.getElementsByClassName('timer').length || 0;
    var nextId = id + 1;

    // then make a parent div that encapsulate the below tags
    var parentDiv = document.createElement('div');
    parentDiv.id = `timer${nextId}`;
    parentDiv.className = 'timer';

    var divTimer = document.createElement('div');
    var divHeader = document.createElement('h1');

    divHeader.textContent = 'Timer';
    divTimer.textContent = '00:00:00';

    parentDiv.appendChild(divHeader);
    parentDiv.appendChild(divTimer);

    document.body.appendChild(parentDiv);
}

So you create you Stopwatch Object passing the desired ID, that will increment only It's own timer:

var stopwatch1 = new Stopwatch('1');

Upvotes: 1

Related Questions