jQuery - 复选框,如单选按钮

Posted

技术标签:

【中文标题】jQuery - 复选框,如单选按钮【英文标题】:jQuery - checkboxes like radiobuttons 【发布时间】:2010-10-27 05:45:54 【问题描述】:

我有组复选框,我喜欢这个组是否有类似具有相同名称属性的单选按钮的行为。

每个复选框都有不同的名称。

复选框只能选择一个。

我该怎么做?


解决方案

为什么我需要这个? 因为我们需要一致性的 webUI。 拜托,这不是关于我们的应用程序架构的问题。 :)

HTML 示例

<div class="multiCheckBox">
 <span class="multiGroup">
  <div><input class="multiItem" value="111" name="list" type="checkbox" />111</div>
  <div><input class="multiItem" value="112" name="list" type="checkbox" />112</div>
  <div><input class="multiItem" value="113" name="list" type="checkbox" />113</div>
 </span>
 <span>
  <div><input class="multiItem" value="121" name="list" type="checkbox" />121</div>
  <div><input class="multiItem" value="122" name="list" type="checkbox" />122</div>
  <div><input class="multiItem" value="133" name="list" type="checkbox" />123</div>
 </span>
 <span>
  <div><input class="multiItem" value="131" name="list" type="checkbox" />131</div>
  <div><input class="multiItem" value="132" name="list" type="checkbox" />132</div>
  <div><input class="multiItem" value="133" name="list" type="checkbox" />133</div>
 </span>
</div>

JavaScript

var $groups = $("span.multiGroup", $that);
$groups.each(function() 
    var $group = $(this);
    var $checkboxes = $(":checkbox", $group);
    $checkboxes.click(function() 
        var $activeCheckbox = $(this);
        var state = $activeCheckbox.attr('checked');
        $checkboxes.attr('checked', false);
        $activeCheckbox.attr('checked', state);
    );
);

【问题讨论】:

为什么不使用单选按钮?哦,你可能想把你尝试做的代码,所以我们知道你在找什么...... 不要对单选按钮使用复选框。使用单选按钮作为单选按钮。您会在门上使用电灯开关而不是门把手吗? Tim:谢谢你的意见,但这是我做我需要的最好的方式。还有这个关于 webUI 的问题,而不是关于我的应用程序架构的问题。 对于我的表单,我需要用户能够取消选择“收音机”选项,因此我必须使用复选框,但如果选中了复选框,则只能选择一个复选框。 这里有一些很好的答案,但我发现这个问题更适合我需要的行为:***.com/questions/2117538/… 【参考方案1】:

这里有一个提示:使用单选按钮。 ;)

我不建议这样做,因为它会被认为不利于可用性,并且肯定会违反最小意外原则。用户已经习惯于期望收音机接受 1 个检查和复选框来接受许多。 Don't make your users think.

不过,如果您有自己的理由,下面是使用 jQuery 进行此操作的方法:

<input type='checkbox' name='mygroup1' value='1' class='unique'>
<input type='checkbox' name='mygroup2' value='2' class='unique'>
<input type='checkbox' name='mygroup3' value='3' class='unique'>

还有 jQuery:

var $unique = $('input.unique');
$unique.click(function() 
    $unique.filter(':checked').not(this).removeAttr('checked');
);

这是live sample。

编辑

正如 cmets 中所指出的,这将允许用户取消选择所有复选框,即使他们最初选择了一个复选框,这与单选按钮不完全一样。如果你想要这个,那么 jQuery 应该是这样的:

var $unique = $('input.unique');
$unique.click(function() 
    $unique.removeAttr('checked');
    $(this).attr('checked', true);
);

【讨论】:

每个复选框都有不同的名称。 @MicTech:我认为即使它们都有不同的名称,您也应该将输入设置为单选按钮 - 这样用户在他们表现得像单选按钮时真的不会感到惊讶,嗯? 非常优雅的解决方案和不错的答案。您的代码允许取消选中所有复选框。这不是“单选按钮”功能。然而,这取决于用户想要什么。 我的用例是,如果他们可以选择多个或不选择,则案例/开关将在它们之间切换。否则他们可以任意数量。你觉得这仍然是不合理的,我应该隐藏/显示一个替代的无线电表单列表吗? @Trip:我认为这可能是一个可以接受的用例,我不喜欢它,但它就是这样。【参考方案2】:

那你为什么不使用单选按钮呢?

差异是有原因的。它是这样设计的,从用户的角度来看,单选按钮的意思是“选择一个”,而复选框的意思是“选择多个”。

不要通过改变这个久经考验的范例来打破用户的期望。当应用程序开发人员更喜欢“外观”而不是可用性和约定时,这是一件坏事,所以不要成为其中之一。

用户界面之所以有效,是因为所使用的隐喻(复选框、按钮、鼠标指针的形状、颜色等)具有某种特定的行为方式。当你做这样的事情时,用户会遇到你的应用程序的问题,甚至可能不知道为什么。

这是一种反模式,与使用复选框状态更改标签属于同一类别:

[ ] 启用选项与 [ ] 选项 [x] 禁用选项 [x] 选项

【讨论】:

【参考方案3】:
$(".checkboxClass").click(function() 
    $(".checkboxClass").each(function() 
        $(this)[0].checked = false;);
    $(this)[0].checked = true;
);

首先清除所有复选框,然后检查被点击的那个。

【讨论】:

【参考方案4】:

我遇到了类似的问题。我不能使用单选按钮,因为在某些情况下,同一个表单必须显示多选复选框。我拿了你的标记,写了一小段 jQuery:

$("span.multiGroup input").click(function() 
    $("span.multiGroup input").attr('checked', false);
    $(this).attr('checked', true);
);

【讨论】:

【参考方案5】:
var $unique = $('input.unique');

$unique.click(function() 

 $checked = $(this).is(':checked') ; // check if that was clicked.
 $unique.removeAttr('checked'); //clear all checkboxes
 $(this).attr('checked', $checked); // update that was clicked.

);

【讨论】:

【参考方案6】:

HTML

<input type='checkbox' name='mygroup1' value='1' class='unique'>
<input type='checkbox' name='mygroup2' value='2' class='unique'>
<input type='checkbox' name='mygroup3' value='3' class='unique'>

Javascript

$('input.unique').each(function() 
    $(this).on('touchstart click', function() 
    $('input.unique').not(this).removeAttr('checked');
);
);

小提琴:http://jsfiddle.net/L2ad1vd8/

【讨论】:

【参考方案7】:

如果您的页面上只有一组这些,Pablo 的回答会非常有效。我在尝试解决引导程序实现时遇到了这个问题,这给我带来了一些麻烦,因为单选按钮已被完全覆盖,事实证明将复选框用作单选按钮会更容易。

这是此代码的一个版本,它通过引用调用元素的第二个类来允许多个集合。

$('input.unique').each(function() 
  $(this).on('touchstart click', function() 
    var secondClass = $(event.target).attr('class').split(' ')[1];
    $('input.' + secondClass).not(this).removeAttr('checked');
  );
);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input type='checkbox' name='mygroup1' value='1' class='unique check1'>
<input type='checkbox' name='mygroup2' value='2' class='unique check1'>
<input type='checkbox' name='mygroup3' value='3' class='unique check1'>
<br>
<hr>
<input type='checkbox' name='mygroup1' value='1' class='unique check2'>
<input type='checkbox' name='mygroup2' value='2' class='unique check2'>
<input type='checkbox' name='mygroup3' value='3' class='unique check2'>

JSFiddle

【讨论】:

【参考方案8】:

此现场演示说明 Radio Button 可以执行您想要的操作:

http://jsfiddle.net/ftnwg8yf/

