根据复选框

时间:2017-12-07 10:14:44

标签: javascript html select checkbox optgroup

所以基本上我想要一个类似于这个问题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();
        });
});

2 个答案:

答案 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>

JS Fiddle demo

或者,可以很容易地重写上述内容以使用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>

JS Fiddle demo

参考文献: