Bootstrap:下拉次点不用jQuery单击打开

发布于 2025-02-13 11:13:55 字数 3680 浏览 0 评论 0原文

我正在创建一个带有多行的表,所有这些都有一个“选项”按钮,该按钮应该显示下拉上下文菜单。为了使代码缩短,我使用一个div,以将其作为上下文菜单的常见标记重复使用。

我正在使用Bootstrap 5.1.3和JQuery 3.6.0。以下是我的代码:

<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Test Code</title>
  <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
</head>

<body>
  <table id="myTable" class="table table-hover">
    <thead>
      <tr>
        <th>#</th>
        <th>Document</th>
        <th>Reference</th>
        <th>Action</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>1</td>
        <td>General Policies</td>
        <td>GP-01-2022</td>
        <td>
          <div class="dropdown">
            <a href="#" class="btn btn-primary optionsButton" data-bs-toggle="dropdown" aria-expanded="false" id="doc1">Options</a>
          </div>
        </td>
      </tr>
      <tr>
        <td>2</td>
        <td>Training Material</td>
        <td>GP-02-2022</td>
        <td>
          <div class="dropdown">
            <a href="#" class="btn btn-primary optionsButton" data-bs-toggle="dropdown" aria-expanded="false" id="doc2">Options</a>
          </div>
        </td>
      </tr>
    </tbody>
  </table>

  <ul id="contextMenu" class="dropdown-menu">
    <li><a tabindex="-1" href="#" class="dropdown-item downloadLink">Download</a></li>
    <li><a tabindex="-1" href="#" class="dropdown-item propertiesLink">Properties</a></li>
  </ul>

  <script>
    //save the selector so you don't have to do the lookup everytime
    var $dropdown = $('#contextMenu');

    $('.optionsButton').click(function(event) {

      //get document ID
      var id = this.id;

      //move dropdown menu
      $(this).after($dropdown);

      //update links
      $dropdown.find(".downloadLink").attr("href", "/data/download?id=" + id);
      $dropdown.find(".propertiesLink").attr("href", "/data/viewproperties?id=" + id);

      //show dropdown
      $(this).dropdown();
    });
  </script>


</body>

</html>

在此代码中,我面临两种类型的问题。首先,下拉菜单未打开。当我在开发人员模式下检查代码时,我可以看到jQuery脚本已成功地传输contextMenu div在“选项”按钮下方,以使其按Bootstrap的要求嵌套。但是,$(this).dropdown();没有打开菜单。

第二个错误是,在开发人员模式控制台中,每次单击“选项”按钮时,我都会看到此错误:

下拉down.js:285 Untured TypeError:无法执行 'window'上的'getComputedStyle':参数1不是类型的'元素'。

此错误的堆栈跟踪指向dropdown.js,没有指定错误在我的代码中的位置。
需要帮助尝试在此处诊断该问题。我是Bootstrap和jQuery的新手。谢谢。

I'm creating a table with multiple rows, all having an "Options" button that is supposed to show a dropdown context menu. To keep the code shorter, I'm using a single div in order to reuse it as a common markup for the context menu.

I'm using Bootstrap 5.1.3 and jQuery 3.6.0. Following is my code:

<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Test Code</title>
  <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
</head>

<body>
  <table id="myTable" class="table table-hover">
    <thead>
      <tr>
        <th>#</th>
        <th>Document</th>
        <th>Reference</th>
        <th>Action</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>1</td>
        <td>General Policies</td>
        <td>GP-01-2022</td>
        <td>
          <div class="dropdown">
            <a href="#" class="btn btn-primary optionsButton" data-bs-toggle="dropdown" aria-expanded="false" id="doc1">Options</a>
          </div>
        </td>
      </tr>
      <tr>
        <td>2</td>
        <td>Training Material</td>
        <td>GP-02-2022</td>
        <td>
          <div class="dropdown">
            <a href="#" class="btn btn-primary optionsButton" data-bs-toggle="dropdown" aria-expanded="false" id="doc2">Options</a>
          </div>
        </td>
      </tr>
    </tbody>
  </table>

  <ul id="contextMenu" class="dropdown-menu">
    <li><a tabindex="-1" href="#" class="dropdown-item downloadLink">Download</a></li>
    <li><a tabindex="-1" href="#" class="dropdown-item propertiesLink">Properties</a></li>
  </ul>

  <script>
    //save the selector so you don't have to do the lookup everytime
    var $dropdown = $('#contextMenu');

    $('.optionsButton').click(function(event) {

      //get document ID
      var id = this.id;

      //move dropdown menu
      $(this).after($dropdown);

      //update links
      $dropdown.find(".downloadLink").attr("href", "/data/download?id=" + id);
      $dropdown.find(".propertiesLink").attr("href", "/data/viewproperties?id=" + id);

      //show dropdown
      $(this).dropdown();
    });
  </script>


