Safari上的动态隐藏选择列表

时间:2017-04-27 14:44:26

标签: javascript jquery html safari

也许我做错了,但这是我在选择元素上实施的行为:

我创建了一个包含多个<select>的网页,并使用样式表对其进行自定义 对于特定的一个,我在div之后添加了样式position: absolute;,其中显示了带复选框的列表,允许多个选择。
这个<select>有一个unic <option> - 其目的是显示一个标题,如&#34;选择你的选项&#34;。
要显示我的自定义列表而不是选项列表,根据主电源浏览器的兼容性,我必须实现这样的onclick函数:

function showList(input,sIdTarget)
{
    //hide the dropdown list, compatible with all browser
    $(input).css({ "display": "none" }).blur().css({"display": "" });
    $("#"+sIdTarget).css("display","");
}

我仍然遇到Safari问题。在onclick事件上调用此函数会在单击列表元素后触发它。

以下是一个示例:https://jsfiddle.net/L6uhkg9h/1/

感谢您的帮助。

3 个答案:

答案 0 :(得分:1)

以跨浏览器方式重新设置select option非常困难,如果不是几乎不可能的话。

如果您需要保持最高的跨浏览器兼容性,并且已经有自定义样式选项下拉菜单,那么您现在需要的是选择的可聚焦和可列表部分。

在我的以下提案中,而不是select我使用input button来允许表单元素之间的鼠标和键盘导航,并避免样式(下拉)和行为(单击,焦点事件)与select的不同浏览器特定实现相关的问题。

input button将保持原生焦点行为,并提供与Safari中所有其他表单元素相同的焦点阴影,以及其他浏览器中的虚线边框(FF,Chrome,IE等)。

关于键盘和鼠标导航,您仍然需要一些全局处理程序,因为您的自定义下拉部分应在代码中处理。

在我的提案中,您还会在下拉列表中的checkboxes中找到键盘导航的示例,该示例还处理隐藏和/或禁用元素的情况。

&#13;
&#13;
function toggleSelectList(el) {
  var customSelect = $(el).closest(".customSelect");
  if (customSelect.length > 0) {
    if ($(el).hasClass("customSelectFocus")) {
      if ($(customSelect).children(".customSelectList").css("display") === "none") {
        clickSelectFocus(customSelect);
        blurSelectFocus(customSelect);
      } else {
        hideSelectList(customSelect);
        focusSelectFocus(customSelect)
      }
    } else {
      // mouse down inside custom drop down list
    }
  } else {
    // mouse down outside any custom select
    hideAllSelectLists();
  }
}

function handleSelectNavigation(e, key) {
  var customSelect = $(".customSelectList").filter(":visible").closest(".customSelect");
  var all = $(".customSelectList input:visible:enabled");
  var first = all[0], last = all[all.length - 1], current = $(".customSelectList input:focus");
  var currentIndex = $(all).index(current);
  switch (key) {
    case 9: // tab
      if(e.shiftKey == 1) {
        if ($(first).is(":focus")) {
          e.preventDefault();
          $(last).focus();
        }
      } else {
        if ($(last).is(":focus")) {
          e.preventDefault();
          $(first).focus();
        }        
      }
      break;
    case 13: // enter
      toggleSelectList(e.target);
      break
    case 27: // escape
      hideAllSelectLists();
      focusSelectFocus(customSelect);
      break
    case 38: // up arrow
      $(first).is(":focus") ? $(last).focus() : $(all)[currentIndex - 1].focus();
      break
    case 40: // down arrow
      $(last).is(":focus") ? $(first).focus() : $(all)[currentIndex + 1].focus();
  }
}

$(document).on("mousedown", function(e) {
  toggleSelectList(e.target);
});

$(document).on("keydown", function(e) {
  var key = e.charCode ? e.charCode : e.keyCode ? e.keyCode : 0;
  var cases = [9, 13, 27, 38, 40];
  if ($.inArray(key, cases) > -1) handleSelectNavigation(e, key);
});

function setSelectLabel(customSelect) {
  var numSelected = $(customSelect).children(".customSelectList").find("input:checked").length;
  var text = (numSelected === 0) ? "- Select your options -" : " %1 option(s) selected".replace("%1", numSelected);
  $(customSelect).find(".customSelectFocus").val(text);
}

function focusSelectFocus(customSelect) {
  setTimeout(function() {
    $(customSelect).find(".customSelectFocus").focus();
  }, 0);
}

