如何使用 jQuery UI selectMenu 小部件在 drop-down 列表中创建 3 列?

How to create 3 columns in the drop-down list using jQuery UI selectMenu widget?

我的任务是创建一个包含 3 列(每行)的 drop-down 列表,如下图所示。

现在,我意识到 jQuery UI 的 Selectmenu 小部件可以满足我的要求,因此,我使用了以下代码(如 their official documentation page 中给出的)。

<!doctype html>

<html lang="en">

<head>

<meta charset="utf-8">

<title>selectmenu demo</title>

<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/smoothness/jquery-ui.css">

<style>

label { display: block; }

select { width: 200px; }

.overflow { height: 200px; }

</style>

<script src="//code.jquery.com/jquery-1.12.4.js"></script>

<script src="//code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

</head>

<body>

<label for="number">Select a number:</label>

<select name="number" id="number">

<option value="1">1</option>

<option value="2" selected>2</option>

<option value="3">3</option>

<option value="4">4</option>

<option value="5">5</option>

<option value="6">6</option>

<option value="7">7</option>

<option value="8">8</option>

<option value="9">9</option>

<option value="10">10</option>

<option value="11">11</option>

<option value="12">12</option>

<option value="13">13</option>

<option value="14">14</option>

<option value="15">15</option>

<option value="16">16</option>

<option value="17">17</option>

<option value="18">18</option>

<option value="19">19</option>

</select>

<script>

$( "#number" )

.selectmenu()

.selectmenu( "menuWidget" )

.addClass( "overflow" );

</script>

</body>

</html>

问题是我想创建 3 列而不是 1 个默认列。因此,我尝试了两种选项来对齐选项标签内的文本内容。

  1. 将文本放在 span 标签内。
  2. 将文本放入由一行三列(单元格)组成的 table 中。

下面给出的是我试过的代码。

<option value="1">
        <span align="left">Apple</span>
        <span align="center">Mango</span>
        <span align="right">Orange</span>
        </option>
      <option value="2" selected>
      <table>
        <tr>
          <td align="left">1</td>
          <td align="center">2</td>
          <td align="right">3</td>
        </tr>
        </table>
      </option>

但这并没有解决我的问题,因为我得到的输出如下图所示。

由于我是 HTML、CSS 和 jQuery 的初学者,因此,我不知道下一步要做什么才能创建 drop-down每行包含 3 列的列表。请注意,我将 select 包含所有 3 列的整行(如下图所示),而不是任何特定 column.Can 的任何单元格 任何人都请建议可以做些什么来解决这个问题问题并创建下拉列表,如第一张图片所示?

这是无效的 HTML,我想大多数浏览器都会忽略它。

如果要更改渲染,请使用扩展点: http://api.jqueryui.com/selectmenu/#method-_renderItem

首先,我们要创建一个合适的 HTML 结构。 select 中有一个元素你会想要了解:<optgroup>。这是一个基本的建议结构。

<label for="options">Select an Option:</label>
<select id="options">
  <optgroup label="PREFERRED OPTIONS">
    <option value="L">Standard Screw Adjustment</option>
  </optgroup>
  <optgroup label="STANDARD OPTIONS">
    <option value="C">Tamper Resistant - Factory Set</option>
    <option value="K">Handknob</option>
  </optgroup>
  <optgroup label="ADDITIONAL OPTIONS">
    <option value="F">Hex Head Screw with Locknut</option>
  </optgroup>
</select>

这仅仅是个开始。您可以使用 $("#options").selectmenu(); 并且更接近您想要的。我们仍然需要添加更多元素并合并额外数据。

The selectmenu widget is built with the widget factory and can be extended. When extending widgets, you have the ability to override or add to the behavior of existing methods.

这正是我们要做的,以 .autocomplete() 为例。在此处查看此示例:http://jqueryui.com/autocomplete/#categories

我们将在 .selectmenu() 内执行相同类型的覆盖。 widget factory 和它的代码有时可能有点高级和有点难以理解,所以你必须自己深入研究它。

HTML

<label for="options">Select an Option:</label>
<select id="options">
  <optgroup label="PREFERRED OPTIONS">
    <option data-short="L" data-price="[=11=].00" value="L">Standard Screw Adjustment</option>
  </optgroup>
  <optgroup label="STANDARD OPTIONS">
    <option data-short="C" data-price=".00" value="C">Tamper Resistant - Factory Set</option>
    <option data-short="K" data-price=".00" value="K">Handknob</option>
  </optgroup>
  <optgroup label="ADDITIONAL OPTIONS">
    <option data-short="F" data-price="-.00" value="F">Hex Head Screw with Locknut</option>
  </optgroup>
</select>

