company_banner

Простой универсальный переключатель на JavaScript

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

    Можно каждый раз писать JavaScript-код и стили к нему, но со временем это приводит к разрастанию кода, с чем в определенный момент мы и столкнулись.

    Однако проблему можно решить гораздо элегантнее. Рассматриваемое ниже решение отличается простотой и не требует последующего участия JavaScript-программиста, так как верстальщик сможет самостоятельно вносить нужные изменения в стили.

    Принцип работы


    Решение предложил наш разработчик Павел Довбуш aka dpp: в HTML-коде на переключающий элемент прописывается класс jst (JavaScript toggle), а на родительский элемент, внутри которого происходят изменения — jsw (JavaScript wrapper).

    Предлагаемый скрипт отслеживает щелчок на элементы с классом jst и переключает определённый класс на оборачивающем элементе с классом jsw. По умолчанию это класс jse (JavaScript enable), но для него может быть указано иное имя в атрибуте rel. Другие классы на элементе при этом не затрагиваются.

    Далее приведён код, который намеренно упрощён для демонстрации идеи, но его нетрудно дополнить или перевести на используемый фреймворк для поддержки браузера Internet Explorer версии 8 и ниже.

    // Отслеживание щелчков.
    document.addEventListener('click', clickEvent, false);
    
    function clickEvent(e) {
       /* Если это щелчок по .jst, выполняется
          функция переключателя toggle(). */
       if (e.target && /(^|\s)jst(\s|$)/.test(e.target.className)) {
           toggle(e.target);
    
           // Отмена действия по умолчанию (например, перехода по ссылке).
           e.preventDefault();
       }
    }
    
    function toggle(el) {
       var cls = el.rel || 'jse',
           // Регулярное выражение для поиска и замены класса.
           rcls = new RegExp('(^|\\s)' + cls + '(?=\\s|$)');
       // Поиск оборачивающего элемента.
       do {
           el = el.parentNode;
           if (!el) return; // Если не найден - делать нечего.
       } while(!/(^|\s)jsw(\s|$)/.test(el.className));
    
       // Переключение класса.
       if (rcls.test(el.className)) {
           el.className = el.className.replace(rcls, '');
       } else {
           el.className += ' ' + cls;
       }
    }

    Обработчик события щелчка «навешивается» сразу на узел document, используя «всплытие событий» (англ. event bubbling). Этот приём позволяет отслеживать щелчки в любом месте документа, не требует его полной загрузки (document уже существует при выполнении скриптов) и начинает работу сразу после того, как выполнен JavaScript, содержащий данный код. При этом увеличивается скорость инициализации страницы за счёт избавления от серии медленных DOM-запросов для «навешивания» обработчиков событий, которая была бы неизбежна при традиционном подходе.

    Атрибут rel в приведённом коде указан непосредственно через точку, однако такой вариант работает только со ссылками. Чтобы извлечь атрибут любого элемента, следует использовать метод getAttribute(). С точки зрения семантики корректней будет использовать атрибуты data-* из HTML5, рассмотрение которых выходит за пределы данной статьи.

    Для стандартных вариантов переключения разумно определить и стандартные стили. В Badoo для этого используются классы вида jsh, jsb, jseh, jseb:

    .js .jsb,
    .js .jse .jseb { display: block }
    .js .jsi,
    .js .jse .jsei { display: inline }
    
    .jsb, .jsi,
    .js .jsh,
    .js .jse .jseh { display: none }
    

    Класс js добавляется скриптом сразу же при выполнении, обеспечивая разделение стилевого оформления в зависимости от того, включён или выключен JavaScript:

    document.documentElement.className += ' js'
    

    Классы jsi и jsb включают при работающем JavaScript отображение строчного и блочного элементов соответственно, jsh — наоборот, скрывает. Классы jsei, jseb и jseh работают так же как и js-аналоги при наличии класса jse.

    С помощью этих классов можно гибко управлять поведением страницы, обеспечивая при этом «изящную деградацию» (англ. graceful degradation) в случае выключенного JavaScript в браузере.

    Примеры использования

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


    После нажатия на текст поля появляются, а сама псевдоссылка исчезает (ширина формы на изображении уменьшена).


    Этого можно добиться, например, с помощью следующего HTML-кода:

    <div class="jsw">
        <span class="change jst jsi jseh">Ваши настоящие имя и фамилия</span>
        <div class="jsh jseb">
            <label for="firstname">Имя</label>
            <input type="text" id="firstname">
        </div>
        <div class="jsh jseb">
            <label for="lastname">Фамилия</label>
            <input type="text" id="lastname">
        </div>
    </div>
    

    Класс change на псевдоссылке задаёт оформление, jsi показывает её при включённом JavaScript, а jseh скрывает после переключения. С помощью класса jsh скрываются поля при включённом JavaScript, а jseb делает их видимыми после переключения.

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

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

    Другие примеры использования на сайте:
    • Нажав на соответствующий текст, можно ознакомиться с условиями оказания платной услуги.

      Примерный HTML-код:
      <div class="jsw">
          <p>Стоимость услуги – 100 кредитов. Они будут сняты с вашего счета. <span class="jst service_conditions">Условия пользования</span></p>
          <p class="jsh jseb"><small>Нажимая на "Поднять наверх!", с вашего аккаунта Badoo будет списано 100 кредитов…</small></p>
      </div>
      
      Класс jsh скрывает текст мелким шрифтом, а jseb обеспечивает показ по нажатию на переключатель — псевдоссылку «Условия использования».
    • Если щёлкнуть по подписи к фотографии, то появится поле редактирования описания. Псевдоссылка «Отменить» возвращает к исходному состоянию.



    Расширенное использование


    Однако не всегда достаточно простого переключения, иногда необходимо переключаться между тремя и более состояниями, или что-то менять в заполняемой форме в зависимости от выбора пользователя из предложенных вариантов (с помощью радиокнопок).

    Функцию несложно доработать и для такого использования. Для этого определяется класс jss, по нажатию на элемент с которым, на родительском элементе с классом jsw будет перезаписываться класс значением из атрибута rel или value. Этот вариант уже стоит использовать аккуратно, так как любой другой класс на элементе, кроме jsw, будет затёрт.

    function clickEvent(e) {
        if (!e.target) return;
    
        // Если это щелчок по .jst, выполняется
        // функция переключателя toggle().
        if (/(^|\s)jst(\s|$)/.test(e.target.className)) {
            toggle(e.target);
    
            // Отмена действия по умолчанию (перехода по ссылке).
            e.preventDefault();
            e.stopPropagation();
        }
        // Если щелчок по .jss, в функцию toggle()
        // передаётся соответствующий параметр.
        if (/(^|\s)jss(\s|$)/.test(e.target.className)) {
            toggle(e.target, true);
    
            // В случае чекбоксов и радиокнопок
            // нужно дать кнопкам переключиться.
            if (e.target.tagName != 'INPUT') {
                e.preventDefault();
                e.stopPropagation();
            }
        }
    }
    
    function toggle(el, set) {
        var cls = el.rel || (el.nodeName == 'INPUT' ?
                            'jse_' + el.value : 'jse');
    
        // Поиск оборачивающего элемента.
        do {
            el = el.parentNode;
            if (!el) return; // Если не найден - делать нечего.
        } while(!/(^|\s)jsw(\s|$)/.test(el.className));
    
        if (set) {
            // Установка класса (.jss).
            el.className = 'jsw ' + cls;
        } else {
            // Регулярное выражение для поиска и замены класса.
            var rcls = new RegExp('(^|\\s)' + cls + '(?=\\s|$)');
    
            // Переключение класса (.jst).
            if (rcls.test(el.className)) {
                el.className = el.className.replace(rcls, '');
            } else {
                el.className += ' ' + cls;
            }
        }
    }
    

    Пример использования

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



    Несколько упрощённо, HTML-код выглядит так:

    <div id="gifts_wrapper" class="jsw all">
        <p class="description">
            <a href="#" class="jss" rel="all">Показать все</a>
            <a href="#" class="jss" rel="popular">Популярные</a>
            <a href="#" class="jss" rel="romantic">Романтические</a>
            <a href="#" class="jss" rel="friendship">Дружба</a>
        </p>
        <div class="gifts_items">
            <div class="giftframe romantic popular">
                <img src="…" title="Поцелуй">
            </div>
            <div class="giftframe friendship popular">
                <img src="…" title="Радуга">
            </div>
            <div class="giftframe friendship">
                <img src="…" title="Футбольный мяч">
            </div>
            <div class="giftframe romantic friendship">
                <img src="…" title="Первый приз">
            </div>
            <div class="giftframe romantic">
                <img src="…" title="Бикини">
            </div>
            <div class="giftframe romantic friendship popular">
                <img src="…" title="Вишня">
            </div>
        </div>
    </div>
    

    Каждый подарок представлен элементом <div class="giftframe"> с картинкой подарка внутри, а дополнительные классы у элемента определяют принадлежность к той или иной группе.

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

    .gift_items .giftframe {
        display:none;
    }
    .all .gift_items .giftframe,
    .popular .gift_items .popular,
    .romantic .gift_items .romantic,
    .friendship .gift_items .friendship { display:inline-block; }
    

    Примером использования функции с радиокнопками может послужить форма бронирования авиабилетов (к сожалению, у нас не нашлось столь же наглядного примера). В зависимости от бронирования билетов в одну сторону или туда-обратно показывается или отсутствует поле обратной даты.



    Пример HTML-кода:

    <div class="jsw">
        <label>
            <input type="radio" name="direction" class="jss" value="oneway">
            В одну сторону
        </label>
        <label>
            <input type="radio" name="direction" class="jss" value="twoway">
            Туда-обратно
        </label>
        <label>Дата туда:
            <input type="date" name="fly_date">
        </label>
        <label class="back_date">Дата обратно:
            <input type="date" name="back_date">
        </label>
    </div>
    

    С указанным кодом скрытие поля обратной даты можно обеспечить лишь одной строчкой в CSS:

    .jse_oneway .back_date { display:none }
    

    Заключение


    Вместо того, чтобы каждый раз изобретать велосипед, можно обобщить класс возникающих задач и найти универсальное решение, удовлетворяющее им в 80% случаев.

    Рассмотренная в данной статье функция позволяет решить множество типовых задач по переключению каких-либо элементов на странице силами одного лишь верстальщика, не перегружая при этом JavaScript-код и не отвлекая ресурсы JavaScript-программистов. Объём CSS-кода в результате тоже уменьшается.

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

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

    Достоинствами данной функции являются простота и универсальность. Она может работать во всех браузерах, где работает JavaScript, имеет все возможности для «изящной деградации» в случае неработающих скриптов и не требует никаких лишних элементов и «хаков», в отличие от метода с использованием скрытого <input type="radio"> и CSS3-селектора :checked.

    Update: По просьбам трудящихся несколько примеров выложено здесь.

    Лев Солнцев Aingis, веб-разработчик Badoo
    Badoo 356,58
    Big Dating
    Поделиться публикацией
    Похожие публикации
    Комментарии 64
      +8
      Извините, что я не по теме, но всё же напишу: очень приятно читать столь подробные и аккуратно оформленные посты! Спасибо :)
        +6
        Спасибо! Я старался, ровно как и наша команда.
        +2
         while(!/(^|\s)jsw(\s|$)/.test(el.className));
        

        Представляется, что такие места могут свести на нет все выигрыши в производительности.
          +1
          При работе переключателя у вас наверняка будет перерисовка, что требует на порядок больше ресурсов. К тому же .jsw как правило очень близко расположен, чаще всего на родителе. (Ситуации что .jsw не найден при нормальной ситуации быть не должно.)
            +1
            это код для примера, чтобы небыло зависимостей. в либе код другой
              0
              Вообще это вполне нормальная практика искать классы регуляркой, классы обычно имеют не более сотни символов, на таких крошечных данных регулярки сработают очень быстро, а удобство их использования на много лучше остальных способов.
              И это я вам говорю как человек который на JS писал парсеры и парсил довольно таки разные куски текста.
                0
                Я придерживаюсь такого же мнения. Конечно, можно сделать ту же логику без использования регулярок, но это лишь усложняет код и требует лишних трудозатрат без каких-либо ощутимых выгод. DOM-запросы и reflow+repaint после смены классы на порядки медленнее. Регулярки созданы именно для такой работы, здесь им самое место.
                  0
                  classList же.
                    0
                    Хорошая штука, но ещё есть не везде.
                      +1
                      Я пользуюсь одним простым правилом: в ие8 нет, значит пользоваться нельзя. Увы, пока я _обязан_ поддерживать этот браузер, и я пишу код как можно проще чтоб он в нем работал. Когда мне скажут что этот браузер можно не поддерживать, я с радостью начну использовать новые технологии =)
                        +1
                        Так по ссылке же есть обертка для ie8. + для нормальных браузеров нативная реализация будет, аль вообще на чистом CSS сделать посредством :checked.
                          0
                          А еще я не люблю делать двойную работу =) Если есть одно решение для ие8, я не буду делать второе для остальных и обьеденять их, потому как первое уже есть и уже работает, а ие8 нужно поддерживать. Так же я не думаю о будущем, если скажут убрать поддержку ие8, я лучше потрачу чуть больше времени, но переделаю все без костылей.
                            +2
                            Так classList получается проще со всех сторон. Не нужна поддержка устаревших браузеров, просто удаляем обертку, а код переключателя остается неизменным.
                              +1
                              У меня так тоже бывает: если есть версия, работающая в старых и новых браузерах, то зачем делать ещё лишнюю работу? Понты ради понтов не нужны, владельцам сайтов интересна отдача от них.
                            0
                            Этот браузер можно не поддерживать.

                            Я сказал — все, больше не будете поддерживать? :)
                              +1
                              Ну если бы вы мне платили за работу, то я бы с радостью отказался бы от него :)
                        0
                        Вообще, если уж сильно смущает этот фрагмент, то можно так:

                        while( (' ' + el.className + ' ').indexOf(' jsw ') > -1 )
                          0
                          А я вот так обычно пишу:
                          while(~ hash.indexOf(needle)) {}
                        –16
                        С помощью этих классов можно гибко управлять поведением страницы, обеспечивая при этом «изящную деградацию» (англ. graceful degradation) в случае выключенного JavaScript в браузере.

                        vk.com/graceful_degradation — приятное совпадение :)
                          +1
                          Думаю, к чему-то похожему универсальному приходит чуть ли не каждый разработчик. Потом это решение переходит из проекта в проект, потихоньку совершенствуясь.

                          Заглядывая под кат, ожидал увидеть jQuery плагин. Или вы по каким-то причинам не пользуетесь сторонними библиотеками?
                            +1
                            Во-первых, мы его не используем, у нас фреймворк собственной разработки (хотя и с включениями других библиотек), во-вторых, не хотелось плодить зависимостей ради такого достаточно простого случая. Не все пользуются jQuery — есть ещё mootools, prototype.js и пр.
                              +1
                              Меня тут поправляют, что весь JS-код наш. Некоторые участки мне просто напомнили другие библиотеки.
                              0
                              Если бы использовался jQuery то всю реализацию можно было бы уместить в 1-3 строчки. И это уже не тянуло бы на статью
                                +2
                                Суть статьи не в коде, а в решении типичной задачи. Иногда для таких моментов такое городят, что диву даёшься. В том числе и на хабре можно увидеть.
                              +5
                              Добавьте пожалуйста ссылку на страницу с живыми примерами.
                              Если дело касается js, я всегда первым делом смотрю демо-сайт, и только если там есть что-то достойное, начинаю читать статью. Думаю я тут не один такой :)
                                +1
                                А что тут смотреть, тут нету анимации или чего-то сверх естественного. Просто изложен принцип. Это не готовый плагин.
                                  +1
                                  Накидал страничку с парой примеров: my.dpp.su/badoo/js-toggle/
                                  +2
                                  Спасибо за статью! Действительно, приятно читать.

                                  Несколько замечаний:
                                  1. Не используйте сокращённые имена классов типа jst, jsw, jsh, jsb, jseh, jseb.
                                  Во-первых, прийдётся запоминать, что каждый из них означает, либо же искать их использование в коде.
                                  Во-вторых, приставка js выглядит несколько странно. Во время вёрстки верстальщику не нужно знать, что переключение режима выполняется javascript'ом. Классы должны определять семантику элементов, а не сведения о способе реализации функциональности.

                                  Я бы предложил следующие имена для этих классов:

                                  .jst —> .expand-toggle
                                  .jsw —> .expandable
                                  .jse —> .expandable.expanded
                                  

                                  Ну, или что-то в этом духе.

                                  2. Это уже мелочь, но всё-таки — название ссылки «Ваши настоящие имя и фамилия» не говорят пользователю о том, что произойдёт, если на неё кликнуть. «Заполнить настоящие имя и фамилию» было бы лучше в этом отношении.
                                    0
                                    С сокращёнными именами ни у кого сложностей не возникало. Зато приставка «js» даёт гарантию, что не будет случайных пересечений с другими классами, и подсказывает, что тут что-то связанное с поведением страницы. (Эдакое пространство имён.)

                                    Также предпочтение отдаётся коротким классам, потому что есть небольшой выигрыш в размере кода и их проще поддерживать: на элементе есть несколько классов. Ваше «expandable» ни о чём не говорит, к сожалению, и, не зная что это, понять его сложнее.
                                      0
                                      приставка js есть только у этих классов из сотен использующихся у нас
                                      это случайность, исторически так сложилось :)
                                        +1
                                        Я думаю, что проблем не возникает, только пока в памяти свежи мысли об этой части функциональности. Со временем, чтобы вспомнить, нужно будет исследовать исходный код.
                                        Ваше «expandable» ни о чём не говорит, к сожалению, и, не зная что это, понять его сложнее.
                                        По-моему, если не знать, что это, понять всё же проще, чем в случае с jsw :)
                                          –1
                                          Далеко не все верстальщики английский знают. Соответственно, большинству из них «expandable» ничего не скажет. А те кто знает язык, как догадаются, что «expandable» значит, что например по щелчку появится подсказка?
                                            +2
                                            Суть моих комментариев — в том, что «expandable» даёт хотя бы какую-то информацию для человека, который изначально не знает, что делает этот класс. jsw же не даёт никакой информации, кроме того, что функциональность как-то связана с javascript'ом.
                                              –2
                                              По-моему, отношение к JS даёт больше информации, чем литературное имя класса. Возможно, другое, более удачное, имя действительно скажет больше, но, как я отметил, мы не испытываем с этим никаких проблем.
                                        0
                                        > Во время вёрстки верстальщику не нужно знать, что переключение режима выполняется javascript'ом.
                                        мы работаем в команде, понимать что ты делаешь и как это будет использовано коллегами — обязательное требование к хорошему сотруднику
                                          +2
                                          Возможно, я неверно выразился. Я имел в виду, что, когда верстальщик верстает форму с разворачиваемыми областями, наиболее полезной информацией для него является семантика.
                                          Например, он забыл, какие классы отвечают за разворачиваемые элементы. Что он первым делом вспомнит? То, что они expandable, или то, что они реализованы при помощи js? :)
                                            –1
                                            Например, он забыл, какие классы отвечают за разворачиваемые элементы. Что он первым делом вспомнит?
                                            Что есть корпоративная вики, где это описано, (а теперь и эта статья) или более опытный коллега рядом.
                                              0
                                              Корпоративная вики — это хорошо. Но это не повод не давать человеку как можно больше информации прямо в коде.
                                              Это примерно как именование методов в классах. Вот некоторая пища для размышлений:

                                              function f1234() { /* ... */ }
                                              
                                              function t() { /* ... */ }
                                              
                                              function toggle() { /* ... */ }
                                              
                                              function toggleExpandable() { /* ... */ }
                                              
                                              function Expandable(element) {
                                                  this.element = element;
                                                  function toggle() { /* this.element. ... */ }
                                              }
                                              

                                              Какой вариант более читабельный?
                                                0
                                                Капитан! извините не удержался )
                                                см #comment_4822637
                                        +1
                                        /(^|\s)jss(\s|$)/.test(...)
                                        

                                        — такую регулярку, наверное, все же лучше заменить на:

                                        /\bjss\b/.test(...)
                                        
                                        0
                                        Только если у вас не встречаются классы с дефисом. Например, в стиле яндекса: «b-menu», а здесь: «jss-mod».
                                          +2
                                          Не знаю, что хорошего, вы находите в статье(кроме подробного изложение), но сам подход очень плохой.
                                          Вешать событие на весь документ, и потом вызывать каждый раз функцию, это не есть хорошо, а если у вас будет тысячу таких функций. Я конечно понимаю, что делегирование это круто, удобно и быстро, но нужно думать, где его использовать. Про навешивания javascript очень интересный подход изложил Андрей Сумин в докладе «Как не утонуть в мегабайтах JS-кода».
                                          Он предложил на все блоки, где нужно навесить js, повесить класс, а в самом элементе в свойстве onclick, указать модуль который нужно подключить. Сумин конечно использует свой велосипед для загрузки js (можно было бы использовать AMD) и кастомные событие, но сам подход по-моему просто супер, дает очень хорошо поддерживаемый и структурированный код.
                                            0
                                            Вешать событие на весь документ, и потом вызывать каждый раз функцию, это не есть хорошо, а если у вас будет тысячу таких функций.
                                            Не понял, а зачем вызывать тысячу функций? Достаточно одну, которая будет проверять, по списку классов или идентификаторов, назначено ли событие, и только в случае совпадения вызывать соответствующие назначенные функции. А вот обход всех элементов при загрузке для «навешивания» событий может сильно замедлить загрузку.
                                              0
                                              Про много функций я имел ввиду, если какое-то другое действие нужно выполнить будет(не переключение), а если к примеру вам понадобиться, где-то остановить всплытие как вы с этим будете бороться.
                                              По поводу обхода лучше я один раз обойду при загрузке(но все надо в меру конечно), чем при каждом клике. По факту вы каждый раз ищите элемент.
                                              Я вот как-то тяжело представляю, как вы это потом будете масштабировать.
                                                0
                                                Всплытие останавливается точно так же.
                                                Элемент дополнительно искать не надо, на него указывает event.target (event.srcElement в случае IE8−).
                                                Какие ещё проблемы с масштабированием?
                                                Время загрузки нам очень дорого. Не забывайте, что 70% времени загрузки приходится на клиентскую часть, а нетерпеливые пользователи уходят, если сайт недостаточно быстр. И это сказывается на доходе от сайта.
                                                  0
                                                  У меня такое ощущение, что мы друг друга не понимаем. В приведенном вами примере, я на всплытие не могу привести проблему. Но у меня возник вопрос в вашем коде
                                                   e.stopPropagation();
                                                  
                                                  То есть, другие элементы которые лежат выше вас уже не интересуют,(хотя у них тоже может быть класс jst), вот кстати и проблема всплытия, которую я хочу до вас донести.
                                                  По поводу скорости, поверьте ни одни Вы работаете на высоко нагруженных сайтах.
                                                  Я с вами полностью согласен, что front-end должен быть оптимизирован. Но по поводу того, что пользователь уйдет вы перебираете, конечно, если ваша страница не грузить минуту, то да уйдет.
                                                  Про масштабирование, мне сложно какие-то доводы привести. Просто это код не модульный и у него сильное связывание. И при нарастании функционала и плюшек, будет спагетти код, который я не раз видел.
                                                  Но желаю, что бы у вас все хорошо развивалось.
                                                    0
                                                    Надо понимать, что код здесь упрощён. У нас, конечно, код более модульный, оптимизированный и т. п.
                                                    Если интересуют элементы выше того, на который нажали, то можно так же подниматься вверх по дереву и проверять их как и основной. С этим проблем нет. Пример упрощён для доступности, чтобы не тащить килобайты используемых библиотек.
                                                      +1
                                                      Если для примера, то конечно подойдет. Но все таки
                                                      e.stopPropagation();
                                                      
                                                      Водит в заблуждение, и хорошей практикой, считается, при проектировании интерфейсов его избегать.
                                                      +1
                                                      «Но по поводу того, что пользователь уйдет вы перебираете, конечно, если ваша страница не грузить минуту, то да уйдет.» — на опытах — на секунду дольше грузится страница (не отдаётся бекэндом, а именно грузится у пользователя) — падение активности на 5%.
                                                        0
                                                        А как интересно делаете замеры? Было очень интересно об это узнать.
                                                          0
                                                          Активность просто смотрим по ключевым показателям. А про замер времени на клиенте я думаю dpp лучше и правильнее расскажет.
                                                            0
                                                            dpp в ближайшее время раскажет это тут: toster.ru
                                                              0
                                                              Нету возможности, его посетить. Но очень интересно было бы послушать.
                                                    0
                                                    это просто тестовый пример. а реализация делегирования не кончается одним jQ.live
                                                    в моей реализации скорость не зависит от количества обработчиков и является константой — в худшем случае 5 hash lookup, какое-либо взаимодействие с DOM только в случае если верстальщики не могут сверстать правильно, а это менее 10 случаев из нескольких сотен.
                                                    маштабируется уже 5й год просто отлично ;)

                                                    на счет «лучше все обойду» — не серьезно, хотя на мелких проектах может и допустимо.
                                                      0
                                                      А вы смотрели реализацию, jQuery live до 1.6 версии, и почему они рекомендуют использовать delegate. У вас как раз классическая реализация live.
                                                      А найти нужные элементы, это не так уже и долго. Посмотрите к примеру код gmail,yandex, там ребята почему-то не цепляют обработчик на весь документ.
                                                      А наш спор без тестов бесполезен.
                                                      Да я посмотрел, ваш код на сайте, действительно, он модульный и разбитый на объекты, и я вполне верю, что он хорошо масштабируемый.
                                                        0
                                                        посмотрел delegate в 1.7.2 — принципиально тоже самое: копание в DOM в цикле (строки 3291, 3297). это и называется «классическая реализация live».

                                                        >А найти нужные элементы, это не так уже и долго.
                                                        как говорится it depends. но практика это плохая.
                                                        вот старый, не очень удачный (сохранен во время аварии) график: время инициализации страницы своего профиля my.dpp.su/badoo/cookie-5-js-1m-aggr.png (на графике среднее из миллионов хитов)

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

                                                        но да, без тестов нет смысла обсуждать дальше
                                                    0
                                                    Не понял, а зачем вызывать тысячу функций?


                                                    Вы вешаете обработчик на документ, и в коде регуляркой проверяете соответствие классу — каждый клик на любом элементе документа запускает ваш обработчик.
                                                      0
                                                      это просто пример. статья демонстрирует подход, а не конкретную реализацию
                                                        0
                                                        Вы так говорите, как будто в этом есть что-то страшное.
                                                        Во-первых, щелчки мышкой довольно редки (по меркам процессора чуть ли не вечность).
                                                        Во-вторых, браузер компилирует регулярное выражение при первом использовании (кроме new RegExp, который можно закешировать самостоятельно).
                                                        В-третьих, у вас вряд ли больше порядка ста обработчиков на одной странице.
                                                        В-четвёртых, щелчок, вероятно, подразумевает какое-то действие, по сравнению с которым время проверки обработчиком ничтожно.
                                                        Вы и моргнуть не успеете, как обработчик выполнится даже на самых медленных браузерах.

                                                        Хотя на боевых используется более быстрая проверка, грубо, выглядящая так:
                                                        if (class in handlers)
                                                            handlers[class](el);
                                                        
                                                        где используется тот факт, что если на элементах есть классы, то очень немного (обычно до пяти, чаще всего только один).

                                                        Здесь всё-таки пример, и подобная реализация заметно усложнит код без видимых преимуществ.
                                                          0
                                                          Во-первых, из таких вот «не успеет глазом моргнуть» выростают «падения активности в 5%» — сперва вы пишите о важности скорости, а потом говорите, что этим можно пренебречь — не понимаю.

                                                          Ну и потом, если почитать тут ответы вашей команды, то через один вы все пишите «это для примера, на продакшене у нас другой, „хороший“ код». Простите, но зачем тогда тут выкладывать «плохой» код? Идея переключения классов совершенно не нова, и смысл статьи лично для меня до сих пор не понятен.
                                                            0
                                                            про «неважно» бред, согласен

                                                            про «другой код» — сама функция три строки, нужные куски либы несколько сотен строк. код не open-source. зачем это в статье? статья не про наш фреймворк.

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

                                                            dpp@www1.d3 ~/badoo> grep -rwoEh 'js[twe]' _templates|wc -l
                                                            498
                                                            и для всех этих случаев у нас 1 строка жс.
                                                            если писать каждый раз, то будут сотни функций делающие похожую работу
                                                    +1
                                                    Нажимая на «Поднять наверх!», с вашего аккаунта Badoo будет списано 100 кредитов…

                                                    Напишите лучше «После нажатия на „Поднять наверх!“, с вашего аккаунта Badoo будет списано 100 кредитов…» либо «Нажимая на „Поднять наверх!“, Вы разрешаете списать с вашего аккаунта Badoo 100 кредитов…».
                                                      0
                                                      мне понравилось)

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

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