• Как воспроизвести видео YouTube при клике по стороннему элементу в 2021?

    @maximrabotaet
    Писал недавно подобное с ресайзом при изменении разрешения, в проекте используется jquery, но в основном для селекторов и слушания событий, можно легко поменять на ванильный.

    YouTube.js:
    export default class YouTube {
    
      states = Object.freeze({
        INIT: 'INIT',
        PLAY: 'PLAY',
        PAUSE: 'PAUSE',
      });
    
      constructor({container, videoId}) {
    
        this.container = container;
        this.videoId = videoId;
        this.isPlayerReady = false;
        this.initState = this.states.INIT;
        this.resizeTimeout = null;
        this.resizeTimeoutDelay = 500;
    
        YouTube.addScript();
    
        YouTube.onYouTubeIframeAPIReady(() => {
    
          this.player = this.getPlayer();
        });
    
        $(window).on('resize', () => {
    
          clearTimeout(this.resizeTimeout);
    
          this.resizeTimeout = setTimeout(() => {
    
            this.setDimensions();
    
          }, this.resizeTimeoutDelay);
        });
      }
    
      setDimensions() {
    
        $.getJSON(`https://www.youtube.com/oembed?url=https://www.youtube.com/watch?v=${this.videoId}&format=json`,
          ({width, height}) => {
    
            const elm = $(this.player.getIframe());
            const elmWidth = elm.width();
            const elmHeight = height * elmWidth / width;
    
            elm.height(Math.floor(elmHeight));
          });
      }
    
      isPauseState() {
    
        return this.states.PAUSE === this.initState;
      }
    
      isPlayState() {
    
        return this.states.PLAY === this.initState;
      }
    
      onPlayerReady() {
    
        this.isPlayerReady = true;
    
        if (this.isPauseState())
          this.pause();
    
        else if (this.isPlayState())
          this.play();
    
        this.setDimensions();
      }
    
      play() {
    
        if (this.isPlayerReady)
          this.player.playVideo();
    
        this.initState = this.states.PLAY;
      };
    
      pause() {
    
        if (this.isPlayerReady)
          this.player.pauseVideo();
    
        this.initState = this.states.PAUSE;
      };
    
      getPlayer() {
    
        return new YT.Player(this.container, {
          videoId: this.videoId,
          width: 945,
          events: {
            'onReady': this.onPlayerReady.bind(this),
          }
        });
      }
    
      static onYouTubeIframeAPIReady(fn) {
    
        if (!window.hasOwnProperty('onYouTubeIframeAPIReadyEvents') && !Array.isArray(window.onYouTubeIframeAPIReadyEvents))
          window.onYouTubeIframeAPIReadyEvents = [];
    
        if (!window.hasOwnProperty('onYouTubeIframeAPIReady') || !window.onYouTubeIframeAPIReady) {
    
          window.onYouTubeIframeAPIReady = function () {
    
            for (let i = 0; i < window.onYouTubeIframeAPIReadyEvents.length; i++)
              window.onYouTubeIframeAPIReadyEvents[i]();
          };
        }
    
        window.onYouTubeIframeAPIReadyEvents.push(fn);
      }
    
      static addScript() {
    
        if (!YouTube.isScriptAdded()) {
    
          const tag = document.createElement('script');
    
          tag.src = 'https://www.youtube.com/iframe_api';
          const firstScriptTag = document.getElementsByTagName('script')[0];
          firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
    
          window.youTubeScriptAdded = true;
        }
      }
    
      static isScriptAdded() {
    
        return window.hasOwnProperty('youTubeScriptAdded') && window.youTubeScriptAdded;
      }
    }


    место где надо вешать эвенты на кнопку:
    import YouTube from '../../../utils/YouTube';
    
    $(window).on('load', () => {
    
      const video = $('.video-js');
      const playButton = $('.video_button-js');
      const youTube = new YouTube({
        container: video.get(0),
        videoId: 'ТУТ ВИДЕО ID', // обычно get параметр в ссылке на видео "v=ВИДЕО_ID'"
      });
    
      
      playButton .on('click', () => {
    
        youTube.play();
        // youTube.pause();
      });
    });


    место где должно быть видео:
    <div class="video-js"></div>
    <div class="video_button-js">Play</div>
    Ответ написан
  • Как синхронизировать действия пользователей и данные в многопользовательской системе?

    @maximrabotaet
    Можно блокировать редактирование данных пока user1 эти данные редактирует, т.е. выводить оповещение для user2 что в данный момент данные редактируются и предложить продолжить редактирование несмотря ни на что.

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

    Это тоже вариант
    Ответ написан
    3 комментария
  • Авторизация по ссылке laravel?

    @maximrabotaet
    Генерируйте ссылку в письме с токеном в url, при регистрации к юзеру в бд добавляйте signup_token (сам токен) и signup
    _token_expired (время жизни токена), на странице подтверждения находите юзера по токену из url и проверяйте актуальность токена, если все хорошо, авторизируйте
    Ответ написан
    Комментировать
  • Как верстать такие "чудо" макеты?

    @maximrabotaet
    Абсолютное позиционирование, задать конкретную высоту контейнера, top left width и height указывать в процентах (height только для тех элементов которые не должны рушатся - стрелки линии и т.п.), тогда стрелки и линии будут на своих местах, + 3 телеги медиа-запросов. И как подметили выше, для мобилки отдельный дизайн нужен.
    Ответ написан
    6 комментариев
  • Как реализовать такое?

    @maximrabotaet
    Самый простой вариант задать в медиа-запросах order для блоков, при верстке с флексбоксами
    .block_container{
        display: flex;
        flex-flow: row wrap;
    }
    /*
    [][]
    [   ]
    [][]
    [   ]
    */
    .block-1, .block-2{ order: 1}
    .banner-1{ order: 2}
    .block-3, .block-4{ order: 3}
    .banner-2{ order: 4}
    /*...*/
    
    /*
    [][][]
    [     ]
    [][][]
    [     ]
    */
    @media (min-width: 768px){
        .block-1, .block-2, .block-3{ order: 1}
        .banner-1{ order: 2}
        .block-4, .block-5, .block-6{ order: 3}
        .banner-2{ order: 4}
    /*...*/
    }
    /*...*/
    Ответ написан
    2 комментария
  • Как в onclick передать родителя?

    @maximrabotaet
    Как в onclick передать родителя?

    https://developer.mozilla.org/ru/docs/Web/API/Elem...

    Есть ли какой-нибудь более элегантный способ, чем мой?

    class FormSubmitHandler{
    
        constructor(form){
    
            this.form = form;
    
            this.isSending = false;
    
            this.form.addEventListener('submit', this.onSubmit.bind(this));
        }
        onSubmit(e){
    
            e.preventDefault();
    
            // не отправляем форму пока ответ не пришел
            if(this.isSending)
                return;
    
            const data = new FormData(this.form);
    
            if(!this.validate(data))
                return;
    
            this.isSending = true;
    
            this.send(this.form.getAttribute("php"), data);
        }
        send(url, data){
    
            fetch(url, {
                method: "POST",
                body: data,
            })
                .then(response => response.json())
                .then(this.onCommit.bind(this))
                .catch(this.onBadRequest.bind(this));
        }
        onCommit(responseData){
    
            console.log(responseData, this.form);
    
            this.isSending = false;
        }
        onBadRequest(error){
    
            console.log(error, this.form);
    
            this.isSending = false;
        }
        validate(data){
    
            console.log(data.getAll(), this.form);
    
            // проверка полей формы
        }
    }
    
    ///////////////////////////////////////////////
    
    document.querySelectorAll('form').forEach((formElm) => {
    
        new FormSubmitHandler(formElm);
    });
    Ответ написан
    Комментировать
  • Как сделать такой календарь?

    @maximrabotaet
    Можете поискать календарь где есть api по смене месяца или года, скрыть через css стандартное отображение смены месяца/года и сделать свое, привязав его к api календаря, например тут есть методы next() и prev(), которые в зависимости от вида меняют месяц или год, и есть свойство view которое меняет вид календаря отображая месяц или год.

    Можно попробовать что-то типа этого:
    //...
    
    // клик на кнопку следующего месяца, если текущее представление дни месяца:
    datepicker.next();
    
    // клик на кнопку следующего года, если текущее представление дни месяца:
    datepicker.view = 'months';
    datepicker.next();
    datepicker.view = 'days';
    
    //...
    Ответ написан
    Комментировать
  • Какое самое легкое направление для удаленной работы в IT, которому можно обучиться самостоятельно?

    @maximrabotaet
    Легче обучится дизайну, анимации, 3D, не it, но подойдёт под требования.
    Ответ написан
    Комментировать
  • Как выравнивать текст внутри кнопки?

    @maximrabotaet
    Удалить заданную высоту у кнопки и настроить внутренние вертикальные отступы одинаковыми
    Ответ написан
    Комментировать
  • Стиль нумерации пунктов Css?

    @maximrabotaet
    ol{
        list-style-position: outside;
    }
    Ответ написан
    Комментировать
  • Для чего тут создается вспомогательный блок, чтобы отделить блоки (html)?

    @maximrabotaet
    Чтобы не прописывать кучу отступов для каждого блока, и изменить их одним махом у одного селектора.
    Ответ написан
    1 комментарий
  • Как в symfony 3.4 вытащить пользователей у которых нет конкретных ролей?

    @maximrabotaet Автор вопроса
    Вот так:
    /**
         * @param string $role
         *
         * @return array
         */
        public function findWithoutRole($role)
        {
            $qb = $this->_em->createQueryBuilder();
            $qb->select('u')
                ->from($this->_entityName, 'u')
                ->where('u.roles NOT LIKE :roles')
                ->setParameter('roles', '%"' . $role . '"%');
            return $qb->getQuery()->getResult();
        }
    Ответ написан
    2 комментария
  • Как реализовать прием команд приложению на node js на сервере?

    @maximrabotaet Автор вопроса
    Рабочий пример, мб кому пригодится, т.к. на php очень мало решений нашёл.

    Клиент php:
    <?
    require __DIR__ . '/vendor/autoload.php';
    
    use Ahc\Jwt\JWT;
    use ElephantIO\Client;
    use ElephantIO\Engine\SocketIO\Version2X;
    
    $secret = 'shecret';
    $host = 'http://localhost';
    $port = 3000;
    $maxAge = 600;
    
    $payload = [
        'data' => '123',
    ];
    $jwt = new JWT($secret, 'HS256', $maxAge);
    $token = $jwt->encode($payload);
    
    $client = new Client(new Version2X($host .':'. $port));
    
    $client->initialize();
    
    $client->emit('authenticate', ['token' => $token]);
    
    $isAuthenticated = formatResponse($client->read());
    
    if('authenticated' !== $isAuthenticated['event']){
    
        $client->close();
    }
    
    $data = [
        'data' => 'from client'
    ];
    $token = $jwt->encode($data);
    
    $client->emit('action', ['token' => $token]);
    
    $response = formatResponse($client->read());
    
    if($response['data']){
    
        $response = ($jwt->decode($response['data']->token))['data'];
    }
    
    $client->close();
    
    echo '<pre>';
    print_r($response);
    echo '</pre>';
    
    
    function formatResponse($response){
    
        $response = json_decode(preg_replace('/^\d*/i', '', $response));
    
        return $response ? [
                'event' => $response[0],
                'data' => $response[1],
            ] : false;
    }


    Сервер nodeJS:
    require("@babel/register");
    const
        socketIO = require('socket.io'),
        jwt = require('jsonwebtoken'),
        socketioJwt = require('socketio-jwt'),
        port = 3000,
        server = socketIO.listen(port),
        secret = 'shecret',
        maxAge = 600;
    
    server
        .on(
            'connection',
            socketioJwt.authorize({
                secret: secret,
                timeout: 10000,
                callback: false
            }
        ))
        .on('connection', socket => {
    
            console.log('on connection to server (server)');
        })
        .on('authenticated', socket => {
    
            console.log('on authenticated to server (server), socket.decoded_token', socket.decoded_token);
    
            socket.on('action', data => {
    
                console.log('on action (server)', data);
    
                if(data && 'token' in data){
    
                    let decoded = null;
    
                    try {
    
                        decoded = jwt.verify(data.token, secret);
    
                    } catch (err) {
    
                        console.log(err);
                    }
    
                    if(decoded){
    
                        console.log(decoded);
    
                        const token = jwt.sign(
                            {
                                exp: Math.floor(Date.now() / 1000) + maxAge,
                                data: 'from server'
                            },
                            secret);
    
                        socket.emit('action', {token: token});
    
                    } else {
    
                        socket.disconnect(true);
                    }
                }
            })
        })
    ;


    Пакеты:
    // composer.json
        "adhocore/jwt": "^0.1.0",
        "wisembly/elephant.io": "^3.3"
    
    // package.json
        "jsonwebtoken": "^8.5.1",
        "socket.io": "^2.3.0",
        "socketio-jwt": "^4.5.0"
    Ответ написан
    Комментировать
  • Снова вопрос по меню с косыми линиями(параллеограмм), как реализовать такой эффект с помощью псевдоэлементов?

    @maximrabotaet
    https://codepen.io/Smiky/pen/dyyGqQp
    Еще вместо трансформации можете использовать svg с preserveAspectRatio="none" с background-size: 100% 100%; для псевдо-элементов
    Ответ написан
  • Поиск по select?

    @maximrabotaet
    https://select2.org/searching триггерит все события на скрытый селект и скорее всего добавляет свои (я точно не помню), этого вполне достаточно для любой задачи, хоть для использования в форме, хоть для построения логики при взаимодействии. Похоже на то что вы либо ищите не стандартный веб-комопнент, либо плагин который никто никогда не делал.

    Вы можете продублировать селект с теми же значениями и выводить его где вам нужно, можно даже инициализировать не заполняя тег селекта, повесить нужные эвенты на выбор значения и выбирать в продублированном НЕ скрытом селекте выбранное значение, но зачем это нужно?
    Ответ написан
    Комментировать
  • Какие сервисы/хостинг могут запустить программу на nodejs, electron и puppeteer на удаленном сервере?

    @maximrabotaet Автор вопроса
    Всем спасибо!

    Воспользовался этой инструкцией, только возникли ошибки с 4 шагом, но и без него пока все работает.
    Can't find file /home/userone/.vnc/example123.com:1.pid

    Для клиента использую VNC® Viewer.

    Заказал обычный дешевый vps, буду менять на более мощный.
    Ответ написан
    Комментировать