Как скрыть <option> в меню <select> с помощью CSS?

104

Я понял, что Chrome, похоже, не позволит мне спрятаться <option>в <select>. Firefox будет.

Мне нужно скрыть <option>символы, соответствующие критериям поиска. В веб-инструментах Chrome я вижу, что они правильно настроены display: none;моим JavaScript, но при <select>нажатии на меню они отображаются.

Как я могу сделать так, чтобы эти <option>символы, соответствующие моим критериям поиска, НЕ отображались при нажатии на меню? Спасибо!

Джесси Аткинсон
источник
4
Вместо того, чтобы скрывать и показывать при поиске. Попробуйте заполнить выбор в зависимости от поиска
Henesnarfel
1
Я согласен с Хенеснарфелем. Если вы уже выполняете поиск или какой-либо запрос, вы можете просто указать те, которые вам нужны.
Майкл Страмел
1
это отлично работает для меня в Chrome 16.0.912.77 m. Я неправильно понимаю проблему?
mgibsonbr
3
@mgibsonbr Не работает кроссбраузерно.
Джаспер
3
@Henesnarfel Могут быть веские причины скрывать варианты. Например, у меня была страница со списком выбора и ссылками для скрытия или отображения элементов, отмеченных как неактивные. Нет причин хранить несколько списков или запрашивать у сервера новый список всякий раз, когда пользователь изменяет этот параметр.
Ryan P

Ответы:

69

Вы должны реализовать два метода сокрытия. display: noneработает для FF, но не для Chrome или IE. Таким образом, второй метод оборачивания <option>в <span>с display: none. FF этого не сделает (технически недействительный HTML согласно спецификации), но Chrome и IE будут, и он скроет эту опцию.

РЕДАКТИРОВАТЬ: О да, я уже реализовал это в jQuery:

jQuery.fn.toggleOption = function( show ) {
    jQuery( this ).toggle( show );
    if( show ) {
        if( jQuery( this ).parent( 'span.toggleOption' ).length )
            jQuery( this ).unwrap( );
    } else {
        if( jQuery( this ).parent( 'span.toggleOption' ).length == 0 )
            jQuery( this ).wrap( '<span class="toggleOption" style="display: none;" />' );
    }
};

РЕДАКТИРОВАТЬ 2: Вот как вы могли бы использовать эту функцию:

jQuery(selector).toggleOption(true); // show option
jQuery(selector).toggleOption(false); // hide option

РЕДАКТИРОВАТЬ 3: добавлена ​​дополнительная проверка, предложенная @ user1521986

Райан П.
источник
1
Этот сумасшедший метод - единственный, который действительно работал полностью в разных браузерах и не предполагал создания искусственно скрытого взлома окна выбора.
Джесси Аткинсон,
15
Будьте осторожны с этим. Поначалу кажется, что это отлично работает, но где-то на ходу это останавливается. Вот небольшая демонстрация: jsfiddle.net/Yb6sk/9
Билл
17
Хотя это решение скрывает элемент, любая попытка прочитать значение <select>(с использованием jQuery .val()) вернется null. Я только что протестировал это в Chrome 29, так что остерегайтесь гуглеров!
Марк
10
Интересный прием, но я бы рекомендовал по возможности избегать "технически недействительного HTML".
Люк,
3
Правда, у всех браузеров разные реализации. Но одна из причин, по которой браузеры не могут строго реализовать стандартные спецификации, заключается в том, что существует слишком много живого кода, который не соответствует спецификациям. ИМО: Если других решений нет, то непременно воспользуйтесь хаком. Но если вы можете следовать спецификации и решить свою проблему, почему бы и нет? Это помогает вашему коду хорошо взаимодействовать с другими и помогает укрепить спецификацию.
Люк,
84

Для HTML5 вы можете использовать атрибут «скрытый».

<option hidden>Hidden option</option>

Это не поддерживается IE <11. Но если вам нужно скрыть только несколько элементов, возможно, было бы лучше просто установить атрибут hidden в сочетании с disabled по сравнению с добавлением / удалением элементов или созданием семантически некорректных конструкций.

<select>  
  <option>Option1</option>
  <option>Option2</option>
  <option hidden>Hidden Option</option>
</select>

Ссылка .