function selectiongrp_control( s_selectiongrpName, b_useJQueryUiThemeToDecorate )

	var ADF_THIS_IS_LAST_SELECTED_ATTR='adf_this-is-last-selected-attr'
	var ADF_THIS_IS_LAST_SELECTED_VALUE='adf_this-is-last-selected-val';

	if ( !s_selectiongrpName ) return -1;

	$( '#fieldset-' + s_selectiongrpName + '-result' ).hide();
	if( b_useJQueryUiThemeToDecorate )   $( '#jQueryUi-' + s_selectiongrpName).buttonset();

	$( 'input[name=' + s_selectiongrpName + ']' ).each( function()
	
		$( this ).on( 'click', function()
		
			if( $( this ).attr( ADF_THIS_IS_LAST_SELECTED_ATTR ) )
			
				$( this ).removeAttr( 'checked' );
				$( this ).removeAttr( ADF_THIS_IS_LAST_SELECTED_ATTR );
			 else
			
				$( this ).attr( ADF_THIS_IS_LAST_SELECTED_ATTR, ADF_THIS_IS_LAST_SELECTED_VALUE );
			

			$( 'input[name=' + s_selectiongrpName + ']' ).not( this ).removeAttr( ADF_THIS_IS_LAST_SELECTED_ATTR );
			if( b_useJQueryUiThemeToDecorate )   $( '#jQueryUi-' + s_selectiongrpName ).buttonset( 'refresh' );

			if( $( 'input[name=' + s_selectiongrpName + ']:checked' ).length > 0 )
			
				$( '#fieldset-' + s_selectiongrpName + '-resultarea' ).html( 'You have selected : [' + $( this ).val() + '].');
			 else
			
				$( '#fieldset-' + s_selectiongrpName + '-resultarea' ).html( 'Nothing is selected.' );
			
			$( '#fieldset-' + s_selectiongrpName + '-result' ).show();
		);
	);


$( document ).ready( function() 
	var ADF_USE_JQUERYUI_THEME_TO_DECORATE=true;
	selectiongrp_control( 'selectiongrp-01', !ADF_USE_JQUERYUI_THEME_TO_DECORATE );
	selectiongrp_control( 'selectiongrp-02', ADF_USE_JQUERYUI_THEME_TO_DECORATE );
);
<!-- Load jQuery core library -->
<script type='text/javascript' src='http://code.jquery.com/jquery-2.1.4.min.js'></script>

<!-- Load jQueryUI library-->
<script type='text/javascript' src='http://code.jquery.com/ui/1.11.4/jquery-ui.js'></script>

<!-- Load jQueryUI Theme library (make either one effective) -->
<!--
<link rel="stylesheet" type="text/css" href='http://code.jquery.com/ui/1.11.4/themes/ui-lightness/jquery-ui.css'>
<link rel="stylesheet" type="text/css" href='http://code.jquery.com/ui/1.11.4/themes/ui-darkness/jquery-ui.css'>
<link rel="stylesheet" type="text/css" href='http://code.jquery.com/ui/1.11.4/themes/blitzer/jquery-ui.css'>
<link rel="stylesheet" type="text/css" href='http://code.jquery.com/ui/1.11.4/themes/eggplant/jquery-ui.css'>
<link rel="stylesheet" type="text/css" href='http://code.jquery.com/ui/1.11.4/themes/flick/jquery-ui.css'>
<link rel="stylesheet" type="text/css" href='http://code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css'>
<link rel="stylesheet" type="text/css" href='http://code.jquery.com/ui/1.11.4/themes/sunny/jquery-ui.css'>
-->
<link rel="stylesheet" type="text/css" href='http://code.jquery.com/ui/1.11.4/themes/redmond/jquery-ui.css'>



<h3>Plain (without styling/decoration):</h3>
<fieldset id='fieldset-selectiongrp-01'>
	<legend>Please <b>click</b> to <b>select</b> or <b>re-click</b> to <b>deselect</b> </legend>
	<span id='jQueryUi-selectiongrp-01'>
		<input type='radio' name='selectiongrp-01' value='Yes' id='selectiongrp-01-option-Y'/><label for='selectiongrp-01-option-Y'>Yes</label>
		<input type='radio' name='selectiongrp-01' value='No' id='selectiongrp-01-option-N'/><label for='selectiongrp-01-option-N'>No</label>
		<input type='radio' name='selectiongrp-01' value='Unknown' id='selectiongrp-01-option-U' /><label for='selectiongrp-01-option-U'>Unknown</label>
	</span>
</fieldset>
<fieldset id='fieldset-selectiongrp-01-result'>
	<legend>Result</legend>
	<span id='fieldset-selectiongrp-01-resultarea'></span>
