Ответы пользователя по тегу JavaScript
  • Почему localStorage.getItem(key) отрабатывает только после второго клика?

    ae_ph
    @ae_ph
    I'm a owl )
    Я исправил данный кода, теперь это должно работать для вас.
    Вот пример на CodePen
    Тот-же код, что и на codepen...

    HTML
    <div class="container">
      <div class="cart">
        <input class="input amount-one" type="text" value="0" />
        <input class="input amount-two" type="text" value="0" />
        <input class="input amount-three" type="text" value="0" />
        <button class="btn">click</button>
      </div>
      <div class="cart">
        <input class="input amount-one" type="text" value="0" />
        <input class="input amount-two" type="text" value="0" />
        <input class="input amount-three" type="text" value="0" />
        <button class="btn">click</button>
      </div>
      <div class="box">
        <input id="clear" type="button" value="clear all" />
        <div class="info"></div>
      </div>
    </div>


    CSS
    body {
      display: flex;
      justify-content: center;
      background-color: #1d1e22;
    }
    .container {
      display: flex;
      flex-direction: row;
      flex-wrap: wrap;
    }
    .cart {
      display: flex;
      flex-direction: column;
      margin: 20px;
    }
    .input {
      padding-left: 20px;
      height: 20px;
      margin-bottom: 5px;
      font-size: 20px;
      border-radius: 10px;
    }
    .btn {
      height: 30px;
      font-size: 20px;
      border-radius: 10px;
    }
    .box {
      display: flex;
      flex-direction: column;
      align-items: center;
      margin: 20px;
    }
    #clear {
      width: 100px;
      height: 40px;
      margin-bottom: 10px;
      font-size: 20px;
      border-radius: 10px;
    }
    .info {
      display: flex;
      justify-content: center;
      align-items: center;
      width: 200px;
      height: 30px;
      border: 2px solid #bbb;
      background-color: #fff;
    }


    JavaScript
    let currentTariff = JSON.parse(localStorage.getItem('cabins') || '[]');
    const passengersMax = 3; // Максимальное количество пассажиров
    let accommodationSum = currentTariff.reduce((acc, curr) => acc + curr.accommodation, 0);
    const btn = document.querySelectorAll('.btn');
    const info = document.querySelector('.info');
    
    // Вывести текущие тарифные данные в информационный блок
    const render = (tariff = currentTariff) => {
      [...tariff].forEach(el => {
        info.insertAdjacentHTML('beforeend', `<div>${el.accommodation}</div>`);
      });
    };
    render();
    
    btn.forEach(button => {
      button.addEventListener('click', function (e) {
        const cart = e.target.closest('.cart');
        const countOne = cart.querySelector('.amount-one').value;
        const countTwo = cart.querySelector('.amount-two').value;
        const countThree = cart.querySelector('.amount-three').value;
        const accommodationPass = parseInt(countOne) + parseInt(countTwo) + parseInt(countThree);
    
        if (accommodationSum + accommodationPass > passengersMax) {
          alert('В этом заказе вы превысили максимальное количество человек');
          return;
        }
    
        const obj = {
          countOne: countOne,
          countTwo: countTwo,
          countThree: countThree,
          accommodation: parseInt(accommodationPass),
        };
    
        // Обновляем текущий тариф и отображаем новые данные
        currentTariff.push(obj);
        updateState();
    
        const sum = currentTariff.reduce((acc, curr) => acc + curr.accommodation, 0);
        info.innerHTML = `<div>Общая сумма: ${sum}</div>`;
    
        accommodationSum = sum; // Устанавливаем сумму размещения на текущую сумму
      });
    
      function updateState() {
        localStorage.setItem('cabins', JSON.stringify(currentTariff));
      }
      // Очищаем входы и информационный блок при нажатии кнопки "clear all"
    function clearData() {
        currentTariff.length = 0;
        localStorage.removeItem('cabins');
        info.innerHTML = '';
        const inputs = document.querySelectorAll('input[type="text"]');
        inputs.forEach(input => {
          input.value = 0;
        });
        accommodationSum = 0;  // Сбрасываем сумму размещения до 0
    }
    
      const clearBtn = document.querySelector('input#clear');
      clearBtn.addEventListener('click', clearData);
    });
    Ответ написан
  • Prompt-компонент на весь сайт?

    ae_ph
    @ae_ph
    I'm a owl )
    Объяснение:
    Я изменил имя переменной состояния isBlock на isBlocking, чтобы было понятнее, что она представляет.
    Добавил прослушиватель событий к событию beforeunload, который будет запущен, когда пользователь попытается покинуть страницу.
    Добавил этот прослушиватель событий в хук useEffect, чтобы его можно было очистить при размонтировании компонента.
    Добавил функцию handleFormChange, которая будет запускаться каждый раз при изменении формы, она проверяет значение ввода или текстового поля, если оно больше 0, оно устанавливает для isBlocking значение true, в противном случае — значение false.
    Добавил событие onchange в форму и текстовое поле и событие onClick на кнопке отмены, это вызовет функцию handleFormChange, а также позволит пользователю отменить и покинуть страницу без каких-либо подсказок.
    Также добавил в форму кнопку отправки и удалил useEffect, который опрашивал элемент textarea, и setTimeout, который использовался для этого.
    Также добавил сообщение к событию beforeunload, которое будет отображаться как подсказка для пользователя с просьбой подтвердить, хотят ли они покинуть страницу.

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

    function MyPrompt() {
      const [isBlocking, setIsBlocking] = React.useState(false);
      const location = useLocation();
    
      const handleBeforeUnload = (event) => {
        if (isBlocking) {
          event.preventDefault();
          event.returnValue = "Are you sure you want to leave?";
        }
      };
    
      React.useEffect(() => {
        window.addEventListener("beforeunload", handleBeforeUnload);
    
        return () => {
          window.removeEventListener("beforeunload", handleBeforeUnload);
        };
      }, [isBlocking]);
    
      const handleFormChange = (event) => {
        if (event.target.value.length > 0) {
          setIsBlocking(true);
        } else {
          setIsBlocking(false);
        }
      };
    
      return (
        <div>
          <form onChange={handleFormChange}>
            <input type="text" placeholder="Type something here" />
            <textarea placeholder="Type something here"></textarea>
            <button type="submit">Submit</button>
            <button type="button" onClick={() => setIsBlocking(false)}>Cancel</button>
          </form>
        </div>
      );
    }
    Ответ написан
    Комментировать
  • Как отформатировать код в HTML?

    ae_ph
    @ae_ph Автор вопроса
    I'm a owl )
    Собственно на самом сайте css-tricks я и нашёл решение )
    Возможно у вас есть свои варианты, когда не используется CMS WordPress
    Ответ написан
    Комментировать
  • Как реализовать видеоплеер с уменьшением длины видео (обрезка)?

    ae_ph
    @ae_ph
    I'm a owl )
    Думаю вам нужно смотреть в эту сторону: Управление видео из JavaScript.
    ссылка 1
    ссылка 2
    А если вы хотите обрезать видео прямо в браузере по таймлайну тогда тут можно на сервере использовать ffmpeg.
    Но я не совсем уверен, чего именно вы хотите добиться.
    Ответ написан
    Комментировать
  • Ошибка в консоли Google Chrome, как понять причину?

    ae_ph
    @ae_ph
    I'm a owl )
    Расширения отключите в браузере
    Ответ написан
    Комментировать
  • Как сделать раздвигающееся меню?

    ae_ph
    @ae_ph Автор вопроса
    I'm a owl )
    На JS я всё это сделал.
    Сделал фиксированную высоту в PX боксу с контентом.
    И при клике на кнопку добавляю 100% высоты и обратно сворачиваю при клике.
    Ответ написан
  • Как воспроизвести видео при наведении на изображение?

    ae_ph
    @ae_ph Автор вопроса
    I'm a owl )
    video-box-1 - это div в котором лежит видео и изображение
    photo-1 - само изображение, которое мы видим изначально
    main-product__photo-off - это класс в котором мы отключаем изображение (display: none;)
    video-1 - это видео которое появится при наведении на изображение
    main-product__video-on - это класс в котором мы включаем видео (display: block;)

    $(".video-box-1").hover(function() {
        $(".photo-1").addClass("main-product__photo-off");
        $(".video-1").addClass("main-product__video-on");
    }, function() {
        $(".photo-1").removeClass("main-product__photo-off");
        $(".video-1").removeClass("main-product__video-on");
    });
    Ответ написан
    Комментировать
  • JS. Как получить размеры элемента для разных размеров экрана при событии load?

    ae_ph
    @ae_ph
    I'm a owl )
    Вы определяете ширину окна браузера а затем отталкиваясь этих значений меняете стили.

    Это просто кусок кода, как пример.
    let userScreen = document.body.clientWidth; // Ширина окна браузера.
    let backgroundHat = document.querySelector(".background-hat");
    let backHat = document.querySelector(".background-hat");
    
    function mine() {
        // Your code...
        // Если размер окна браузера меньше или равен 599px 
        if (userScreen <= 599) {
            backgroundHat.style.zIndex = 5;
            backgroundHat.style.backgroundColor = "rgba(255,255,255,0.9)";
            backHat.classList.add("background_hat-true-forma");
        }
    }
    Ответ написан
  • Как практиковать JS?

    ae_ph
    @ae_ph
    I'm a owl )
    Открываете сайт qna.habr.com ищите вопросы связанные с JS и пытаетесь решать эти проблемы )
    Ответ написан
    Комментировать
  • Как сделать так, чтобы при наведении на отдельную квартиру (path) менялся стиль ссылки, соответствующей этой квартире?

    ae_ph
    @ae_ph
    I'm a owl )
    Я накидал готовый пример, посмотрите его.
    Надеюсь это поможет!
    CodePen
    Ответ написан
    Комментировать
  • Как отменить скролл по блоку в мобильной версии swiper slider?

    ae_ph
    @ae_ph
    I'm a owl )
    simulateTouch принимает только события мыши.
    Я думаю, что нужно попробовать следующее, это может помочь вам:

    Отключить / включить возможность перемещения ползунка, захватив его мышью или коснувшись его пальцем (на сенсорных экранах), назначив этому свойству false / true
    swiper.allowTouchMove: true,

    Если false, то единственный способ переключить слайд - использовать внешние функции API, такие как slidePrev или slideNext.
    allowTouchMove: false,

    Включение / отключение прокрутки элементов, соответствующих классу, указанному в noSwipingClass
    noSwiping: true,
    Укажите класс css элемента noSwiping
    noSwipingClass: 'swiper-no-swiping'

    Когда он включен, он не позволяет менять слайды смахиванием или кнопками навигации / разбивки на страницы во время перехода.
    preventInteractionOnTransition: true,
    Ответ написан
    Комментировать
  • Как добавить атрибут к тегу с помощью JS?

    ae_ph
    @ae_ph
    I'm a owl )
    Примерно так можно добавить.
    Вам нужно выбрать или искать элемент по его id let liElem = document.getElementById("id");
    Или по имени тега let liElem = document.getElementsByTagName('link');
    В зависимости от этого удалить ненужный.
    Можете добавить id нужному элементу и вызывать на него функцию после загрузки страницы.

    function addAtrib() {
        let yourElem = document.getElementById("id");
        let yourElem = document.getElementsByTagName('link');
        yourElem.setAttribute('rel', 'preload');
    };
    
    window.addEventListener("load", addAtrib);


    Fedor Vlasenko дело говорит. Я что-то сразу не догнал, что он не у вас лежит на сервере.
    Тогда вам и скрипт не нужен уже будет.
    Ответ написан
    Комментировать
  • Как реализовать частичное накрывание 1го блока вторым при скролле?

    ae_ph
    @ae_ph
    I'm a owl )
    На JS можно сделать подобное, задавая разные стили боксам при прокрутки страницы.
    Эта статья может помочь вам ссылка.
    Ответ написан
    Комментировать
  • Как сделать бесконечную горизонтальную прокрутку с остановкой при наведении курсора?

    ae_ph
    @ae_ph
    I'm a owl )
    В вашем первом примере используются css стили завязанные на обычной анимации.
    В нутри класса box распологаются 22 бокса которые катаются с права на лево.
    По крайней мере они это так сделали.
    Вот пример я сделал Infiniti scroll on css
    .box {
        width: 3421px;
        transform: translate3d(0, 0, 0);
        animation: dReeeA 50s linear infinite;
    }
    
    @keyframes dReeeA {
        100% {
            transform: translate3d(-100%, 0, 0);
        }
    }


    На этом сайте из примера кстати говоря вёрстка кривая в некоторых местах..
    Ответ написан
  • Почему происходит задержка применения CSS?

    ae_ph
    @ae_ph
    I'm a owl )
    iframe будут работать медленнее по тому, что для браузера есть дополнительные накладные расходы (его рендеринг, поддержка его экземпляра и ссылки на него).
    Ответ из статьи
    =====================================================
    Иван Кулаков,
    Проверьте ваш HTML документ.
    Если вы указывали в <head> JavaScript и если вы его указали раньше стилей CSS тогда возможна изначальная загрузка JavaScript а затем и CSS стилей из за чего могут быть эти баги.
    Нужно указывать сначало CSS стили а затем уже JavaScript код. Но в иделе конечно писать JavaScript перед закрывающим тегом </body>
    Также хотелось-бы добить, чтобы вы указали ваш <title>Document</title> в низу под стилями.
    6066728f7d82e434619101.jpeg

    Попробуйте написать в конце HTML документа в "скрипт с пробелом" или с комментарием.
    Примеры:
    <script type="text/javascript"> </script>
    <script type="text/javascript">//</script>


    Или за место верхнего скрипта с пробелом просто добавьте пустой JS скрипт там.
    6066681e0d4db105801708.jpeg

    Так-же попробуйте это решение описанное в css-tricks.
    Transitions только после загрузки страницы.

    Цитата из w3 org

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


    Также перехода можно избежать, задав стили в HTML файле вместо использования CSS, которые загружаются асинхронно.
    Ответ написан
    9 комментариев
  • Можно ли в js проверить чему равен style display в css?

    ae_ph
    @ae_ph
    I'm a owl )
    Оставлю это здесь может кому-то пригодится.
    Получить значение css свойства transform. Оно будет выдавать значения 3D-матрицы.
    И вам нужен будет определённый номер для получения значения.

    Одно из 16 значений однородной матрицы 4x4. Например, m12 представляет значение в первой строке и втором столбце.
    Находим значение в матрице для css свойства "transform: scaleY(0);" изменив 0 в css на 44 например.
    (мем: нет ты - нет ты lol. Поймёте если не поставите другое значение в css)

    let box = document.querySelector('.menu-1');
    let getStyle = getComputedStyle(box);
    let matrix = new DOMMatrixReadOnly(getStyle.transform);
    console.clear();
    console.info("gmatrix.m11 = ", matrix.m11);
    console.info("gmatrix.m12 = ", matrix.m12);
    console.info("gmatrix.m13 = ", matrix.m13);
    console.info("gmatrix.m14 = ", matrix.m14);
    console.info("gmatrix.m21 = ", matrix.m21);
    console.info("gmatrix.m22 = ", matrix.m22);
    console.info("gmatrix.m23 = ", matrix.m23);
    console.info("gmatrix.m24 = ", matrix.m24);
    console.info("gmatrix.m31 = ", matrix.m31);
    console.info("gmatrix.m32 = ", matrix.m32);
    console.info("gmatrix.m33 = ", matrix.m33);
    console.info("gmatrix.m34 = ", matrix.m34);
    console.info("gmatrix.m41 = ", matrix.m41);
    console.info("gmatrix.m42 = ", matrix.m42);
    console.info("gmatrix.m43 = ", matrix.m43);
    console.info("gmatrix.m44 = ", matrix.m44);


    Использование DOMMatrixReadOnly интерфейса вместо WebKitCSSMatrix.
    WebKitCSSMatrix является псевдонимом DOMMatrix, который является изменяемой версией DOMMatrixReadOnly, наследующей от него свойства.
    Ответ написан
    Комментировать
  • Почему ранее добавленный класс не удаляется?

    ae_ph
    @ae_ph Автор вопроса
    I'm a owl )
    mahmudchon Gary_Ihar
    Да верно, допустил ошибку в написании.. Спасибо!

    На JS
    let msBtn = document.querySelector(".message-good-btn");
    msBtn.onclick = function() {
        let off = document.querySelector(".message-good");
        off.classList.remove('ms-on');
    };

    ========================================================

    На jQuery
    $(function() {
        let msBtn = document.querySelector(".message-good-btn");
        msBtn.onclick = function() {
            let off = document.querySelector(".message-good");
            off.classList.remove('ms-on');
        };
    });
    Ответ написан
    Комментировать
  • Как защитить форму отправки писем от ботов и XSS?

    ae_ph
    @ae_ph Автор вопроса
    I'm a owl )
    Да для защиты от XSS нужен бэкенд и как они это там делают я вот вообще не в курсе, точно так-же как и ставят серверную часть.
    Но хотя-бы экрнирование input'ов можно произвести на фронте. Что в принципе я уже и написал на JS.
    Ответ написан
    Комментировать
  • Почему gulp uglify выдаёт ошибку?

    ae_ph
    @ae_ph
    I'm a owl )
    Или как вариант
    Для того, что-бы uglify-js поддерживал ES2015 + (ES6 +)
    Нужно установить дополнительно экспериментальную ветвь harmony
    npm install --save-dev uglify-js@github:mishoo/UglifyJS2#harmony

    Ничего в gulpfile.js менять (подключать её) не нужно, просто установить и всё будет работать.
    Все настройки в gulp-uglify встанут автоматически.

    Более подробно uglify-js-es6
    Ответ написан
    Комментировать