Нестандартные чекбоксы

Задача


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



Посмотреть пример на jsfiddle
Скачать исходники из github

Проблема которую нужно решить


Надо иметь возможность на «лету» изменять одно из состояний стилизованного чекбокса:
  • чекнут
  • не чекнут
  • в фокусе
  • задизейбленый
  • задизейбленый и чекнутий
  • чекнутый и в фокусе

При этом дать какие то классы на него + на его родителя (что бы соотвествувало дизайну).

Возможность одержать на каждое изменение чекбокса соответствующее событие и обработать его.

Чтобы работало у всех популярных браузерах.

Как это работает


HTML:
<fieldset class="frame-checks-not-standart">
    <label>
        <span class="niceCheck b_n">
            <input autofocus type="checkbox" checked="checked" tabindex="1"/>
        </span>
        <span class="title">focus checked</span>
    </label>
</fieldset>

CSS:
Класс b_n в стилях должен иметь правило background-image:none для того, чтобы при выключенном javascript-е сберечь стандартные чекбоксы.

JS:
$(‘.frame-checks-not-standart’).nStCheck();


Что еще можно знать


  1. Параметры
    Все параметры имеют дефолтное значение.

    • wrapper (jQuery объект)
      Элемент-обертка, по которому будет производиться переключение чекбокса;

    • elCheckWrap (jQuery селектор)
      Элемент-обертка, который и будет использоваться для отображения различных состояний чекбокса;

    • classRemove
      название класса, который надо удалить у $(elCheckWrap) (позволяет оставлять стандартное или же использовать нестандартное отображение чекбоксов).

    • evCond (булевый тип)
      Эсли true будет вызван метод trigger, иначе будет вызван метод after;

    • trigger (метод)
      при вызове получает четыре параметра:
      • объект, в контексте которого вызван плагин;
      • wrapper;
      • elCheckWrap;
      • объект события (функции обработчика события).

    • after (метод)
      при вызове получает те же параметры, что и trigger. Если используется, то состояние чекбокса не меняется, его можно изменить непосредственно в функции (это нужно, к примеру, если мы ждем ответ от сервера);


  2. Методы
    Все методы принимают единственный параметр $(elCheckWrap) — если метод вызван как функция. Если метод вызван в контексте $(elCheckWrap), то в функции обработчика принимает значение оператора this.
    Напомню пример вызова метода:
    $(‘.niceCheck’).nStCheck(‘changeCheck’)
    

    Также методы этого плагина можно вызвать так:
    $.nStCheck(‘changeCheck’)($(‘.niceCheck’))
    

    • _changeCheckStart
      Метод задает начальное состояние (вызывается при инициализации плагина);

    • checkChecked
      Задает положительное значение атрибута checked, добавляет класс active для wrapper и $(elCheckWrap);

    • checkUnChecked
      Задает отрицательное значение атрибута checked, убирает класс active для wrapper и $(elCheckWrap);

    • changeCheck
      Задает отрицательное значение атрибута checked, если оно положительное, и наоборот (своего рода toogle);

    • checkAllChecks
      Задает положительное значение атрибута checked для всех переданных объектов;

    • checkAllReset
      Задает отрицательное значение атрибута checked для всех переданных объектов;

    • checkAllDisabled
      Задает положительное значение атрибута disabled для всех переданных объектов, добавляет класс disabled к wrapper и $(elCheckWrap);

    • checkAllEnabled
      Задает отрицательное значение атрибута disabled для всех переданных объектов, убирает класс disabled для wrapper и $(elCheckWrap);


  3. События
    Навешивание всех событий используется с namespace-ом (nstcheck)
    • reset (form)
      Обработчик события задействует метод checkAllReset для всех прежде не выбраных и checkAllChecks для прежде выбраных;

    • mousedown (input)
      Обработчик события отменяет стандартное поведение и изменяет состояние;

    • click (input)
      Обработчик задейстует метод stopPropagation() к объекту события;

    • keyup (input)
      Обработчик события отменяет стандартное поведение при нажатии клавиши «пробел» и изменяет состояние;

    • focus (input)
      Обработчик события добавляет класс focus для $(elCheckWrap) и wrapper;

    • blur (input)
      Обработчик события убирает класс focus для $(elCheckWrap) и wrapper;

    • change (input)
      Обработчик события отменяет стандартное поведение;

    • click (wrapper)
      Обработчик события “повешен” на элемент wrapper (изменяет состояние).


  4. Кастомные события
    Навешивание всех кастомных событий происходит с namespace-ом (nstcheck)

    Все кастомные события записывают в объект события одно свойство:
    el ($(elCheckWrap));

    Эти события можно повесить на какой-нибудь input, который задействован в этом плагине, например так:
    $('input').on('nstcheck.cc', function(e){
         console.log(this); // $('input') - объект, в контексте которого вызывается //событие
         console.log(e.el); // выведет $(elCheckWrap)
    });
    

    • nstcheck.cc
      Настает при вызове метода checkChecked;

    • nstcheck.cuc
      Настает при вызове метода checkUnChecked;

    • nstcheck.ad
      Настает при вызове метода checkAllDisabled;

    • nstcheck.ae
      Настает при вызове метода checkAllEnabled.