</body>

</html>

In this code I'm facing two types of problems. Firstly, the dropdown menu isn't opening. When I inspect the code in Developer Mode, I can see that the jQuery script is successfully transferring the contextmenu DIV underneath the "Options" button so that it becomes nested as required by Bootstrap. But then the $(this).dropdown(); isn't opening the menu.

Second error is that in Developer Mode console, I see this error every time I click the 'Options' button:

dropdown.js:285 Uncaught TypeError: Failed to execute
'getComputedStyle' on 'Window': parameter 1 is not of type 'Element'.

And the stack trace of this error points to dropdown.js, does not specify where the error lies in my code.
Need help in trying to diagnose the issue here. I'm fairly new to Bootstrap and jQuery. Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

妄想挽回 2025-02-20 11:13:55

tl; dr: 不要在任何地方移动#contextmenu。阅读: 解决方案*


您遇到的错误

dropdown.js:285 Unduck typeError:在'window''上无法执行'getComputedStyle':参数1不是类型的'element'。

// @l62:
const SELECTOR_MENU = '.dropdown-menu'

// @l103:
  constructor(element, config) {
    super(element);
    //...
    this._menu = this._getMenuElement()
    //...
  }

// @l269:
  _getMenuElement() {
    return SelectorEngine.next(this._element, SELECTOR_MENU)[0]
  }

// @l285:
   _getPlacement() {
    // ...
    const isEnd = getComputedStyle(this._menu).getPropertyValue('--bs-position').trim() === 'end'
    // ...
  }

shere selectorengine.next(this._element,

如您所见,除了BS硬编码的一个,没有办法传递给构造函数另一个元素。 _getMenuelement() 〜Line285。

下一个同胞元素在方法/code>并盲目期望切换下一个同胞元素下拉 - 它实际上尚不存在(尚未)!

我会:

  • 扩展类下拉 手动,或
  • 提出问题并为相关的

所需元素作为this._menu;类似:

  constructor(element, config) {
    //...
    // Fix: allow for custom reusable menu Element
    this._menu = config.menuElement || this._getMenuElement()
    //...
  }

免责声明: 主要分支关于上述剥离代码,我不确定在编写这些问题时是否已解决。


同时,您可以简单地做什么,而无需使用“ Mousedown”事件(要领先BS的“单击”事件 - 就像在此 重复的问题答案 ),并且不使用愚蠢的event.stoppropagation()(除了您不应该使用,除了您,除了您是否真的知道自己在做什么,或用于调试仅目的) - 是:

解决方案:

不要使用ul#contextMenu使用.after()或(使用JS) .insertadjacentelement(),而是,关于扩展的Popper实例的实例化更改预期的bootstrap this._menu属性属性指向所需的可重复使用元素 - 您的 in- in- in-身体“ #contextmenu”喜欢:

<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Test Code</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
</head>

<body>
  <table id="myTable" class="table table-hover">
    <thead>
      <tr>
        <th>#</th>
        <th>Document</th>
        <th>Reference</th>
        <th>Action</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>1</td>
        <td>General Policies</td>
        <td>GP-01-2022</td>
        <td>
          <div class="dropdown">
            <button type="button" class="btn btn-primary optionsButton" data-bs-toggle="dropdown" aria-expanded="false" id="doc1">Options</button>
          </div>
        </td>
      </tr>
      <tr>
        <td>2</td>
        <td>Training Material</td>
        <td>GP-02-2022</td>
        <td>
          <div class="dropdown">
            <button type="button" class="btn btn-primary optionsButton" data-bs-toggle="dropdown" aria-expanded="false" id="doc2">Options</button>
          </div>
        </td>
      </tr>
    </tbody>
  </table>

  <ul id="contextMenu" class="dropdown-menu">
    <li><button type="button" tabindex="-1" class="dropdown-item downloadLink">Download</button></li>
    <li><button type="button" tabindex="-1" class="dropdown-item propertiesLink">Properties</button></li>
  </ul>

  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>

  <script>
    // DOM utility functions:
    const el = (sel, par) => (par || document).querySelector(sel);
    const els = (sel, par) => (par || document).querySelectorAll(sel);

    // Task: BS5 Popper fix for single static dropdown menu:
    const elDropdown = el('#contextMenu');
    const elsBtns = els(".optionsButton");
    const dropdownList = [...elsBtns].map(function(elBtn) {
      const instance = new bootstrap.Dropdown(elBtn);
      instance._menu = elDropdown;
      return instance;
    });
    // console.log(dropdownList); 
  </script>

</body>

</html>

以上的好东西是,DOM没有变化会触发回流。 popper代码将计算浮动上下文的最佳位置并将其称为工作。
不是那么 nice thick 是在您将TR元素动态添加到表中的情况下应给予特殊护理;在某种程度上,应在创建时将每个新添加的按钮作为new Bootstrap.dropdown(elbtn)

使用“ Mousedown”使用“ Mousedown”

的另一个(不是那么好的)解决方案,以实例化。不必要地)移动DOM 中的下拉菜单。可以使用“ Mousedown”事件来实现它,以便在BS的“单击” 事件触发器之前移动下拉列表“在这个相关问题的答案)。但这将无法正常工作。单击另一个按钮,一个按钮可以看到内容 /故障(实际下拉列表的)。可能有一些方法可以减轻问题……但是,为什么。无论如何,fyeo这是代码:

