0

我需要一个包含多个步骤的表单,其中第一步限制了后续步骤中的选项。

所以下面是一个使用示例:

  1. 用户从 4 个全局选项中进行选择

    • 如果用户选择选项 1
      • 然后用户只能从多选框中选择 8 个选项(不多不少)。
    • 如果用户选择选项 2
      • 然后用户只能从多选框中选择 10 个选项(不多不少)。
    • 选项 3 和 4 也是如此
  2. 在所有这些选择之后,此表格必须根据用户在第一步中选择的选项显示最终价格。无论在连续的步骤中选择了什么选项。

  3. 当此表格显示最终价格时,用户必须单击提交按钮并通过电子邮件发送此结果以及所有这些选项。

有人可以帮我弄清楚执行此操作所需的 javascript 吗?现在对我来说最重要的是找出多个项目选择框中的“限制代码”。

这是我正在考虑的形式:

<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 ($20)
            <input type="radio"  name="selectedmenu" value="Menu2"
onclick="calculateTotal()" />
        Menu 2 - serves 12 courses ($25)
            <input type="radio"  name="selectedmenu" value="Menu3"
onclick="calculateTotal()" />
        Menu 3 - serves 16 courses ($35)
            <input type="radio"  name="selectedmenu" value="Menu4"
onclick="calculateTotal()" />
        Menu 4 - serves 30 courses ($75)

        <label >Filling</label>
            <select id="filling" name='filling'
onchange="calculateTotal()">
                <option value="dish1">Dish 1 ($1)</option>
                <option value="dish2">Dish 2 ($5)</option>
                <option value="dish3">Dish 3 ($5)</option>
                (more...)
            </select>
        <br/>
        <div id="totalPrice"></div>
    </fieldset>
</form>

然后,对于 Javascript 代码,我尝试使用它来存储和返回一些值,但我的问题是如何在第二步中强制选择确切数量的选项:

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;
}
4

1 回答 1

0

仔细构建您的 HTML 标记,这有助于您轻松地通过 JavaScript 定位元素。特别是,在单选按钮上使用数据属性来表示数量和价格,然后可以在相应的事件处理程序中轻松检索这些属性。像这样的东西:

<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 ($20)</span>
        </label>
        ...
    <fieldset>
        <legend id='fillingsPrompt'>Select fillings</legend>
        <select id="fillings" name="fillings" size="6" multiple>
            <option value="1">Dish 1 ($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>

识别并选择您需要的所有元素:

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 = '$'
;

将事件侦听器添加到您的单选按钮、选择和提交按钮:

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;
        }
    }
}

所有东西放在一起,演示看起来像这样:

小提琴: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 ($20)</span>
		</label>
		<label>
			<input type="radio" name="selectedmenu" 
				value="menu02" data-qty='4' data-price='25' />
			<span>2 - serves 4 courses ($25)</span>
		</label>
		<label>
			<input type="radio" name="selectedmenu" 
				value="menu03" data-qty='5' data-price='35' />
			<span>3 - serves 5 courses ($35)</span>
		</label>
		<label>
			<input type="radio" name="selectedmenu" 
				value="menu04" data-qty='6' data-price='75' />
			<span>4 - serves 6 courses ($75)</span>
		</label>
	</fieldset>
	<fieldset>
		<legend id='fillingsPrompt'>Select fillings</legend>
		<select id="fillings" name="fillings" size="6" multiple>
			<option value="1">Dish 1 ($1)</option>
			<option value="2">Dish 2 ($5)</option>
			<option value="3">Dish 3 ($5)</option>
			<option value="4">Dish 4 ($1)</option>
			<option value="5">Dish 5 ($5)</option>
			<option value="6">Dish 6 ($5)</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>


...我怎样才能改变<option>和使用<input type="checkbox"> 第二步?

为了使用复选框而不是选择,不需要进行重大更改。

更改标记:

<fieldset>
    <legend id='fillingsPrompt'>Select fillings</legend>
    <label>
        <input type='checkbox' name='fillings' value="1" />
        <span>Dish 1 ($5)</span>
    </label>
    ...

JavaScript 更改:

  1. 为复选框添加事件处理程序而不是选择,只需要遍历这些:

就像已经完成的收音机一样

for (var i = fillings.length; i--; ) {
    fillings[i].addEventListener('change', handleFillings);
}
  1. 在所有辅助函数中,删除选项的变量声明:

因为现在不再需要

var options = fillings.options
  1. 而且,在所有辅助函数中,

    改变:options.lengthoptions[i].selected

    到,fillings.lengthfillings[i].checked分别。

而已。

小提琴 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 ($20)</span>
		</label>
		<label>
			<input type="radio" name="selectedmenu" 
				value="menu02" data-qty='4' data-price='25' />
			<span>2 - serves 4 courses ($25)</span>
		</label>
		<label>
			<input type="radio" name="selectedmenu" 
				value="menu03" data-qty='5' data-price='35' />
			<span>3 - serves 5 courses ($35)</span>
		</label>
		<label>
			<input type="radio" name="selectedmenu" 
				value="menu04" data-qty='6' data-price='75' />
			<span>4 - serves 6 courses ($75)</span>
		</label>
	</fieldset>
	<fieldset>
		<legend id='fillingsPrompt'>Select fillings</legend>
		<label>
			<input type='checkbox' name='fillings' value="1" />
			<span>Dish 1 ($5)</span>
		</label>
		<label>
			<input type='checkbox' name='fillings' value="2" />
			<span>Dish 2 ($5)</span>
		</label>
		<label>
			<input type='checkbox' name='fillings' value="3" />
			<span>Dish 3 ($5)</span>
		</label>
		<label>
			<input type='checkbox' name='fillings' value="4" />
			<span>Dish 4 ($5)</span>
		</label>
		<label>
			<input type='checkbox' name='fillings' value="5" />
			<span>Dish 5 ($5)</span>
		</label>
		<label>
			<input type='checkbox' name='fillings' value="6" />
			<span>Dish 6 ($5)</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>


于 2016-01-15T08:45:30.203 回答