Jak ukryć <opcję> w menu <select> za pomocą CSS?

104

Zdałem sobie sprawę, że wydaje się, że Chrome nie pozwoli mi ukryć się <option>w pliku <select>. Firefox to zrobi.

Muszę ukryć te, <option>które pasują do kryteriów wyszukiwania. W narzędziach internetowych Chrome widzę, że są one poprawnie ustawiane display: none;przez mój JavaScript, ale po <select>kliknięciu menu są wyświetlane.

Jak mogę sprawić, aby te, <option>które pasują do moich kryteriów wyszukiwania, NIE były wyświetlane po kliknięciu menu? Dzięki!

Jesse Atkinson
źródło
4
Zamiast się ukrywać i pokazywać podczas wyszukiwania. Spróbuj wypełnić pole wyboru w zależności od wyszukiwania
Henesnarfel,
1
Zgadzam się z Henesnarfel. Jeśli już wyszukujesz lub wykonujesz jakieś zapytanie, powinieneś być w stanie po prostu wypełnić te, które chcesz.
Michael Stramel
1
to działa dobrze dla mnie w Chrome 16.0.912.77 m. Czy źle rozumiem problem?
mgibsonbr
3
@mgibsonbr To nie działa w różnych przeglądarkach.
Jasper
3
@Henesnarfel Mogą być dobre powody, aby ukryć opcje. Na przykład miałem stronę z polem wyboru wyboru i łączami do ukrywania lub pokazywania elementów oznaczonych jako nieaktywne. Nie ma powodu, aby przechowywać wiele list lub wysyłać zapytania do serwera o nową listę za każdym razem, gdy użytkownik zmieni tę opcję.
Ryan P

Odpowiedzi:

69

Musisz zaimplementować dwie metody ukrywania. display: nonedziała dla FF, ale nie Chrome czy IE. Więc drugą metodą jest zawijanie <option>w a <span>with display: none. FF tego nie zrobi (technicznie nieprawidłowy HTML, zgodnie ze specyfikacją), ale Chrome i IE to zrobią i ukryją opcję.

EDYCJA: O tak, już to zaimplementowałem w 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;" />' );
    }
};

EDYCJA 2: Oto jak możesz użyć tej funkcji:

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

EDYCJA 3: Dodano dodatkowe sprawdzenie sugerowane przez @ user1521986

Ryan P
źródło
1
Ta szalona metoda jest jedyną, która faktycznie działała całkowicie w różnych przeglądarkach i nie obejmowała tworzenia fałszywie ukrytego hackowania pola wyboru.
Jesse Atkinson
15
Ostrożnie z tym. Na początku wydaje się działać świetnie, ale gdzieś po drodze się zatrzymuje. Oto małe demo: jsfiddle.net/Yb6sk/9
Bill Criswell
17
Chociaż to rozwiązanie ukrywa element, każda próba odczytania wartości <select>(przy użyciu jQuery .val()) zwróci null. Właśnie przetestowałem to w Chrome 29, więc Googlersi uważajcie!
Mark
10
Interesujący hack, ale radziłbym unikać „technicznie nieprawidłowego HTML”, jeśli to w ogóle możliwe.
Łukasz
3
To prawda, że ​​wszystkie przeglądarki mają różne implementacje. Ale jednym z powodów, dla których przeglądarki nie mogą ściśle zaimplementować standardowych specyfikacji, jest to, że istnieje zbyt dużo aktywnego kodu, który nie jest zgodny ze specyfikacjami. IMO: Jeśli nie ma innych rozwiązań, zdecydowanie użyj hacka. Ale jeśli możesz postępować zgodnie ze specyfikacją i rozwiązać problem, dlaczego nie? Pomaga Twojemu kodowi grać dobrze z innymi i pomaga wzmocnić specyfikację.
Łukasz
84

W przypadku HTML5 możesz użyć atrybutu „ukryty”.

<option hidden>Hidden option</option>

