Switch on / off Links on the page with one button: toggle() two functions

Viewed 1541

I've written a working code for the two buttons:

HTML:

<button class="OFF-LINK">OFF</button>
<button class="ON-LINK">ON</button>

<div class="box">...<a></a>...<a></a>...</div>
<div class="box">...<a></a>...<a></a>...</div>

Script:

$(".OFF-LINK").click(function off() {
    var box = document.getElementsByClassName("box"); 
    var x; for (x = 0; x < box.length; x++) 
    {box[x].innerHTML = box[x].innerHTML.replace( /href/ig,'hren');}
}); ///links stop working

$(".ON-LINK").click(function on() {
    var box = document.getElementsByClassName("box"); 
    var y; for (y = 0; y < box.length; y++) 
    {box[y].innerHTML = box[y].innerHTML.replace( /hren/ig,'href');}
}); ///links work again

How can I combine this two functions, to toggle them with one button?

4 Answers

You can achieve this by checking the returned match from RegEx pattern inside .replace() and swap it as per the below snippet

function toggleLinks() {
    var box = document.getElementsByClassName("box"); 
    var x;
    for (x = 0; x < box.length; x++) {
      box[x].innerHTML = box[x].innerHTML.replace(/hre(f|n)/gi,
          g1 => {return (g1=="href") ? "hren" : "href"});  
    }
}
<button onclick="toggleLinks()">Toggle Links</button>

<div class="box">
  <a href="http://www.google.com">google</a>
  <br>
  <a href="http://www.yahoo.com" >yahoo</a>
</div>
<div class="box">
  <a href="http://www.stackoverflow.com"> stackoverflow</a>
  <br>
  <a href="http://www.github.com" >github</a>
</div>

I put some text in so you could see the changes

$(".OFF-LINK,.ON-LINK").on('click', function() {
  var box = document.getElementsByClassName("box");
  var x;
  for (x = 0; x < box.length; x++) {
    box[x].innerHTML = $(this).is('.OFF-LINK') ? box[x].innerHTML.replace(/href/ig, 'hren') : box[x].innerHTML.replace(/hren/ig, 'href');
  }
});
   
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<button class="OFF-LINK">OFF</button>
<button class="ON-LINK">ON</button>

<div class="box">...
  <a>href</a>...
  <a>X</a>...
</div>
<div class="box">...
  <a>href</a>...
  <a>Y</a>...
</div>

How can I combine this two functions, to toggle them with one button?

If I'm understanding you correctly, you want to toggle the class on the button between on-link and off-link, and call the appropriate function afterwards? If so:

<button class="button off-link">Off</button>

$('body').on('click', '.button', function(){
  $(this).toggleClass('off-link on-link');
  if ($(this).hasClass('off-link')) {
    $(this).innerHTML('Off');
    // Do your 'off-link' code here
  } else {
    $(this).innerHTML('On');
    // Do your 'on-link' code here
  }
});

Generally, it's bad practice to replace all innerHTML, just to change a little detail. If you need to toggle links, would be better to find the required links and work only with their attributes:

$('.box a').each(function(){
  var link = $(this).attr("href");
  $(this).attr("data-link", link);
  // saving each link in data-attribute
});

$('#toggle').on('click', function toggler(){
  let on = toggler.on = !toggler.on; // (*1)
  
  $('.box a').each(function(){
    var link = $(this).attr("data-link");
    
    $(this)[ on ? "removeAttr" : "attr" ]( "href", link ); // (*2)
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<button id="toggle">Toggle Links</button>

<div class="box">
  <a href="https://google.com" target="_blank">link</a>
  <a href="https://google.com" target="_blank">link</a>
</div>
<div class="box">
  <a href="https://google.com" target="_blank">link</a>
  <a href="https://google.com" target="_blank">link</a>
</div>

(*1) let on = toggler.on = !toggler.on; — each function is an object. You can work with it's name just like with common objects - setting him new properties or methods. I could declare a variable let on = true; out of the function, but decided to make everything inside. ! — it's the boolean "NOT": transforms falsetrue and vice versa. So, when you click the button, toggler.on is undefined (false), ! will become true and assign to itself (toggler.on = !toggler.on;) → the same value will be assigned to variable on.

At the next click, property toggler.on already will keep the true value, and become !true → false, and so on.

(*2) $(this)[ on ? "removeAttr" : "attr" ]( "href", link );

Ternary operator, general form: (boolean expression) ? (return this value if true) : (else)

In this example, expression will return a "removeAttr" string, if on === true, and "attr" otherwise.

Bracket notation. Mostly we use the dot notation, because it's shorter. Example, elem.innerHTML may be written as elem["innerHTML"]. Here I used a ternary expression, to pick the required method. Translation into if-else:

if( on ){
  $(this).removeAttr("href")
} else {
  var link = $(this).attr("data-link");
  $(this).attr("href", link );
}

And the same code without jQ:

let links = document.querySelectorAll('.box a');
for( let i = 0; i < links.length; i++ ){
  links[i].dataset.link = links[i].getAttribute("href");
}

let toggle = document.getElementById('toggle');
toggle.addEventListener('click', function toggler(){
  let on = toggler.on = !toggler.on;
  
  for( let i = 0; i < links.length; i++ ){
    let link = links[i].dataset.link;
    links[i][ on ? "removeAttribute" : "setAttribute"]("href", link);
  }
});
<button id="toggle">Toggle Links</button>

<div class="box">
  <a href="https://google.com" target="_blank">link</a>
  <a href="https://google.com" target="_blank">link</a>
</div>
<div class="box">
  <a href="https://google.com" target="_blank">link</a>
  <a href="https://google.com" target="_blank">link</a>
</div>

Related