Ответы пользователя по тегу JavaScript
  • Как скопировать значение из div в input, если таких конструкций на странице много одинаковых?

    mizutsune
    @mizutsune
    Frontend Developer
    document.querySelectorAll(".section").forEach(n => {
    	let databox = n.querySelector("span");
    	let input = n.querySelector(".hidden_price");
    	input.value = databox.textContent;
    });


    Кстати атрибут ID должен быть уникальным.
    Ответ написан
    1 комментарий
  • Как запустить несколько Pop Up на одной странице?

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



    Но, в целом реализация модальных окон это не пара строчек кода, а намного больше и чтобы сделать хорошо, нужно потратить больше 5-ти минут времени. В любом случае, можно взять готовую библиотеку и посмотреть из чего она состоит. Это в некоторых случаях может помочь и возможно упростит создание своего велосипеда.
    Ответ написан
    Комментировать
  • Есть ли плагин, для изменения DOM при адаптиве?

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

    Например, задачу из вопроса, можно легко решить по старинке, используя два HTML - блока, плюс переключение display через медиа запросы. Например одна кнопка находится в одном месте страницы и отображается по дефолту на десктопах, а вторая кнопка находится совсем в другом месте страницы и "активируется" соответственно на планшетах и мобильниках.

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

    Волшебной таблетки, скажем так, не существует, поэтому нужно решать задачу тем способом, который будет более выгодным и если всё же хочется JS плагин, то есть такой вот вариант: dynamic_adapt. Правда, можно конечно сделать и получше, но если нет опыта написать что-то годное самостоятельно, можно попробовать этот плагин. Альтернатив, увы, не встречал.
    Ответ написан
    Комментировать
  • Как с помощью js при уменьшении ширины экрана обрезался текст?

    mizutsune
    @mizutsune
    Frontend Developer
    Вообще подобные задачи хорошо решаются и без JS, например если просто нужно обрезать одну строку по ширине родителя, без переноса строки, тогда можно воспользоваться свойством text-overflow.

    Пример

    .target {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }



    Или если нужно обрезать текст по количеству строк, тогда вполне подойдёт webkit-line-clamp.

    Пример

    .target {
      overflow: hidden;
      display: -webkit-box;
      -webkit-line-clamp: 5;
      -webkit-box-orient: vertical;
    }



    Однако если всё же хочется сделать с помощью JS, тогда как вариант можно сделать так:



    Свойство breakpoints содержит двумерный массив с парами значений: [[min-width, max-width], wordsLimit].
    Ответ написан
    Комментировать
  • Как организовать код на js?

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

    const fn = (..args) => {
      // выходим из функции если элемент не найден
      if(!document.querySelector(".target-element-selector")) return;
      
      // код функции
    };


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

    if (window.location.href === "https://you-site.com/blog"){
       // код который нужно выполнить на странице blog
    }


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

    mizutsune
    @mizutsune
    Frontend Developer
    На самом деле не совсем понятно, когда запускается анимация? Если после нажатия на кнопку или после события сhange, тогда можно сделать например так:

    .is-active {
         animation-name: shake;
         animation-direction: alternate;
         animation-duration: 1s;
         animation-iteration-count: 4;
    }
    
    @keyframes shake {
         from {
              transform: translateX(0px);
         }
         to {
              transform: translateX(150px);
         }
    }


    const button = document.querySelector(".button");
    
    button.classList.add("is-active");
    
    button.addEventListener("animationend", (event) => {
         event.stopPropagation();
         button.classList.remove("is-active");
    }, { once: true });


    То есть добавить активный класс кнопке, а после окончания анимации удалить добавленный класс.

    Или кнопка "убегает" от курсора в каком-то определенном направлении?

    Ответ написан
    Комментировать
  • Почему при добавлении новых элементов в массив, цикл их не видит?

    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.

    Первый вариант

    but.addEventListener("click", () => {
        goods.push({
            item: input1.value,
            price: input2.value,
            index: input3.value,
        });
    
        ul.innerHTML = goods.map(({ item, price, index }) => {
            return `<li>${item}, цена ${price}, номер ${index}</li>`
        }).join("");
    });



    Или:

    Второй вариант

    but.addEventListener("click", () => {
        goods.push({
            item: input1.value,
            price: input2.value,
            index: input3.value,
        });
    
        const { item, price, index } = goods[goods.length - 1];
    
        let li = document.createElement("li");
        let content = `${item}, цена ${price}, номер ${index}`;
        li.textContent = content;
        ul.append(li);
    });

    Ответ написан
    3 комментария
  • Почему не работает 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"));
    Ответ написан
  • Как убрать закрытие вкладки аккордеона при нажатии на кнопку?

    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);
    Ответ написан
    Комментировать