Создание «гибкого / отзывчивого» поля выбора / варианта для формы - PullRequest
1 голос
/ 02 июля 2019

Я пытаюсь создать сложную форму с «гибкими» элементами выбора / выбора для простоты использования, которые должны проявляться только в зависимости от выбора пользователя. Другими словами, если пользователь выбирает определенную опцию в одной группе <select>, то новый набор опций должен проявить себя во второй группе <select>. Моя ситуация на бит более сложная, чем эта, но это краткое изложение ее поведения.

Тем не менее, я хочу более приятный интерфейс, чем у меня сейчас; а именно, я хочу, чтобы форма поддерживалась и идеально подходила для всех браузеров.


У меня есть один конкретный элемент <select> (давайте назовем этот элемент 'selectA'), который имеет список различных опций, а именно, 'optionA-1', 'optionA-2' и 'optionA-3'.

У меня есть еще один элемент <select>, называемый «selectB», который должен раскрываться только при выборе «optionA-1» или «optionA-3». У «selectB» также есть четыре других параметра, с острым названием «optionB-1», «optionB-2», «optionB-3» и, конечно, «optionB-4».

Наличие «selectB» исчезает и появляется вновь по желанию - это обычное дело - всего лишь немного JS и, как известно, «магически» отзывчивая форма!

Вот проблема, однако: 'optionB-3' и 'option-B-4' должны быть видимы, только если выбрана опция 'optionA-3'; в противном случае они не должны отображаться.

Это не так уж много, что я не могу сделать это, но я хочу, чтобы дизайн был четким (то есть без лишних пробелов, где он не нужен) и не был бы слишком зависимым от JavaScript (так как пользователи могут включать или отключать его по своему желанию, и я не хочу, чтобы основная функциональность нарушалась).

Вот примерно структура формы, как есть:

<form>
    <select name='selectA' id='selectA' onchange='showSelectB()'>
        <option value='DEFAULT-A'>---Choose one---</option>
        <option value='optionA-1'>OptionA-1</option>
        <option value='optionA-2'>OptionA-2</option>
        <option value='optionA-3'>OptionA-3</option>
    </select>

    <select name='selectB' id='selectB'>
        <option value='DEFAULT-B'>---Choose another one---</option>
        <option value='optionB-1'>OptionB-1</option>
        <option value='optionB-2'>OptionB-2</option>
        <option class='hideable' value='optionB-3'>OptionB-3</option>
        <option class='hideable' value='optionB-4'>OptionB-4</option>
    </select>
</form>

Кажется довольно просто, верно? Хорошо, теперь функция JavaScript делает «selectB» более «гибкой / отзывчивой» (подразумевается, что это находится в том же файле в элементе <script>):

function showSelectB()
{
    var selectABox = document.getElementById("selectA");
    var selectedValue = selectABox.options[selectABox.selectedIndex].value;
    var selectBBox = document.getElementById("selectB");

    if(selectedValue == "optionA-1" || selectedValue == "optionA-3")
    {
        selectBBox.style.display = ""; //Ta-da!

        var options = document.getElementsByClassName("hideable");
        var length = options.length;

        if(selectedValue == 'optionA-3')
        {
            for(var i = 0; i < length; i++)
            {
                options[i].style.display = ""; //Now you see me...
            }
        }
        else
        {
            for(var i = 0; i < length; i++)
            {
                options[i].style.display = "none"; //...Now you don't
            }
        }
    }
    else
    {
        selectBBox.style.display = "none"; //Disappear!
    }
}

//I was being lazy here
document.getElementById("selectB").style.display = "none";

(Теперь я знаю, что синтаксис jQuery чище, но в этом случае я предпочитаю хороший старый JavaScript).

Если вы проверите это, вы увидите, что оно работает нормально; опции приходят и уходят, как и ожидалось ... за исключением одного предупреждения:

  • Когда опция «optionA-1» выбрана в «selectA», «selectB» возвращает эти ужасные пробелы, когда опции B-3 и B-4 больше не отображаются (по крайней мере, они делают это в моей версии Microsoft Edge, который мне показался довольно странным, поскольку это больше похоже на то, как должен работать атрибут visibility); для меня это выглядит довольно некрасиво.

Заменитель, который я пытался использовать для этого кода JavaScript, заключался в том, чтобы рассматривать «скрываемые» параметры как дочерние узлы «selectB» и добавлять или удалять их всякий раз, когда «optionA-3» был выбран или «не выбран», но это казалось ужасным грязный и подверженный ошибкам (а именно, он добавил бы слишком много опций, если бы я выбрал «optionA-3» прямо из ворот). Возможно, я где-то пренебрегал условием if или else, но оно просто не работало в значительном количестве моих тестовых прогонов.

Мне было интересно, может быть, существует третья альтернатива, которая поддерживает адаптивность формы, но не запутывается в этих несоответствиях, которые всплывают в «selectB» (по крайней мере, в Microsoft Edge и IE).


РЕДАКТИРОВАТЬ: Вот рабочий фрагмент, как и требовалось.

function showSelectB()
{
    var selectABox = document.getElementById("selectA");
    var selectedValue = selectABox.options[selectABox.selectedIndex].value;
    var selectBBox = document.getElementById("selectB");

    if(selectedValue == "optionA-1" || selectedValue == "optionA-3")
    {
        selectBBox.style.display = ""; //Ta-da!

        var options = document.getElementsByClassName("hideable");
        var length = options.length;
        
        if(selectedValue == 'optionA-3')
        {
            for(var i = 0; i < length; i++)
            {
                options[i].style.display = ""; //Now you see me...
            }
        }
        else
        {
            for(var i = 0; i < length; i++)
            {
                options[i].style.display = "none"; //...Now you don't
            }
        }
    }
    else
    {
        selectBBox.style.display = "none"; //Disappear!
    }
}

//I was being lazy here
document.getElementById("selectB").style.display = "none";
<form>
    <select name='selectA' id='selectA' onchange='showSelectB()'>
        <option value='DEFAULT-A'>---Choose one---</option>
        <option value='optionA-1'>OptionA-1</option>
        <option value='optionA-2'>OptionA-2</option>
        <option value='optionA-3'>OptionA-3</option>
    </select>

    <select name='selectB' id='selectB'>
        <option value='DEFAULT-B'>---Choose another one---</option>
        <option value='optionB-1'>OptionB-1</option>
        <option value='optionB-2'>OptionB-2</option>
        <option class='hideable' value='optionB-3'>OptionB-3</option>
        <option class='hideable' value='optionB-4'>OptionB-4</option>
    </select>
</form>

Интересно, что я не достаточно хорошо протестировал это в браузерах; Теперь я замечаю, что он отлично работает на Chrome и Firefox, но, к сожалению, не на Microsoft Edge (и IE совершенно не работает). Итак, ясно, что это кросс-браузерная проблема. Проблема в том, откуда возникла проблема с кроссбраузерностью?

1 Ответ

1 голос
/ 03 июля 2019

Один из вариантов - добавить атрибут hidden вместо изменения видимости компонента.

Таким образом, эта строка:

options[i].style.display = ""; //Now you see me...

станет такой

options[i].removeAttribute("hidden"); //Now you see me...

И эта строка:

options[i].style.display = "none"; //...Now you don't

станет такой

options[i].setAttribute("hidden", ""); //Now you don't

Ссылки:

https://developer.mozilla.org/en-US/docs/Web/API/Element/setAttribute

https://developer.mozilla.org/en-US/docs/Web/API/Element/removeAttribute

Совместимость браузера:

https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/hidden#Browser_compatibility

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...