<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Test Code</title>

  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
</head>

<body>
  <table id="myTable" class="table table-hover">
    <thead>
      <tr>
        <th>#</th>
        <th>Document</th>
        <th>Reference</th>
        <th>Action</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>1</td>
        <td>General Policies</td>
        <td>GP-01-2022</td>
        <td>
          <div class="dropdown">
            <button type="button" class="btn btn-primary optionsButton" data-bs-toggle="dropdown" aria-expanded="false" id="doc1">Options</button>
          </div>
        </td>
      </tr>
      <tr>
        <td>2</td>
        <td>Training Material</td>
        <td>GP-02-2022</td>
        <td>
          <div class="dropdown">
            <button type="button" class="btn btn-primary optionsButton" data-bs-toggle="dropdown" aria-expanded="false" id="doc2">Options</button>
          </div>
        </td>
      </tr>
    </tbody>
  </table>

  <ul id="contextMenu" class="dropdown-menu">
    <li><button type="button" tabindex="-1" class="dropdown-item downloadLink">Download</button></li>
    <li><button type="button" tabindex="-1" class="dropdown-item propertiesLink">Properties</button></li>
  </ul>

  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>

  <script>
    // DOM utility functions:
    const el = (sel, par) => (par || document).querySelector(sel);
    const els = (sel, par) => (par || document).querySelectorAll(sel);

    // Task: BS5 Popper fix for single static dropdown menu:
    const elDropdown = el('#contextMenu');
    const elsBtns = els(".optionsButton");

    const prepareDropdown = (evt) => {
      const elBtn = evt.currentTarget;
      elBtn.insertAdjacentElement("afterend", elDropdown);
    };

    elsBtns.forEach(elBtn => elBtn.addEventListener("mousedown", prepareDropdown));
  </script>


</body>

</html>

PS:使用始终&lt;按钮类型=“ button”&gt;而不是锚定(如上所述),如果您不需要导航,而只是一个普通的UI交互按钮元素。

BS使用和实施弹出窗口,选择等的方式是破坏的。如果已经打开了弹出窗口(或模态),则单击另一个按钮 - 应立即显示第二个(或同一)弹出窗口 (第二次单击后)。这是设计中的UI/UX缺陷。 Bootstrap通常非常奇怪地实现想法,但不要忘记您可以随时提供拉请求