您在上面看到的是我们最初构建的内容的扩展。我添加了 data 属性。它们对我们的 HTML 意义不大,但对我们的 jQuery 很有用。这里的好处是,如果我们遇到不支持 JavaScript 的浏览器(因此无法加载 jQuery 库),代码将退回到基本的 HTML 标记并且仍然是用户的类似体验。

CSS

.ui-selectmenu-category {
  color: #5F5F5F;
  padding: .5em .25em;
}
.ui-menu-item {
}
.ui-menu-item .ui-menu-item-wrapper {
  display: inline-block;
  padding: 1em 2px;
}

.ui-menu-item .ui-menu-item-wrapper.ui-state-active {
  border-width: 1px 0 1px 0;
  border-color: #CCCCCC;
  background-color: #E4EBF1;
  color: #000;
}

.ui-menu-item .ui-menu-item-wrapper.ui-state-active.short {
  color: #2E6D99;
}

.ui-menu-item div.ui-menu-item-wrapper {
  width: 295px;
}

.ui-menu-item .short {
  color: #2E6D99;
  font-weight: strong;
  width: 30px;
  padding-left: .5em;
}

.ui-menu-item .price {
  font-weight: strong;
  width: 75px;
  margin-right: -6px;
}

我们将为 .selectmenu() 覆盖和扩展一些主题元素。这一切只是为了帮助它符合所需的外观和感觉。

JavaScript

$(function() {
  $.widget("custom.mySelectMenu", $.ui.selectmenu, {
    _renderMenu: function(ul, items) {
      var that = this,
        currentCategory = "";
      $.each(items, function(index, item) {
        var li, name, short, price;
        if (item.optgroup != currentCategory) {
          ul.append("<li class='ui-selectmenu-category'>" + item.optgroup + "</li>");
          currentCategory = item.optgroup;
        }
        li = that._renderItemData(ul, item);
        console.log(ul);
        name = li.text();
        short = item.element.data("short");
        price = item.element.data("price");
        console.log(li, short, price);
        li.prepend($("<span>", {
          class: "short"
        }).html(short));
        li.append($("<span>", {
          class: "price"
        }).html(price));
        if (item.optgroup) {
          li.attr("aria-label", item.optgroup + " : " + item.label);
        }
      });
    }
  });
  $("#options").mySelectMenu({
    width: 400
  });
});

工作示例: https://jsfiddle.net/Twisty/sn1z5vzn/7/

这里是我们使用 $.ui.selectmenu 并将其扩展到我们自己使用的地方。您可以看到我们只为 _renderMenu 扩展点编写了一个函数。关于 select 菜单的其他所有内容都将保持不变。

这很重要,因为我们需要定义一个 width 选项。我们需要知道宽度,以便我们可以创建适当的列,本质上。

这将遍历每个 items 并创建 li 元素以与 select 菜单创建的 ul 一起使用。生成的项目将如下所示:

<li aria-label="PREFERRED OPTIONS : Standard Screw Adjustment" class="ui-menu-item">
  <span class="short ui-menu-item-wrapper ui-state-active" id="ui-id-1" tabindex="-1" role="option">L</span>
  <div id="ui-id-2" tabindex="-1" role="option" class="ui-menu-item-wrapper ui-state-active">Standard Screw Adjustment</div>
  <span class="price ui-menu-item-wrapper ui-state-active" id="ui-id-3" tabindex="-1" role="option">[=14=].00</span>
</li>

jQuery UI 为我们做了很多额外的工作,分配唯一的 ID 和应用悬停 类 等。我们的添加允许我们为每个的不同部分设置样式和主题项目。

类别项目不想玩好。到目前为止,我发现如果我尝试将任何 HTML 元素添加到它的 li 中,它就无法正确呈现菜单的其余部分。我可能会回去看看 _renderItem 是否对这里有帮助。

简单吧!?有问题请评论。

参考文献


更新

如果您像这样更改选项:

<option data-icon-url="https://www.gravatar.com/avatar/b3e04a46e85ad3e165d66f5d927eb609?d=monsterid&r=g&s=16" data-price="[=15=].00" value="L">Standard Screw Adjustment</option>

然后您可以更新 <span> 以将其用作背景。

CSS 片段

.ui-menu-item .icon {
  background-repeat: no-repeat;
  background-size: 30px;
  background-position: center center; 
  color: #2E6D99;
  font-weight: strong;
  width: 30px;
  padding-left: .5em;
}

JavaScript 片段

    li.prepend($("<span>", {
      class: "icon",
      style: "background-image: url('" + iconUrl + "')"
    }).html("&nbsp;"));

&nbsp; 呈现不间断 Space 字符。

A common character entity used in HTML is the non-breaking space: &nbsp;

A non-breaking space is a space that will not break into a new line.

Two words separated by a non-breaking space will stick together (not break into a new line). This is handy when breaking the words might be disruptive.

工作示例:https://jsfiddle.net/Twisty/sn1z5vzn/12/