0

I've create a simple log viewer, that, when you click on the log you want to see, it display the textarea and display none the 3 others and if you choose another one, it display that one and display none the 3 others again.

It work with what I did, but it's way not optimise and I would like to know a way to optimise that kind of stuff, here's my code:

var txtarea1 = document.getElementById("txtarea1");
            var txtarea2 = document.getElementById("txtarea2");
            var txtarea3 = document.getElementById("txtarea3");
            var txtarea4 = document.getElementById("txtarea4");

            var btn1 = document.getElementById("btn1");
            var btn2 = document.getElementById("btn2");
            var btn3 = document.getElementById("btn3");
            var btn4 = document.getElementById("btn4");

            btn1.addEventListener('click', ftxtarea1);
            btn2.addEventListener('click', ftxtarea2);
            btn3.addEventListener('click', ftxtarea3);
            btn4.addEventListener('click', ftxtarea4);

            function ftxtarea1() {
                if (txtarea1.style.display == "none") {
                    txtarea1.style.display = "block";
                    txtarea2.style.display = "none";
                    txtarea3.style.display = "none";
                    txtarea4.style.display = "none";
                }
            }

            function ftxtarea2() {
                if (txtarea2.style.display == "none") {
                    txtarea1.style.display = "none";
                    txtarea2.style.display = "block";
                    txtarea3.style.display = "none";
                    txtarea4.style.display = "none";
                }
            }

            function ftxtarea3() {
                if (txtarea3.style.display == "none") {
                    txtarea1.style.display = "none";
                    txtarea2.style.display = "none";
                    txtarea3.style.display = "block";
                    txtarea4.style.display = "none";
                }
            }

            function ftxtarea4() {
                if (txtarea4.style.display == "none") {
                    txtarea1.style.display = "none";
                    txtarea2.style.display = "none";
                    txtarea3.style.display = "none";
                    txtarea4.style.display = "block";
                }
            }

Here's the php that eco the HTML code:

echo <div id="log_textarea">';
                echo '<textarea id="txtarea1" rows="15" readonly style="display:none;">' . $loginAttempt . '</textarea>';
                echo '<textarea id="txtarea2" rows="15" readonly style="display:none;">' . $loginHistory . '</textarea>';
                echo '<textarea id="txtarea3" rows="15" readonly style="display:none;">' . $view . '</textarea>';
                echo '<textarea id="txtarea4" rows="15" readonly">' . $editingHistory . '</textarea>';
                echo '</div>';

2 Answers2

0

You can do this all with some simple loops and one event listener for all the buttons.

I also added an additional feature of toggling an active class on the buttons

const textAreas = document.querySelectorAll('textarea.log-view'),
       buttons = document.querySelectorAll('button.btn')

buttons.forEach((btn)=>{
    btn.addEventListener('click', function(){
        // active claass toggle on buttons
        buttons.forEach(el => el.classList.toggle('active', el === btn))
       // parse matching textarea id
       const txtId = this.id.replace('btn','txtarea');
       // loop textareas and hide/show based on id
       textAreas.forEach((el)=> el.style.display = el.id === txtId ? 'block': 'none')
    });
});
.log-view {
  display: none;
}

.log-view:first-of-type {
  display: block;
}

.btn.active{
  color: red
}
<button class="btn active" id="btn1">btn1</button>
<button class="btn" id="btn2">btn2</button>
<button class="btn" id="btn3">btn3</button>

<textarea class="log-view" id="txtarea1" >txt1</textarea>
<textarea class="log-view" id="txtarea2" >txt2</textarea>
<textarea class="log-view" id="txtarea3" >txt3</textarea>
charlietfl
  • 170,828
  • 13
  • 121
  • 150
0

Simple refactor is reducing the ftxtarea1, ftxtarea2, ftxtarea3, and ftxtarea4 functions into a single higher order function that takes the area to show and hides the rest:

var txtarea1 = document.getElementById("txtarea1");
var txtarea2 = document.getElementById("txtarea2");
var txtarea3 = document.getElementById("txtarea3");
var txtarea4 = document.getElementById("txtarea4");

var btn1 = document.getElementById("btn1");
var btn2 = document.getElementById("btn2");
var btn3 = document.getElementById("btn3");
var btn4 = document.getElementById("btn4");

btn1.addEventListener('click', ftxtarea(txtarea1));
btn2.addEventListener('click', ftxtarea(txtarea2));
btn3.addEventListener('click', ftxtarea(txtarea3));
btn4.addEventListener('click', ftxtarea(txtarea4));

function ftxtarea(area) {
  return function() {
    if (area.style.display == "none") {
      txtarea1.style.display = "none";
      txtarea2.style.display = "none";
      txtarea3.style.display = "none";
      txtarea4.style.display = "none";

      area.style.display = "block";
    }
  }
}
<div id="log_textarea">
  <textarea id="txtarea1" rows="5" readonly style="display:none;">$loginAttempt</textarea>
  <textarea id="txtarea2" rows="5" readonly style="display:none;">$loginHistory</textarea>
  <textarea id="txtarea3" rows="5" readonly style="display:none;">$view</textarea>
  <textarea id="txtarea4" rows="5" readonly>$editingHistory</textarea>
</div>

<div id="buttons">
  <button id="btn1">one</button>
  <button id="btn2">two</button>
  <button id="btn3">three</button>
  <button id="btn4">four</button>
</div>

Much simpler by using data-* custom attributes on the buttons to link them to the areas they should show. Then using event delegation with a single event handler is enough to handle any button's work

document.getElementById("buttons")
  .addEventListener("click", ftxtarea);

function ftxtarea(event) {
  if (!event.target.matches("button"))
    return;
    
  document.querySelectorAll("textarea")
    .forEach(el => el.style.display = "none");

  const id = event.target.dataset["show"];
  const area = document.getElementById(id);
  area.style.display = "block";
}
<div id="log_textarea">
  <textarea id="txtarea1" rows="5" readonly style="display:none;">$loginAttempt</textarea>
  <textarea id="txtarea2" rows="5" readonly style="display:none;">$loginHistory</textarea>
  <textarea id="txtarea3" rows="5" readonly style="display:none;">$view</textarea>
  <textarea id="txtarea4" rows="5" readonly>$editingHistory</textarea>
</div>

<div id="buttons">
  <button id="btn1" data-show="txtarea1">one</button>
  <button id="btn2" data-show="txtarea2">two</button>
  <button id="btn3" data-show="txtarea3">three</button>
  <button id="btn4" data-show="txtarea4">four</button>
</div>

This can be made more concise further using jQuery:

$("#buttons").on("click", "button", ftxtarea);

function ftxtarea(event) {
  $("textarea").hide();

  const id = $(event.target).data("show");
  $("#" + id).show()
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div id="log_textarea">
  <textarea id="txtarea1" rows="5" readonly style="display:none;">$loginAttempt</textarea>
  <textarea id="txtarea2" rows="5" readonly style="display:none;">$loginHistory</textarea>
  <textarea id="txtarea3" rows="5" readonly style="display:none;">$view</textarea>
  <textarea id="txtarea4" rows="5" readonly>$editingHistory</textarea>
</div>

<div id="buttons">
  <button id="btn1" data-show="txtarea1">one</button>
  <button id="btn2" data-show="txtarea2">two</button>
  <button id="btn3" data-show="txtarea3">three</button>
  <button id="btn4" data-show="txtarea4">four</button>
</div>
VLAZ
  • 26,331
  • 9
  • 49
  • 67
  • Thank you for the code example and the description of it! It's appreciate and interesting!!:D –  May 31 '21 at 20:34