Лукас Елинек
источник
4
IE 11 поддерживает это.
Иван Перес,
7
Это современный ответ. В идеале мы также устанавливаем это disabledтак, чтобы те браузеры, которые не поддерживают глобальный hiddenатрибут HTML5 , имели визуальную индикацию для пользователя.
cloudworks
1
Как вы используете эту технику с CSS?
GetFree,
7
Не работает в Safari, Edge и IE. Багу для Safari 10 лет, помогите, обновив существующие патчи. Не удается найти ошибку в системе отслеживания проблем Edge.
Indolering
7
Обходной путь для этого - использование <option hidden disabled>, поэтому он скрывается во всех хороших браузерах и отключает его в других.
Рамон Бальтазар
37

Я бы посоветовал вам не использовать решения, использующие <span>оболочку, потому что это недопустимый HTML, что может вызвать проблемы в будущем. Я думаю, что предпочтительное решение - удалить все параметры, которые вы хотите скрыть, и восстановить их по мере необходимости. Используя jQuery, вам понадобятся только эти 3 функции:

Первая функция сохранит исходное содержимое выбора . На всякий случай вы можете вызвать эту функцию при загрузке страницы.

function setOriginalSelect ($select) {
    if ($select.data("originalHTML") == undefined) {
        $select.data("originalHTML", $select.html());
    } // If it's already there, don't re-set it
}

Следующая функция вызывает указанную выше функцию, чтобы убедиться, что исходное содержимое было сохранено, а затем просто удаляет параметры из модели DOM.

function removeOptions ($select, $options) {
    setOriginalSelect($select);
    $options.remove();
 }

Последнюю функцию можно использовать всякий раз, когда вы хотите «сбросить» все исходные параметры.

function restoreOptions ($select) {
    var ogHTML = $select.data("originalHTML");
    if (ogHTML != undefined) {
        $select.html(ogHTML);
    }
}

Обратите внимание, что все эти функции ожидают, что вы передадите элементы jQuery. Например:

// in your search function...
var $s = $('select.someClass');
var $optionsThatDontMatchYourSearch= $s.find('options.someOtherClass');
restoreOptions($s); // Make sure you're working with a full deck
removeOptions($s, $optionsThatDontMatchYourSearch); // remove options not needed

Вот рабочий пример: http://jsfiddle.net/9CYjy/23/

Люк
источник
3
Надежный и не взломанный. Отличный ответ!
Джереми Кук
1
@DanBeaulieu В предыдущем jsfiddle была функция с неправильным названием. Я исправил и обновил ссылку выше. Спасибо, что уловили это.
Люк,
Да, это тоже был мой выбор. На самом деле мне удалось уменьшить размер кода, сначала взяв значение данных в переменную, если не определено, он сохранит параметры, иначе восстановит параметры. Моя потребность была специфичной для таких.
diynevala
1
Мне пришлось добавить, var value=$select.val(); $select.html(ogHTML); $select.val(value);чтобы выбранное значение оставалось выбранным даже после восстановления.
diynevala
Цикл выбора параметров для удаления и их удаления сработал только один раз. После этого options.remove () на меня не повлиял. Как только я переместил restoreOptions ($ s) на несколько строк, чтобы я всегда работал с полным, свежим объектом Select, это сработало.
Newclique
18

Ответ Райана П. следует изменить на:

    jQuery.fn.toggleOption = function (show) {
        $(this).toggle(show);
        if (show) {
            if ($(this).parent('span.toggleOption').length)
                $(this).unwrap();
        } else {
            **if ($(this).parent('span.toggleOption').length==0)**
                $(this).wrap('<span class="toggleOption" style="display: none;" />');
        }
    };

В противном случае он будет заключен в слишком много тегов

Джефф
источник
5
Обратите внимание, что в соответствии со спецификациями HTML ( w3.org/TR/html5/forms.html#the-select-element ), a <select>должен содержать только элементы, поддерживающие скрипт, <option>or <optgroup>or. Поэтому вам следует избегать использования недопустимых <span>оболочек.
Люк,
9

Функция toggleOption не идеальна и внесла неприятные ошибки в мое приложение. jQuery запутается с .val () и .arraySerialize (). Попробуйте выбрать варианты 4 и 5, чтобы понять, что я имею в виду:

<select id="t">
<option value="v1">options 1</option>
<option value="v2">options 2</option>
<option value="v3" id="o3">options 3</option>
<option value="v4">options 4</option>
<option value="v5">options 5</option>
</select>
<script>
jQuery.fn.toggleOption = function( show ) {
    jQuery( this ).toggle( show );
    if( show ) {
        if( jQuery( this ).parent( 'span.toggleOption' ).length )
            jQuery( this ).unwrap( );
    } else {
        jQuery( this ).wrap( '<span class="toggleOption" style="display: none;" />' );
    }
};

$("#o3").toggleOption(false); 
$("#t").change(function(e) {
    if($(this).val() != this.value) {
    console.log("Error values not equal", this.value, $(this).val());
    }
});
</script>
Батист Билер
источник
8

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

$('select').children(':nth-child(even)').prop('disabled', true);

Это отключит все остальные <option>элементы, но вы можете выбрать, какой хотите.

Вот демонстрация: http://jsfiddle.net/jYWrH/

Примечание. Если вы хотите удалить отключенное свойство элемента, вы можете использовать его .removeProp('disabled').

Обновить

Вы можете сохранить <option>элементы, которые хотите скрыть, в скрытом элементе выбора:

$('#visible').on('change', function () {
    $(this).children().eq(this.selectedIndex).appendTo('#hidden');
});

Затем вы можете добавить <option>элементы обратно в исходный элемент выбора:

$('#hidden').children().appendTo('#visible');

В этих двух примерах ожидается, что видимый элемент выбора имеет идентификатор, visibleа скрытый элемент выбора имеет идентификатор hidden.

Вот демонстрация: http://jsfiddle.net/jYWrH/1/

Обратите внимание, что .on()это новинка в jQuery 1.7, и использование этого ответа такое же, как .bind(): http://api.jquery.com/on

Джаспер
источник
7

Простой ответ: нельзя. Элементы формы имеют очень ограниченные возможности стилизации.

Лучшей альтернативой было бы установить disabled=trueэту опцию (и, возможно, серый цвет, поскольку только IE делает это автоматически), и это сделает эту опцию неактивной.

С другой стороны , если вы можете полностью удалить optionэлемент.

Ниет Темный Абсол
источник
6
// Simplest way

var originalContent = $('select').html();

$('select').change(function() {
    $('select').html(originalContent); //Restore Original Content
    $('select option[myfilter=1]').remove(); // Filter my options
});
Рене Бервангер
источник
4

Поскольку вы уже используете JS, вы можете создать скрытый элемент SELECT на странице и для каждого элемента, который вы пытаетесь скрыть в этом списке, переместить его в скрытый список. Таким образом, их можно легко восстановить.

Я не знаю, как сделать это на чистом CSS ... Я бы подумал, что уловка display: none не сработает.

Деррек Дин
источник
2

!!! ВНИМАНИЕ !!!

Замени второй «ЕСЛИ» на «ПОКА» или не работает!

jQuery.fn.toggleOption = function( show ) {
    jQuery( this ).toggle( show );
    if( show ) {
        while( jQuery( this ).parent( 'span.toggleOption' ).length )
            jQuery( this ).unwrap( );
    } else {
        jQuery( this ).wrap( '<span class="toggleOption" style="display: none;" />' );
    }
};
Арраксас
источник
2

Вы должны удалить их из <select>использования JavaScript. Это единственный гарантированный способ заставить их уйти.

Иордания
источник
1
Используя jQuery, это можно сделать с помощью remove:$('options').remove();
Люк,
2

этот, кажется, работает для меня в хроме

$("#selectid span option").unwrap();
$("#selectid option:not([filterattr=filtervalue])").wrap('<span/>');
сослан
источник
1
Пожалуйста, добавьте формат кода в свой код, сделав отступ с 4 пробелами или заключив код в `.
Banana
1
этот код отличный! он работает на последних
версиях
1
до моего последнего комментария эта штука работает и с IE 7! Итак, ff 3.5, это то, что я придумал в последний раз, он каким-то образом в IE и chrome сохраняет значение, которое было выбрано до того, как параметры будут скрыты, и если другое значение не будет установлено после возврата параметров, браузер установит параметр выбрал как раньше!
Сиджав
0

Поздно в игре, но большинство из них кажутся довольно сложными.

Вот как я это сделал:

var originalSelect = $('#select-2').html();

// filter select-2 on select-1 change
$('#select-1').change(function (e) {

    var selected = $(this).val();

    // reset select ready for filtering
    $('#select-2').html(originalCourseSelect);

    if (selected) {
        // filter
        $('#select-2 option').not('.t' + selected).remove();
    }

});

разметка select-1:

<select id='select-1'>
<option value=''>Please select</option>
<option value='1'>One</option>
<option value='2'>Two</option>
</select>

разметка select-2:

<select id='select-2'>
<option class='t1'>One</option>
<option class='t2'>Two</option>
<option>Always visible</option>
</select>
RichardAtHome
источник