简体   繁体   中英

jQuery Accordion auto-selects all containing text when expanding

I have the following Codepen , showing a simple dropdown I created. One will notice that when clicking on the down-arrow at times all the containing text will be selected.

How do I stop all the text/content from being auto-selected on active, while leaving the user's option to select text manually?

$(document).ready(function() {
  //   Open first panel automatically
  $(".accordion_trigger")[0].nextElementSibling.classList.add("active");
  $(".accordion_trigger")[0].lastElementChild.classList.replace(
    "fa-chevron-down",
    "fa-chevron-up"
  );

  // Click event listener
  $(".accordion_trigger").on("click", function() {
    // Show panel on click
    this.nextElementSibling.classList.toggle("active");

    // update the font-awesome icon up/down
    const fa = this.lastElementChild.classList;
    fa.contains("fa-chevron-down")
      ? fa.replace("fa-chevron-down", "fa-chevron-up")
      : fa.replace("fa-chevron-up", "fa-chevron-down");

    // Remove all other chevron down icons
    const chevrons = $(".fa-chevron-up").filter(
      (index, item) => item != this.lastElementChild
    );
    for (var item of chevrons) {
      item.classList.replace("fa-chevron-up", "fa-chevron-down");
    }

    // Hide all other panels on click
    const others = $(".accordion_trigger").filter(
      (index, item) => item != this
    );
    for (var item of others) {
      item.nextElementSibling.classList.remove("active");
    }
  });
});

In order to replicate this, navigate to the page, then quickly close and re-open the text. Please note that this issue does not occur in Firefox or Edge.

<div class="accordion">
  <ul class="accordion_ul">
    <li class="accordion_trigger">
      <h5>Test Entry</h5>
      <i class="fas fa-chevron-down"></i>
    </li>
    <div class="panel">
      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    </div>
    <li class="accordion_trigger">
      <h5>Test Entry</h5>
      <i class="fas fa-chevron-down"></i>
    </li>
    <div class="panel">
      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    </div>
  </ul>
</div>

Add window.getSelection().removeAllRanges(); to $(".accordion_trigger").on("click", function(){}

This will deselect any text you have selected when the panel is displayed (which will be the second click of the double-click that selects everything and triggers opening the panel).

I found the solution here: Is there a function to deselect all text using JavaScript?

Allow me to first explain why this is happening.

First notice that the panels are positioned absolutely at the top. Then notice the visibility and opacity which are initially both set to hidden and 0 respectively and are switched to visible and 1 respectively, that's how the animation is being done.

Think about the initial panel, it is visible and opaque (opacity 0) and has no absolute position. When you add active class to it(clicking on the chevron) the page becomes absolutely positioned, comes to the top and the opacity takes 0.2s to become 0.

If you look at the specifications for both opacity and visibility: Having opacity value(even 0) makes the element intractable, that's why quickly double clicking the chevron also means double clicking the text inside it. This only happens on some browsers as others (FF, IE and Edge) will ignore the interactibility since visibility is set to hidden. That's why you'll only notice it if the cursor is placed a little lower than the top. You can easily see this in action if you change the transition rule from transition: visibility 0s, opacity 0.2s linear; to transition: visibility 1s, opacity 0.2s linear; .

To solve it call window.getSelection().removeAllRanges(); as the first thing in the click event listener.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM