skip to Main Content

I’ve got 4 buttons and each button opens a section and closes the other. There is a possibility that one or the buttons are stay hidden because of a switch in the backend which you can toggle to make it visible (or to hide).

Now, if one or more buttons are not visible the script stops working. If I toggle all the buttons on, the buttons display and the script is working.

I have this code and it works fine (as long as all the buttons are visible):

<style> 
.elementor-editor-active .hidden { 
    display:block; 
} 
.hidden{ 
    display:none; 
} 
.shown{ 
    display: block !important; 
} 

.btn_active_state{
background-color: #FFCC00 !important;
}
.btn_active_state a{
font-weight: bold !important;
}

</style>

<script>
var divs
var btn1 = document.getElementById("btn1");
var btn2 = document.getElementById("btn2");
var btn3 = document.getElementById("btn3");
var btn4 = document.getElementById("btn4");

    btn1.onclick = function(event){
    event.preventDefault();
    toggleDivs("sect1",this);
    };

    btn2.onclick = function(event){
    event.preventDefault();
    toggleDivs("sect2",this);
    };
    

    btn3.onclick = function(event){
    event.preventDefault();
    toggleDivs("sect3",this);
    };

    btn4.onclick = function(event){
    event.preventDefault();
    toggleDivs("sect4",this);
    };

function toggleDivs(s,btn){
if(btn.classList.contains("btn_active_state")){
document.getElementById(s).classList.remove("shown");
btn.classList.remove("btn_active_state");
document.getElementById(s).classList.remove("shown");
return;
}else{
btn1.classList.remove("btn_active_state");
btn2.classList.remove("btn_active_state");
btn3.classList.remove("btn_active_state");
btn4.classList.remove("btn_active_state");
btn.classList.add("btn_active_state");
document.getElementById("sect1").classList.remove("shown");
document.getElementById("sect2").classList.remove("shown");
document.getElementById("sect3").classList.remove("shown");
document.getElementById("sect4").classList.remove("shown");
document.getElementById(s).classList.add("shown","fade");
}
}
//force button1 state initialise, if required
//btn1.focus();
//btn1.click();



</script>

The script stops working when I toggle one or more buttons to OFF (so they don’t display on the front-end). I saw solutions with a Try Catch method, but I don’t know (if this is the right way to fix it), where to implement it…

I am using Elementor in WordPress to accomplish this. (HTML widget where I pasted this code and named the sections and buttons to the names named in the code).

Side note: I’m not an expert in Javascript.

Thanks advance!

3

