3状态CSS切换开关

时间:2014-05-14 18:07:25

标签: javascript jquery css css3

我一直在寻找一个3状态切换开关,但没有太多运气。

基本上我需要一个具有以下状态的开关:  | ON | N / A |关闭|

默认情况下,滑块从中间开始,一旦用户向左或向右滑动,它们就无法返回到N / A(未应答)状态。

任何人都知道如何处理这个问题?

8 个答案:

答案 0 :(得分:30)

尝试这样的事情:

.switch-toggle {
  width: 10em;
}

.switch-toggle label:not(.disabled) {
  cursor: pointer;
}
<link href="https://cdn.jsdelivr.net/css-toggle-switch/latest/toggle-switch.css" rel="stylesheet" />

<div class="switch-toggle switch-3 switch-candy">
  <input id="on" name="state-d" type="radio" checked="" />
  <label for="on" onclick="">ON</label>

  <input id="na" name="state-d" type="radio" disabled checked="checked" />
  <label for="na" class="disabled" onclick="">&nbsp;</label>

  <input id="off" name="state-d" type="radio" />
  <label for="off" onclick="">OFF</label>

  <a></a>
</div>

这将从N/A开始作为默认选项(通过checked="checked"),但稍后会使其无法选择(使用disabled

JSFiddle Demo (简体)

答案 1 :(得分:6)

.switch-toggle {
   float: left;
   background: #242729;
}
.switch-toggle input {
  position: absolute;
  opacity: 0;
}
.switch-toggle input + label {
  padding: 7px;
  float:left;
  color: #fff;
  cursor: pointer;
}
.switch-toggle input:checked + label {
  background: green;
}
 <div class="switch-toggle switch-3 switch-candy">

  <input id="on" name="state-d" type="radio" checked="" />
  <label for="on" onclick="">ON</label>

  <input id="na" name="state-d" type="radio" checked="checked" />
  <label for="na" class="disabled" onclick="">N/A</label>

  <input id="off" name="state-d" type="radio" />
  <label for="off" onclick="">OFF</label>

</div>

答案 2 :(得分:5)

除了gat的回复,还可以通过Bootstrap将其建模为分组单选按钮:

<div class="btn-group" data-toggle="buttons">
    <label class="btn btn-primary">
        <input type="radio" name="options" id="On" />ON</label>
    <label class="btn btn-primary">
        <input type="radio" name="options" id="NA" />N/A</label>
    <label class="btn btn-primary">
        <input type="radio" name="options" id="Off" />OFF</label>
</div>

JSFiddle:http://jsfiddle.net/p7DGe/1/

答案 3 :(得分:5)

作为jQuery插件

function filterme(value) {
  value = parseInt(value, 10); // Convert to an integer
  if (value === 1) {
    $('#RangeFilter').removeClass('rangeAll', 'rangePassive').addClass('rangeActive');
    $('span').text('Active');
  } else if (value === 2) {
    $('#RangeFilter').removeClass('rangeActive', 'rangePassive').addClass('rangeAll');
    $('span').text('All');
  } else if (value === 3) {
    $('#RangeFilter').removeClass('rangeAll', 'rangeActive').addClass('rangePassive');
    $('span').text('Passive');
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p class="range-field" style=" width:60px">
  <input type="range" id="RangeFilter" name="points" onchange="filterme(this.value);" min="1" class="rangeAll" max="3" value="2">
</p>
<span>All</span>

enter image description here

(function($) {
  $.fn.removeClasses = function(classes) {
    return this.removeClass(classes.join(' '));
  };
  $.fn.switchify = function(config) {
    config = config || {};
    var prefix   =           config.prefix   || 'range-';
    var onCls    = prefix + (config.onCls    || 'on'   );
    var offCls   = prefix + (config.offCls   || 'off'  );
    var unsetCls = prefix + (config.unsetCls || 'unset');
    var $self = this;
    return this.on('change', function(e) {
      var value = parseInt(this.value, 10);
      switch (value) {
        case 1  :  return $self.removeClasses([unsetCls, offCls]).addClass(onCls);
        case 2  :  return $self.removeClasses([onCls, offCls]).addClass(unsetCls);
        case 3  :  return $self.removeClasses([onCls, unsetCls]).addClass(offCls);
        default :  return $self;
      }
    });
  };
})(jQuery);

$('#range-filter').switchify({
   onCls    : 'active',
   offCls   : 'passive',
   unsetCls : 'all'
}).on('change', function(e) {
  var $self = $(this);
  if      ($self.hasClass('range-active'))  $('span').text('Active');
  else if ($self.hasClass('range-passive')) $('span').text('Passive');
  else if ($self.hasClass('range-all'))     $('span').text('All');
  else                                      $('span').text('Error!');
});
.range-field { width: 60px; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p class="range-field">
  <input type="range" id="range-filter" name="points" min="1" class="rangeAll" max="3" value="2">
</p>
<span>All</span>

答案 4 :(得分:1)

我创建了一个JSFiddle,演示了一个功能齐全的三态切换器。请注意,JSfiddle中的javascript窗口无法正常工作,因此脚本会在html窗口中加载。

&#13;
&#13;
function togglebutton(range) {
  var val = range.value;
  if (val == 1) {
    //change color of slider background
    range.className = "rangeFalse";

    //alter text 
    $('.toggle-false-msg').attr('id', 'textActive');
    $('.toggle-neutral-msg').attr('id', '');
    $('.toggle-true-msg').attr('id', '');
  } else if (val == 2) {
    //change color of slider background
    range.className = "rangeNeutral";

    //alter text 
    $('.toggle-false-msg').attr('id', '');
    $('.toggle-neutral-msg').attr('id', 'textActive');
    $('.toggle-true-msg').attr('id', '');

  } else if (val == 3) {
    //change color of slider background
    range.className = "rangeTrue";

    //alter text 
    $('.toggle-false-msg').attr('id', '');
    $('.toggle-neutral-msg').attr('id', '');
    $('.toggle-true-msg').attr('id', 'textActive');
  }
}
&#13;
.test_div {
  height: 50px;
  width: 50px;
  background: #204d75 !important;
  top: 100px;
  position: relative;
  display: block;
}

.toggle-container {
  position: relative;
  width: 8em;
  margin: 1em;
  padding: 0.25em;
  border: thin solid lightgrey;
  text-align: center;
}

.range-field {
  display: inline-block;
  width: 100px;
  margin: 0px;
  border-radius: 2px;
}

input[type=range] {
  -webkit-appearance: none;
  margin: 0;
  width: 100%;
  padding: 0px;
  outline: none;
  border: none;
}

.toggle-false-msg {
  display: none;
  opacity: .2;
  transition: .5s opacity;
  display: inline-block;
  position: relative;
  top: -8px;
}

.toggle-true-msg {
  display: none;
  opacity: .2;
  transition: .5s opacity;
  display: inline-block;
  position: relative;
  top: -8px;
}

.toggle-neutral-msg {
  display: none;
  opacity: .2;
  transition: .5s opacity;
  display: none;
  position: relative;
  top: -8px;
}

#rangeActive {
  background-color: blue;
}

#textActive {
  opacity: 1;
  color: black;
}

input[type=range]:focus {
  outline: none;
}

input[type=range]::-webkit-slider-runnable-track {
  width: 100%;
  height: 30px;
  cursor: pointer;
  animate: 0.2s;
  box-shadow: 0px 0px 0px #000000;
  background: #3071A9;
  border-radius: 0px;
  border: 0px solid #000000;
}

input[type=range]::-webkit-slider-thumb {
  box-shadow: 0px 0px 0px #000000;
  border: 0px solid #000000;
  height: 30px;
  width: 19px;
  border-radius: 0px;
  background: #FFFFFF;
  cursor: pointer;
  -webkit-appearance: none;
  margin-top: 0px;
}

input[type=range]:focus::-webkit-slider-runnable-track {
  background: #3071A9;
}

input[type=range]::-moz-range-track {
  width: 100%;
  height: 30px;
  cursor: pointer;
  animate: 0.2s;
  box-shadow: 0px 0px 0px #000000;
  background: #3071A9;
  border-radius: 0px;
  border: 0px solid #000000;
}

input[type=range]::-moz-range-thumb {
  box-shadow: 0px 0px 0px #000000;
  border: 0px solid #000000;
  height: 30px;
  width: 19px;
  border-radius: 0px;
  background: #FFFFFF;
  cursor: pointer;
}

input[type=range]::-ms-track {
  width: 100%;
  height: 30px;
  cursor: pointer;
  animate: 0.2s;
  background: transparent;
  border-color: transparent;
  color: transparent;
}

input[type=range]::-ms-fill-lower {
  background: #3071A9;
  border: 0px solid #000000;
  border-radius: 0px;
  box-shadow: 0px 0px 0px #000000;
}

input[type=range]::-ms-fill-upper {
  background: #3071A9;
  border: 0px solid #000000;
  border-radius: 0px;
  box-shadow: 0px 0px 0px #000000;
}

input[type=range]::-ms-thumb {
  box-shadow: 0px 0px 0px #000000;
  border: 0px solid #000000;
  height: 30px;
  width: 19px;
  border-radius: 0px;
  background: #FFFFFF;
  cursor: pointer;
}

input[type=range]:focus::-ms-fill-lower {
  background: #3071A9;
}

input[type=range]:focus::-ms-fill-upper {
  background: #3071A9;
}

.rangeFalse::-webkit-slider-runnable-track {
  background: #5d0a0a !important;
}

.rangeFalse::-webkit-slider-thumb {
  background: white !important;
}

.rangeNeutral::-webkit-slider-runnable-track {
  background: #204d75 !important;
}

.rangeNeutral::-webkit-slider-thumb {
  background: white !important;
}

.rangeTrue::-webkit-slider-runnable-track {
  background: #0e4e1f !important;
}

.rangeTrue::-webkit-slider-thumb {
  background: white !important;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="toggle-container">
  <div class="toggle-false-msg">Off</div>
  <div class="range-field" style=" width:60px">
    <input type="range" name="points" min="1" class="" max="3" value="2"
           onchange="togglebutton(this);">
  </div>
  <div class="toggle-neutral-msg">Neutral</div>
  <div class="toggle-true-msg">On</div>
</div>
&#13;
&#13;
&#13;

此交换机不使用单选按钮,而是使用范围并将值传递给JavaScript以确定交换机的操作。设计这个的最大障碍是改变范围的伪元素(特别是其轨道的背景颜色)。这可以通过使用pseduo元素设置不同的类并使用java在类中循环来实现。

有关修改伪元素的信息,请参阅以下链接。我使用了文章中描述的方法1。

资源

答案 5 :(得分:0)

$(function() {
  $("input[name=radgroup]:checked").click(function() {
    var state = $(this).val();
    // do action depending on state
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type='radio' name='radgroup' value='on' id='on' />
<label for='on'>On</label>
<input type='radio' name='radgroup' value='na' id='na' checked='true' />
<label for='na'>NA</label>
<input type='radio' name='radgroup' value='off' id='off' />
<label for='off'>Off</label>

答案 6 :(得分:0)

这是具有前进,后退,未锁定音轨和键盘控件的3向React开关,您可以在CodePen here上看到它的运行情况。它从左侧位置开始,称为选项1,但您可以对其进行修改,使其从任何位置开始。

/*React Component*/
class ThreeWayToggleSwitchComponent extends React.Component {
  constructor(props) {
    super(props);

    this.threeWayToggleSwitchComponentDivRef = React.createRef();
    this.option1Ref = React.createRef();
    this.option3Ref = React.createRef();
    this.slidingButtonDivRef = React.createRef();

    this.state = {
      selectedOption: "Option 1"
    };

    this.handleOptionChange = this.handleOptionChange.bind(this);
    this.keyboardPress = this.keyboardPress.bind(this);
  }

  handleOptionChange(event) {
    if (event.target.value === "Option 1") {
      if (this.state.selectedOption === "Option 2") {
        this.setState({
          selectedOption: event.target.value
        });

        this.slidingButtonDivRef.current.style.transform = "translate(0px)";
        this.slidingButtonDivRef.current.style.background = "green";  
      }
      else if (this.state.selectedOption === "Option 3") {
        this.setState({
          selectedOption: "Option 2"
        });

        this.slidingButtonDivRef.current.style.transform = "translate(40px)";
        this.slidingButtonDivRef.current.style.background = "yellow";
      }
    }
    else if (event.target.value === "Option 2") {
      this.setState({
        selectedOption: "Option 2"
      });

      this.slidingButtonDivRef.current.style.transform = "translate(40px)";
      this.slidingButtonDivRef.current.style.background = "yellow";
    }
    else if (event.target.value === "Option 3") {
      if (this.state.selectedOption === "Option 1") {
        this.setState({
          selectedOption: "Option 2"
        });

        this.slidingButtonDivRef.current.style.transform = "translate(40px)";
        this.slidingButtonDivRef.current.style.background = "yellow";
      }
      else if (this.state.selectedOption === "Option 2") {
        this.setState({
          selectedOption: "Option 3"
        });

        this.slidingButtonDivRef.current.style.transform = "translate(80px)";
        this.slidingButtonDivRef.current.style.background = "red";
      }
    }
  }

  keyboardPress(event) { 
    if (event.keyCode === 37) {
      this.option1Ref.current.click();
    }
    else if (event.keyCode === 39) {
      this.option3Ref.current.click();
    }
  }

  componentDidMount() {
    this.threeWayToggleSwitchComponentDivRef.current.focus();
  }

  render() {    
    return(
      <div ref={this.threeWayToggleSwitchComponentDivRef} id="three-way-toggle-switch-component-div" tabIndex="0" onKeyDown={this.keyboardPress}>
        <div id="radio-buttons-and-sliding-button-container-div">
          <div id="radio-buttons-div">
            <label id="option-1-label" className="single-option-label" for="option-1">Label 1
              <input type="radio" ref={this.option1Ref} id="option-1" className="radio-input-class" name="radio-input" value="Option 1" checked={this.state.selectedOption === "Option 1"} onChange={this.handleOptionChange}/>
            </label>

            <label id="option-2-label" className="single-option-label" for="option-2">Label 2
              <input type="radio" id="option-2" className="radio-input-class" name="radio-input" value="Option 2" checked={this.state.selectedOption === "Option 2"} onChange={this.handleOptionChange}/>
            </label>

            <label id="option-3-label" className="single-option-label" for="option-3">Label 3
              <input type="radio" ref={this.option3Ref} id="option-3" className="radio-input-class" name="radio-input" value="Option 3" checked={this.state.selectedOption === "Option 3"} onChange={this.handleOptionChange}/>
            </label>
          </div>

          <div ref={this.slidingButtonDivRef} id="sliding-button-div">
          </div>
        <div>

        <div id="selected-option">Option Selected: {this.state.selectedOption}
        </div>

        <div id="keyboard-message">
          You can control the sliding button via the left arrow key or the right arrow key on your keyboard.
        </div>
      </div>
    );
  }
};

ReactDOM.render(<ThreeWayToggleSwitchComponent/>, document.getElementById("react-component-div"));

/*CSS Styling*/
#three-way-toggle-switch-component-div:focus {
  outline: none;
}

#radio-buttons-and-sliding-button-container-div {
  position: relative;
  display: inline-block;
  height: 30px;
  width: 120px;
  border: 2px solid black;
  border-radius: 5px;
}

#sliding-button-div {
  position: absolute;
  display: inline-block;
  top: 0;
  height: 30px;
  width: 40px;
  background: green;
  transition: 0.8s;
  border-radius: 3px;
}

#radio-buttons-div {
  display: flex;
  justify-content: space-between;
}

.single-option-label {
  width: 100%;
  color: transparent;
}

.radio-input-class {
  display: none;
}

答案 7 :(得分:0)

如果您希望用颜色切换“否” /“未设置” /“是”,则如下所示:

toggle

然后使用上面DarkAjax的答案,但是添加以下CSS:

.switch-toggle  input:checked.toggle-no ~ a {
    background-color:  red;
 }

 .switch-toggle  input:checked.toggle-yes ~ a {
    background-color:  green;
 }

 .switch-toggle  input:checked.toggle-unset ~ a {
    background-color:  grey;
 }

并将相应的类(class =“ toggle-no”等)添加到相应的单选按钮输入中。而且,您还可以根据需要添加图标等。

希望这对某人有帮助!