</fieldset>

<br/>

<h3>Decorated by &quot;jQueryUI Theme&quot;:</h3>
<fieldset id='fieldset-selectiongrp-02'>
	<legend>Please <b>click</b> to <b>select</b> or <b>re-click</b> to <b>deselect</b> </legend>
	<span id='jQueryUi-selectiongrp-02'>
		<input type='radio' name='selectiongrp-02' value='Yes' id='selectiongrp-02-option-Y'/><label for='selectiongrp-02-option-Y'>Yes</label>
		<input type='radio' name='selectiongrp-02' value='No' id='selectiongrp-02-option-N'/><label for='selectiongrp-02-option-N'>No</label>
		<input type='radio' name='selectiongrp-02' value='Unknown' id='selectiongrp-02-option-U' /><label for='selectiongrp-02-option-U'>Unknown</label>
	</span>
</fieldset>
<fieldset id='fieldset-selectiongrp-02-result'>
	<legend>Result</legend>
	<span id='fieldset-selectiongrp-02-resultarea'></span>
</fieldset>

【讨论】:

这似乎是相当多的代码。您介意解释一下它的好处吗?它如何比现有答案更好地解决原始问题?【参考方案9】:

基于“单选按钮组”的原始行为,即在同一组中只能选择一个单选按钮,“单选按钮方法”始终优于“复选框方法”,因为它有助于防止异常数据提交JavaScript 或 jQuery 编码的事件无法正常加载。

那么,我们要解决的唯一挑战就是让选中的单选按钮成为“可取消选择”。

所以,这里有一个例子表明,通过使用额外的 JavaScript 控件,仍然可以取消选择单选按钮。本示例使用 jQuery 作为主要的 JavaScript 框架。

JSFiddle.net 也提供在线版本: http://jsfiddle.net/0fbef3up/

本示例考虑了在 JavaScript 或 jQuery 编码未加载的情况下应对意外情况,因此提供了“意外选项项”。为了了解这种特殊情况将如何以及应急措施如何发挥作用,您可以通过注释/删除相关代码行来简单地省略jQuery库的加载:

<script type='text/javascript' src='http://code.jquery.com/jquery-2.1.4.min.js'></script>

以下是用于演示的完整 HTML/JavaScript 代码。本质在JavaScript函数'selectiongrp_logicControl',大家可以学习参考。

第一个编码帧的 JavaScript(即控制/模型层)和第二个编码帧的 HTML(即表示层):

function selectiongrp_logicControl( s_selectiongrpName, b_useJQueryUiThemeToDecorate )

	// Safeguard measure: If the mandatory function parameter is undefined or empty, nothing can be proceed further, so quit the current function with excit code:
	if ( !s_selectiongrpName ) return -1;


	// Define a constant for future use:
	var ADF_THIS_IS_LAST_SELECTED='adf_this-is-last-selected';

	// Hide the 'contingent select option item' and all its relevant ancillary objects (i.e. the label element):
	$( '#' + s_selectiongrpName + '-option-X' ).hide();
	$( '#' + s_selectiongrpName + '-option-X' ).next( 'label' ).hide();

	// Decorate the selection group option items and their labels by applying the jQueryUI 'buttonset' function:
	if( b_useJQueryUiThemeToDecorate )   $( '#jQueryUi-' + s_selectiongrpName).buttonset();

	// Loop for each option item within the selection group:
	$( 'input[name=' + s_selectiongrpName + ']' ).each( function()
	
		// Define an 'onClick' event for every option item within the selection group:
		$( this ).on( 'click', function()
		
			// If the option item being clicked is the last selected one, then de-select such item.
			// Two ways can achieve de-selection, apply either one below to adapt to your programming style or desired controller mechanism.

			if( $( this ).attr( ADF_THIS_IS_LAST_SELECTED ) )
			
				// Way[1]: Force selecting another item within the same selection group.
				// This Way entails the 'contingent select option item'.  So, if you consider such 'contingent select option item' is unnecessary/inappropriate to your programming style or controller mechanism, please don't choose this Way.
				// (Note: Such 'contingent select option item' was deliberately hidden at the outset).
				// $( '#' + s_selectiongrpName + '-option-X' ).prop( 'checked', true );

				// Way[2]: Simply remove the current item's "checked" attribute:
				$( this ).removeAttr( 'checked' );

				// Both Way[1] and Way[2]: Remove the additional attribute from the item being clicked.
				$( this ).removeAttr( ADF_THIS_IS_LAST_SELECTED );
			 else
			
				// Apply an additional attribute to the item being clicked.  This additional attribe functioned as a secret hint for internal reference to signify the item was the last seledcted one:
				$( this ).attr( ADF_THIS_IS_LAST_SELECTED, ADF_THIS_IS_LAST_SELECTED );
			
			// Other than the item being clicked, all other items (i.e. denotes by the jQuery 'not( this )' selector) should have removed such additional attribute:
			$( 'input[name=' + s_selectiongrpName + ']' ).not( this ).removeAttr( ADF_THIS_IS_LAST_SELECTED );

			// Force the jQueryUI engine to re-render the decoration to reflect the latest selection by applying the 'buttonset' function again ( provide the 'refresh' parameter ):
			if( b_useJQueryUiThemeToDecorate )   $( '#jQueryUi-' + s_selectiongrpName ).buttonset( 'refresh' );

			// Lastly, this is an optional step, refresh the Result Area for displaying user's latest selection on specific screen area:
			selectiongrp_visualControl_refreshResultArea( s_selectiongrpName );
		);
	);




