0

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.

2
  • Can you confirm when are you calling changeClass()? Commented May 16, 2019 at 11:23
  • You are still going about this the wrong way, as I tried to point out to you in a comment on your previous question that was pretty much about the same topic/problem already. Do not loop through all elements and modify something about them directly - but let CSS do it’s job! Set or change the class of one common ancestor element, and then use the descendant combinator in your stylesheet to format all those elements differently based on that. Commented May 16, 2019 at 11:29

3 Answers 3

2

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>

Sign up to request clarification or add additional context in comments.

Comments

0

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>

Comments

0

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>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.