Заключение


Плагин снабжен полным функционалом стандартных чекбоксов, имеет компактную структуру HTML — представление по сравнении со структурой стандартных, а также снабжен кастомными событиями и колбеками. Можно стилизовать любое состояние, которое есть в стандартных, работает при Tab обходе, работает стандартная кнопка reset.
ImageCMS
42.64
Company
Share post

Comments 76

    +10
    а чем вас не устраивает использование label for=""? Просто любопытно :)
      –7
      потому что нельзя стилизовать чекбоксы.
        +5
        Их не надо стилизовать, вот вариант jsfiddle.net/kpanenko/4f76m/
          0
          вы не учли много вариантов:

          если чекбокс при старте страницы
          — чекнут
          — в фокусе
          — задизейбленый
          — задизейбленый и ченутий
          — чекнут и в фокусе

          плюс в вашем варианте нет колбеков, нет кастомных событей, не изменится состояние чекбокса когда у него фукус и вы жмете пробел, не подсвечивается при таб-обходе, при ресете не изменится картинка…
            +7
            jsfiddle.net/Z27rL/ вот вам с выполнением всех требований. И без js.
              –4
              но это не работает ниже ie9
                +2
                может, все же лучше и аккуратнее использовать полифилл вроде selectivizr.com/?
                  –3
                  этот плагин рассчитан не только иметь возможность стилизировать чекбоксы, но и иметь инструмент для того чтобы изменять разные состояния одного или групы чекбоксов.
                –5
                И, как насчет колбеков и кастомных событей?
                  +2
                  а почему бы их просто не навесить на сами чекбоксы?
                    –2
                    как вы навесите событие изминение атрибута чекбокса например в disabled=«disabled»?
                      +2
                      $input.on('change'). А вас что-то смущает?
                        –3
                        Вы хотите сказать что обработчик событие change сработает если атрибут disabled получит значение disabled?

                        Я тепер понимаю какой у вас уровень jQuery, и почему вы так отстаиваете на не всюду рабочей версии CSS с малым количеством возможностей.
                          +3
                          Отличная дуэль, господа.
                            +2
                            А кто победил, заплюсованный или заминусованный?
                            0
                            да, прошу прощения, задумался, перепутал с checked.
                            Checked (параметр html-ноды, не атрибут) запускает событие change:
                            document.querySelector('input').checked = true

                            Корректно и правильно возможно отлавливать изменение любого атрибута, в том числе disabled, только так(возможно, где-то есть баг, я не проверял код):

                            (new MutationObserver(function(mutationRecords){
                                [].forEach.call(mutationRecords, function(mutationRecord){
                                    if ((mutationRecord.target.tagName === 'INPUT') && 
                                        (mutationRecord.target.type === 'checkbox') && 
                                        (mutationRecord.attributeName === 'disabled')) 
                                              mutationRecord.target.dispatchEvent(new CustomEvent('disable', {
                                                   bubbles: false,
                                                   cancelable: false
                                              }))
                                    
                                })
                            })).observe(document.body, {
                                attriubutes: true, 
                                subtree: true
                            }).
                            


                            С полифиллом будет ie9+. А
                    –3
                    плюс без плагина вроде єтого вы не имеете возможности, чекнуть или сделать одно и с выше перечисленных состояний для групы чекбоксов
                      –3
                      нет возможности стилизировать родителя, что часто требуется.
                    0
                    нельзя внутри label размещать input клик по label ставит у фокус, тригает клик или изменяет стан (как у случаи с чекбоксом) внутринего элемента формы, может наблюдатся у некоторых браузерах «двойной клик», если нужна такая структура, то надо в обработчику события клику по input написать event.stopPropagation()
                  –2
                  нельзя стилизовать отца, а еще надо различные колбеки — что есть в этом плагине.
                    +2
                    колбэки можно и нужно вешать на 'change' событие, так более, гхм, семантично, как минимум.
                    а стилизовать отца как-то тоже зло очень.
                      –1
                      а если вам не надо чекать чекбокс при клике, а только когда придет ответ от сервера?
                        –1
                        или же задизейблить
                        или в фокус поставить
                        и т. п.

                        этот плагин снабжен необходимыми методами.
                          +2
                          <input type="checkbox" disabled>
                          

                          input:disabled ~ {}
                          


                          <input type="checkbox" checked>
                          

                          input:checked ~ {}
                          


                          <input type="checkbox" autofocus>
                          

                          input:focus ~ {}
                          


                          не вижу сути проблемы
                        0
                        А еще он борщ умеет варить.
                        Никто не говорит что плагин плох, но вам предложили более простое, лаконичное и семантически более верное решение.
                        Все остальные требования как, то: колбэки, «стилизовать отца» (надо бы запомнить фразу) и т.д., могут понадобиться, а могут и нет. Если они нужны они решаются элементарно в пару строчек JS.
                          0
                          требование простые и понятные чтобы всюду работало и без костылей.
                          Я же не опровергаю тот факт что хорошо смотрится решение на CSS + различные костыли, но я с самого начала написал о чем статья и какие возможности должны быть у представленного функционала.
                      +3
                      Спасибо вам за труд.
                      Но я как-то привык делать нестандартные переключатели для форм через :checked, т.е. на гольном CSS.
                      А для IE7-8 checked-polyfill.
                        0
                        Примеров много:
                        kizu.ru/fun/controls/,
                        pepelsbey.net/2012/08/stylish-switch/,
                        www.thecssninja.com/demo/css_custom-forms/legacy/ первая ссылка из гугла.
                          0
                          все они используют селекторы которые не работают в всех браузерах.
                            +1
                            image
                            А для IE7-8 checked-polyfill.
                            Основная мысль моего комментария в том, что можно использовать вашу разработку как polyfill для старых браузеров, но в подавляющем большинстве современных браузеров данная задача проще и быстрее решается средствами CSS.
                              0
                              А как насчет комментариев ниже
                                0
                                но checked-polyfill не стилезирует задизейблены чекбоксы, чекбоксы в фокусе, задизейблены и чекнуты чекбоксы, чекбосы при навидении, чекбоксы в активном стане.
                            –1
                            но, нет возможности стилизировать блок который обертывает чекбокс и label
                              –1
                              А представте если вам надо чекнуть чекбокс после прихода ajax запроса.
                              С етим плагином можно ето сделать.
                              Нативными методами — нет.
                                0
                                В чем проблема его чекнуть как обычный чекбокс через JS?
                                  –1
                                  но если вы на него нажмете то он автоматически изменится, а с имеющимися колбеками вы это сделаете правильно
                                    0
                                    Извините, не понимаю вас. Поясните, что вы имеете в виду?
                                      –1
                                      если вы жмете на чекбокс то он изменяется, а если вам нужно чекнуть или анчекнуть чекбокс после того как придет ajax — запрос, с помощь метода trigger это можно сделать
                                        0
                                        И что? В чем проблема строчечку в js написать?
                                        $('input').attr('checked');
                                          –1
                                          но, если вы физически кликните на него то он изменится посредством браузера
                                            +4
                                            Извините, какие вещества вы употребляли за последнее время? :D
                                              –1
                                              например вам надо чтобы чекбокс чекнулся или же одержал какое то иное состояние после прихода ответа от сервера, если вы на него кликните левой кнопкой мышки то он изменится мгновенно — посредством браузера. А нам этого не надо!
                                                0
                                                return false вам о чем-нибудь говорит?
                                                  –1
                                                  все правильно пишете, но если вам придется изменить состояние чекбокса, на

                                                  — чекнут
                                                  — не чекнут
                                                  — в фокусе
                                                  — задизейбленый
                                                  — задизейбленый и чекнутий
                                                  — чекнут и в фокусе

                                                  при этом дать какие то классы на него + на его родителя (что бы соотвествувало дизайну)
                                                  а сначало ище удалить все ненужные класы
                                                  Вы будете для этого писать велосипед, а зачем новый если есть старый

                                                  все что нужно написать:
                                                  $(‘.frame-checks-not-standart’).nStCheck();
                                                  +1
                                                  preventDefault() в событии onclick вам ни о чем не говорит? Сначала запоминаем target при возникновении события, отправляем запрос на сервер и по возвращению меняем атрибут у target. Делов-то. Всегда задавался вопросом при мысли о таких плагинах — если плагин по каким-то причинам придётся отключить будет ли работать основной функционал чекбоксов? Если нет, то на помойку такой плагин — все события должны быть навешаны на чекбоксы, а плагин должен их всего лишь перехватывать, чтобы отображать состояние.
                                                    0
                                                    preventDefault(); — говорит как и retrun false;
                                                    Плагин рабатет при выключеном javascript-е. Описано как задача с самого начала статьи, и чуть ниже написано:

                                                    Класс b_n в стилях должен иметь правило background-image:none для того, чтобы при выключенном javascript-е сберечь стандартные чекбоксы.
                                                      0
                                                      я не про выключенный js говорил, а про выключенный плагин стилизации контролов. Я понимаю, что ситуация специфическая, но смысл в том, чтобы изначально все события привязывать к оригинальному контролу, а не эмулированному.
                                                        0
                                                        У вас есть функция checkChecked, которая устанавливает атрибут checked оригинальному контролу, но нет события change на этот контрол, поэтому я не смогу какой-то внешней функцией привязаться на onchange к оригинальному контролу, мне придется привязываться к специфичному nstcheck.cc. А если завтра по каким-то причинам мне придется отказаться от этого плагина или заменить его на другой? То всё, весь функционал рухнет, потому что был завязан на специфичные события несуществующего плагина?

                                                        В общем все это плохо, потому что вы лишаете разработчика стандартных методов работы с контролом и подсовываете свой велосипед предлагая весь функционал завязать на нём.
                                                          0
                                                          может я чего то не понял, но не обезательно привязываться примеру к nstcheck.cc, вы можете и далее обрабатывать change
                                                          здесь я дописал $('input').change(function(){alert(1)})
                                                            0
                                                            Посмотреть пример на jsfiddle
                                                            jsfiddle.net/domovoj/9BPAf/

                                                            P. S. сылка почему то не вставилась — может через recovery mode :)
                                    +1
                                    Не хочу показаться занудой, но это скорее называется non-standard checkboxes, так будет правильнее. Not Standart — слишком уж по-русски :)
                                      0
                                      Согласен :)
                                      0
                                      Без js csscheckbox.com
                                        0
                                        <ie9 — нет
                                          +6
                                          И слава богу.
                                            +1
                                            Но и ваш в IE8 не работает.
                                              0
                                              там data-uri используется для картинки, если поставить физическую картинку все будет нормально.
                                          0
                                          jsfiddle ссылка из поста не работает. вижу одинаковые чекбоксы в обоях случаях
                                            0
                                            поправил
                                              0
                                              1 focus checked и 2 disabled, и 3 disabled and checked не работают как надо.
                                              1. после снятия чека с бокса теряется фокус и больше не восстанавливается.
                                              2. не видно что задизаблен чекбокс
                                              3. можно снять галочку и поставить.
                                                0
                                                С disabled and checked можно снять галочку, просто покликав по другим и кликнув на него.
                                                  0
                                                  спасибо, поправил.
                                                  0
                                                  1,2 — там табиндексы прописаны,

                                                  2 — визуально не видно?
                                                  3 — поправил
                                                    0
                                                    2 — да, если чекбоксы без галочки, то активный от задисэйбленного не отличить.
                                              +10
                                              В Internet Explorer 5.5 немножко сбоит верстка, нельзя ли поправить?
                                                0
                                                Хороший троллинг — незлобный такой :)
                                                0
                                                Поправил TabIndex'ы: jsfiddle.net/9BPAf/23/embedded/result/

                                                Действительно классно работает.
                                                  0
                                                  Ваши tabindex неправильно работают. Только что чекнутый чекбокс должен стать текущим и при нажатии на таб переходы должны с него начинаться.
                                                    0
                                                    Я только расставил номера табиндексов по порядку в HTML-коде. Все претензии к автору поста.
                                                      0
                                                      Вы написали: «поправил», ну я и подумал всякое…
                                                  0
                                                  209 строк чтобы кликнуть чекбокс… там люди игрушки за 30 строк пишут…
                                                    0
                                                    209 строк не считая что ещё и жЫквери нужен.
                                                      0
                                                      Хорошо еще jquery ui здесь нет, а то всякое бывает…
                                                        0
                                                        И немного YUI для пряности.
                                                          0
                                                          этот плагин написан по потребности, а не чтоб навешать всего подряд, если вам етого не нужно то я за вас рад. Какое-то стихотворение вышло :)
                                                    –2
                                                    Если используете почту Gmail там есть фильтр на фронте (http://prntscr.com/282n9o)

                                                    Там есть и подсвечевание родителя и элемента-обертки чекбокса (енужность которого так сильно оговаривалось здесь) и колбеки и изменение групы чекбоксов.

                                                    Конечно там не используются чекбоксы только в упрощенной версии, но суть таже.

                                                    Only users with full accounts can post comments. Log in, please.