Search code examples
javascripthtmlbuttoniconsmaterialize

How can i change a text of a button without changing it's icon


i have a "Pause" button with a pause_circle_outline materialize icon, and when it clicked i want to change the text to "Resume" and changing the icon to play_circle_outline, but when i try to change the text it changed the text and deletes the icon. here is my code snippet example:

jQuery(document).ready(function($){
  
  $(document.getElementById("pause_btn")).click(function(){
      document.getElementById("pause_btn").innerText = "Resume"
  });
})
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
    <script src = "Sources/js/select_require.js"></script>
    <script src = "Sources/js/routes.js"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
    <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
  <body>
    <a class="waves-effect waves-light btn" id="pause_btn">Pause<i class="material-icons right">pause_circle_outline</i></a>
  </body>
</html>


Solution

  • .innerText is a sort of "safe"* way to access a node's innerHTML, which in your case includes both the Pause-text, as well as the <i.../> tag.

    A way to solve this is to add a span to hold the text. spans don't do anything (as they are inline elements and are by default formatted/shown as a simple text element), but they help by making the text node selectable by document.querySelector!

    Example:

    var playing = true
    
    window.addEventListener("load", () => {
      document.querySelector("#pause_btn").addEventListener("click", () => {
          playing = !playing
          if(playing) {
            document.querySelector("#pause_btn span").innerText = "Pause"
            document.querySelector("#pause_btn i").innerText = "pause_circle_outline"
          } else {
            document.querySelector("#pause_btn span").innerText = "Resume"
            document.querySelector("#pause_btn i").innerText = "play_circle_outline"
          }
      });
    })
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
        <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
      <body>
        <a class="waves-effect waves-light btn" id="pause_btn">
          <span>Pause</span>
          <i class="material-icons right">pause_circle_outline</i>
        </a>
      </body>
    </html>

    I also added some extra code to make it clickable multiple times!


    *: By safe, in this context, I mean that it's safe from a security issue called XSS. Generally it's better to use innerText when you don't explicitly need to change the HTML itself, but if you do: Make sure that there's NO way a user can input something that gets put into the innerHTML. What I initially meant was simply that writing to either innerHTML and innerText will always overwrite whatever contents the element has, and that innerText is generally the safer of the two.