To jest nie obsługiwane przez IE <11. Ale jeśli potrzebujesz tylko ukryć kilka elementów, może byłoby lepiej po prostu ustawić atrybut ukryty w połączeniu z przyjaznym niepełnosprawnym w porównaniu do dodawania / usuwania elementów lub nie robi semantycznie poprawne konstrukcje.

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

Odniesienie .

Lukas Jelinek
źródło
4
IE 11 to obsługuje.
Iván Pérez
7
Oto współczesna odpowiedź. W idealnym przypadku ustawiamy to również disabledtak, aby przeglądarki, które nie obsługują globalnego hiddenatrybutu HTML5 , miały pewne wizualne wskazania dla użytkownika.
Cloudworks
1
Jak używasz tej techniki w CSS?
GetFree
7
Nie działa w Safari, Edge ani IE. Błąd dla Safari ma 10 lat, prosimy o pomoc, aktualizując istniejące łatki. Nie można znaleźć błędu w narzędziu do śledzenia błędów Edge.
Indolering
7
Istnieje obejście tego problemu <option hidden disabled>, więc ukrywa się we wszystkich dobrych przeglądarkach i wyłącza je w innych.
Ramon Balthazar
37

Sugerowałbym, abyś nie korzystał z rozwiązań wykorzystujących rozszerzenie<span> opakowanie, ponieważ nie jest to prawidłowy HTML, co może powodować problemy w . Myślę, że preferowanym rozwiązaniem jest faktycznie usunięcie wszystkich opcji, które chcesz ukryć, i przywrócenie ich w razie potrzeby. Korzystając z jQuery, będziesz potrzebować tylko tych 3 funkcji:

Pierwsza funkcja zapisze oryginalną zawartość pliku zaznaczenia . Dla pewności możesz chcieć wywołać tę funkcję podczas ładowania strony.

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

Ta następna funkcja wywołuje powyższą funkcję, aby upewnić się, że oryginalna zawartość została zapisana, a następnie po prostu usuwa opcje z DOM.

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

Ostatnia funkcja może być używana, gdy chcesz „zresetować” z powrotem do wszystkich oryginalnych opcji.

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

Zauważ, że wszystkie te funkcje oczekują, że przekazujesz elementy jQuery. Na przykład:

// 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

Oto działający przykład: http://jsfiddle.net/9CYjy/23/

Łukasz
źródło
3
Niezawodny i niezawodny. Świetna odpowiedź!
Jeremy Cook
1
@DanBeaulieu W poprzednim pliku jsfiddle była niepoprawnie nazwana funkcja. Naprawiłem i zaktualizowałem powyższy link. Dzięki, że to złapałeś.
Łukasz
Tak, ten też był moim wyborem. Właściwie udało mi się nieco zmniejszyć kod, najpierw biorąc wartość danych do zmiennej, jeśli jest niezdefiniowana, zapisze opcje, w przeciwnym razie przywróci opcje. Moja potrzeba była specyficzna.
diynevala
1
Musiałem dodać, var value=$select.val(); $select.html(ogHTML); $select.val(value);aby zachować wybraną wartość nawet po przywróceniu.
diynevala
Cykl wybierania opcji do usunięcia i ich usuwania działał tylko jeden raz. Po tym, options.remove () nie przyniosło mi żadnego efektu. Po przeniesieniu opcji restoreOptions ($ s) wywołaj kilka wierszy, aby zawsze pracować z pełnym, świeżym obiektem Select, zadziałało.
Newclique
18

Odpowiedź Ryana P powinna zostać zmieniona na:

    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;" />');
        }
    };

W przeciwnym razie zostanie opakowany w zbyt wiele tagów

