Javascript 到 Select 有限制的多个选项
Javascript to Select Multiple options with restrictions
我需要一个包含多个步骤的表单,其中第一步限制后续步骤中的选项。
下面是一个使用示例:
用户 select 来自 4 个全局选项
- 如果用户 selects 选项 1
- 然后用户只能select 8个选项(不多也不少)从一个多选框。
- 如果用户select选项2
- 那么用户只能从多选框中select10个选项(不多也不少)。
- 选项3和4也是如此
完成所有这些 select 之后,此表格必须根据用户在第一步 select 中输入的选项显示最终价格。无论在连续的步骤中 select 做了什么选择。
当此表单显示最终价格时,用户必须单击“提交”按钮并通过电子邮件发送包含所有这些选项的结果。
有人可以帮我弄清楚执行此操作所需的 javascript 吗?现在对我来说最重要的事情是在多个项目选择框中找出 'restrictions codes'。
这是我正在考虑的形式:
<form action="" id="menuform" onsubmit="return false;">
<fieldset>
<legend>Select one of this four menus</legend>
<label >Menu Option</label>
<input type="radio" name="selectedmenu" value="Menu1"
onclick="calculateTotal()" />
Menu 1 - serves 8 courses ()
<input type="radio" name="selectedmenu" value="Menu2"
onclick="calculateTotal()" />
Menu 2 - serves 12 courses ()
<input type="radio" name="selectedmenu" value="Menu3"
onclick="calculateTotal()" />
Menu 3 - serves 16 courses ()
<input type="radio" name="selectedmenu" value="Menu4"
onclick="calculateTotal()" />
Menu 4 - serves 30 courses ()
<label >Filling</label>
<select id="filling" name='filling'
onchange="calculateTotal()">
<option value="dish1">Dish 1 ()</option>
<option value="dish2">Dish 2 ()</option>
<option value="dish3">Dish 3 ()</option>
(more...)
</select>
<br/>
<div id="totalPrice"></div>
</fieldset>
</form>
然后,对于 Javascript 代码,我尝试用它来存储和 return 一些值,但我的问题是如何强制 select 第二个选项中的确切数量步骤:
var menu_prices = new Array();
menu_prices["Menu1"]=20;
menu_prices["Menu2"]=25;
menu_prices["Menu3"]=35;
menu_prices["Menu4"]=75;
function getMenuPrice()
{
var menuPrice=0;
var theForm = document.forms["menuform"];
var selectedMenu = theForm.elements["selectedmenu"];
for(var i = 0; i < selectedMenu.length; i++)
{
if(selectedMenu[i].checked)
{
menuPrice = menu_prices[selectedMenu[i].value];
break;
}
}
return menuPrice;
}
function getTotal()
{
var menuPrice = getMenuPrice() + getOtherOptionsPrices();
document.getElementById('totalPrice').innerHTML =
"Total Price For Menu $"+menuPrice;
}
仔细构建您的 HTML 标记,这有助于您轻松地通过 JavaScript 定位元素。特别是,在单选按钮上使用 data-attributes 来获取数量和价格,然后可以在相应的事件处理程序中轻松检索这些按钮。像这样:
<form action="" method="post" id="menuform" name="menuform">
<fieldset>
<legend>Select menu option</legend>
<label>
<input type="radio" name="selectedmenu" checked value="menu01" data-qty='3' data-price='20' />
<span>1 - serves 3 courses ()</span>
</label>
...
<fieldset>
<legend id='fillingsPrompt'>Select fillings</legend>
<select id="fillings" name="fillings" size="6" multiple>
<option value="1">Dish 1 ()</option>
...
<fieldset>
<legend>Checkout</legend>
<div id="totalPrice"></div>
<input type="submit" value="Submit" />
</fieldset>
<fieldset>
<legend>Messages</legend>
<p id="result"></p>
</fieldset>
</form>
确定并select您需要的所有元素:
var menuform = document.getElementById('menuform'),
radios = document.getElementsByName('selectedmenu'),
fillings = document.getElementById('fillings'),
fillingsPrompt = document.getElementById('fillingsPrompt'),
totalPrice = document.getElementById('totalPrice'),
result = document.getElementById('result'),
fillingsAllowed = 0, currentSelection = [], currency = '$'
;
将事件侦听器添加到您的单选按钮 select 和提交按钮:
menuform.addEventListener('submit', handleSubmit);
fillings.addEventListener('change', handleFillings);
for (var i = radios.length; i--; ) {
radios[i].addEventListener('change', handleLimit);
}
编写实际的事件处理程序:
// When radio buttons are selected, update parameters for limit
function handleLimit(e) { updateParameters(e.target); }
// When options are selected in the dropdown,
// check against the limit and reset the selection if it exceeds
function handleFillings(e) {
var count = getSelectedCount();
if (count > fillingsAllowed) { resetSelect(); }
else { currentSelection = getSelectedValues(); }
}
// When submit button is clicked,
// check the count of selection against the limit, and
// show appropriate error message
function handleSubmit(e) {
var count = getSelectedCount();
e.preventDefault();
if (count != fillingsAllowed) {
result.textContent = 'Must select exactly ' + fillingsAllowed + ' fillings!';
} else {
result.textContent = 'Ok. ';
}
}
然后对上述处理程序中使用的所有辅助函数进行编码:
function updateParameters(elem) {
// update the limit based on quantity data attribute on radio
fillingsAllowed = elem.getAttribute('data-qty');
// show the amount based on price data-attribute
totalPrice.textContent = 'Amount: ' + currency + elem.getAttribute('data-price');
// show the hint on legend of fieldset for selecting options
fillingsPrompt.textContent = 'Select ' + fillingsAllowed + ' fillings';
}
// iterate options and get count of selected ones
function getSelectedCount() {
var options = fillings.options, count = 0;
for (var i=0; i < options.length; i++) {
if (options[i].selected) count++;
}
return count;
}
// iterate options and get selected values in an array
function getSelectedValues() {
var options = fillings.options, values = [0];
for (var i=0; i < options.length; i++) {
if (options[i].selected) values.push(options[i].value);
}
return values;
}
// remove selection from all options, and
// re-select based on the array used in the previous function
function resetSelect() {
var options = fillings.options;
for (var i=0; i < options.length; i++) {
options[i].selected = false;
if (currentSelection.indexOf(options[i].value) != -1) {
options[i].selected = true;
}
}
}
所有内容放在一起,演示如下所示:
Fiddle: https://jsfiddle.net/abhitalks/L813qudw/
片段:
var menuform = document.getElementById('menuform'),
radios = document.getElementsByName('selectedmenu'),
fillings = document.getElementById('fillings'),
fillingsPrompt = document.getElementById('fillingsPrompt'),
totalPrice = document.getElementById('totalPrice'),
result = document.getElementById('result'),
fillingsAllowed = 0, currentSelection = [], currency = '$'
;
// listen to events
menuform.addEventListener('submit', handleSubmit);
fillings.addEventListener('change', handleFillings);
for (var i = radios.length; i--; ) {
radios[i].addEventListener('change', handleLimit);
}
// event handlers
function handleLimit(e) { updateParameters(e.target); }
function handleFillings(e) {
var count = getSelectedCount();
if (count > fillingsAllowed) { resetSelect(); }
else { currentSelection = getSelectedValues(); }
}
function handleSubmit(e) {
var count = getSelectedCount();
e.preventDefault();
if (count != fillingsAllowed) {
result.textContent = 'Must select exactly ' + fillingsAllowed + ' fillings!';
} else {
result.textContent = 'Ok. ';
}
}
// fire initial update based on the first radio
updateParameters(radios[0]);
// helper functions
function updateParameters(elem) {
fillingsAllowed = elem.getAttribute('data-qty');
totalPrice.textContent = 'Amount: ' + currency + elem.getAttribute('data-price');
fillingsPrompt.textContent = 'Select ' + fillingsAllowed + ' fillings';
}
function getSelectedCount() {
var options = fillings.options, count = 0;
for (var i=0; i < options.length; i++) {
if (options[i].selected) count++;
}
return count;
}
function getSelectedValues() {
var options = fillings.options, values = [0];
for (var i=0; i < options.length; i++) {
if (options[i].selected) values.push(options[i].value);
}
return values;
}
function resetSelect() {
var options = fillings.options;
for (var i=0; i < options.length; i++) {
options[i].selected = false;
if (currentSelection.indexOf(options[i].value) != -1) {
options[i].selected = true;
}
}
}
fieldset {
margin: 1vw; font-family: monospace;
display: inline-block; width: 40vw; vertical-align: top;
}
legend { color: #d33; padding: 0px 4px; }
legend::before { content: '[ '; }
legend::after { content: ' ]'; }
fieldset > label { display: block; margin: 4px 0px; }
fieldset input, fieldset span { vertical-align: middle; }
fieldset > select { width: 100%; font-family: monospace; }
input[type=submit] { margin-top: 12px; }
#totalPrice, #result {
height: 24px; line-height: 24px;
background-color: #dde; padding: 4px;
font-family: monospace;
}
#result { color: #d33; font-family: monospace; }
<form action="" method="post" id="menuform" name="menuform">
<fieldset>
<legend>Select menu option</legend>
<label>
<input type="radio" name="selectedmenu" checked
value="menu01" data-qty='3' data-price='20' />
<span>1 - serves 3 courses ()</span>
</label>
<label>
<input type="radio" name="selectedmenu"
value="menu02" data-qty='4' data-price='25' />
<span>2 - serves 4 courses ()</span>
</label>
<label>
<input type="radio" name="selectedmenu"
value="menu03" data-qty='5' data-price='35' />
<span>3 - serves 5 courses ()</span>
</label>
<label>
<input type="radio" name="selectedmenu"
value="menu04" data-qty='6' data-price='75' />
<span>4 - serves 6 courses ()</span>
</label>
</fieldset>
<fieldset>
<legend id='fillingsPrompt'>Select fillings</legend>
<select id="fillings" name="fillings" size="6" multiple>
<option value="1">Dish 1 ()</option>
<option value="2">Dish 2 ()</option>
<option value="3">Dish 3 ()</option>
<option value="4">Dish 4 ()</option>
<option value="5">Dish 5 ()</option>
<option value="6">Dish 6 ()</option>
</select>
</fieldset>
<fieldset>
<legend>Checkout</legend>
<div id="totalPrice"></div>
<input type="submit" value="Submit" />
</fieldset>
<fieldset>
<legend>Messages</legend>
<p id="result"></p>
</fieldset>
</form>
<hr>
...how can I change <option>
and use <input type="checkbox">
instead for the SECOND STEP?
为了使用复选框而不是 select,不需要进行重大更改。
已更改 mark-up:
<fieldset>
<legend id='fillingsPrompt'>Select fillings</legend>
<label>
<input type='checkbox' name='fillings' value="1" />
<span>Dish 1 ()</span>
</label>
...
JavaScript 变化:
- 为复选框添加 event-handlers 而不是 select,只需要迭代这些:
(就像收音机已经做的一样)
for (var i = fillings.length; i--; ) {
fillings[i].addEventListener('change', handleFillings);
}
- 在所有辅助函数中,删除选项的变量声明:
(因为现在不再需要)
var options = fillings.options
并且,在所有辅助函数中,
更改:options.length
和 options[i].selected
分别为fillings.length
和fillings[i].checked
。
就是这样。
Fiddle 2: https://jsfiddle.net/abhitalks/hp88wdfc/
代码段 2:
var menuform = document.getElementById('menuform'),
radios = document.getElementsByName('selectedmenu'),
fillings = document.getElementsByName('fillings'),
fillingsPrompt = document.getElementById('fillingsPrompt'),
totalPrice = document.getElementById('totalPrice'),
result = document.getElementById('result'),
fillingsAllowed = 0, currentSelection = [], currency = '$'
;
// listen to events
menuform.addEventListener('submit', handleSubmit);
for (var i = fillings.length; i--; ) {
fillings[i].addEventListener('change', handleFillings);
}
for (var i = radios.length; i--; ) {
radios[i].addEventListener('change', handleLimit);
}
// event handlers
function handleLimit(e) { updateParameters(e.target); }
function handleFillings(e) {
var count = getSelectedCount();
if (count > fillingsAllowed) { resetSelect(); }
else { currentSelection = getSelectedValues(); }
}
function handleSubmit(e) {
var count = getSelectedCount();
e.preventDefault();
if (count != fillingsAllowed) {
result.textContent = 'Must select exactly ' + fillingsAllowed + ' fillings!';
} else {
result.textContent = 'Ok. ';
}
}
// fire initial update based on the first radio
updateParameters(radios[0]);
// helper functions
function updateParameters(elem) {
fillingsAllowed = elem.getAttribute('data-qty');
totalPrice.textContent = 'Amount: ' + currency + elem.getAttribute('data-price');
fillingsPrompt.textContent = 'Select ' + fillingsAllowed + ' fillings';
}
function getSelectedCount() {
var count = 0;
for (var i=0; i < fillings.length; i++) {
if (fillings[i].checked) count++;
}
return count;
}
function getSelectedValues() {
var values = [0];
for (var i=0; i < fillings.length; i++) {
if (fillings[i].checked) values.push(fillings[i].value);
}
return values;
}
function resetSelect() {
for (var i=0; i < fillings.length; i++) {
fillings[i].checked = false;
if (currentSelection.indexOf(fillings[i].value) != -1) {
fillings[i].checked = true;
}
}
}
fieldset {
margin: 1vw; font-family: monospace;
display: inline-block; width: 40vw; vertical-align: top;
}
legend { color: #d33; padding: 0px 4px; }
legend::before { content: '[ '; }
legend::after { content: ' ]'; }
fieldset:first-of-type > label { display: block; margin: 4px 0px; }
fieldset:nth-of-type(2) > label {
display: inline-block; width: 45%;
}
fieldset input, fieldset span { vertical-align: middle; }
input[type=submit] { margin-top: 12px; }
#totalPrice, #result {
height: 24px; line-height: 24px;
background-color: #dde; padding: 4px;
font-family: monospace;
}
#result { color: #d33; font-family: monospace; }
<form action="" method="post" id="menuform" name="menuform">
<fieldset>
<legend>Select menu option</legend>
<label>
<input type="radio" name="selectedmenu" checked
value="menu01" data-qty='3' data-price='20' />
<span>1 - serves 3 courses ()</span>
</label>
<label>
<input type="radio" name="selectedmenu"
value="menu02" data-qty='4' data-price='25' />
<span>2 - serves 4 courses ()</span>
</label>
<label>
<input type="radio" name="selectedmenu"
value="menu03" data-qty='5' data-price='35' />
<span>3 - serves 5 courses ()</span>
</label>
<label>
<input type="radio" name="selectedmenu"
value="menu04" data-qty='6' data-price='75' />
<span>4 - serves 6 courses ()</span>
</label>
</fieldset>
<fieldset>
<legend id='fillingsPrompt'>Select fillings</legend>
<label>
<input type='checkbox' name='fillings' value="1" />
<span>Dish 1 ()</span>
</label>
<label>
<input type='checkbox' name='fillings' value="2" />
<span>Dish 2 ()</span>
</label>
<label>
<input type='checkbox' name='fillings' value="3" />
<span>Dish 3 ()</span>
</label>
<label>
<input type='checkbox' name='fillings' value="4" />
<span>Dish 4 ()</span>
</label>
<label>
<input type='checkbox' name='fillings' value="5" />
<span>Dish 5 ()</span>
</label>
<label>
<input type='checkbox' name='fillings' value="6" />
<span>Dish 6 ()</span>
</label>
</fieldset>
<fieldset>
<legend>Checkout</legend>
<div id="totalPrice"></div>
<input type="submit" value="Submit" />
</fieldset>
<fieldset>
<legend>Messages</legend>
<p id="result"></p>
</fieldset>
</form>
<hr>
我需要一个包含多个步骤的表单,其中第一步限制后续步骤中的选项。
下面是一个使用示例:
用户 select 来自 4 个全局选项
- 如果用户 selects 选项 1
- 然后用户只能select 8个选项(不多也不少)从一个多选框。
- 如果用户select选项2
- 那么用户只能从多选框中select10个选项(不多也不少)。
- 选项3和4也是如此
- 如果用户 selects 选项 1
完成所有这些 select 之后,此表格必须根据用户在第一步 select 中输入的选项显示最终价格。无论在连续的步骤中 select 做了什么选择。
当此表单显示最终价格时,用户必须单击“提交”按钮并通过电子邮件发送包含所有这些选项的结果。
有人可以帮我弄清楚执行此操作所需的 javascript 吗?现在对我来说最重要的事情是在多个项目选择框中找出 'restrictions codes'。
这是我正在考虑的形式:
<form action="" id="menuform" onsubmit="return false;">
<fieldset>
<legend>Select one of this four menus</legend>
<label >Menu Option</label>
<input type="radio" name="selectedmenu" value="Menu1"
onclick="calculateTotal()" />
Menu 1 - serves 8 courses ()
<input type="radio" name="selectedmenu" value="Menu2"
onclick="calculateTotal()" />
Menu 2 - serves 12 courses ()
<input type="radio" name="selectedmenu" value="Menu3"
onclick="calculateTotal()" />
Menu 3 - serves 16 courses ()
<input type="radio" name="selectedmenu" value="Menu4"
onclick="calculateTotal()" />
Menu 4 - serves 30 courses ()
<label >Filling</label>
<select id="filling" name='filling'
onchange="calculateTotal()">
<option value="dish1">Dish 1 ()</option>
<option value="dish2">Dish 2 ()</option>
<option value="dish3">Dish 3 ()</option>
(more...)
</select>
<br/>
<div id="totalPrice"></div>
</fieldset>
</form>
然后,对于 Javascript 代码,我尝试用它来存储和 return 一些值,但我的问题是如何强制 select 第二个选项中的确切数量步骤:
var menu_prices = new Array();
menu_prices["Menu1"]=20;
menu_prices["Menu2"]=25;
menu_prices["Menu3"]=35;
menu_prices["Menu4"]=75;
function getMenuPrice()
{
var menuPrice=0;
var theForm = document.forms["menuform"];
var selectedMenu = theForm.elements["selectedmenu"];
for(var i = 0; i < selectedMenu.length; i++)
{
if(selectedMenu[i].checked)
{
menuPrice = menu_prices[selectedMenu[i].value];
break;
}
}
return menuPrice;
}
function getTotal()
{
var menuPrice = getMenuPrice() + getOtherOptionsPrices();
document.getElementById('totalPrice').innerHTML =
"Total Price For Menu $"+menuPrice;
}
仔细构建您的 HTML 标记,这有助于您轻松地通过 JavaScript 定位元素。特别是,在单选按钮上使用 data-attributes 来获取数量和价格,然后可以在相应的事件处理程序中轻松检索这些按钮。像这样:
<form action="" method="post" id="menuform" name="menuform">
<fieldset>
<legend>Select menu option</legend>
<label>
<input type="radio" name="selectedmenu" checked value="menu01" data-qty='3' data-price='20' />
<span>1 - serves 3 courses ()</span>
</label>
...
<fieldset>
<legend id='fillingsPrompt'>Select fillings</legend>
<select id="fillings" name="fillings" size="6" multiple>
<option value="1">Dish 1 ()</option>
...
<fieldset>
<legend>Checkout</legend>
<div id="totalPrice"></div>
<input type="submit" value="Submit" />
</fieldset>
<fieldset>
<legend>Messages</legend>
<p id="result"></p>
</fieldset>
</form>
确定并select您需要的所有元素:
var menuform = document.getElementById('menuform'),
radios = document.getElementsByName('selectedmenu'),
fillings = document.getElementById('fillings'),
fillingsPrompt = document.getElementById('fillingsPrompt'),
totalPrice = document.getElementById('totalPrice'),
result = document.getElementById('result'),
fillingsAllowed = 0, currentSelection = [], currency = '$'
;
将事件侦听器添加到您的单选按钮 select 和提交按钮:
menuform.addEventListener('submit', handleSubmit);
fillings.addEventListener('change', handleFillings);
for (var i = radios.length; i--; ) {
radios[i].addEventListener('change', handleLimit);
}
编写实际的事件处理程序:
// When radio buttons are selected, update parameters for limit
function handleLimit(e) { updateParameters(e.target); }
// When options are selected in the dropdown,
// check against the limit and reset the selection if it exceeds
function handleFillings(e) {
var count = getSelectedCount();
if (count > fillingsAllowed) { resetSelect(); }
else { currentSelection = getSelectedValues(); }
}
// When submit button is clicked,
// check the count of selection against the limit, and
// show appropriate error message
function handleSubmit(e) {
var count = getSelectedCount();
e.preventDefault();
if (count != fillingsAllowed) {
result.textContent = 'Must select exactly ' + fillingsAllowed + ' fillings!';
} else {
result.textContent = 'Ok. ';
}
}
然后对上述处理程序中使用的所有辅助函数进行编码:
function updateParameters(elem) {
// update the limit based on quantity data attribute on radio
fillingsAllowed = elem.getAttribute('data-qty');
// show the amount based on price data-attribute
totalPrice.textContent = 'Amount: ' + currency + elem.getAttribute('data-price');
// show the hint on legend of fieldset for selecting options
fillingsPrompt.textContent = 'Select ' + fillingsAllowed + ' fillings';
}
// iterate options and get count of selected ones
function getSelectedCount() {
var options = fillings.options, count = 0;
for (var i=0; i < options.length; i++) {
if (options[i].selected) count++;
}
return count;
}
// iterate options and get selected values in an array
function getSelectedValues() {
var options = fillings.options, values = [0];
for (var i=0; i < options.length; i++) {
if (options[i].selected) values.push(options[i].value);
}
return values;
}
// remove selection from all options, and
// re-select based on the array used in the previous function
function resetSelect() {
var options = fillings.options;
for (var i=0; i < options.length; i++) {
options[i].selected = false;
if (currentSelection.indexOf(options[i].value) != -1) {
options[i].selected = true;
}
}
}
所有内容放在一起,演示如下所示:
Fiddle: https://jsfiddle.net/abhitalks/L813qudw/
片段:
var menuform = document.getElementById('menuform'),
radios = document.getElementsByName('selectedmenu'),
fillings = document.getElementById('fillings'),
fillingsPrompt = document.getElementById('fillingsPrompt'),
totalPrice = document.getElementById('totalPrice'),
result = document.getElementById('result'),
fillingsAllowed = 0, currentSelection = [], currency = '$'
;
// listen to events
menuform.addEventListener('submit', handleSubmit);
fillings.addEventListener('change', handleFillings);
for (var i = radios.length; i--; ) {
radios[i].addEventListener('change', handleLimit);
}
// event handlers
function handleLimit(e) { updateParameters(e.target); }
function handleFillings(e) {
var count = getSelectedCount();
if (count > fillingsAllowed) { resetSelect(); }
else { currentSelection = getSelectedValues(); }
}
function handleSubmit(e) {
var count = getSelectedCount();
e.preventDefault();
if (count != fillingsAllowed) {
result.textContent = 'Must select exactly ' + fillingsAllowed + ' fillings!';
} else {
result.textContent = 'Ok. ';
}
}
// fire initial update based on the first radio
updateParameters(radios[0]);
// helper functions
function updateParameters(elem) {
fillingsAllowed = elem.getAttribute('data-qty');
totalPrice.textContent = 'Amount: ' + currency + elem.getAttribute('data-price');
fillingsPrompt.textContent = 'Select ' + fillingsAllowed + ' fillings';
}
function getSelectedCount() {
var options = fillings.options, count = 0;
for (var i=0; i < options.length; i++) {
if (options[i].selected) count++;
}
return count;
}
function getSelectedValues() {
var options = fillings.options, values = [0];
for (var i=0; i < options.length; i++) {
if (options[i].selected) values.push(options[i].value);
}
return values;
}
function resetSelect() {
var options = fillings.options;
for (var i=0; i < options.length; i++) {
options[i].selected = false;
if (currentSelection.indexOf(options[i].value) != -1) {
options[i].selected = true;
}
}
}
fieldset {
margin: 1vw; font-family: monospace;
display: inline-block; width: 40vw; vertical-align: top;
}
legend { color: #d33; padding: 0px 4px; }
legend::before { content: '[ '; }
legend::after { content: ' ]'; }
fieldset > label { display: block; margin: 4px 0px; }
fieldset input, fieldset span { vertical-align: middle; }
fieldset > select { width: 100%; font-family: monospace; }
input[type=submit] { margin-top: 12px; }
#totalPrice, #result {
height: 24px; line-height: 24px;
background-color: #dde; padding: 4px;
font-family: monospace;
}
#result { color: #d33; font-family: monospace; }
<form action="" method="post" id="menuform" name="menuform">
<fieldset>
<legend>Select menu option</legend>
<label>
<input type="radio" name="selectedmenu" checked
value="menu01" data-qty='3' data-price='20' />
<span>1 - serves 3 courses ()</span>
</label>
<label>
<input type="radio" name="selectedmenu"
value="menu02" data-qty='4' data-price='25' />
<span>2 - serves 4 courses ()</span>
</label>
<label>
<input type="radio" name="selectedmenu"
value="menu03" data-qty='5' data-price='35' />
<span>3 - serves 5 courses ()</span>
</label>
<label>
<input type="radio" name="selectedmenu"
value="menu04" data-qty='6' data-price='75' />
<span>4 - serves 6 courses ()</span>
</label>
</fieldset>
<fieldset>
<legend id='fillingsPrompt'>Select fillings</legend>
<select id="fillings" name="fillings" size="6" multiple>
<option value="1">Dish 1 ()</option>
<option value="2">Dish 2 ()</option>
<option value="3">Dish 3 ()</option>
<option value="4">Dish 4 ()</option>
<option value="5">Dish 5 ()</option>
<option value="6">Dish 6 ()</option>
</select>
</fieldset>
<fieldset>
<legend>Checkout</legend>
<div id="totalPrice"></div>
<input type="submit" value="Submit" />
</fieldset>
<fieldset>
<legend>Messages</legend>
<p id="result"></p>
</fieldset>
</form>
<hr>
...how can I change
<option>
and use<input type="checkbox">
instead for the SECOND STEP?
为了使用复选框而不是 select,不需要进行重大更改。
已更改 mark-up:
<fieldset>
<legend id='fillingsPrompt'>Select fillings</legend>
<label>
<input type='checkbox' name='fillings' value="1" />
<span>Dish 1 ()</span>
</label>
...
JavaScript 变化:
- 为复选框添加 event-handlers 而不是 select,只需要迭代这些:
(就像收音机已经做的一样)
for (var i = fillings.length; i--; ) {
fillings[i].addEventListener('change', handleFillings);
}
- 在所有辅助函数中,删除选项的变量声明:
(因为现在不再需要)
var options = fillings.options
并且,在所有辅助函数中,
更改:
options.length
和options[i].selected
分别为
fillings.length
和fillings[i].checked
。
就是这样。
Fiddle 2: https://jsfiddle.net/abhitalks/hp88wdfc/
代码段 2:
var menuform = document.getElementById('menuform'),
radios = document.getElementsByName('selectedmenu'),
fillings = document.getElementsByName('fillings'),
fillingsPrompt = document.getElementById('fillingsPrompt'),
totalPrice = document.getElementById('totalPrice'),
result = document.getElementById('result'),
fillingsAllowed = 0, currentSelection = [], currency = '$'
;
// listen to events
menuform.addEventListener('submit', handleSubmit);
for (var i = fillings.length; i--; ) {
fillings[i].addEventListener('change', handleFillings);
}
for (var i = radios.length; i--; ) {
radios[i].addEventListener('change', handleLimit);
}
// event handlers
function handleLimit(e) { updateParameters(e.target); }
function handleFillings(e) {
var count = getSelectedCount();
if (count > fillingsAllowed) { resetSelect(); }
else { currentSelection = getSelectedValues(); }
}
function handleSubmit(e) {
var count = getSelectedCount();
e.preventDefault();
if (count != fillingsAllowed) {
result.textContent = 'Must select exactly ' + fillingsAllowed + ' fillings!';
} else {
result.textContent = 'Ok. ';
}
}
// fire initial update based on the first radio
updateParameters(radios[0]);
// helper functions
function updateParameters(elem) {
fillingsAllowed = elem.getAttribute('data-qty');
totalPrice.textContent = 'Amount: ' + currency + elem.getAttribute('data-price');
fillingsPrompt.textContent = 'Select ' + fillingsAllowed + ' fillings';
}
function getSelectedCount() {
var count = 0;
for (var i=0; i < fillings.length; i++) {
if (fillings[i].checked) count++;
}
return count;
}
function getSelectedValues() {
var values = [0];
for (var i=0; i < fillings.length; i++) {
if (fillings[i].checked) values.push(fillings[i].value);
}
return values;
}
function resetSelect() {
for (var i=0; i < fillings.length; i++) {
fillings[i].checked = false;
if (currentSelection.indexOf(fillings[i].value) != -1) {
fillings[i].checked = true;
}
}
}
fieldset {
margin: 1vw; font-family: monospace;
display: inline-block; width: 40vw; vertical-align: top;
}
legend { color: #d33; padding: 0px 4px; }
legend::before { content: '[ '; }
legend::after { content: ' ]'; }
fieldset:first-of-type > label { display: block; margin: 4px 0px; }
fieldset:nth-of-type(2) > label {
display: inline-block; width: 45%;
}
fieldset input, fieldset span { vertical-align: middle; }
input[type=submit] { margin-top: 12px; }
#totalPrice, #result {
height: 24px; line-height: 24px;
background-color: #dde; padding: 4px;
font-family: monospace;
}
#result { color: #d33; font-family: monospace; }
<form action="" method="post" id="menuform" name="menuform">
<fieldset>
<legend>Select menu option</legend>
<label>
<input type="radio" name="selectedmenu" checked
value="menu01" data-qty='3' data-price='20' />
<span>1 - serves 3 courses ()</span>
</label>
<label>
<input type="radio" name="selectedmenu"
value="menu02" data-qty='4' data-price='25' />
<span>2 - serves 4 courses ()</span>
</label>
<label>
<input type="radio" name="selectedmenu"
value="menu03" data-qty='5' data-price='35' />
<span>3 - serves 5 courses ()</span>
</label>
<label>
<input type="radio" name="selectedmenu"
value="menu04" data-qty='6' data-price='75' />
<span>4 - serves 6 courses ()</span>
</label>
</fieldset>
<fieldset>
<legend id='fillingsPrompt'>Select fillings</legend>
<label>
<input type='checkbox' name='fillings' value="1" />
<span>Dish 1 ()</span>
</label>
<label>
<input type='checkbox' name='fillings' value="2" />
<span>Dish 2 ()</span>
</label>
<label>
<input type='checkbox' name='fillings' value="3" />
<span>Dish 3 ()</span>
</label>
<label>
<input type='checkbox' name='fillings' value="4" />
<span>Dish 4 ()</span>
</label>
<label>
<input type='checkbox' name='fillings' value="5" />
<span>Dish 5 ()</span>
</label>
<label>
<input type='checkbox' name='fillings' value="6" />
<span>Dish 6 ()</span>
</label>
</fieldset>
<fieldset>
<legend>Checkout</legend>
<div id="totalPrice"></div>
<input type="submit" value="Submit" />
</fieldset>
<fieldset>
<legend>Messages</legend>
<p id="result"></p>
</fieldset>
</form>
<hr>