假设您需要创建一个用户界面,用户可以在其中根据最喜爱到最不喜爱的顺序对三种巧克力棒进行评分。使用单选按钮网格并不是一个糟糕的选择。

好消息是,单选按钮在其名称组中具有天然的排他性,我们可以利用这一点。坏消息是,我们有相互关联的组,并且无法仅通过 HTML 以功能的方式表达这一点。

让我们以这样一种方式设计 HTML:水平组共享相同的名称,从而自动授予排他性。我们还将添加一个 HTML data-* 属性,该属性表示列,我们将使用 JavaScript1 模拟垂直排他性。
<table>
<tr>
<th></th>
<th>1</th>
<th>2</th>
<th>3</th>
</tr>
<tr>
<td>Twix</td>
<td><input type="radio" name="row-1" data-col="1"></td>
<td><input type="radio" name="row-1" data-col="2"></td>
<td><input type="radio" name="row-1" data-col="3"></td>
</tr>
<tr>
<td>Snickers</td>
<td><input type="radio" name="row-2" data-col="1"></td>
<td><input type="radio" name="row-2" data-col="2"></td>
<td><input type="radio" name="row-2" data-col="3"></td>
</tr>
<tr>
<td>Butterfingers</td>
<td><input type="radio" name="row-3" data-col="1"></td>
<td><input type="radio" name="row-3" data-col="2"></td>
<td><input type="radio" name="row-3" data-col="3"></td>
</tr>
</table>
我们的极其简单的设计可以通过以下 CSS 实现
table {
border-collapse: collapse;
}
td, th {
border: 1px solid #ccc;
padding: 10px;
}
th:empty {
border: 0;
}
如果不是因为我认为这是一个非常有用的 :empty
伪类选择器案例,我甚至不会发布这个 CSS。
现在要授予垂直组的排他性,我们将使用一点 jQuery
var col, el;
$("input[type=radio]").click(function() {
el = $(this);
col = el.data("col");
$("input[data-col=" + col + "]").prop("checked", false);
el.prop("checked", true);
});
当单击单选按钮时,将确定列,并关闭该列中的所有其他单选按钮,然后重新打开所单击的按钮。
这就是全部内容。
需要说明的是,我确实从 我之前链接的屏幕截图 中获得了这个想法,其中简要提到了这个想法,然后就被放弃了。
此外,我很想知道大家是否对“对这三种巧克力棒进行评分”有其他设计模式的想法。思考这些总是很有趣的。
1 或者,您可以通过 JavaScript 以编程方式应用数据属性,甚至根据需要动态计算列。一如既往,杀猫的方法比用黄油闷死它要多得多。
非常巧妙!
至于其他建议,简单的拖放(可排序)解决方案也可以。
喜欢它!我一直想知道调查是如何做到这一点的。谢谢!
不错!如果可以交换列中的其他项,而不是取消选中它们,那就更有用了。
谢谢!非常有用的文章。
将 prettyprint 上的 html rel 更改为 css,这样这篇文章就完美了;)
我更喜欢一个项目的拖放列表,这样列表顶部的项目就更重要。我认为单选按钮网格对用户来说有点令人困惑。但这是我的意见 :P
(嗨,妈妈!)
在你的示例中,由于 3 个评分是互斥的,因此实际上只有 3 个选项,而不是你使用的 9 个。就像 Corey 说的那样,可拖动列表似乎最合乎逻辑。
您还可以使用一个界面,要求用户简单地按从最喜爱到最不喜爱的顺序依次单击三个选项(从技术上讲,这只需要 2 次点击)。
你真是个狂人,Coyier。
我喜欢这个演示,绝对是那些很难思考的事情之一,但当你做的时候很有趣。
您知道如何将标签与多个输入关联吗?我从未真正想过是否可以这样做
<label for="id1 id2">thing</label>
你喜欢 Twix 比 Butterfingers 吗?
一个新的投票
谢谢!我刚刚了解到 HTML5 规范不要求默认的单选按钮组输入被选中。
HTML5:“如果单选按钮组中的任何单选按钮在插入文档时未被选中,则它们在界面中最初都将未被选中,直到其中一个被选中(由用户或脚本)为止。” http://www.w3.org/TR/html5/number-state.html#radio-button-state
HTML4:“始终,一组单选按钮中只有一个被选中。如果一组单选按钮的任何元素都没有指定 `CHECKED`,则用户代理必须最初选中该组的第一个单选按钮。” http://www.w3.org/TR/html4/interact/forms.html#radio
首先,史尼克尔斯,这个神圣无比的巧克力,没有排在你的列表第一位,这让我想要将你的网站列入黑名单。那真是太不地道了,伙计。
正如其他人所说,对于这个特定示例,可排序列表会更好。我还会考虑使用
selects
(下拉列表),然后在为给定元素选择每个值时禁用options
。随着元素数量的增加,您的单选按钮网格也会变得越来越宽;想象一下 20×20 或 50×50 等。使用selects
,无论选择数量多少,您都将拥有一个 2 列表格,并且每个select
中的options
数量将为 1 到 n,其中 n 是他们正在评分的项目数量。一旦有人选择某个项目作为 #1,所有其他 #1 的options
将被禁用/删除,等等。虽然可拖动界面可能是更好的 UI,但从 JS 的角度来看,如果您将值放入 HTML 中,您是否可以使用它来使事物唯一,而不是 data-col?无论如何,在这种情况下,value 属性和 data-col 属性似乎是冗余的。
我忍不住笑了“Butterfingers”。
:)
它实际上被称为 Butterfinger(没有“s”!)。但它确实让我想起了 Leon Lett。
哇,这是一个毫无意义的评论。我想我得不到星星? :)
我一定看过太多次这个视频了:http://www.youtube.com/watch?v=Zp-PX13ZlX8
完美 - 我刚刚删除了大约花费了一天左右的时间创建的内容,这些内容与您在这里展示的内容完全相同!令人沮丧!但谢谢
很棒的东西!我非常喜欢这个简单的设计。
AVID 的工作人员可以在他们的新音频接口对决中使用它。
http://apps.avid.com/mbox-challenge/
很有趣!干得好 :)
这是一个很棒的技巧,但是当我尝试选择所有行的相同评分时,它会取消选择其他行。我唯一可以让所有三个单选按钮都选中方法是,如果我为所有三个选择使用不同的列。
这就是全部目的=)
很棒的更新,喜欢阅读其中的每一部分。
这也可以在不使用数据属性的情况下完成,从而进一步推动选择器用法。
不确定两种解决方案之间的性能差异。
老实说,Chris,这并不直观。我想可能有更好的方法来做到这一点,以获得更好的 UX。但是,它很有趣也很有创意。
很酷的小方法。我想知道为什么有人需要这个。我渴望听到例子!
非常棒!这在各种用途下都会派上用场。谢谢。
偶然发现了这个,并想采纳Rikudo Sennin提出的“值交换”方法的请求。
我的大脑也一直在思考一个使用MooTools的事件委托场景,所以,无论好坏,这就是我所使用的: http://jsfiddle.net/sullenfish/64xWG/
巧妙。当你选择一个通常会取消选择另外两个的选项时(因为它只是移动了其中一个),感觉有点“扫兴”。
感谢分享,Chris。
我建议使用
onchange
事件监听器来更改按钮,因为它专门用于执行此操作。虽然这对于a11y来说可能稍微好一点。也许目前我还没有意识到有什么缺点……
我用你的代码做了一个非常简单的示例。
你仍然只能在一列中选中一个单选按钮。比如,如果我想给士力架和德芙都评3分,我做不到。有办法吗?