Ответы пользователя по тегу JavaScript
  • Есть массив, перебираемый циклом, элементы которого выводятся в список ul. При добавлении новых элементов в массив цикл их не видит. Как исправить?

    mizutsune
    @mizutsune
    Frontend Developer
    Создаю с нуля инпуты и кнопку для добавления новых элементов массива, добавляю, но цикл их не видит и не выводит в окно.


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

    let li = document.createElement("li");
    let content = `${elem.item}, цена ${elem.price}, номер ${elem.index}`;
    li.textContent = content;
    ul.appendChild(li);


    Но указав новые данные для: item, price, index.
    Ответ написан
    Комментировать
  • Photoswipe - как приближать и отдалять двумя пальцами картинку из самого поп-апа?

    mizutsune
    @mizutsune
    Frontend Developer
    Если я правильно понял, вам нужно что-то вроде Pinch zoom gestures, но точно не знаю, имеется ли в photoswipe подобный функционал. В любом случае эту функцию можно добавить с помощью своего кастомного кода или с помощью готовой библиотеки, например pinchzoom.
    Ответ написан
  • Почему не работает for внутри append?

    mizutsune
    @mizutsune
    Frontend Developer
    Почему не работает for внутри append?


    Потому что это синтаксическая ошибка. Цикл for не будет возвращать подобным образом массив с шестью элементами, которые вы пытаетесь вставить как набор HTML тегов в элемент с классом second.

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

    const getSetOfElements = () => {
         let arr = [];
    
         for (let i = 1; i <= 6; i++) {
              arr.push(`<div class="test">${i}</div>`);
         }
    
         return arr;
    }
    
    const setOfElements = getSetOfElements();
    
    $('.second').append(`<p>hello</p> ${setOfElements.join("")}`);


    Или:

    const setOfElements = [...Array(6)].map((_, i) => (`<div class="test">${i + 1}</div>`)).join("");
    
    $('.second').append(`<p>hello</p> ${setOfElements}`);


    Чтобы более корректно описать суть вашей ошибки, понадобиться много букв и возможно вам будет не интересно читать, а мне жалко тратить своё время. Поэтому можете пройтись по документации, ознакомиться с синтаксисом языка. Многое сразу встанет на свои места.
    Ответ написан
    2 комментария
  • Как переделать double range slider, чтобы использовать несколько на странице?

    mizutsune
    @mizutsune
    Frontend Developer
    Как вариант, можно обернуть элементы управления, инпуты и сам слайдер в родительский контейнер, с определенным id атрибутом или классом. Далее нужно обернуть код слайдера в функцию и передавать в эту функцию в качестве аргумента селектор родительского контейнера. Таким образом можно будет привязать функцию к элементу разными способами.

    Например так:

    slider("#target-element-id-1");
    slider("#target-element-id-2");


    Или если слайдеров много и у них одинаковый класс, тогда можно так:

    document.querySelectorAll(".element").forEach(n => slider(n));


    Пример:

    Ответ написан
    Комментировать
  • Как проверить, что класс существует и выполнить действие alert?

    mizutsune
    @mizutsune
    Frontend Developer
    Например с помощью Mutation Observer API.

    const targetElement = document.querySelector(".player-selector");
    
    const observer = new MutationObserver((mutations) => {
         mutations.forEach(({ target: t }) => {
              t.classList.contains("is-finished") ?
                   alert("element contains class") :
                   alert("element does not contain a class");
         })
    });
    
    observer.observe(targetElement, {
         attributes: true,
         attributeFilter: ['class']
    });
    Ответ написан
    Комментировать
  • У e.target из KeyboardEvent нет метода classList.contains()?

    mizutsune
    @mizutsune
    Frontend Developer
    Вы используете квадратные скобки, вместо круглых.

    - console.log(e.target.parentElement.classList.contains["valide"]);
    + console.log(e.target.parentElement.classList.contains("valide"));


    - if (e.target.parentElement.classList.contains["valide"]);
    + if (e.target.parentElement.classList.contains("valide"));
    Ответ написан
  • Как кликнуть по элементу, у которого один Class, но уникальный id?

    mizutsune
    @mizutsune
    Frontend Developer
    document.querySelector("[data-episode-type='3']").click();
    Ответ написан
  • Как убрать закрытие вкладки аккордеона при нажатии на кнопку?

    mizutsune
    @mizutsune
    Frontend Developer
    Если немного подправить ваш скрипт, то можно сделать так:

    const accordions = document.querySelectorAll('.accordion');
    const accordionsButtons = document.querySelectorAll(".accordion__tittle")
    const accordionsDataboxes =  document.querySelectorAll(".accordion__content");
    
    accordions.forEach(n => {
         const currentButton = n.querySelector(".accordion__tittle");
         const currentDatabox = n.querySelector(".accordion__content");
    
         const toggleActiveElements = () => {
              accordionsButtons.forEach(v => {
                   if (v !== currentButton) {
                        v.classList.remove("open");
                   }
              });
    
              accordionsDataboxes.forEach(v => {
                   if (v !== currentDatabox) {
                        v.classList.remove("open");
                        v.style.setProperty("--height", "0px");
                   }
              });
    
              currentButton.classList.toggle("open");
              currentDatabox.classList.toggle("open");
    
              currentDatabox.classList.contains("open")
                   ? currentDatabox.style.setProperty("--height", `${currentDatabox.scrollHeight}px`)
                   : currentDatabox.style.setProperty("--height", "0px");
         };
    
         currentButton.addEventListener("click", toggleActiveElements);
    });


    И добавить строчку в CSS:

    .accordion__content.open {
        max-height: var(--height, 0);
      }
    Ответ написан
    1 комментарий
  • Как добавить класс в зависимости от ширины экрана?

    mizutsune
    @mizutsune
    Frontend Developer
    Вам не класс нужно переключать на элементе, а включать и выключать слайдер, при достижении определенного брейкпоинта. Всё это дело можно легко решить с помощью matchMedia.

    Вот небольшой пример:

    const slider = $(".slider").slick({
         centerMode: true,
         slidesToShow: 4
    });
    
    const breakpoint = window.matchMedia("(max-width: 992px)");
    
    const breakpointChecker = () => {
       if (breakpoint.matches) {
          slider.slick('init');
       } else {
          slider.slick('destroy');
       }
    };
    
    breakpoint.addEventListener("change", breakpointChecker);
    breakpointChecker();


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

    mizutsune
    @mizutsune
    Frontend Developer
    Это самое обычное модальное окно, без центрирования по центру экрана и с оверлей элементом. Можно написать с нуля, или воспользоваться какой-нибудь библиотекой.



    Добавить нужных стилей и всё будет как нужно.
    Ответ написан
    Комментировать
  • Как копировать в буфер обмена строки по отдельности по клику?

    mizutsune
    @mizutsune
    Frontend Developer
    <button class="trigger" data-text="Hello">Скопировать</button>


    const button = document.querySelector(".trigger");
    const dataText = button.dataset.text.trim();
    
    button.addEventListener('click', e => {
    
      if(!dataText.length) return;
      
      navigator.clipboard.writeText(dataText)
        .then(() => console.log("Done!"))
        .catch(err => console.error(err))
    })


    Clipboard API
    Ответ написан
    Комментировать
  • Как показать значение input в div блоке?

    mizutsune
    @mizutsune
    Frontend Developer
    document.addEventListener("DOMContentLoaded", () => { 
       const input = document.querySelector("input");
       const targetElement = document.querySelector("#res");
       
        targetElement.innerHTML = input.value;
    })
    Ответ написан
    Комментировать
  • Не удается получить дочерний элемент родителя, в чем проблема?

    mizutsune
    @mizutsune
    Frontend Developer
    Свойство children хранит в себе псевдомассив дочерних элементов. Дочерними элементами считаются все теги, которые непосредственно расположены внутри блока. Подробнее можно прочитать в документации.

    Ну, а так... интересная конечно строка:

    var parent = this.closest('div').className;

    Как вы думаете что содержит в себе переменная parent? HTMLElement или строку содержащую селектор класса выбранного элемента?

    В общем правильнее сделать так:

    const parent = this.closest('.parent-selector');
    const child = parent.querySelector(".b24-form-control-label");


    И вообще, пора бы уже использовать const/let вместо устаревшего var.
    Ответ написан
    Комментировать
  • Проверка на пустоту в input после заполнения?

    mizutsune
    @mizutsune
    Frontend Developer
    Как вариант:

    const debounce = (fn, ms = 300) => {
         let timer;
         return (...args) => {
              clearTimeout(timer);
              timer = setTimeout(() => {
                   fn.apply(this, args);
              }, ms);
         };
    }
    
    const inputbox = document.querySelector(".input");
    
    const checkForEmpty = ({ value: v }) => v === "" && console.log("Empty");
    
    const processChanges = debounce(() => checkForEmpty(inputbox), 500);
    
    inputbox.addEventListener("input", processChanges);
    Ответ написан
    Комментировать
  • Как добавить класс по клику на кнопку внутри карточки товара?

    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 комментарий