Ответы пользователя по тегу JavaScript
  • Как заставить предупреждение срабатывать только после нажатия "Да/Нет" в диалоговом окне?

    Первое, что вам надо сделать - изучить самые базовые основы Javascript и DOM, и как это всё работает.
    Вы должны понимать, что Javascript - это не PHP. PHP работает только в один поток и выполняет операции исключительно одну за другой по порядку. В Javascript же есть возможность выполнять код асинхронно с использованием такого инструмента, как Event Loop. Ещё обязательно изучить, что такое Promise и как подсластить его использование при помощи сахарка async - await

    Т.е. ваш обычный код, который выполняется по порядку, может выполняться как бы "одновременно" с кодом, который выполняется при нажатии на кнопку. Т.е. пока ваша кнопка ждёт события click, чтобы выполнить какой-то код по нажатию, остальная программа спокойно себе исполняется по порядку. Таким образом, пользователь еще не успел кликнуть, но ваша программа уже создала диалог при помощи функции Myconfirmselect, и спокойно себе приступила к следующей операции. А этой следующей операцией как раз и является тот самый alert("!"). Вот он и появляется на экране.

    Т.е. нам надо как бы подсунуть этот alert внутрь функции Myconfirmselect. Как это сделать? В Javascript функции - это такие же объекты. Т.е. функцию можно назначить какой-то переменной и передать эту переменную в другую функцию. Вот мы и передаём наш callback в функцию Myconfirmselect просто в качестве аргумента, и вызываем этот аргумент как функцию уже в том месте, где обрабатывается событие click на кнопку.

    P.S. В коде постоянно происходит выборка одного и того же элемента. Это не очень хорошо, потому что такая выборка не бесплатна, все операции с DOM - довольно медленные, поэтому я позволил себе переписать часть кода, не меняя самой его структуры, чтобы вам было понятнее. Выбрав один раз наш конкретный dialog нет смысла выбирать его постоянно еще и еще раз. Запихнём его в переменную и будем с ним работать. То же самое касается и textarea и div

    <html>
        <body onload="Load()">
            <dialog></dialog>
            <script>
                function Load() {
                    setTimeout(() => {
                        // Создаём колбэк, функцию, которая будет вызываться только после нажатия на кнопку
                        const callback = function () {
                            alert("!");
                        };
    
                        Myconfirmselect(
                            "Готовы?" +
                                "¤" +
                                "Да" +
                                "¥" +
                                "alert('Да');" +
                                "º" +
                                "Нет" +
                                "¥" +
                                "alert('Нет');",
                            callback, // Передаём колбэк в функцию создания диалога
                        );
                    }, 500);
                }
    
                function Myconfirmselect(VarInput, callback) {
                    const dialog = document.querySelector("dialog");
                    dialog.innerHTML += `
       <div>
        <textarea></textarea>
       </div>
       `;
    
                    const textarea = dialog.querySelector("textarea");
                    const div = dialog.querySelector("div");
                    dialog.style.textAlign = "center";
                    textarea.style.width = "100%";
                    textarea.style.textAlign = "center";
                    textarea.style.resize = "none";
                    textarea.readOnly = true;
                    textarea.value = VarInput.split("¤")[0];
                    for (
                        let i = 0;
                        i < VarInput.split("¤")[1].split("º").length;
                        i++
                    ) {
                        const VarButton = document.createElement("button");
                        VarButton.textContent = VarInput.split("¤")[1]
                            .split("º")
                            [i].split("¥")[0];
                        VarButton.id = VarInput.split("¤")[1]
                            .split("º")
                            [i].split("¥")[1];
                        VarButton.style.marginLeft = "10px";
                        VarButton.style.marginTop = "10px";
                        VarButton.addEventListener("click", () => {
                            eval(event.target.id);
                            // Вызов того самого callback после нажатия на кнопку
                            callback();
                            //ButtonClosealert();
                        });
                        div.appendChild(VarButton);
                    }
                    function ButtonClosealert() {
                        dialog.style.animation = "AnimFormHide 0.1s both";
                        setTimeout(() => {
                            dialog.style.textAlign = "initial";
                            const div = dialog.querySelector("div");
                            dialog.removeChild(div);
                            dialog.close();
                        }, 100);
                    }
                    dialog.style.animation = "AnimFormShow 0.25s both";
                    dialog.showModal();
                }
            </script>
            <style>
                @keyframes AnimFormShow {
                    0% {
                        transform: translateY(-150%);
                    }
                }
    
                @keyframes AnimFormHide {
                    100% {
                        transform: translateY(-150%);
                        display: none;
                    }
                }
    
                dialog,
                #DialogCycle {
                    border: 2px solid black;
                    border-radius: 15px;
                }
    
                dialog div,
                #DialogCycle div {
                    position: initial;
                }
    
                dialog::backdrop,
                #DialogCycle::backdrop {
                    background: rgba(0, 0, 0, 0.6);
                }
            </style>
        </body>
    </html>
    Ответ написан
    Комментировать
  • Как в js, scss, html реализовать tooltip который показывается если навести на объект ниже?

    А зачем такие сложности с такой простой задачей, как тултипы? Их ведь можно реализовать полностью на CSS, просто добавив нужному элементу, например, атрибут "tooltip"



    Анимацию уже сами добавите, если очень нужна

    Если же очень хотите именно при наведении на следующий элемент что-то делать, то могу просто предложить идею селектора, который позволяет таким образом выбирать



    .custom-tooltip:has(+ *:hover) означает, что выбрать надо те элементы .custom-tooltip, у которых на следующем за ними элементе наведена мышь.
    "+" выбор непосредственно следующего элемента
    "+ *"- выбор любого непосредственного следующего элемента
    "+ *:hover" - выбор любого непосредственного следующего элемента, на который наведена мышь.
    has  выбирает элементы .custom-tooltip, с которым связаны элементы, выбранные при помощи уточняющего селектора в скобках.
    Ответ написан
    1 комментарий
  • Как отследить нажатие по определенной границе в canvas?

    У canvas есть прекрасный метод isPointInPath

    Документация https://developer.mozilla.org/en-US/docs/Web/API/C...

    Ответ написан
    Комментировать
  • Как сделать кривую линию между двумя блоками диаграммы?

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

    https://github.com/clientIO/joint

    Примеры:
    https://codepen.io/jointjs
    Ответ написан
    Комментировать
  • По какому принципу работает алгоритм с массивом очереди?

    Вот вам готовая простейшая очередь в виде объекта без всяких переборов:

    class Queue {
      constructor() {
        this.items = {};
        this.front = 0;
        this.rear = 0;
      }
      enqueue(item) {
        this.items[this.rear] = item;
        this.rear++;
      }
      dequeue() {
        const item = this.items[this.front];
        delete this.items[this.front];
        this.front++;
        return item;
      }
      peek() {
        return this.items[this.front];
      }
      get size() {
        return this.rear - this.front;
      }
      isEmpty() {
        return this.rear == 0;
      }
    }
    const queue = new Queue();
    queue.enqueue(1);
    queue.enqueue(2);
    queue.enqueue(3);
    queue.enqueue(4);
    queue.enqueue(5);
    
    console.log("Объект очереди: ", queue);
    
    const removed_element = queue.dequeue();
    console.log("Обработанный (удаленный) элемент: ", removed_element);
    
    console.log("Объект очереди:", queue);
    
    const top_element = queue.peek();
    console.log("Текущий элемент очереди для обработки (без удаления): ", top_element);
    
    const queue_length = queue.size;
    console.log("Размер очереди: ", queue_length);
    Ответ написан
    Комментировать
  • Из-за чего инкрементация в for и while срабатывает по разному?

    Обратите внимание на конструкцию for.
    Вы не замечаете, что выражения между скобками разделены не запятой, как, например, в аргументах функции, а точкой с запятой?

    Так создатели языка как бы намекают нам, что тут что-то не так, как обычно, что эти выражения выполняются в разное время, на разных этапах прохождения цикла.

    Уяснив этот момент, можно пойти в документацию, прочитать там все, а особенно обратить внимание на табличку, где расписано, когда именно выполняется каждая составная часть цикла for. И тогда вам всё станет гораздо понятнее.
    https://learn.javascript.ru/while-for

    Советы:
    1. Всегда читайте документацию, если вам что-то не понятно в конструкциях языка. Не туториалы от балбесов с Ютуба, а документацию. И желательно оригинальную на английском, потому что переводчики иногда такие же балбесы.

    2. Не используйте никаких циклов, кроме for. Он очень мощный и позволяет реализовать функциональность и while и do-while. Так вы убережёте себя от таких ситуаций. Я за много лет работы понял, что большое количество конструкций языка скорее вредно, чем полезно.
    Ответ написан
    2 комментария
  • Почему не работает проверка NAN?

    Это JavaScript, детка!
    661a3785d1ef6444222209.png
    661a37a01e49d767748270.jpeg
    661a37d8b28b9965055125.png
    Ответ написан
    Комментировать
  • Как реализовать домашний ПК для веб сервера и pet проектов?

    Если не боитесь использовать Cloudflare в наших волшебных политических реалиях, то у них есть прекрасное решение для обеспечения безопасности: "Zero trust tunnel". Это не просто прокси-сервер, а самый настоящий туннель. Т.е. ваш сервак может находиться за непробиваемым файрволом, но по туннелю вы сможете организовать безопасный доступ к тем ресурсам, к которым пожелаете.
    Таким образом, даже если кто-то будет атаковать ваши ресурсы, то атаковать они будут Cloudflare, а не ваш ненаглядный сервачок.
    Ответ написан
    Комментировать
  • Как добавить элемент в массив по условию JS?

    Элегантный способ - это не всегда хорошо. Если массив не занимает мегабайты данных, то самым простым способом будет создание нового выходного массива нулевой длины, а потом, просто перебирая элементы оригинального массива, вставляете их в новый массив, а в нужные моменты просто вставляйте сперва эту вставку , а потом сразу элемент оригинального массива.
    И не нужны вам эти "шикарные" reduce в данной ситуации. Обычный цикл for. Потому что reduce совершенно бесполезен конкретно в данном случае, а читаемость ухудшит.

    const arr = [
        {src: 'some-path-1', video: 'some-path-1'},
        {src: 'some-path-2', video: 'some-path-2'},
        {src: 'some-path', video: null},
    ];
    
    const result = [];
    for (let i = 0; i < arr.length; i++) {
      if (arr[i]?.video) {
        result.push({ src_video: arr[i].video });
      }
      result.push(arr[i]);
    }
    
    console.log(result);
    Ответ написан
    9 комментариев
  • Как решить зависимость класса от другого класса?

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

    Всем "опасным" кнопкам по умолчанию устанавливаем атрибут disabled. Тогда их нельзя будет нажать.

    <button class="dangerous"  disabled>Сохранить</button>


    И сделать обработчик события загрузки страницы, который уберет этот самый атрибут с опасных кнопок по окончании полной загрузки страницы

    document.addEventListener(‘load’, function() { 
    	const dangers = document.querySelectorAll(".dangerous");
            dangers.forEach((item) => {
                  item.removeAttribute('disabled'):
            });
    }


    Если же вас беспокоят именно элементы, остающиеся на экране при старте перезагрузки, то самым простым решением было бы вообще удалить весь html страницы до перезагрузки, а потом спокойно её запустить. Либо вы можете точно так же в момент, когда вам надо запустить перезагрузку, установить всем опасным кнопкам атрибут disabled, а потом стартовать перезагрузку страницы.

    Но!!! Данный подход только лишь сделает жизнь пользователей более приятной. Не забывайте, что фронтенд-фрогнтендом, но бэкенд должен всё же уметь работать с такими запросами, которые не будут содержать в себе все нужные данные.
    Первое правило бэкенда - "Никогда не верь фронтенду и его данным, проверяй и валидируй всё"
    Ответ написан
    Комментировать
  • Как создавать, принимать и обрабатывать socket?

    1. Вебсокеты - это сложновато.
    2. Вебсокеты на PHP - вдвойне сложно. Проблема в том, что PHP задуман как скриптовый язык, т.е. скрипт выполняется заканчивает свою работу. А вебсокет - это постоянное соединение, т.е нам надо, чтобы программа постоянно крутилась в фоне. Вебсокеты можно реализовать на PHP, но, как персонально мне кажется, проще будет выучить Go )) , или же, как в ответе уважаемого Артём , сделать сервер на ноде.
    3. Если ваш чат не такой супер-функциональный, как чат в мессенджерах, то вместо вебсокетов можно обойтись SSE (Server Sent Events). SSE так же требует постоянного соединения, но всё работает через HTTP, и это ну прямо намного проще. Единственный недостаток - это то, что SSE работает только в одну сторону: от сервера в браузер. Т.е. запросы из браузера можно получать обычным POST запросом, а отдавать обратно информацию уже через SSE.

    С SSE есть два пути:
    1. Написать сервер самому, используя какую-то простую библиотеку вроде этой https://github.com/hhxsv5/php-sse
    2. Но я бы сделал ещё проще. Есть такой великолепный проект под названием Mercure https://mercure.rocks
    Это отдельный сервис на Go, задача которого как раз поддерживать SSE соединение и отправлять сообщения в браузеры. Сервис сидит в фоне, а браузеры подписываются на события через EventSource буквально в три строчки, как описано тут https://mercure.rocks/docs/getting-started
    Прелесть этого в том, что для того, чтобы отправить сообщение всем браузерам из кода на PHP, вам надо просто сделать обычный POST запрос на специальный адрес этого сервиса Mercure с телом самого сообщения и его id. Т.е. вам не надо делать никаких долгоживущих процессов на PHP, всё будет работать как раньше.

    Т.е. подытожим:
    - Браузеры пользователей подписываются на события в Mercure
    - Пользователь 1 отправляет текстовое сообщение обычным POST запросом на обычный PHP сайт.
    - PHP сайт получает этот POST запрос, определяет, что его надо отправить Пользователю 2, и отправляет соответствующее сообщение обычным POST запросом в сервис Mercure
    - Mercure отправляет сообщение Пользователю 2 через SSE, на которые он подписан.
    - Сообщение появляется у него на страничке
    Ответ написан
    5 комментариев
  • Как предотвратить бесконечную загрузку страницы при отправке post запроса?

    Использовать SSE (Server Sent Events). Это на порядок проще, чем вебсокеты, но мощь практически такая же.
    Вот неплохая статья на английском.
    https://blog.stackademic.com/real-time-communicati...

    Кстати, библиотека HTMX позволяет это обрабатывать и без написания Javascript
    https://htmx.org/extensions/server-sent-events/
    Ответ написан
    Комментировать
  • Есть ли сейчас необходимость в HTML5Shiv и Modernizr?

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

    Если ваш продукт рассчитан на банки или корпорации, то надо заморочиться с обратной совместимостью. Там люди сидят иногда на очень старых версиях всего.

    Если же это обычные люди, сидящие в интернете, то, скорей всего они используют Chrome или Microsoft Edge. Эти браузеры постоянно обновляются в фоне, и перед внедрением новых фич вам просто нужно периодически заходить на https://caniuse.com/ и ориентироваться на последние 2 версии этих браузеров. Safari может стать проблемой, если ваши пользователи часто покупают Маки. Safari - это, к большому сожалению, новый IE6, который тормозит индустрию...

    Самый лучший способ - это собрать информацию. Если у вас уже есть какой-то сайт для вашей аудитории, то там и собирайте статистику. Исходя из этой статистики принимайте решение. Охватывать все 100% не стоит, лишняя трата времени, денег, нервов. Оно не окупается. Каким процентом пользователей вы можете пренебречь - это всегда индивидуальное решение, но убедить руководство, что такое решение надо принять, всегда надо, потому что вы потом закопаете проект в этой обратной совместимости и потенциальных багах и уязвимостях, идущих с ней в пакете...
    Ответ написан
    6 комментариев
  • Есть ли смысл учить jquery?

    1. Выучить JS
    2. Поверхностно ознакомиться с jQuery
    3. Написать собственную микро-jQuery в учебных целях - реально поможет со всем разобраться.
    4. Использовать jQuery, если надо быстро клепать лендинги. Использовать чистый JS в более сложных проектах.

    Без знания JS не стоит браться за jQuery, потому что не захочется учить сам JS, а это вызовет огромные проблемы, когда нужно будет сделать что-то посложней. Сам когда-то давно начал с jQuery, и потом пришлось в авральном режиме изучать JS, много заказов потерял
    Ответ написан
    3 комментария
  • Кнопка - переключатель на jQuery?

    Вот идея кастомного чекбокса на CSS без всякого JS.
    https://codepen.io/vitiok78/pen/pmbyzE
    Ответ написан
    Комментировать