function blurSelectFocus(customSelect) {
  setTimeout(function() {
    var firstInput = $(customSelect).find(".customSelectList input:visible:enabled").first();
    var selectFocus = $(customSelect).find(".customSelectFocus").first();
    firstInput.length > 0 ? $(firstInput).focus() : $(selectFocus).blur();
  }, 0);
}

function clickSelectFocus(customSelect) {
  $(".customSelect").not(customSelect).each(function() {
    hideSelectList(this); // hiding all other than the one clicked
  });
  if ($(customSelect).children(".customSelectList").css("display") === "none") {
    showSelectList(customSelect);
  } else {
    hideSelectList(customSelect);
  }
}

function showSelectList(customSelect) {
  $(customSelect).children(".customSelectList").css("display", "");
  $(customSelect).find(".customSelectFocus").addClass("expanded").removeClass("collapse");
}

function hideSelectList(customSelect) {
  $(customSelect).children(".customSelectList").css("display", "none");
  $(customSelect).find(".customSelectFocus").addClass("collapse").removeClass("expanded");
  setSelectLabel(customSelect);
}

function hideAllSelectLists() {
  $(".customSelect").each(function() {
    hideSelectList(this);
  });
}

$(document).ready(function() {
  $(".customSelect").each(function() {
    setSelectLabel(this);
  });
  $(".customSelect input[type=checkbox]").change(function() {
    setSelectLabel($(this).closest(".customSelect"));
  });
  focusSelectFocus($(".customSelect").first());
});
&#13;
.customSelect {
  width: 195px;
  margin-left: -5px;
  padding: 5px;
  border: 0 none transparent;
  display: inline-block;
  position: relative;
}

.customSelectBox {
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: block;
  border: 1px solid #AAAAAA;
}

.customSelectFocus {
  width: 100%;
  height: 100%;
  padding: 5px;
  border: 0 none transparent;
  display: inline-block;
  text-align: left;
  -webkit-border-radius: 2px;
  -moz-border-radius: 2px;
  border-radius: 2px;
}

.customSelectFocus.collapsed {
  background: white url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAB3RJTUUH4QUIDC0RXxhGYQAAAAlwSFlzAAALEwAACxMBAJqcGAAAAARnQU1BAACxjwv8YQUAAAA1SURBVHjaY2AYcHAFiP/jwJeRFSoB8Qssil5A5VCAARB/RFIEYuvjcoIdEL+DYtuBDg8oAACLqxRIufkW/wAAAABJRU5ErkJggg==") no-repeat;
  background-size: 10px;
  background-position: right 10px center;
  background-position: top 10px right 6px;
  background-position-x: 178px;
  background-position-y: 8px;
}

.customSelectFocus.expanded {
  background: white url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAB3RJTUUH4QUIDCwtaWwLpwAAAAlwSFlzAABOIAAATiABFn2Z3gAAAARnQU1BAACxjwv8YQUAAACESURBVHjaZZBBCoMwEEUHD2Ndil3b64veQN3ZlSktinGlYP/IDIxj4EGS/xJ+QkT0ABXI6T4uWQ0OMDo5BYNkHW88wcfJVprBS0+zHCT4ygGeT1bSUYCfCEwEpYaJEVewmfUOFn9bZjpF6XV7IEtv06mUGsHLjZNsZ/2NVjd6J9nfOLM/MU0xq4g4dtgAAAAASUVORK5CYII=") no-repeat;
  background-size: 10px;
  background-position: right 10px center;
  background-position: top 10px right 6px;
  background-position-x: 178px;
  background-position-y: 8px;
}

.customSelectList {
  position: relative;
  z-index: 10;
  font: -webkit-small-control;
  font-size: 14px;
  font-family: "MS Shell Dlg \32";
  font-weight: 400;
}

.customSelectList div {
  background-color: white;
  max-height: 300px;
  width: 250px;
  overflow-y: auto;
  overflow-x: hidden;
  position: absolute;
  padding: 0 10px;
  border: solid 1px #C0C0C0;
}
&#13;
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <script src="https://code.jquery.com/jquery-1.11.2.min.js"></script>
</head>