function selectiongrp_visualControl_refreshResultArea( s_selectiongrpName )

	// Safeguard measure: If the mandatory function parameter is undefined or empty, nothing can be proceed further, so quit the current function with excit code:
	if( !s_selectiongrpName )   return -1;


	var adf_resultArea_string;
	var ADF_RESULTAREA_STRING_NOTHING_SELECTED='Nothing is selected';

	// If Way[1] is adopted:
	if( $( '#' + s_selectiongrpName + '-option-X' ).prop( 'checked' ) )
	
		adf_resultArea_string=ADF_RESULTAREA_STRING_NOTHING_SELECTED;
	 else // If Way[2] is adopted:
	
		// If some option items are selected within the selection group:
		if( $( 'input[name=' + s_selectiongrpName + ']:checked' ).length > 0 )
		
			adf_resultArea_string='You have selected : [' + $( 'input[name=' + s_selectiongrpName + ']:checked' ).next( 'label' ).text() + ']';
		 else
		
			adf_resultArea_string=ADF_RESULTAREA_STRING_NOTHING_SELECTED;
		
	

	$( '#fieldset-' + s_selectiongrpName + '-resultarea' ).html( adf_resultArea_string );
	$( '#fieldset-' + s_selectiongrpName + '-result' ).show();


$( document ).ready( function()

	var ADF_USE_JQUERYUI_THEME_TO_DECORATE=true;
	selectiongrp_logicControl( 'selectiongrp-01', !ADF_USE_JQUERYUI_THEME_TO_DECORATE );
	selectiongrp_logicControl( 'selectiongrp-02', ADF_USE_JQUERYUI_THEME_TO_DECORATE );

	// If jQuery can be loaded properly, the error message must be hidden:
	$( '#jquery-compatibility-error' ).hide();
);
<!-- Load jQuery core library -->
<script type='text/javascript' src='http://code.jquery.com/jquery-2.1.4.min.js'></script>

<!-- Load jQueryUI library -->
<script type='text/javascript' src='http://code.jquery.com/ui/1.11.4/jquery-ui.min.js'></script>

<!-- Load jQueryUI Theme library (make either one effective) -->
<!--
<link rel="stylesheet" type="text/css" href='http://code.jquery.com/ui/1.11.4/themes/ui-lightness/jquery-ui.min.css'/>
<link rel="stylesheet" type="text/css" href='http://code.jquery.com/ui/1.11.4/themes/ui-darkness/jquery-ui.min.css'/>
<link rel="stylesheet" type="text/css" href='http://code.jquery.com/ui/1.11.4/themes/blitzer/jquery-ui.min.css'/>
<link rel="stylesheet" type="text/css" href='http://code.jquery.com/ui/1.11.4/themes/eggplant/jquery-ui.min.css'/>
<link rel="stylesheet" type="text/css" href='http://code.jquery.com/ui/1.11.4/themes/flick/jquery-ui.min.css'/>
<link rel="stylesheet" type="text/css" href='http://code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.min.css'/>
<link rel="stylesheet" type="text/css" href='http://code.jquery.com/ui/1.11.4/themes/sunny/jquery-ui.min.css'/>
-->
<link rel='stylesheet' type='text/css' href='http://code.jquery.com/ui/1.11.4/themes/redmond/jquery-ui.min.css'>


