Simon Kiely
Simon Kiely

Reputation: 6050

How to target CSS (not inject HTML) in JS?

I am building a simple chatbot. On each new message received from the server, a new HTML element is created and pushed to the browser.

So, for example, message 1 will be :

 <div class="message-computer"><p>Hi, how are you?</p></div>

Then you (the user) types/sends a message, which shows up as :

 <div class="message-user"><p>I am good, thanks!</p></div>

and so on and so forth.

I am trying to add a button to change the background color of all existing chat messages AND any new incoming messages from the computer.

This would work if I edited the CSS for .message-computer. I want to be able to switch between the two colours though.

So, I have added a button in my HTML, and it links to this javascript :

<script>
function changeClass(){

      var myElements = document.querySelectorAll(".message-computer");
      for (var i = 0; i < myElements.length; i++) {
        myElements[i].style.color = "black";
        myElements[i].style.backgroundColor = "yellow";
      }

    }
  </script>

This kind of works - it injects the CSS into existing elements like so -

<div class="message-computer" style="color: black; background-color: yellow;"><p>Hi, how are you?</p></div>

It doesn't work for new messages at all though.

How can I make it work for any new and incoming messages? I have tried setting the parent element, but since a new div is created for every new element this does not work.

Upvotes: 0

Views: 2304

Answers (3)

dschu
dschu

Reputation: 5374

Instead of adding new styles for each element, you should define your different styles and simply toggle between the states.

// Select input (checkbox)
const checkBox = document.querySelector('label#darkMode > input')

// Define a function, which handles the event (arrow function)
const handleDarkModeChange = (event) => {
  if(event.target.checked) {
    document.body.classList.add('darkMode');
  }
  else {
    document.body.classList.remove('darkMode');
  }
}

// Adds an event listener
checkBox.addEventListener('change', handleDarkModeChange)
body.darkMode {
  background-color: #000
}

.darkMode p.user {
  color: green;
}

.darkMode p.computer {
  color: yellow;
}
<div class="chatLog">
  <p class="user">Hi, I'm a user</p>
  <p class="computer">Nice, I'm a computer</p>
</div>
<input type="text" placeholder="Type some text...">
<hr>

<label id="darkMode">
  Dark mode
  <input type="checkbox">
</label>

Upvotes: 2

VLAZ
VLAZ

Reputation: 29096

You can dynamically create a stylesheet and add it to the document, this will act as a normal stylesheet complete with precedence rules and will trigger any changes as any rules you've defined:

function changeClass() {
  var sheet = document.createElement('style')
  sheet.innerHTML = ".message-computer {color: black; background-color: yellow;}";
  document.body.appendChild(sheet);
}

document.getElementById("change-style").addEventListener("click", changeClass);

//add a dummy message from computer
document.getElementById("add-message").addEventListener("click", function(){
  var p = document.createElement("p");
  p.textContent = "New Message";

  var newMessage = document.createElement("div");
  newMessage.appendChild(p);
  newMessage.classList.add("message-computer");

  document.getElementById("chat").appendChild(newMessage)
})
<button id="add-message">Add message</button>
<button id="change-style">Change style</button>

<div id="chat">
  <div class="message-computer">
    <p>Hi, how are you?</p>
  </div>
  <div class="message-user">
    <p>I am good, thanks!</p>
  </div>
</div>

Upvotes: 0

Md. Abu Sayed
Md. Abu Sayed

Reputation: 2486

You can try this code.

Description: at first we call the function on script load, window load or document load for the already generated element's style. after that I am a create a button with click action. the button click add a dynamic element and append body then again call the changeClass() function. that is looking good.

another way is you write a CSS for .message-computer{ background: yellow; color: black; } it's also fine for the prev solutions.

== Thanks ==

changeClass();

function changeClass(){
    var myElements = document.querySelectorAll(".message-computer");
    for (var i = 0; i < myElements.length; i++) {
      myElements[i].style.color = "black";
      myElements[i].style.backgroundColor = "yellow";
    }
}

function addMsg() {
  var wrap=  document.createElement('div');
      wrap.classList +='message-computer';
  var p =  document.createElement('p');
      p.innerHTML = "Hi, how are you?";
      wrap.appendChild(p);
  document.getElementsByTagName('body')[0].appendChild(wrap);
  changeClass();
  
}
<button type="button" onClick="addMsg()">addMessage</button>
<div class="message-computer"><p>Hi, how are you?</p></div>
<div class="message-user"><p>I am good, thanks!</p></div>

Upvotes: 0

Related Questions