You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Popup弹窗外部单次点击无法关闭及添加隐藏反向动画问题求助

Hey there! Let's work through those two popup issues you're facing—they're pretty common, and we can fix them with a few targeted tweaks to your code.


Problem 1: Single Click Outside Doesn't Close the Popup

What's going wrong?

Right now, your code only hides the popup when there's no text selected in the textarea on mouseup. There's no logic to detect clicks outside the popup itself to trigger a close. Also, if you click the popup directly, we don't want it to close—we need to ignore those clicks to prevent accidental closures.

The Fix

We'll add a click event listener to the entire document. When a click happens, we'll check if the target is the popup or inside it. If not, we'll trigger the popup to hide. We'll also stop event propagation when clicking the popup so the document-level click doesn't fire.


Problem 2: Reverse Transition Animation When Hiding the Popup

What's going wrong?

Using display:none immediately removes the element from the DOM, which means any transition or animation won't run—there's nothing left to animate! Instead, we need to use properties that let the element stay in the DOM while animating out, like opacity and visibility.

The Fix

We'll adjust the CSS to use opacity: 0 and visibility: hidden for the hidden state instead of display:none. We'll also create a reverse rotation animation and use class toggles to manage the show/hide states, making it easy to trigger the correct animations.


Updated Complete Code

JavaScript

function getSelected() { 
  if(window.getSelection) { 
    return window.getSelection(); 
  } else if(document.getSelection) { 
    return document.getSelection(); 
  } else { 
    var selection = document.selection && document.selection.createRange(); 
    if(selection.text) { 
      return selection.text; 
    } 
    return false; 
  } 
  return false; 
}

$(document).ready(function() {
  const $popup = $("span.popup-tag");

  $('#my-textarea').mouseup(function(event) {
    var selection = getSelected();
    selection = $.trim(selection);
    
    if(selection != ''){
      // Show popup with rotation animation
      $popup.text(selection)
            .css({ top: event.clientY, left: event.clientX })
            .removeClass('popup-tag--hidden')
            .addClass('popup-tag--visible');
    } else {
      // Hide popup with reverse animation
      hidePopup();
    }
  });

  // Close popup when clicking outside of it
  $(document).click(function(event) {
    if (!$popup.is(event.target) && $popup.has(event.target).length === 0) {
      hidePopup();
    }
  });

  // Prevent clicks on the popup from triggering the close action
  $popup.click(function(event) {
    event.stopPropagation();
  });

  // Helper function to handle smooth popup closure
  function hidePopup() {
    $popup.removeClass('popup-tag--visible').addClass('popup-tag--hidden');
    // Optional: After animation finishes, set display:none to free up layout space
    setTimeout(() => {
      if ($popup.hasClass('popup-tag--hidden')) {
        $popup.css('display', 'none');
      }
    }, 600); // Match the duration of your animation
  }
});

CSS

.popup-tag {
  position: absolute;
  display: none; /* Start fully hidden */
  opacity: 0;
  visibility: hidden;
  background-color: #785448d4;
  color: white;
  padding: 10px;
  font-size: 20px;
  font-weight: bold;
  text-decoration: underline;
  cursor: pointer;
  box-shadow: 0px 0px 1px 5000px rgba(0,0,0,0.8);
  -webkit-filter: drop-shadow(0 1px 10px rgba(113,158,206,0.8));
  transition: opacity 0.6s ease-in-out, visibility 0.6s ease-in-out;
}

/* Show state with forward rotation animation */
.popup-tag--visible {
  display: block;
  opacity: 1;
  visibility: visible;
  -webkit-animation: rotate-center .6s ease-in-out both;
  animation: rotate-center .6s ease-in-out both;
}

/* Hide state with reverse rotation and fade-out */
.popup-tag--hidden {
  opacity: 0;
  visibility: hidden;
  -webkit-animation: rotate-center-reverse .6s ease-in-out both;
  animation: rotate-center-reverse .6s ease-in-out both;
}

@-webkit-keyframes rotate-center {
  0% {-webkit-transform: rotate(0); transform: rotate(0)}
  100% {-webkit-transform: rotate(360deg); transform: rotate(360deg)}
}

@keyframes rotate-center {
  0% {-webkit-transform: rotate(0); transform: rotate(0)}
  100% {-webkit-transform: rotate(360deg); transform: rotate(360deg)}
}

@-webkit-keyframes rotate-center-reverse {
  0% {-webkit-transform: rotate(360deg); transform: rotate(360deg)}
  100% {-webkit-transform: rotate(0); transform: rotate(0)}
}

@keyframes rotate-center-reverse {
  0% {-webkit-transform: rotate(360deg); transform: rotate(360deg)}
  100% {-webkit-transform: rotate(0); transform: rotate(0)}
}

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.js"></script>
Select any text :<br>
<div type="text" id="my-textarea" style="width:100%; height:200px;" >
 While delivering a lecture at the Indian Institute of Management Shillong, Kalam collapsed and died from an apparent cardiac arrest on 27 July 2015, aged 83. Thousands including national-level dignitaries attended the funeral ceremony held in his hometown of Rameshwaram, where he was buried with full state honours.
</div>
<span class="popup-tag"></span>

Key Changes Breakdown

  1. Click Outside Closure: We added a document click listener that checks if the click isn't targeting the popup, then triggers the hide function. We also stop event propagation on popup clicks to keep it open when users interact with it.
  2. Reverse Animation: We created a reverse rotation animation and used CSS classes to toggle visibility/opacity instead of display:none directly. The setTimeout ensures we only set display:none after the animation completes, so the transition is fully visible.

内容的提问来源于stack exchange,提问作者Rakesh Suthar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 10:57:32