This webpage is primarily to demonstrate de-selectable radio boxes.

<h3 id='jquery-compatibility-error'>ERROR: It was detected that JavaScript or jQuery coding does not load properly, so some advance feature cannot be realised.</h3>

<h3>Style1: Raw (i.e. no styling/decoration):</h3>
<fieldset id='fieldset-selectiongrp-01'>
	<legend>Please <b>click</b> to <b>select</b> or <b>re-click</b> to <b>deselect</b></legend>
	<span id='jQueryUi-selectiongrp-01'>
		<input type='radio' name='selectiongrp-01' value='X' id='selectiongrp-01-option-X' checked/><label for='selectiongrp-01-option-X'>None/NULL/Non-Selected <small><small>(This option is provided for contingency purpose in case JavaScript or jQuery does not load)</small></small></label>
		<input type='radio' name='selectiongrp-01' value='Y' id='selectiongrp-01-option-Y'/><label for='selectiongrp-01-option-Y'>Yes</label>
		<input type='radio' name='selectiongrp-01' value='N' id='selectiongrp-01-option-N'/><label for='selectiongrp-01-option-N'>No</label>
		<input type='radio' name='selectiongrp-01' value='U' id='selectiongrp-01-option-U' /><label for='selectiongrp-01-option-U'>Unknown</label>
	</span>
</fieldset>
<fieldset id='fieldset-selectiongrp-01-result' style='display:none'>  <!-- Initaially hidden by using stylesheet attribute "style='display:none'"-->
	<legend>Selection</legend>
	<span id='fieldset-selectiongrp-01-resultarea'><br/></span>
</fieldset>

<br/>

<h3>Style2: Decorated by &quot;jQueryUI Theme&quot; <small><small>(jQueryUI Theme adopted: '<i>Redmond</i>')</small></small>:</h3>
<fieldset id='fieldset-selectiongrp-02'>
	<legend>Please <b>click</b> to <b>select</b> or <b>re-click</b> to <b>deselect</b></legend>
	<span id='jQueryUi-selectiongrp-02'>
		<input type='radio' name='selectiongrp-02' value='X' id='selectiongrp-02-option-X' checked/><label for='selectiongrp-02-option-X'>None/NULL/Non-Selected <small><small>(This option is provided for contingency purpose in case JavaScript or jQuery does not load)</small></small></label>
		<input type='radio' name='selectiongrp-02' value='Y' id='selectiongrp-02-option-Y'/><label for='selectiongrp-02-option-Y'>Yes</label>
		<input type='radio' name='selectiongrp-02' value='N' id='selectiongrp-02-option-N'/><label for='selectiongrp-02-option-N'>No</label>
		<input type='radio' name='selectiongrp-02' value='U' id='selectiongrp-02-option-U' /><label for='selectiongrp-02-option-U'>Unknown</label>
	</span>
</fieldset>
<fieldset id='fieldset-selectiongrp-02-result'style='display:none;'>  <!-- Initaially hidden by using stylesheet attribute "style='display:none'"-->
	<legend>Selection</legend>
	<span id='fieldset-selectiongrp-02-resultarea'><br/></span>
</fieldset>

【讨论】:

以上是关于jQuery - 复选框,如单选按钮的主要内容,如果未能解决你的问题,请参考以下文章

如何用jquery美化单选按钮和复选框

jQuery 验证,将错误消息放在复选框和单选按钮组下方

jQuery:使复选框像单选按钮一样?

简单的jquery模仿单选按钮效果

jQuery怎样判断按钮是不是被选中

jquery Tree 如何设置单选