所以基本上我想要一个类似于这个问题here的解决方案,但需要&#34; master&#34;是<checkbox>
而不是<select>
例如,我有四个复选框和一个带有四个optgroup的选择。我想只显示这些选中的选项组
我是javascript的新手,无法想到解决方案。我尝试调整我发布的问题的解决方案,但没有成功。我也无法在互联网上找到完全相同的问题
谢谢你的帮助。
修改
这是代码(尽管多余的imo):
<input type="checkbox" id="1" name="serviceType" checked="checked" />
<label for="1">Application</label>
<input type="checkbox" id="2" name="serviceType" />
<label for="2">Infrastructure Service</label>
<input type="checkbox" id="3" name="serviceType" />
<label for="3">Platform</label>
<input type="checkbox" id="4" name="serviceType" checked="checked" />
<label for="4">Software</label>
<select name="services">
<optgroup label="Application"> <!-- Shown -->
<option value="Office">Office</option>
<option value="SAP">SAP</option>
</optgroup>
<optgroup label="Infrastructure Service"> <!-- Hidden -->
<option value="Router">Router</option>
<option value="Switch">Switch</option>
</optgroup>
<optgroup label="Platform"> <!-- Hidden -->
<option value="Server">Server</option>
<option value="Client">Client</option>
</optgroup>
<optgroup label="Software"> <!-- Shown -->
<option value="Word">Word</option>
<option value="Excel">Excel</option>
</optgroup>
</select>
当然,它应该根据改变的选择进行自我调整 这里是Javascript(ctrl + c,ctrl + v来自其他问题):
$(document).ready(function () {
$("checkbox[name='serviceType']:eq(0)").on("change",
function () {
console.log(this.value);
$("select[name='services']:eq(0)")
.find("optgroup,option")
.hide()
.filter("[label='" + this.value + "'],[label = '" + this.value + "'] > *")
.show();
});
});
答案 0 :(得分:0)
CSS替代方案(但我建议使用valid identifiers代替数字):
[id="1"]:not(:checked) ~ select > [label=Application],
[id="2"]:not(:checked) ~ select > [label="Infrastructure Service"],
[id="3"]:not(:checked) ~ select > [label=Platform],
[id="4"]:not(:checked) ~ select > [label=Software] { display: none; }
<input type="checkbox" id="1" name="serviceType" checked>
<label for="1">Application</label>
<input type="checkbox" id="2" name="serviceType">
<label for="2">Infrastructure Service</label>
<input type="checkbox" id="3" name="serviceType">
<label for="3">Platform</label>
<input type="checkbox" id="4" name="serviceType" checked>
<label for="4">Software</label>
<br>
<select name="services" size=10 style="width: 166px">
<optgroup label="Application"> <!-- Shown -->
<option value="Office">Office</option>
<option value="SAP">SAP</option>
</optgroup>
<optgroup label="Infrastructure Service"> <!-- Hidden -->
<option value="Router">Router</option>
<option value="Switch">Switch</option>
</optgroup>
<optgroup label="Platform"> <!-- Hidden -->
<option value="Server">Server</option>
<option value="Client">Client</option>
</optgroup>
<optgroup label="Software"> <!-- Shown -->
<option value="Word">Word</option>
<option value="Excel">Excel</option>
</optgroup>
</select>
可能需要JavaScript来取消选择未显示的选项:
services.value = ''
document.onclick = function(e) { if (e.target.checked === false) services.value = '' }
[id="1"]:not(:checked) ~ select > [label=Application],
[id="2"]:not(:checked) ~ select > [label="Infrastructure Service"],
[id="3"]:not(:checked) ~ select > [label=Platform],
[id="4"]:not(:checked) ~ select > [label=Software] { display: none; }
<input type="checkbox" id="1" name="serviceType" checked>
<label for="1">Application</label>
<input type="checkbox" id="2" name="serviceType">
<label for="2">Infrastructure Service</label>
<input type="checkbox" id="3" name="serviceType">
<label for="3">Platform</label>
<input type="checkbox" id="4" name="serviceType" checked>
<label for="4">Software</label>
<br>
<select id="services">
<optgroup label="Application"> <!-- Shown -->
<option value="Office">Office</option>
<option value="SAP">SAP</option>
</optgroup>
<optgroup label="Infrastructure Service"> <!-- Hidden -->
<option value="Router">Router</option>
<option value="Switch">Switch</option>
</optgroup>
<optgroup label="Platform"> <!-- Hidden -->
<option value="Server">Server</option>
<option value="Client">Client</option>
</optgroup>
<optgroup label="Software"> <!-- Shown -->
<option value="Word">Word</option>
<option value="Excel">Excel</option>
</optgroup>
</select>
答案 1 :(得分:0)
最简单的解决方案,使用jQuery,我能想到的是:
// selecting all <input> elements whose 'type' attribute
// is equal to 'checkbox,' binding an event-listener to
// the 'change' event on those elements which executes the
// supplied anonymous function:
$('input[type=checkbox]').on('change', function() {
// here we first find the <label> element(s) which are
// attached (via either the 'for' attribute-value or by
// nesting the <input> within the <label> element); we
// check that this labels property is true/truthy using
// a ternary operator. If there are <label> elements
// available via the labels property, we select the first
// otherwise we select the nextElementSibling of the
// <input> (this approach does require a predictable HTML)
// and will require change should the structure change:
let label = this.labels.length ? this.labels[0] : this.nextElementSibling;
// here select the <optgroup> element(s) whose 'label'
// attribute-value is equal to the text of the <label>
// element's textContent property, with leading and
// trailing white-space removed (using String.prototype.trim():
$('optgroup[label="' + label.textContent.trim() + '"]')
// we then toggle the display of the retrieved elements,
// using the supplied switch (this.checked), which will
// show elements if 'this.checked' evaluates to true, and
// hide them if it evaluates to false:
.toggle(this.checked);
// here we trigger the 'change' event on the elements matching
// the initial selector, in order to hide, or show, the relevant
// <optgroup> elements on page-load:
}).change();
$('input[type=checkbox]').on('change', function() {
let label = this.labels.length ? this.labels[0] : this.nextElementSibling;
$('optgroup[label="' + label.textContent.trim() + '"]').toggle(this.checked);
}).change();
label::after {
content: '';
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="checkbox" id="1" name="serviceType" checked="checked" />
<label for="1">Application</label>
<input type="checkbox" id="2" name="serviceType" />
<label for="2">Infrastructure Service</label>
<input type="checkbox" id="3" name="serviceType" />
<label for="3">Platform</label>
<input type="checkbox" id="4" name="serviceType" checked="checked" />
<label for="4">Software</label>
<select name="services">
<optgroup label="Application">
<!-- Shown -->
<option value="Office">Office</option>
<option value="SAP">SAP</option>
</optgroup>
<optgroup label="Infrastructure Service">
<!-- Hidden -->
<option value="Router">Router</option>
<option value="Switch">Switch</option>
</optgroup>
<optgroup label="Platform">
<!-- Hidden -->
<option value="Server">Server</option>
<option value="Client">Client</option>
</optgroup>
<optgroup label="Software">
<!-- Shown -->
<option value="Word">Word</option>
<option value="Excel">Excel</option>
</optgroup>
</select>
或者,可以很容易地重写上述内容以使用DOM API或“普通”JavaScript:
// here we create a named function to handle the
// events:
function toggleIfChecked() {
// we cache the 'this' element node, supplied from
// EventTarget.addEventListener():
let el = this,
// as before we retrieve the relevant <label> element,
// and, as before, it's equally fragile should the
// HTML structure change:
label = el.labels.length ? el.labels[0] : el.nextElementSibling,
// we retrieve the relevant textContent from the <label>,
// and - again - remove leading/trailing white-space:
text = label.textContent.trim(),
// here we hard-code the relevant <select> element within
// which to search, retrieving it via
// document.querySelector() which retrieves the first
// element matching the supplied selector or, if no
// such element is found, returns null:
select = document.querySelector('select[name=services]');
// we use Array.from() to convert the Array-like NodeList
// returned from wrapped call to document.querySelectorAll()
// into an Array, which allows us to use Array methods on
// the returned Array of element nodes:
Array.from(
// as above we retrieve all <optgroup> elements whose
// 'label' attribute is equal to the textContent retrieved
// earlier:
select.querySelectorAll('optgroup[label="' + text + '"]')
// using Array.prototype.forEach() to iterate over the
// Array of nodes, using arrow function syntax:
).forEach(
// 'optgroup' is the current element node of the Array of
// elements over which we're iterating; the ternary operator
// returns 'block' (if the changed-<input> element is checked)
// or 'none' (if the changed-<input> element is not checked);
// this allows us to set the display property of the
// <optgroup>'s 'style' CSSStyleDeclarationObject according
// to the un/checked state of the changed-<input> element:
optgroup => optgroup.style.display = el.checked ? 'block' : 'none'
);
}
// creating an Event Object to refer to the 'change' event:
let changeEvent = new Event('change');
// using Array.from() again, to convert the nodeList
// from document.querySelectorAll() into an Array of
// nodes in order to use Array.prototype.forEach():
Array.from(
// selecting all <input> elements whose type is set
// to 'checkbox':
document.querySelectorAll('input[type=checkbox]')
// iterating over the Array:
).forEach(
// 'input' is the current <input> element of the Array of
// <input> elements within the Array over which we're
// iterating:
input => {
// because we're performing multiple actions in this
// Arrow function expression, we're wrapping those
// actions - or statements - in a block-scope;
// first: we bind the toggleIfChecked() (note the lack
// of parentheses in the call to addEventListener()),
// to handle the 'change' event on the <input> element:
input.addEventListener('change', toggleIfChecked);
// then we dispatch the changeEvent Event object
// in order to trigger that event-listener; causing
// the function to be fired on page-load, and setting
// the visibility of the relevant <optgroup> to the
// appropriate state (shown or hidden):
input.dispatchEvent(changeEvent);
}
);
function toggleIfChecked() {
let el = this,
label = el.labels.length ? el.labels[0] : el.nextElementSibling,
text = label.textContent.trim(),
select = document.querySelector('select[name=services]');
Array.from(
select.querySelectorAll('optgroup[label="' + text + '"]')
).forEach(
optgroup => optgroup.style.display = el.checked ? 'block' : 'none'
);
}
let changeEvent = new Event('change');
Array.from(
document.querySelectorAll('input[type=checkbox]')
).forEach(
input => {
input.addEventListener('change', toggleIfChecked);
input.dispatchEvent(changeEvent);
}
);
label::after {
content: '';
display: block;
}
<input type="checkbox" id="1" name="serviceType" checked="checked" />
<label for="1">Application</label>
<input type="checkbox" id="2" name="serviceType" />
<label for="2">Infrastructure Service</label>
<input type="checkbox" id="3" name="serviceType" />
<label for="3">Platform</label>
<input type="checkbox" id="4" name="serviceType" checked="checked" />
<label for="4">Software</label>
<select name="services">
<optgroup label="Application">
<!-- Shown -->
<option value="Office">Office</option>
<option value="SAP">SAP</option>
</optgroup>
<optgroup label="Infrastructure Service">
<!-- Hidden -->
<option value="Router">Router</option>
<option value="Switch">Switch</option>
</optgroup>
<optgroup label="Platform">
<!-- Hidden -->
<option value="Server">Server</option>
<option value="Client">Client</option>
</optgroup>
<optgroup label="Software">
<!-- Shown -->
<option value="Word">Word</option>
<option value="Excel">Excel</option>
</optgroup>
</select>
参考文献:
Array.from()
。Array.forEach()
。document.querySelector()
。document.querySelectorAll()
。Event()
。EventTarget.addEventListener()
。EventTarget.dispatchEvent()
。HTMLElement.style
。HTMLInputElement.labels
property。Node.textContent
。NodeList.length
。NonDocumentTypeChildNode.nextElementSibling
。String.prototype.trim()
。