首页 > 解决方案 > JQuery Toggle visibility of divs

问题描述

My theme uses the following structure (doesn't allow me to have a separate class for each button):

<button class="x-active" role="tab" aria-selected="true" aria-controls="panel-1" data-x-toggle="tab" data-x-toggleable="tab-item-1"><span>Button 1</span></button>

<button class="x-active" role="tab" aria-selected="true" aria-controls="panel-2" data-x-toggle="tab" data-x-toggleable="tab-item-2"><span>Button 2</span></button>

I am looking for some JQuery code which will toggle the visibility of two different divs, depending on which button the user presses.

i.e. If Button 1 is pressed the divs should be:

<div id="section-1" style="display:block;"></div>
<div id="section-2" style="display:none;"></div>

and If Button 2 is pressed the divs should be:

<div id="section-1" style="display:none;"></div>
<div id="section-2" style="display:block;"></div>

Any help would be much appreciated as not sure how to start on this.

标签: jquery

解决方案


我建议:

// select all <button> elements, using the on() method
// to bind the anonymous function as the event-handler
// for the 'click' event:
$('button').on('click', function() {

  // here we find the attribute-value of the
  // data-x-toggleable attribute as a String,
  // and use the String.prototype.match() method
  // along with a regular expression, to find a
  // sequence of one-or-more numbers "\d+" at the
  // end of the string "$":
  const num = this.dataset.xToggleable.match(/\d+$/);

  // if match doesn't find a result then it returns
  // null; here we check that we have a result:
  if (num) {

    // if we have a result we hide all <div> elements
    // whose 'id' attribute-value starts with the string
    // of 'section', and then we hide them using the
    // hide() method:
    $('div[id^=section]').hide();

    // here we use a template literal string to interpolate
    // the value of the 'num' variable into the string,
    // which finds the <div> element with an 'id' of
    // "section" which ends with the number found earlier,
    // and we show it using the show() method:
    $(`div#section-${num}`).show();
  }
});

$('button').on('click', function() {
  const num = this.dataset.xToggleable.match(/\d+$/);
  if (num) {
    $('div[id^=section]').hide();
    $(`div#section-${num}`).show();
  }
});
*,
 ::before,
 ::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

div[id^=section] {
  border: 2px solid #f90;
  margin: 0.5em 1em;
}

div[id^=section]::before {
  content: attr(id);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="x-active" role="tab" aria-selected="true" aria-controls="panel-1" data-x-toggle="tab" data-x-toggleable="tab-item-1"><span>Button 1</span></button>

<button class="x-active" role="tab" aria-selected="true" aria-controls="panel-2" data-x-toggle="tab" data-x-toggleable="tab-item-2"><span>Button 2</span></button>

<div id="section-1"></div>
<div id="section-2"></div>

作为 jQuery 的替代方案,同样的事情可以用纯 JavaScript 轻松完成:

// here we have a named function, defined using Arrow Syntax
// since we don't need to use the 'this' of the function; one
// argument, the Event object, is automatically passed in from
// EventTarget.addEventListener():
const toggleDisplay = (evt) => {

  // here we retrieve the element upon which the event-listener
  // was bound, using evt.currentTarget (the 'currentTarget'
  // property of the Event Object 'evt'), we then use the
  // Element.dataset API to access - as before - the sequence
  // of numbers at the end of the data-x-toggleable attribute-
  // value:
  const num = evt.currentTarget.dataset.xToggleable.match(/\d+$/);

  // if we have a matching number, therefore 'num' is not
  // false/falsey:
  if (num) {

    // we retrieve all <div> elements whose 'id' attribute-
    // value starts with "section" and then iterate over that
    // NodeList using NodeList.prototype.forEach():
    document.querySelectorAll('div[id^=section]').forEach(

      // the first argument to the anonymous Arrow function
      // expression is a reference to the current Node of the
      // NodeList over which we're iterating, here I called
      // id 'div', but you can call it anything you like (so
      // long as it's not a reserved word); in this function
      // we hide the elements by updating the 'display' property
      // of the 'style' to 'none':
      (div) => div.style.display = 'none'
    );

    // because we're using an id selector, again using a
    // template literal (as in the jQuery example), we 
    // can only retrieve one element (if there's a match)
    // or null if no element is found. As we can only find
    // one element we can update its display to 'block' to
    // in order to show it:
    document.querySelector(`#section-${num}`).style.display = 'block';
  }
};

// here we find all the <button> elements on the page,
// using document.querySelectorAll() and then use
// NodeList.prototype.forEach() to iterate over those
// element-nodes using another Arrow function expression:
document.querySelectorAll('button').forEach(

  // the first argument represents the current node of
  // the nodeList, here called 'btn'; with the arrow
  // function we bind the toggleDisplay() function, note
  // the deliberate lack of parentheses, as the event-
  // handler for clicks on the <button> elements:
  (btn) => btn.addEventListener('click', toggleDisplay)
);

const toggleDisplay = (evt) => {
  const num = evt.currentTarget.dataset.xToggleable.match(/\d+$/);
  if (num) {
    document.querySelectorAll('div[id^=section]').forEach(
      (div) => div.style.display = 'none'
    );
    document.querySelector(`#section-${num}`).style.display = 'block';
  }
};

document.querySelectorAll('button').forEach(
  (btn) => btn.addEventListener('click', toggleDisplay)
);
*,
 ::before,
 ::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

div[id^=section] {
  border: 2px solid #f90;
  margin: 0.5em 1em;
}

div[id^=section]::before {
  content: attr(id);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="x-active" role="tab" aria-selected="true" aria-controls="panel-1" data-x-toggle="tab" data-x-toggleable="tab-item-1"><span>Button 1</span></button>

<button class="x-active" role="tab" aria-selected="true" aria-controls="panel-2" data-x-toggle="tab" data-x-toggleable="tab-item-2"><span>Button 2</span></button>

<div id="section-1"></div>
<div id="section-2"></div>

参考:


推荐阅读