JeffT
źródło
5
Zwróć uwagę, że zgodnie ze specyfikacjami HTML ( w3.org/TR/html5/forms.html#the-select-element ) a <select>powinien zawierać tylko elementy obsługujące skrypty <option>lub <optgroup>lub. Dlatego należy unikać używania nieprawidłowych <span>opakowań.
Łukasz
9

Funkcja toggleOption nie jest doskonała i wprowadziła nieprzyjemne błędy w mojej aplikacji. jQuery będzie mylony z .val () i .arraySerialize () Spróbuj wybrać opcje 4 i 5, aby zobaczyć, o co mi chodzi:

<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>
Batiste Bieler
źródło
8

W ten sposób wybieranie danych wejściowych jest trudne. A co z wyłączeniem go zamiast tego, zadziała to w różnych przeglądarkach:

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

Spowoduje to wyłączenie wszystkich <option> elementów, ale możesz wybrać dowolny, który chcesz.

Oto demo: http://jsfiddle.net/jYWrH/

Uwaga: Jeśli chcesz usunąć wyłączoną właściwość elementu, możesz użyć .removeProp('disabled').

Aktualizacja

Możesz zapisać <option>elementy, które chcesz ukryć w ukrytym elemencie wyboru:

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

Następnie możesz dodać <option>elementy z powrotem do oryginalnego elementu select:

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

W tych dwóch przykładach oczekuje się, że widoczny element select ma identyfikator, visiblea ukryty element select ma identyfikator hidden.

Oto demo: http://jsfiddle.net/jYWrH/1/

Zauważ, że .on()jest to nowość w jQuery 1.7, a użycie tej odpowiedzi jest takie samo, jak .bind(): http://api.jquery.com/on

Jaspis
źródło
7

Prosta odpowiedź: nie możesz. Elementy formy mają bardzo ograniczone możliwości stylizacji.

Najlepszą alternatywą byłoby ustawienie disabled=true opcji (i być może szarego koloru, ponieważ tylko IE robi to automatycznie), co spowoduje, że opcja będzie niemożliwa do kliknięcia.

Alternatywnie, jeśli możesz, całkowicie usuń optionelement.

Niet the Dark Absol
źródło
6
// Simplest way

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

$('select').change(function() {
    $('select').html(originalContent); //Restore Original Content
    $('select option[myfilter=1]').remove(); // Filter my options
});
Rene Berwanger
źródło
4

Ponieważ używasz już JS, możesz utworzyć ukryty element SELECT na stronie i dla każdego elementu, który próbujesz ukryć na tej liście, przenieść go na listę ukrytą. W ten sposób można je łatwo przywrócić.

Nie znam sposobu na zrobienie tego w czystym CSS ... Myślałem, że display: żadna sztuczka by nie zadziałała.

Derreck Dean
źródło
2

!!! OSTRZEŻENIE !!!

Zamień drugie „JEŚLI” na „GDY” lub nie działa!

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;" />' );
    }
};
Arraxas
źródło
2

Powinieneś je usunąć z <select>using JavaScript. To jedyny gwarantowany sposób, aby odejść.

Jordania
źródło
1
Korzystając z jQuery, można to zrobić, usuwając:$('options').remove();
Luke
2

ten wydaje się działać dla mnie w chrome

$("#selectid span option").unwrap();
$("#selectid option:not([filterattr=filtervalue])").wrap('<span/>');
zesłany
źródło
1
Dodaj format kodu do swojego kodu, poprzez wcięcie 4 spacjami lub zawijanie kodu za pomocą `.
Banan
1
ten kod jest świetny! działa na najnowszym chrome, firefox i IE 11, to mi wystarczy :)
Sijav,
1
przed moim ostatnim komentarzem, ta rzecz działa również w IE 7! wiec ff 3.5 to na koniec wymyśliłem to jakoś na IE i chrome zachowują wybraną wartość zanim opcje zostaną ukryte i jeśli inna wartość nie zostanie ustawiona po przywróceniu opcji przeglądarka ustawi opcję wybrane jak poprzednio!
Sijav
0

Spóźniona gra, ale większość z nich wydaje się dość skomplikowana.

Oto jak to zrobiłem:

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();
    }

});

znaczniki select-1:

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

znaczniki select-2:

<select id='select-2'>
<option class='t1'>One</option>
<option class='t2'>Two</option>
<option>Always visible</option>
</select>
RichardAtHome
źródło