Answers


  1. Chosen as BEST ANSWER

    While I had 4 Elementor widgets (I used this as buttons) with every widget a unique ID (#btn1, #btn2, #btn3 & #btn4). I had also 4 different Elementor sections with their own ID (#sect1, #sect2, #sect3 & #sect4). If you clicked one of the button, the respective section would display (btn1 shows sect1, btn2 shows sect2 etc..).

    The standard script (posted in first place) worked fined when all the buttons (btn1, btn2 etc.) where visible (not rendered, not in the code) on the page. This is because I used the Dynamic Visibility options in the 'Advanced' tab in Elementor (Crocoblock JetEngine/Elementor Pro).

    The problem arose when 1 or more buttons were missing because of the Dynamic Visibility (If a switch in the CPT turned off, it will not show the widget). The script stopped working and none of the buttons worked again.

    Now, I used this code in a HTML widget and placed the HTML widget under the sections (above the sections are the widgets acting like buttons). The first part of the script gives an 'active' state to the button you click on. Assure that you set the class of the button you want to have an active state as default, to 'active':

    <style> 
    .elementor-editor-active .hidden { 
        display:block; 
    } 
    .hidden{ 
        display:none; 
    } 
    .shown{ 
        display: block !important; 
    } 
    
    #btn1, #btn2, #btn3, #btn4 {
        cursor: pointer;
    }
    
    
    .active h2  {
    font-weight: bold !important;
    }
    
    
    
    </style>
    
    <script>
    var activeButton = document.getElementById("btn1");
    
    function toggleActive(btn) {
      if (activeButton && activeButton != btn) {
        activeButton.classList.remove("active");
      }
      activeButton = btn;
      btn.classList.add("active");
    }
    
    var sect1 = document.getElementById("sect1");
    var sect2 = document.getElementById("sect2");
    var sect3 = document.getElementById("sect3");
    var sect4 = document.getElementById("sect4");
    
    try {
    var btn1 = document.getElementById("btn1");
    btn1.onclick = function(event){
        toggleActive(btn1);
        document.getElementById("sect1").classList.add("shown");
        document.getElementById("sect2").classList.remove("shown");
        document.getElementById("sect3").classList.remove("shown");
        document.getElementById("sect4").classList.remove("shown");
    };
    } catch (error) {
      console.log("btn1 not found on the page. Error: " + error);
    }
    try {
    var btn2 = document.getElementById("btn2");
    btn2.onclick = function(event){
        toggleActive(btn2);
        document.getElementById("sect1").classList.remove("shown");
        document.getElementById("sect2").classList.add("shown");
        document.getElementById("sect3").classList.remove("shown");
        document.getElementById("sect4").classList.remove("shown");
    };
    } catch (error) {
      console.log("btn1 not found on the page. Error: " + error);
    }
    try {
    var btn3 = document.getElementById("btn3");
    btn3.onclick = function(event){
        toggleActive(btn3);
        document.getElementById("sect1").classList.remove("shown");
        document.getElementById("sect2").classList.remove("shown");
        document.getElementById("sect3").classList.add("shown");
        document.getElementById("sect4").classList.remove("shown");
    };
    } catch (error) {
      console.log("btn1 not found on the page. Error: " + error);
    }
    try {
    var btn4 = document.getElementById("btn4");
    btn4.onclick = function(event){
        toggleActive(btn4);
        document.getElementById("sect1").classList.remove("shown");
        document.getElementById("sect2").classList.remove("shown");
        document.getElementById("sect3").classList.remove("shown");
        document.getElementById("sect4").classList.add("shown");
    };
    } catch (error) {
      console.log("btn1 not found on the page. Error: " + error);
    }
    
    </script>


  2. OK. I have finished this up. you can extend it easily by adding to the buttons list ( at the top of the document ). This is a system to create the buttons, action and sections. It allows you to toggle between them, essentially like tabs. It is likely not the best implementation, but it is a working system, something to get started with. It separates the views from the buttons, two functions to control the state of each. one is controlling the buttons, the other the views. this should be your approach moving forward… Keep It Stupid Simple. Avoid complexity, embrace readability. if you want code to be ultra compact and "efficient", use webpack 😀

    //define buttons
    const buttons = [ 
        { id:'btn1',
          section:'sect1',
          label:'Button 1'},
        { id:'btn2',
          section:'sect2',
          label:'Button 2'},
        { id:'btn3',
          section:'sect3',
          label:'Button 3'},
        { id:'btn4',
          section:'sect4',
          label:'Button 4'}
          ];
    //console.table(buttons);
    const views = [];
    // create buttons and assign click, create sections
    for ( const button of buttons){
      let nB = document.createElement('button');
      nB.id=button.id;
      nB.innerText=button.label;
      nB.onclick=(e)=>{
        e.preventDefault();
        toggleView( button.section, views );
        toggleButton( button.id, buttons );
      }
      document.getElementById('menu').appendChild(nB);
      // create the span / divs
      let nD = document.createElement('div');
      nD.id=button.section;
      // put something in here for testing
      nD.innerText=button.section;
      nD.classList.add('hidden');
      views.push(button.section);
      document.getElementById('viewer').appendChild(nD);
    }
    
    // function to change sections
    function toggleView( view, viewList ){
      //console.log( view );
      //console.log( viewList );
      // hide all
      for ( const v of viewList ){
        // not actually the elements, but just reference
        document.getElementById( v ).classList.remove('shown');
        // unhide 'view' by id
        if ( v == view ) {
          //console.log(`view ${v} found`);
          document.getElementById( v ).classList.add('shown');
        }
      }
    }
    
    function toggleButton( button, buttonList ){
      // console.log(button);
      // console.log(buttonList);
      // enable all
      // disable this button id
      // iterate through managed list
      for ( const b of buttonList ){
        // console.log(b);
        document.getElementById(b.id).classList.add('btn_active_state');
        if ( b.id == button ) document.getElementById(b.id).classList.remove('btn_active_state');
      }
    }
    toggleButton( buttons[0], buttons );
    .elementor-editor-active .hidden { 
        display:block; 
    } 
    .hidden{ 
        display:none; 
    } 
    .shown{ 
        display: block !important; 
    } 
    
    .btn_active_state{
    background-color: #FFCC00 !important;
    }
    .btn_active_state a{
    font-weight: bold !important;
    }
    <html>
    <body>
    <div id='menu'></div>
    <div id='viewer'></div>
    </body>
    </html>
    Login or Signup to reply.
  3. Does this help? I’ve replaced ‘this’ with the btn var itself when calling toggleDivs(). So rather than toggleDivs("sect1", this) use toggleDivs("sect1", btn1)

        btn1.onclick = function(event){
        event.preventDefault();
        toggleDivs("sect1",btn1);
        };
    
        btn2.onclick = function(event){
        event.preventDefault();
        toggleDivs("sect2",btn2);
        };
        
    
        btn3.onclick = function(event){
        event.preventDefault();
        toggleDivs("sect3",btn3);
        };
    
        btn4.onclick = function(event){
        event.preventDefault();
        toggleDivs("sect4",btn4);
        };
    // try to assign the var btn1 to the element
    var btn1 = document.getElementById('btn1');
    // check to see if it is valid / not null
    if ( btn1 ){
      // if it gets here, then the button is valid
      btn1.onclick = (e) =>{
        // show / hide sections
      }
    }
    //otherwise, if btn1==null it will continue to the next
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search