<body>
  <div class="customSelect">
    <div class="customSelectBox">
      <input type="button" class="customSelectFocus collapsed" value="- Select your options -">
    </div>
    <div class="customSelectList" style="display: none;">
      <div>
        <ul style="list-style-type: none;">
          <li>
            <input type="checkbox">val 1</li>
          <li>
            <input type="checkbox" checked="checked">val 2</li>
          <li>
            <input type="checkbox">val 3</li>
          <li>
            <input type="checkbox">val 4</li>
          <li>
            <input type="checkbox">val 5</li>
        </ul>
      </div>
    </div>
  </div>

  <hr>

  <div class="customSelect">
    <div class="customSelectBox">
      <input type="button" class="customSelectFocus collapsed" value="- Select your options -">
    </div>
    <div class="customSelectList" style="display: none;">
      <div>
        <ul style="list-style-type: none;">
          <li>
            <input type="checkbox" disabled="disabled">val 1</li>
          <li>
            <input type="checkbox" disabled="disabled" checked="checked">val 2</li>
          <li>
            <input type="checkbox" disabled="disabled" checked="checked">val 3</li>
          <li>
            <input type="checkbox" disabled="disabled">val 4</li>
          <li>
            <input type="checkbox" disabled="disabled">val 5</li>
        </ul>
      </div>
    </div>
  </div>
  <hr>

</body>

</html>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

您可以禁用下拉列表并将点击处理程序附加到父DIV,而不是使用JQuery在用户选择后隐藏下拉列表。在pointer-events: none元素上设置select样式将阻止该元素响应任何点击事件。然后,您可以将点击处理程序附加到.customSelect

$('.customSelect').on('click.selectList', function(e) {
  e.stopPropagation();
  if($("#listeSecteurs").css("display") === "none")
    $("#listeSecteurs").css("display","");
  else
    $("#listeSecteurs").css("display","none");
});

当用户点击.customSelect DIV时,您将切换是否显示#listeSecteurs。当用户点击#listSecteurs以外的任何内容时,您希望摆脱#listSecteurs,因此您需要将点击处理程序附加到window以执行此操作:

$(window).on('click.selectListWindow', function(e) {
      $("#listeSecteurs").css({"display":"none"});
});

请注意e.stopPropagation()处理程序中的.customSelect将阻止在单击.customSelect div时触发此窗口单击处理程序。您还需要停止点击事件从.hideableSelectList传播到window,因为当用户点击前者时,您希望显示#listSecteurs

$('.hideableSelectList').on('click.selectList', function(e) {
  e.stopPropagation();
});

全部放在一起:

<html>
  <head>
  <style>
  .customSelect{
    width: calc(100% - 2px);
    background-color: white; 
    border: solid 1px #AAAAAA;
    border-top-width: 2px;
    -webkit-border-radius: 2px;
    -moz-border-radius: 2px;
    border-radius: 2px;            
}     
.customSelect select{
    width: 100%; 
    padding: 5px 8px;
    border: 0px;        
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    overflow:hidden; 
}
.customSelect select.collapse{
    background: transparent url('https://cdn4.iconfinder.com/data/icons/ionicons/512/icon-arrow-down-b-128.png') no-repeat; 
    background-size: 10px;
    background-position: right 10px center;
}
.customSelect select.expanded{
    background: transparent url('https://cdn2.iconfinder.com/data/icons/flat-ui-icons-24-px/24/cross-24-128.png') no-repeat; 
    background-size: 10px;
    background-position: right 10px center;
}
.hideableSelectList{
    position: relative;    
}
.hideableSelectList div{
    background-color: white;
    max-height: 300px;
    width: 250px;
    overflow-y: auto;
    overflow-x: hidden;
    position: absolute;
    padding: 0px 10px;
    border: solid 1px #C0C0C0;
    z-index: 3;
}
  </style>
  </head>
  <body>
  <div class="customSelect" style="width: 195px;">
    <select class="collapse" style="width: 195px; z-index: 0; pointer-events: none" >
        <option style="height: 0px">-&nbsp;Select your options&nbsp;-</option>
    </select><br>
    <div class="hideableSelectList" style="z-index: 10;">
        <div id="listeSecteurs" style="display: none; left: 0px;">
          <ul style="list-style-type: none;">
            <li><input type="checkbox">val 1</li>
            <li><input type="checkbox">val 2</li>
            <li><input type="checkbox">val 3</li>
            <li><input type="checkbox">val 4</li>
            <li><input type="checkbox">val 5</li>
          </ul>
        </div>
    </div>
</div>
  </body>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
  <script>

  $(function () {

    $('.hideableSelectList').on('click.selectList', function(e) {
      e.stopPropagation();
    });

    $('.customSelect').on('click.selectList', function(e) {
      e.stopPropagation();
      if($("#listeSecteurs").css("display") === "none")
        $("#listeSecteurs").css("display","");
      else
        $("#listeSecteurs").css("display","none");
    });

    $(window).on('click.selectListWindow', function(e) {
          $("#listeSecteurs").css({"display":"none"});
    });
  });

  </script>
</html>

答案 2 :(得分:0)

也许你应该考虑使用一些jQuery插件进行多选? 例如,这一个https://select2.github.io/examples.html