Ответы пользователя по тегу JavaScript
  • Как добавить класс по клику на кнопку внутри карточки товара?

    mizutsune
    @mizutsune
    Frontend Developer
    const container = document.querySelector('.box');
    
    container.addEventListener("click", ({ target: t }) => {
       if(t.classList.contains("btn")) {
           const card = t.closest(".item");
           card && card.classList.add("active");
       }
    })


    А так касательно кода из вопроса, то тут всё достаточно просто. Чтобы решить задачу, вам нужно добавлять обработчик клика кнопке которая является дочерним элементом карточки, плюс можно заменить цикл for на forEach, что сделает код более читабельным.

    document.querySelectorAll('.item').forEach(v => {
       v.querySelector(".btn").addEventListener('click', () => {
          v.classList.add('active');
       });
    });


    Однако в целом такой подход не очень. То есть я хочу сказать что добавление обработчиков в цикле, имеет свои подводные камни, про которые можно найти достаточно информации.
    Ответ написан
    1 комментарий
  • Как правильно реализовать модальное подтверждением удаления элементов?

    mizutsune
    @mizutsune
    Frontend Developer
    Не пойму в чем дело, разъясните пожалуйста.


    Действительно, что-то тут не так...

    Немного об оригинальном коде из вопроса...


    Для начала поставьте console.log в определенном месте своего кода:

    document.querySelector('.list').addEventListener('click', (event) => {
      const target = event.target
      if (target.classList.contains('delete')) {
        const task = document.querySelector(`[data-id="${target.dataset.delete}"]`)
        // Посмотрим что будет выводиться в консоль?
        console.log(target.dataset.id)
        deleteTask(task)
      }
    })


    И попробуйте проделать все описанные в вопросе действия, после чего посмотрите сколько идентификаторов текущего "таска" - выводятся в консоль. Что-то тут не так... Разобраться конечно в этом можно, но нужно разбираться и тратить время...


    Ну, а вообще, если как-то по простому решить проблему + немного подчистить код, то можно сделать например вот так:

    const modal = document.querySelector(".modal");
    const listbox = document.querySelector(".list");
    const modalCancelButton = modal.querySelector(".cancel");
    const modalConfirmButton = modal.querySelector(".confirm");
    
    let currentTaskID = null;
    
    listbox.addEventListener("click", ({ target: t }) => {
      if (t.classList.contains("delete")) {
        currentTaskID = t.dataset.delete;
        modal.classList.remove("hidden");
      }
    });
    
    modalCancelButton.addEventListener("click", () => {
      modal.classList.add("hidden");
      currentTaskID = null;
    });
    
    modalConfirmButton.addEventListener("click", () => {
      modal.classList.add("hidden");
      deleteTask(currentTaskID);
    });
    
    const deleteTask = id => id && listbox.querySelector(`[data-id="${id}"]`).remove();
    Ответ написан
    Комментировать
  • Есть ли хорошие конверторы из jquery в js?

    mizutsune
    @mizutsune
    Frontend Developer
    Есть такая штука - replace-jquery, которая в той или иной степени может помочь в некоторых случаях, но это не 100-процентный конвертер или что-то в этом духе.

    Вообще самым лучшим способом будет ручное переписывание кода. Статей описывающих как и чем заменить методы Jquery , достаточно чтобы справиться со столь "сложной" задачей. Да, количество кода на нативном JS будет больше и ручная "конвертация" займёт время, но это не столь критично. Я бы сказал бы что будет даже полезно, но это смотря с какой стороны смотреть на это всё.

    ИМХО, но в большинстве случаев, разгребать тонну кода, ради простого функционала, бессмысленно, ведь можно написать всё с нуля, возможно даже лучше... просто нужно понять, что нужно сделать и какой результат ожидается.

    Но вылазит то один баг, то другой. Уже нервишки здают...


    У вас очень маленький объём кода, но качество конечно оставляет желать лучшего. Попробуйте разбить код на мелкие функции, проверьте на работоспособность, после чего переписывайте на нативный JS. Таким образом вам будет проще решить эту задачу. Тут работы на пару часиков...

    Есть ли хорошие конвертеры из jquery в js?


    Нет и не будет, потому что JQuery это всего лишь библиотека написанная на JS, а не какой-то там инопланетный артефакт.
    Ответ написан
    Комментировать
  • Как сделать что мы можно было пролистать элементы в блоке?

    mizutsune
    @mizutsune
    Frontend Developer
    Есть библиотека под названием Conveyer которая имеет подобный функционал.

    В качестве альтернативного варианта, можно взять слайдер Swiper. В этом слайдере есть всё что нужно для реализации подобных элементов со скроллом. Ну, а ещё можно выпилить лишнее и собрать слайдер с нужными модулями, после чего вес слайдера уменьшится.

    Думаю что есть ещё много других альтернатив, в том числе и реализация данного функционала без стороннего кода, но такой вариант стоит рассматривать если вы уверены в своих знаниях и способны учесть множество моментов, которые нужно учитывать.
    Ответ написан
    Комментировать
  • Как сделать такое окно загрузки фото?

    mizutsune
    @mizutsune
    Frontend Developer
    Например как-то так:



    В примере выше для функционала Drag & Drop or Draggable - используется библиотека Sortable. С её помощью реализуется основная "магия". Всё остальное настраивается по вкусу и цвету.
    Ответ написан
    1 комментарий
  • В чем причина не рабочего бургер меню на GitHub?

    mizutsune
    @mizutsune
    Frontend Developer
    Добавил бургер меню на свой сайт портфолио.


    Если речь идёт об этом портфолио, то тут ошибка в этом:

    <script src="/source/js/script.js"></script>

    - <script src="/source/js/script.js"></script>
    + <script src="source/js/script.js"></script>
    Ответ написан
    1 комментарий
  • Есть сайт для оценки npm модуля?

    mizutsune
    @mizutsune
    Frontend Developer
    Не уверен что это то что нужно, но есть такой сайт openbase. При выборе какой-нибудь библиотеки/плагина/etc, выводит информацию плюс предлагает альтернативы.
    Ответ написан
    Комментировать
  • Как поменять свойства слайдера в js зависимости от размера окна?

    mizutsune
    @mizutsune
    Frontend Developer
    У Swiper хорошая и богатая документация, в которой можно найти параметр Breakpoints. Так вот, через Breakpoints можно менять многие свойства Swiper, в том числе количество отображаемых слайдов.

    Пример:

    const swiper = new Swiper('.swiper', {
          breakpoints: {
            640: {
              slidesPerView: 2,
            },
            768: {
              slidesPerView: 4,
            },
            1024: {
              slidesPerView: 5,
            },
          }
        });
    Ответ написан
  • Как реализовать выпадающее меню?

    mizutsune
    @mizutsune
    Frontend Developer
    Если нет опыта в создании подобных компонентов, то наверное стоит использовать какую-нибудь готовую библиотеку для аккордеонов. Например такую Accordion или такую metismenujs или поискать какие-нибудь ещё варианты. С помощью любой из этих двух библиотек, можно решить описанную в вопросе задачу.

    Или можно сделать как-то так без библиотек:

    Ответ написан
    3 комментария
  • Как разделить данные в html формате?

    mizutsune
    @mizutsune
    Frontend Developer
    function getAllNextSiblings(el, subElement, selectorFilter) {
         let collection = [];
         let target = el.nextElementSibling;
    
         while (target) {
              if (target.matches(subElement)) break;
              if (selectorFilter && !target.matches(selectorFilter)) {
                   target = target.nextElementSibling;
                   continue;
              }
              collection.push(target.textContent.trim());
              target = target.nextElementSibling;
         }
         return collection;
    }


    // собираем заголовки и параграфы в массив объектов 
    // разбивая полученные данные на группы
    [...document.querySelectorAll("h1")].map(target => {
         return {
              heading: target.textContent,
              paragraphs: getAllNextSiblings(target, "h1", "p")
         };
    });


    В итоге имея например такую HTML - разметку:

    <div class="container">
        <h1>Глава 1</h1>
        <p>Текстовой блок - 1</p>
        <p>Текстовой блок - 2</p>
        <p>Текстовой блок - 3</p>
        <p>Текстовой блок - 4</p>
    
        <h1>Глава 2</h1>
        <p>Текстовой блок - 1</p>
        <p>Текстовой блок - 2</p>
        <p>Текстовой блок - 3</p>
      </div>


    Получим такой результат:

    [
       {
          "heading": "Глава 1",
          "paragraphs": [
             "Текстовой блок - 1",
             "Текстовой блок - 2",
             "Текстовой блок - 3",
             "Текстовой блок - 4"
          ]
       },
       {
          "heading": "Глава 2",
          "paragraphs": [
             "Текстовой блок - 1",
             "Текстовой блок - 2",
             "Текстовой блок - 3"
          ]
       }
    ]
    Ответ написан
    3 комментария
  • Как убрать блок с помощью JS и добавить новый после отправки формы?

    mizutsune
    @mizutsune
    Frontend Developer
    Если кратко ответить на вопрос, то как-то так:

    1. При нажатии на кнопку Отправить, делаем валидацию полей.
    2. Если валидация прошла успешно, скрываем форму и переходим к следующему шагу.
    3. Показываем popup окно с уведомлением или добавляем активный класс скрытому блоку с уведомлением.
    4. Profit.

    Вообще обычно используется вызов popup окна для подобных уведомлений, так как оно лучше привлекает внимание пользователя и сообщает что то или иное действие прошло, например, успешно.
    Ответ написан
  • Как определить при помощи JS браузер пользователя и его ip?

    mizutsune
    @mizutsune
    Frontend Developer
    Можно достать информацию из navigator.userAgent и регулярными выражениями разбить полученную информацию на нужные фрагменты, после чего использовать. Но такой вариант подходит если есть опыт работы с регулярными выражениями.

    Если пойти другим путем, можно вывести в консоль объект navigator и посмотреть какие свойства имеются в наличии, после чего подготовить функцию в которой будет происходить получение информации из нужных свойств объекта. Например в navigator.userAgentData хранится информация, которую можно использовать сразу, без обработки регулярными выражениями.

    Или поискать библиотеки для подобных задач и использовать их для решения своих задач. Например есть такая библиотека UAParser.js или browser-dtector или Detect.js или куча других готовых решений.

    Про получение IP - адреса, уже написали в соседних ответах.
    Ответ написан
    Комментировать
  • Как сделать на JS чтобы скрипт срабатывал только на определенной ширине экрана?

    mizutsune
    @mizutsune
    Frontend Developer
    Как вариант можно использовать window.matchMedia.

    Пример:

    const slider = new Slider();
    const breakpoint = window.matchMedia("(min-width: 1200px)");
    
    if (breakpoint.matches) {
       slider.init();
    }


    Или:

    const slider = new Slider();
    const breakpoint = window.matchMedia("(max-width: 1200px)");
    
    const breakpointChecker = () => {
       if (breakpoint.matches) {
          slider.init();
       } else {
          slider.destroy();
       }
    };
    
    breakpoint.addEventListener("change", breakpointChecker);
    breakpointChecker();


    У нормальных слайдеров имеются методы init() и destroy() или аналогичные методы для включения и отключения слайдера. Так вот, используя эти методы в связке с matchMedia(), можно добиться желаемого результата.

    Альтернативный вариант.

    Можно использовать window.innerWidth или element.clientWidth или window.outerWidth в связке с условным оператором if.

    Пример:

    // если ширина окна больше или равна 1200px,
    // выполняем инициализацию слайдера
    
    if(window.innerWidth >= 1200) {
       slider.init();
    }


    Однако данная проверка будет работать только при загрузке страницы и если нужно включать/отключать слайдер при ресайзе, то в таком случае потребуется использование обработчика с событием resize + с каким-нибудь флагом или с функцией debounce, чтобы не допускать вызова функций при каждом изменении размера окна.
    Ответ написан
    Комментировать
  • Как прикрепить меню навигации кверху при скролле?

    mizutsune
    @mizutsune
    Frontend Developer
    Переместить навигацию из элемента с классом hero в общий контейнер. Сейчас навигация находится в блоке hero и не сможет выйти за его пределы при использовании position: sticky, так как не является прямым дочерним элементом блока, внутри которого и нужна липкая навигация. Рекомендую почитать как на самом деле работает position: sticky.

    Ну и вообще, зачем у элемента .container - стоит max-height: 50px? Думаю что надо бы убрать это ограничение.
    Ответ написан
  • Как ограничить видимость переменных между html страницами?

    mizutsune
    @mizutsune
    Frontend Developer
    Допустим нужно проделать какие-то манипуляции с DOM. Например, сделать вывод массива в определенный элемент на определенной странице. В таком случае, можно использовать нечто такое:

    function myAwesomeFunction() {
      if(!document.querySelector("#target")) return;
    
      //some code 
    }


    То есть нужно вложить код в функцию, внутри которой проверять есть ли нужный элемент на странице и если он есть, продолжаем выполнение, а если элемента нет на странице выходим из функции. Ну вообще не обязательно ставить условие внутри функции, можно вызов основной функции переместить в условие. То есть:

    if(document.querySelector("#target")) {
       myAwesomeFunction(); 
    }


    Альтернативный вариант.

    Можно использовать window.location для решения подобных задач, но у данного способа есть свои подводные камни.
    Ответ написан
  • Почему transition не срабатывает при скрытии элемента?

    mizutsune
    @mizutsune
    Frontend Developer
    Для начала несколько рекомендаций:

    1. Следует отказаться от стилизации элементов по ID селектору, потому что это считается плохой практикой.
    2. Для простой функции переключения класса у элемента, не нужно столько кода.

    Почему transition не срабатывает при скрытии элемента?


    - transition: opacity 0.3s;
    + transition: opacity 0.3s, visibility 0.3s;


    При комбинированном использовании свойств opacity и visibility, следует указывать оба свойства в transition, желательно с одинаковым временем перехода от одного состояния к другому.

    CSS и JS можно сократить и привести к нормальному виду.


    CSS:

    .block {
        width: 250px;
        height: 250px;
        background: #eee;
        opacity: 0;
        visibility: hidden;
        transition: opacity 0.3s, visibility 0.3s;
      }
    
      .block-active {
        opacity: 1;
        visibility: visible;
      }


    JS:

    function show() {
        const element = document.getElementById("block");
        element.classList.toggle("block-active");
      }


    Или:

    function show() {
         const element = document.getElementById("block");
    
         switch (Boolean(element.classList.contains("block-active"))) {
              case false:
                   return element.classList.add("block-active");
              case true:
                   return element.classList.remove("block-active");
         }
    }
    Ответ написан
    5 комментариев
  • Как скрыть все блоки при выборе одного?

    mizutsune
    @mizutsune
    Frontend Developer
    .tabs-panels__panel {
         display: none;
    }
    
    .tabs-panels__panel-active {
         display: block;
    }


    <div id="tabs" class="tabs">
        <div class="tabs__nav">
            <button class="tabs-nav__button tabs-nav__button-active" data-tabs-target="tabs-panel-1">
                Section 1
            </button>
            <button class="tabs-nav__button" data-tabs-target="tabs-panel-2">
                Section 2
            </button>
        </div>
        <div class="tabs__panels">
            <div id="tabs-panel-1" class="tabs-panels__panel">
                <div class="tabs-panels-panel__container">
                    Content Of Section 1
                </div>
            </div>
            <div id="tabs-panel-2" class="tabs-panels__panel tabs-panels__panel-active">
                <div class="tabs-panels-panel__container">
                    Content Of Section 2
                </div>
            </div>
        </div>
    </div>


    const container = document.querySelector("#tabs");
    
    container.addEventListener("click", ({ target: t }) => {
         if (t.classList.contains("tabs-nav__button")) {
              const tabsTriggerButton = container.querySelectorAll(".tabs-nav__button");
              const tabsContentPanels = container.querySelectorAll(".tabs-panels__panel");
    
              const currentPanelID = t.dataset.tabsTarget;
    
              if (!currentPanelID) return;
    
              tabsTriggerButton.forEach(v => v.classList.remove("tabs-nav__button-active"));
              t.classList.add("tabs-nav__button-active");
    
              tabsContentPanels.forEach(v => {
                   v.id === currentPanelID ?
                        v.classList.add("tabs-panels__panel-active") :
                        v.classList.remove("tabs-panels__panel-active");
              });
         }
    });
    Ответ написан
    Комментировать
  • Насколько часто в js библиотеках попадаются бэкдоры?

    mizutsune
    @mizutsune
    Frontend Developer
    Как от этого защититься?


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

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

    1. Хранить используемые библиотеки у себя.
    2. Не обновляться без нужды, а если и обновляться, то проводить анализ обновленного кода.
    3. Нужно уметь читать код библиотек, полностью понимать что там написано, что делает каждая функция.
    4. Подключать библиотеки в проекте без использования CDN версий и прочего. Желательно со своего сайта, чтобы строго контролировать используемую версию библиотеки.
    5. Желательно не использовать библиотеки, имеющие кучу внешних зависимостей.
    6. По возможности использовать популярные библиотеки, но не доверять им на 100%. Тот факт что библиотека популярна и имеет сколько-то тысяч звездочек на Github, не гарантирует того, что однажды там не появится какой-нибудь гнилой код, выполняющий не очень хорошие действия. Помним про пункты: 1, 2, 3, 4, 5.

    Конечно выполнение этих пунктов тоже требует ресурсов, но по крайней мере увеличивает шанс защититься от всяких нехороших сценариев.
    Ответ написан
    Комментировать
  • Как передать значение textarea в переменную с сохранением абзацев используя JS?

    mizutsune
    @mizutsune
    Frontend Developer
    Можно сделать просто через CSS. Добавляем элементу #res свойство white-space c любым из этих значений: pre-wrap или pre-line и переносы строк визуально будут сохраняться.
    Ответ написан
    1 комментарий
  • Как получить значение внутри блока на который нажали?

    mizutsune
    @mizutsune
    Frontend Developer
    Для начала:

    1. ID атрибуты HTML - элементов должны быть уникальными.
    2. Использование вызова функции через onclick в HTML тегах, выглядит так себе.

    А по вопросу, то это можно сделать через делегирование событий:

    document.addEventListener("click", ({ target }) => {
        if (target.classList.contains("lk-addapp-ajax-block")) {
          const value = target.querySelector("input").value;
          alert(value);
        }
      });


    Для того чтобы всё работало корректно, придётся добавить в CSS одну строчку с правилом:

    .lk-addapp-ajax-block  * {
            pointer-events: none;
    }


    Это для того чтобы клик попадал именно на родительский блок, а не на дочерние. Хотя это всё можно решить и по другому, но на мой взгляд и этого будет достаточно.
    Ответ написан
    Комментировать