如果您对如何使用JavaScript从头开始创建(类似的)弹出窗口 - 您可以在此处找到更多:在鼠标位置

TL;DR: Don't move the #contextMenu anywhere. Read: Solution*


The error you're getting

dropdown.js:285 Uncaught TypeError: Failed to execute 'getComputedStyle' on 'Window': parameter 1 is not of type 'Element'.

is related to the Bootstrap (v5.1.3): dropdown.js code:

// @l62:
const SELECTOR_MENU = '.dropdown-menu'

// @l103:
  constructor(element, config) {
    super(element);
    //...
    this._menu = this._getMenuElement()
    //...
  }

// @l269:
  _getMenuElement() {
    return SelectorEngine.next(this._element, SELECTOR_MENU)[0]
  }

// @l285:
   _getPlacement() {
    // ...
    const isEnd = getComputedStyle(this._menu).getPropertyValue('--bs-position').trim() === 'end'
    // ...
  }

here: SelectorEngine.next(this._element,

as you can see, there's no way to pass to the constructor another Element .menu-dropdown besides the one that BS hardcoded, and that's a next Sibling element in the Method _getMenuElement() ~line285.

BS assigns a "click" Event to every button with data-bs-toggle="dropdown" and blindly expects to toggle a next sibling Element dropdown — which does not actually exists (yet)!

I would either:

  • extend the class Dropdown manually, or
  • raise an Issue and create a pull-request to the related Bootstrap module

as a way to pass any desired Element as the this._menu; something like:

  constructor(element, config) {
    //...
    // Fix: allow for custom reusable menu Element
    this._menu = config.menuElement || this._getMenuElement()
    //...
  }

Disclaimer: There are some changes in the main branch regarding the above stripped-off code, I'm not sure if at the time of writing those issues were addressed.


In the meantime what you can simply do, without using the "mousedown" Event (to be one step ahead the BS's "click" event - like in this duplicate question's answer), and without using the silly Event.stopPropagation() (which should never be used, besides you really, really know what you're doing, or for debugging purpose only) — is:

Solution:

Don't move the UL#contextMenu using .after() or (with JS) .insertAdjacentElement(), rather, on instantiation of the extended Popper instances change the expected Bootstrap this._menu property to point to the desired reusable Element — your in-body "#contextMenu" like:

<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Test Code</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
</head>

<body>
  <table id="myTable" class="table table-hover">
    <thead>
      <tr>
        <th>#</th>
        <th>Document</th>
        <th>Reference</th>
        <th>Action</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>1</td>
        <td>General Policies</td>
        <td>GP-01-2022</td>
        <td>
          <div class="dropdown">
            <button type="button" class="btn btn-primary optionsButton" data-bs-toggle="dropdown" aria-expanded="false" id="doc1">Options</button>
          </div>
        </td>
      </tr>
      <tr>
        <td>2</td>
        <td>Training Material</td>
        <td>GP-02-2022</td>
        <td>
          <div class="dropdown">
            <button type="button" class="btn btn-primary optionsButton" data-bs-toggle="dropdown" aria-expanded="false" id="doc2">Options</button>
          </div>
        </td>
      </tr>
    </tbody>
  </table>

  <ul id="contextMenu" class="dropdown-menu">
    <li><button type="button" tabindex="-1" class="dropdown-item downloadLink">Download</button></li>
    <li><button type="button" tabindex="-1" class="dropdown-item propertiesLink">Properties</button></li>
  </ul>

  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>

  <script>
    // DOM utility functions:
    const el = (sel, par) => (par || document).querySelector(sel);
    const els = (sel, par) => (par || document).querySelectorAll(sel);

    // Task: BS5 Popper fix for single static dropdown menu:
    const elDropdown = el('#contextMenu');
    const elsBtns = els(".optionsButton");
    const dropdownList = [...elsBtns].map(function(elBtn) {
      const instance = new bootstrap.Dropdown(elBtn);
      instance._menu = elDropdown;
      return instance;
    });
    // console.log(dropdownList); 
  </script>

</body>

</html>

The nice thing of the above is that there are no changes in the DOM that would trigger a reflow. The Popper code will calculate the best position of your floating contextMenu and call it job-done.
The not so nice thing is that special care should be given in the case you dynamically add TR elements to the Table; in the means that every newly added Button should be instantiated upon creation as a new bootstrap.Dropdown(elBtn)

Using "mousedown"

Another (not so good) solution to your original idea is to (unnecessarily) move the dropdown in DOM. It can be achieved using the "mousedown" Event, in order to move the dropdown "ahead-of-time" — before the BS's "click" event triggers (as suggested in this related question's answer). But such will not work correctly. Clicking one button after the other, a flash of content / glitch (of the actual dropdown) can be seen. There might be ways to mitigate the issue… but, why. Anyways, FYEO here's the code:

<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Test Code</title>

  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
</head>

<body>
  <table id="myTable" class="table table-hover">
    <thead>
      <tr>
        <th>#</th>
        <th>Document</th>
        <th>Reference</th>
        <th>Action</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>1</td>
        <td>General Policies</td>
        <td>GP-01-2022</td>
        <td>
          <div class="dropdown">
            <button type="button" class="btn btn-primary optionsButton" data-bs-toggle="dropdown" aria-expanded="false" id="doc1">Options</button>
          </div>
        </td>
      </tr>
      <tr>
        <td>2</td>
        <td>Training Material</td>
        <td>GP-02-2022</td>
        <td>
          <div class="dropdown">
            <button type="button" class="btn btn-primary optionsButton" data-bs-toggle="dropdown" aria-expanded="false" id="doc2">Options</button>
          </div>
        </td>
      </tr>
    </tbody>
  </table>

  <ul id="contextMenu" class="dropdown-menu">
    <li><button type="button" tabindex="-1" class="dropdown-item downloadLink">Download</button></li>
    <li><button type="button" tabindex="-1" class="dropdown-item propertiesLink">Properties</button></li>
  </ul>

  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>

  <script>
    // DOM utility functions:
    const el = (sel, par) => (par || document).querySelector(sel);
    const els = (sel, par) => (par || document).querySelectorAll(sel);

    // Task: BS5 Popper fix for single static dropdown menu:
    const elDropdown = el('#contextMenu');
    const elsBtns = els(".optionsButton");

    const prepareDropdown = (evt) => {
      const elBtn = evt.currentTarget;
      elBtn.insertAdjacentElement("afterend", elDropdown);
    };

    elsBtns.forEach(elBtn => elBtn.addEventListener("mousedown", prepareDropdown));
  </script>


</body>

</html>

PS: use always <button type="button"> instead of Anchors (as in the examples above) if you don't need to navigate, but just a plain UI interaction button Element.

The way that BS uses and implements popups, selects etc. is kind of broken anyways. If a popup (or modal) is already opened, by clicking another button — the second (or the same) popup should be shown immediately (not after a second click). It's a UI/UX flaw in the design. Bootstrap often implements ideas quite oddly, but don't forget you can always help the Open Source community by providing a Pull Request.


If you're interested on how to create a (similar) Popup from scratch using JavaScript — you can find out more here: Show custom popup on mouse location.

迷乱花海 2025-02-20 11:13:55

我已经评论了您对Bootstrap CDN的加载,并仅处理您的实际JavaScript。

您只有显示下拉词的逻辑,尽管我将其从$(this).dropdown(); $ dropdown.show()更改为已经使用此变量进行了跟踪。

我还实现了切换效果,也就是说,如果打开您的下拉列表,那么我们有以下方案:

  • 您单击表中的其他地方,在这种情况下,下拉列表将被隐藏,
  • 您单击相同的按钮,在这种情况下,下拉列表将隐藏
  • 您单击另一行中的类似按钮,在这种情况下,下拉列表将使用适当的参数正确移动到适当的位置
<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Test Code</title>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
</head>
<body>
    <table id="myTable" class="table table-hover" onclick="hideall()">
        <thead>
            <tr>
                <th>#</th>
                <th>Document</th>
                <th>Reference</th>
                <th>Action</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>1</td>
                <td>General Policies</td>
                <td>GP-01-2022</td>
                <td>
                    <div class="dropdown">
                        <a href="#" class="btn btn-primary optionsButton" aria-expanded="false" id="doc1">
                            Options
                        </a>
                    </div>
                </td>
            </tr>
            <tr>
                <td>2</td>
                <td>Training Material</td>
                <td>GP-02-2022</td>
                <td>
                    <div class="dropdown">
                        <a href="#" class="btn btn-primary optionsButton" aria-expanded="false" id="doc2">
                            Options
                        </a>
                    </div>
                </td>
            </tr>
        </tbody>
    </table>
    


    <ul id="contextMenu" class="dropdown-menu">
        <li><a tabindex="-1" href="#" class="dropdown-item downloadLink">Download</a></li>
        <li><a tabindex="-1" href="#" class="dropdown-item propertiesLink">Properties</a></li>
    </ul>
    
    <script>
        //save the selector so you don't have to do the lookup everytime
        var $dropdown = $('#contextMenu');
        var activeOptionsButton;

        $('.optionsButton').click(function(event) {
        
            event.stopPropagation();
            if (activeOptionsButton === this) {
                hideall();
                activeOptionsButton = undefined;
                return;
            }
            activeOptionsButton = this;
            //get document ID
            var id = this.id;
            
            //move dropdown menu
            $(this).after($dropdown);

            //update links
            $dropdown.find(".downloadLink").attr("href", "/data/download?id="+id);
            $dropdown.find(".propertiesLink").attr("href", "/data/viewproperties?id="+id);
            
            //show dropdown
            $dropdown.show();
        });
        
        function hideall() {
            $dropdown.hide();
        }
    
    </script>


</body>
</html>

I have commented your loading of the bootstrap cdn and dealt with only with your actual Javascript.

You only had a logic to display the dropdown, albeit I changed it from $(this).dropdown(); to $dropdown.show(), because your dropdown is already tracked with this variable.

I have also implemented the toggling effect, that is, if your dropdown is opened, then we have the following scenarios:

  • you click somewhere else in the table, in which case the dropdown will be hidden
  • you click on the same button, in which case the dropdown will be hidden
  • you click on a similar button in another line, in which case the dropdown will be properly moved to the appropriate place using the appropriate parameters

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Test Code</title>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
</head>
<body>
    <table id="myTable" class="table table-hover" onclick="hideall()">
        <thead>
            <tr>
                <th>#</th>
                <th>Document</th>
                <th>Reference</th>
                <th>Action</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>1</td>
                <td>General Policies</td>
                <td>GP-01-2022</td>
                <td>
                    <div class="dropdown">
                        <a href="#" class="btn btn-primary optionsButton" aria-expanded="false" id="doc1">
                            Options
                        </a>
                    </div>
                </td>
            </tr>
            <tr>
                <td>2</td>
                <td>Training Material</td>
                <td>GP-02-2022</td>
                <td>
                    <div class="dropdown">
                        <a href="#" class="btn btn-primary optionsButton" aria-expanded="false" id="doc2">
                            Options
                        </a>
                    </div>
                </td>
            </tr>
        </tbody>
    </table>
    


    <ul id="contextMenu" class="dropdown-menu">
        <li><a tabindex="-1" href="#" class="dropdown-item downloadLink">Download</a></li>
        <li><a tabindex="-1" href="#" class="dropdown-item propertiesLink">Properties</a></li>
    </ul>
    
    <script>
        //save the selector so you don't have to do the lookup everytime
        var $dropdown = $('#contextMenu');
        var activeOptionsButton;

        $('.optionsButton').click(function(event) {
        
            event.stopPropagation();
            if (activeOptionsButton === this) {
                hideall();
                activeOptionsButton = undefined;
                return;
            }
            activeOptionsButton = this;
            //get document ID
            var id = this.id;
            
            //move dropdown menu
            $(this).after($dropdown);

            //update links
            $dropdown.find(".downloadLink").attr("href", "/data/download?id="+id);
            $dropdown.find(".propertiesLink").attr("href", "/data/viewproperties?id="+id);
            
            //show dropdown
            $dropdown.show();
        });
        
        function hideall() {
            $dropdown.hide();
        }
    
    </script>


</body>
</html>

春花秋月 2025-02-20 11:13:55

尝试这个..

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Test Code</title>
  
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-zCbKRCUGaJDkqS1kPbPd7TveP5iyJE0EjAuZQTgFLD2ylzuqKfdKlfG/eSrtxUkn" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-VHvPCCyXqtD5DqJeNxl2dtTyhF78xXNXdkwX1CZeRusQfRKp+tA7hAShOK/B/fQ2" crossorigin="anonymous"></script>
  
</head>
<body>
    <table id="myTable" class="table table-hover">
        <thead>
            <tr>
                <th>#</th>
                <th>Document</th>
                <th>Reference</th>
                <th>Action</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>1</td>
                <td>General Policies</td>
                <td>GP-01-2022</td>
                <td>
                    <div class="dropdown">
                        <a href="#" class="btn btn-primary optionsButton" data-bs-toggle="dropdown" aria-expanded="false" id="doc1">
                            Options
                        </a>
                    </div>
                </td>
            </tr>
            <tr>
                <td>2</td>
                <td>Training Material</td>
                <td>GP-02-2022</td>
                <td>
                    <div class="dropdown">
                        <a href="#" class="btn btn-primary optionsButton" data-bs-toggle="dropdown" aria-expanded="false" id="doc2">
                            Options
                        </a>
                    </div>
                </td>
            </tr>
        </tbody>
    </table>
    


    <ul id="contextMenu" class="dropdown-menu">
        <li><a tabindex="-1" href="#" class="dropdown-item downloadLink">Download</a></li>
        <li><a tabindex="-1" href="#" class="dropdown-item propertiesLink">Properties</a></li>
    </ul>
    
    <script>
        //save the selector so you don't have to do the lookup everytime
        var $dropdown = $('#contextMenu');

        $('.optionsButton').click(function(event) {
            
            //get document ID
            var id = this.id;
            
            //move dropdown menu
            $(this).after($dropdown);

            //update links
            $dropdown.find(".downloadLink").attr("href", "/data/download?id="+id);
            $dropdown.find(".propertiesLink").attr("href", "/data/viewproperties?id="+id);
            
            //show dropdown
            $(this).dropdown();
        });
    
    </script>


</body>
</html>

try this..

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Test Code</title>
  
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-zCbKRCUGaJDkqS1kPbPd7TveP5iyJE0EjAuZQTgFLD2ylzuqKfdKlfG/eSrtxUkn" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-VHvPCCyXqtD5DqJeNxl2dtTyhF78xXNXdkwX1CZeRusQfRKp+tA7hAShOK/B/fQ2" crossorigin="anonymous"></script>
  
</head>
<body>
    <table id="myTable" class="table table-hover">
        <thead>
            <tr>
                <th>#</th>
                <th>Document</th>
                <th>Reference</th>
                <th>Action</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>1</td>
                <td>General Policies</td>
                <td>GP-01-2022</td>
                <td>
                    <div class="dropdown">
                        <a href="#" class="btn btn-primary optionsButton" data-bs-toggle="dropdown" aria-expanded="false" id="doc1">
                            Options
                        </a>
                    </div>
                </td>
            </tr>
            <tr>
                <td>2</td>
                <td>Training Material</td>
                <td>GP-02-2022</td>
                <td>
                    <div class="dropdown">
                        <a href="#" class="btn btn-primary optionsButton" data-bs-toggle="dropdown" aria-expanded="false" id="doc2">
                            Options
                        </a>
                    </div>
                </td>
            </tr>
        </tbody>
    </table>
    


    <ul id="contextMenu" class="dropdown-menu">
        <li><a tabindex="-1" href="#" class="dropdown-item downloadLink">Download</a></li>
        <li><a tabindex="-1" href="#" class="dropdown-item propertiesLink">Properties</a></li>
    </ul>
    
    <script>
        //save the selector so you don't have to do the lookup everytime
        var $dropdown = $('#contextMenu');

        $('.optionsButton').click(function(event) {
            
            //get document ID
            var id = this.id;
            
            //move dropdown menu
            $(this).after($dropdown);

            //update links
            $dropdown.find(".downloadLink").attr("href", "/data/download?id="+id);
            $dropdown.find(".propertiesLink").attr("href", "/data/viewproperties?id="+id);
            
            //show dropdown
            $(this).dropdown();
        });
    
    </script>


</body>
</html>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文