• Как фильтровать элементы с кириллицей в isotope.js?

    firedragon
    @firedragon
    Не джун-мидл-сеньор, а трус-балбес-бывалый.
    Я бы использовал транслит.

    абиссинское золото -> abessinskoye_zoloto

    https://github.com/greybax/cyrillic-to-translit-js
    Ответ написан
    Комментировать
  • Устарел ли getElementsBy* и чем лучше querrySelector?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Вот народ ушел в спор о производительности, но никто даже не попытался разобраться, а что под капотом... Производительность ведь искусственными бенчмарками меряют, ага...
    Что ж, времена сейчас такие
    многие на работу кодеров берут, которые даже интереса не имеют в глубь копать. Инженеров брать... - это устаревший подход, как выразился автор "популярного сайта", который прочел автор вопроса. Инженеры они дорогие, и найти их сложно, лучше кодер, пусть и не желающий на работе мозг включать, не говоря уж о желании в устройстве инструментов разбираться.

    Говорить о том, что некие фичи устарели - крайне глупо, если знать, что они ведут себя иначе, чем более модные альтернативы. Предлагаю немного разобраться и начать с того что на поверхности:
    - getElementById и querySelector возвращают конкретную ноду в единственном экземпляре
    - querySelectorAll и getElementsByName возвращает статичную коллекцию NodeList
    - getElementsByClassName, getElementsByTagName и getElementsByTagNameNS возвращают динамическую коллекцию HTMLCollection
    Как видим результат у разного апи различен, а значит и говорить, что некоторые из них устарели - глупо.
    Правда тут есть забавный момент
    в спеке HTMLCollection отмечен как "исторический артефакт", который не стоит использовать при проектировании нового апи. Но заметка эта не для веб-разработчиков, а для тех кто проектирует новое DOM апи.

    С устареванием вроде разобрались, но в вопросе еще есть часть "чем лучше". И тут есть теория, что getElementsBy* быстрее querySelector*. Чисто теоретически звучит логично, querySelector* должен делать полный поиск по дереву со сложностью O(n), а getElementsBy* могут использовать индексы на базе HashMap и получать данные со сложностью O(1), тут и особенности HTMLCollection будут кстати, так как можно не копировать коллекцию, а отдавать одну и ту же (и браузеры действительно так делают). Но без пруфов теория так и останется теорией.
    И бенчмарки - так себе пруф
    Хотя направлять инвесторов в нужную сторону - самое то. Проблема бенчмарков, что можно написать их так, что любая из сравниваемых сторон заметно обгонит другую. Дело техники. Например BubbleSort с O(n2) при определенных условиях в чистую уделывает MergeSort и QuickSort с их O(n×log2n), а именно при n=20 или меньше, 400 простых memswap в наглую рвут 87 рекурсивных операций с memcpy внутри
    Гораздо лучше тут выглядят исходники. И я выбрал исходники chromium, как самого распространенного:
    - getElementsBy* методы все как один обращаются к некой шаблонной функции EnsureCachedCollection, которая в свою очередь обращается к некоему NodeLists кэшу, устроенному внутри действительно как HashMap или что-то наподобие. Никакого поиска тут нет, просто берутся готовые значения, сложность у всего этого действительно константная O(1).
    - querySelector* используют абстракцию SelectorQuery, которая и в самом деле делает поиск по DOM. Но данный поиск неплохо оптимизирован и обвешан кэшами. Притом CSSOM использует абсолютно тот же алгоритм поиска DOM нод для каждого селектора в css.
    Для примера
    в подключенных на странице этого вопроса стилях более 1600 правил (некоторые из которых потенциально могут содержать несколько селекторов), полная обработка стилей из этого файла заняла на моей машине (Ryzen 3600 в стоке) чуть больше 9 мс. Если все это немного округлить, то понадобится 15000 querySelectorAll подряд, притом с разными селекторами, чтоб был промах кэша, дабы я ощутил заметную глазу задержку в ~100мс


    На этом спор думаю можно закрыть. querySelector* методы действительно могут быть медленнее, но чтоб убить ими производительность, нужно очень постараться. На фоне того, что пишут кривые ручки среднестатистического дешевого js-кодера это будет незначительной потерей измеряемой в наносекундах. Используйте то что удобнее в каждой конкретной ситуации.
    Ответ написан
    1 комментарий
  • Когда использовать микс, а когда модификатор?

    Realetive
    @Realetive
    MODX Ambassador России, самозванный БЭМ-евангелист
    Первое, что нужно научиться делать — находить повторяющиеся сущности (которые в последствии станут Блоками и Элементами). Вы уже пытаетесь сделать это, но пока получается слишком многословно, судя по количеству классов и это, очевидно, сбивает с толку.
    Я уже рассказывал на последнем БЭМапе (https://youtu.be/d4dcGj8abv0) о том, как я ищу эти повторяющиеся закономерности, поэтому постараюсь кратко:
    1) Собираем и группируем «данные»
    Разберём «шапку» и «подвал». И там, и там есть логотип, какая-то навигация, контактная информация, ссылки на соц. сети, в шапке есть кнопка:
    1.1) «Шапка»

    {
      logo: {
        img: 'путь до картинки',
        text: '…',
      },
      contacts: [
        'телефон',
        'email',
        'график работы',
        'адрес',
        'соц. сети',
        'кнопка обратной связи',
      ],
      navigation: [
        'пункт меню…',
        'пункт меню…',
        'пункт меню…',
      ]
    }


    1.2) В «подвале» почти то же самое, что-то в другом порядке, но это неважно, и нет «кнопки обратной связи» из секции «Контактов».

    1.3) Есть ещё самостоятельные секции «Свяжитесь с нами» на главной странице и на странице контактов, которые тоже используют пункты из секции «Контактов» (теперь уже понятно, что такое частое повторение позволяет выделить это в блок).

    1.4) Логотип и навигацию тоже выделим в блоки (я разделил логотип на два элемента — изображение и текст, потому что на малых экранах текст превращается в замыленое нечитаемое говно, поэтому его лучше убрать).

    1.5) Получается какая-то такая структура:

    // Блок логотипа
    {
      logo: [
        { img: '…' },
        { text: '…' },
      ]
    }
    
    // Блок контактов
    {
      contacts: [
        { tel: '…' },
        { email: '…' },
        { schedule: '…' },
        { address: '…' },
        { socials: [
          { vk: '…' },
          { telegram: '…' },
          { instagram: '…' },
        ] },
        { map: '…' },
        { feedback: '…' },
      ]
    }
    
    // Блок навигации
    {
      navigation: [
        { item: '', link: '…' },
        { item: '', link: '…' },
        { item: '', link: '…' },
      ]
    }
    
    // Блок «Шапки»
    {
      header: [
        {
          logo: [] // Тут всё без изменений
        },
        {
          contacts: [
            'tel',
            'email',
            'schedule',
            'address',
            'socials',
            'feedback',
          ]
        },
        {
          navigation: [] // Тут тоже без изменений
        }
      ]
    }
    
    // Блок «Подвала»
    {
      footer: [
        {
          logo: [] // Тут всё без изменений
        },
        {
          navigation: [ // Тут почти без изменений
            // …
            'Марки автомобилей' // Без выпадающего списка
            // …
          ]
        },
        {
          contacts: [
            'tel',
            'email',
            'address',
            'socials',
            'schedule', // Без иконки
          ]
        },
      ]
    }



    2) Вроде, пока хватит. «БЭМизируем» эти данные.
    Структура в формате JSON

    // Блок логотипа
    {
      block: 'logo'
      content: [
        { elem: 'img', src: '…' },
        { text: '…' },
      ]
    }
    
    // Блок контактов
    {
      block: 'contacts'
      content: [
        { elem: 'tel', content: '…' },
        { elem: 'email', content: '…' },
        { elem: 'schedule', content: '…' },
        { elem: 'address', content: '…' },
        { elem: 'socials', content: [
          { elem: 'vk', content: '…' },
          { elem: 'telegram', content: '…' },
          { elem: 'instagram', content: '…' },
        ] },
        { elem: 'map', content: '…' },
        { elem: 'feedback', content: '…' },
      ]
    }
    
    // Блок навигации
    {
      navigation: [
        { item: '', link: '…' },
        { item: '', link: '…' },
        { item: '', link: '…' },
      ]
    }
    
    // Блок «Шапки»
    {
      header: [
        {
          block: 'logo'
        },
        {
          block: 'contacts',
          // У этого блока определённо свой контент,
          // будем отличать его от других вариантов
          // этого блока с помощью модификатора
          mods: { view: 'header' },
          content: [
            { elem: 'tel' },
            { elem: 'email' },
            { elem: 'schedule' },
            { elem: 'address' },
            { elem: 'socials' },
            { elem: 'feedback' },
          ]
        },
        {
          block: 'navigation',
          // Этот блок по внешнему виду отличается от блока в «Подвале»,
          // поэтому обозначим его модификатором
          mods: { view: 'header' },
          content: [
            // …
            // У одного пункта выпадающий список
            {
              elem: 'item',
              item: 'Марки автомобилей',
              elemMods: { dropdown: true },
              content: [
                // …
                { elem: 'subitem', item: 'Infinity', href: '…' }
              ]
            },
            // …
          ]
        }
      ]
    }
    
    // Блок «Подвала»
    {
      footer: [
        {
          block: 'logo'
        },
        {
          block: 'navigation',
          mods: { view: 'footer' },
          content: [ // Тут почти без изменений
            // …
            { elem: 'Марки автомобилей', link: '…' }, // Без выпадающего списка
            // …
          ]
        },
        {
          contacts: [
            'tel',
            'email',
            'address',
            'socials',
            { elem: 'schedule', elemMods: { noIcon: true } }, // Без иконки
          ]
        },
      ]
    }


    2.1) Базовый лэйаут: https://codepen.io/Realetive/pen/PoGRjZo
    2.2) Добавляем обёртки для группировки некоторых элементов: https://codepen.io/Realetive/pen/KKgoBdN
    Про обёртки и зачем они нужны уже обсуждалось в https://ru.bem.info/forum/656/, очень советую.
    2.3) Добавим отступы: https://codepen.io/Realetive/pen/bGwvjow
    Как видите, миксы по-прежнему не нужны.
    3) У контента есть фиксированная ширина, обозначим её через класс-элемент блока page: например, .page__layout:
    https://codepen.io/Realetive/pen/WNGzgjJ
    Но вёрстка закономерно сбилась, потому что классы, которые мы назначали для родительского уровня, «поднялись» ещё н один уровень. Добавим ещё обёртки, чтобы «выровнять» лэйаут: стили header перенесутся в header__body, из footer в footer__body: https://codepen.io/Realetive/pen/wvzmEpy
    4) Получилось достаточно много «лишних» обёрток только лишь для позиционирования. Можно было бы этого избежать, если бы стили были описаны в одном классе. Но тогда мы лишимся пользы разделения логики благодаря БЭМ-неймингу. Вместо этого объединим эти слои с помощью миксов: page__header + header, header__body + page__layout, page__footer + footer, footer__body + page__layout: https://codepen.io/Realetive/pen/RwGMYyV

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

    Блок с контактами делается аналогичным способом:
    .page__section.page__section_view_feedback
      .page__layout
        .form.form_view_feedback.page__column_width_half (миксуем блок формы обратной связи и лэйаут 1/2 колонки)
          …
        .contacts_view_feedback.page__column_width_half
          .contacts__info
            .contacts__address
            .contacts__email
            .contacts__tel
            .contacts__schedule
          .contacts__map
    Ответ написан
    1 комментарий
  • Как получить реальные 100vh на смартфоне?

    SkiperX
    @SkiperX Куратор тега CSS
    Решение на js
    /*Viewport Height Correction
        https://github.com/Faisal-Manzer/postcss-viewport-height-correction
         .foo {
                height: 100vh;
                height: calc(var(--vh, 1vh) * 100); //
          }
        */
        var customViewportCorrectionVariable = 'vh';
        function setViewportProperty(doc) {
            var prevClientHeight;
            var customVar = '--' + ( customViewportCorrectionVariable || 'vh' );
            function handleResize() {
                var clientHeight = doc.clientHeight;
                if (clientHeight === prevClientHeight) return;
                requestAnimationFrame(function updateViewportHeight(){
                    doc.style.setProperty(customVar, (clientHeight * 0.01) + 'px');
                    prevClientHeight = clientHeight;
                });
            }
            handleResize();
            return handleResize;
        }
        window.addEventListener('resize', setViewportProperty(document.documentElement));
        /*/Viewport Height Correction*/
    Ответ написан
    Комментировать
  • Как найти участок проблемного кода если исходники не поддаются анализу?

    @dmitry-toster
    Как выявить то самое проблемное место в коде, где добавляется лишний класс к кнопке?

    1. Брейкпоинтом браузера
    5ff3aaebcc55a434489373.png
    Также можно отследить любые события и манипуляции с DOM
    2. Поиск по коду проекта (искать по названию класса). В любой современной IDE это делается за пару секунд
    3. Браузерным расширением фреймворка (если таковой используется). Которое покажет название компонента и его искать уже в исходниках проекта
    Ответ написан
    1 комментарий
  • Как сделать много 301 редиректов?

    shambler81
    @shambler81 Куратор тега htaccess
    1 собираешь в экселе файл с 500 урлами что и куда.
    2. https://donatstudios.com/RewriteRule_Generator
    собственно все.
    Если есть логика типа изменить 1 часть урла например у 400 товаров заменить /catalog на /tovar
    ТО прикрепляй файлик сюда, я тебе сделюаю регулярки на повторяющиеся элементы.
    Ответ написан
    Комментировать
  • Функция .next() на чистом Javascript?

    dollar
    @dollar
    Делай добро и бросай его в воду.
    <div class="one">
          <p class="text"></p>
    </div>
    <div class="two">
          <p class="text"></p>
    </div>
    <script type="text/javascript">
          let contain = document.querySelector('.one > .text');
          contain.innerHTML = 'Текст 1';
          let next = contain.parentElement.nextElementSibling.firstElementChild;
          next.innerHTML = 'Текст 2';
    </script>
    Ответ написан
    Комментировать
  • Как реализовать подобное меню на css?

    Ankhena
    @Ankhena Куратор тега CSS
    Нежно люблю верстку
    UPD:
    Модифицированный вариант, разбитый на 2 псевдо. Будет работать для любой ширины ссылок


    OLD
    Примерно так, градиент нужно доводить до ума (это самостоятельно) или заменить на SVG
    Ответ написан
    Комментировать
  • Как сделать фильтр товаров на сайте?

    Stalker_RED
    @Stalker_RED
    Это называется фасетный поиск или фасетный фильтр.
    Теперь, обладая знанием о том, как такая штука называется, ты легко найдешь и туториалы и готовые реализации.
    Ответ написан
    Комментировать
  • Как сделать подобный заданий фон для заголовка?

    Ankhena
    @Ankhena Куратор тега CSS
    Нежно люблю верстку
    Примерно так
    Ответ написан
    1 комментарий
  • Как сделать галерею картинок как в альбомах ВК, одной высоты?

    vladchv
    @vladchv
    WordPress Developer
    Например эта: Flex Gallery или Flexbox Gallery
    А вообще их полно в сети, лентяи.
    Ответ написан
    Комментировать
  • Как правильно подключить внешнюю JS библиотеку чтобы она загружалась только после загрузки всей html страницы?

    Tim-A-2020
    @Tim-A-2020
    window.onload = function() {
      const script = document.createElement('script');
      script.src = 'https://www.google.com/recaptcha/api.js';
      script.async = 1;
      script.defer = 1;
      document.body.append(script);
    }
    Ответ написан
    Комментировать
  • Почему данный код работает не правильно?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Причина номер раз: потому что автор кода говнокодер. Ну, то есть - вы даже отформатировать код не удосужились. Причина номер два: проверяется состояние только одного инпута, того, где случилось событие. А надо проверять все.

    Исправляем:

    $('form').on('input', function() {
      $('.button').prop('disabled', $('input', this).get().some(n => !n.value));
    }).trigger('input');
    
    // или
    
    const form = document.querySelector('form');
    const button = document.querySelector('.button');
    const inputs = [...form.querySelectorAll('input')];
    form.addEventListener('input', () => button.disabled = !inputs.every(n => n.value));
    form.dispatchEvent(new Event('input'));
    Ответ написан
    5 комментариев
  • Как вытащить из строки слово, заключенное в скобки?

    0xD34F
    @0xD34F Куратор тега JavaScript
    str.match(/(?<=\{{2}).*?(?=\}{2})/g) ?? []
    
    // или
    
    Array.from(str.matchAll(/\{\{(.*?)\}\}/g), n => n[1])
    Ответ написан
    3 комментария
  • Как верстать изогнутые секции?

    RAX7
    @RAX7
    SVG + 2 маски, одна пропорционально растягивается, другая непропорционально. Отрицательным margin загнать секции одна на другую.
    Ответ написан
    6 комментариев
  • Как сделать плавный набор текста в input?

    Aetae
    @Aetae Куратор тега JavaScript
    Тлен
    Чтобы избежать головняка с contenteditable можно подложить стилизованный div под input с прозрачным текстом. Но это всё равно не будет просто, т.к. потребуется вычислять разницу состояний и анимировать именно по месту ввода.
    Вот чисто концепт с анимацией только последнего символа:
    Ответ написан
    Комментировать
  • Как в зависимости от положения слайдера позиционировать подсказку?

    Get-Web
    @Get-Web Куратор тега JavaScript
    Front-End Developer
    После переключения слайда первым 3-м активным задайте класс который будет делать подсказку справа, остальным слева
    Ответ написан
    1 комментарий