• Как принудительно остановить отрисовку всех vuejs компонентов?

    dubr
    @dubr
    пыхарь
    Ну вот надо чтобы до перезагрузки страницы интерфейс "замер".

    Попробуйте примерно так:
    const appNode = document.querySelector('#app');
    appNode.innerHTML = appNode.innerHTML;

    По идее обработчики событий должны пропасть, а компоненты потеряют связь с DOM и всякие отложенные действия перестанут работать. Но это не точно =)
    Ответ написан
    Комментировать
  • Добавить в массив rows (vue.js) данные из базы mysql (php)?

    dubr
    @dubr
    пыхарь
    Если я правильно понимаю, тут не SPA со сборкой, а олдскульные пхп-шаблоны, верно?
    Тогда можно данные пихать в дата-атрибут примерно так:
    <div id="app" data-rows='<?=json_encode($rows)?>'>...</div>

    А потом читать их примерно так:
    data() {
       return { rows: JSON.parse(this.$el.getAttribute('data-rows')) };
    }

    Но вообще да, лучше, как писали выше, отдавать апишкой и забирать аксиосом =)
    Ответ написан
    Комментировать
  • Как в компоненте отследить изменение полей для включения кнопок сохранения?

    dubr
    @dubr
    пыхарь
    Вотчеры - это обычно признак джейквири-программирования =)
    Лучше сохранять оригинальные данные и их сравнивать с текущими. Так и честный changed будет (у вас скорее "touched").

    Вот набросал примерно:
    const api = {
      async getData() {
        return {name: 'Foo', email: 'foo@bar.com'};
      }
    }
    
    new Vue({
      el:'#app',
      template: `<div v-if="current">
        <input v-model="current.name" />
        <input v-model="current.email" />
        <button :disabled="!isChanged">submit</button>
      </div>`,
      data() {
        return {
          original: null,
          current: null,
        }
      },
      async created() {
        const data = await api.getData();
        this.original = JSON.stringify(data);
        this.current = data;
      },
      computed: {
        isChanged() {
          return JSON.stringify(this.current) !== this.original;
        }
      }
    });

    https://codepen.io/dubrowsky/pen/BvdKZE?editors=1010

    UPD: Если нужен не changed, а touched - сделайте
    <input type="text" v-model="name" @input="name_changed = true">
    и будет счастие
    Ответ написан
    3 комментария
  • Как отследить удаление DOM элемента во vue.js?

    dubr
    @dubr
    пыхарь
    1) можно поюзать https://developer.mozilla.org/en-US/docs/Web/API/M... - если не нужны старые IE (если нужны - для 9-10 можно подпереть вот этим https://developer.mozilla.org/en-US/docs/Web/API/M... )

    2) можно пропатчить либу (и заслать MR, если либа живая)

    3) самый тупой и рабочий способ, который советовали в комментах и который я бы скорее всего и взял - проверять присутствие элемента через интервал / requestAnimationFrame

    4) есть совсем злое решение: переопределить node.parentNode.removeChild, добавив туда ваш колбек - только никому не показывайте =)
    Ответ написан
    Комментировать
  • Как поднять блок наверх?

    dubr
    @dubr
    пыхарь
    Если я правильно понял вопрос, есть два варианта:

    1) после отрисовки перетащить кнопку по DOM-дереву в нужное место. На jQuery как-то так:

    $('.ul-widget-feedBack-form-group').eq(3).after($('.ul-w-button1').eq(0))


    Дальше отступы поправить стилями.

    2) Поскольку все элементы формы находятся на одном уровне, можно форме назначить display: flex и поставить кнопку на нужное место через свойство order. Так надежнее, но придется повозиться со стилями - вам нужно будет проставить правильную ширину всем элементам, чтобы сохранился текущий лейаут.
    Ответ написан
  • На какую CMS сделать упор, MODX, Wordpress, или...?

    dubr
    @dubr
    пыхарь
    старичкой и профессионалов фронтенда. На какую CMS вы обычно натягиваете свой макет

    старички и профессионалы фронтенда обычно натягивают свой макет на вебпак + [ву/реакт/ангуляр]

    а которые на [любимая пхп-цмс] - не фронтенды, а фуллстеки!
    Ответ написан
  • Как изменить порядок div-ов на мобильном устройстве Bootstrap?

    dubr
    @dubr
    пыхарь
    У вас в "а вот как должно" как-то дофига всего =) Поэтому вопрос не понял, а отвечаю, ориентируясь на заголовок =)

    Менять порядок дивов без JS можно при помощи свойства order из flexbox. Например, если мы хотим на мобиле сделать блок "Pasakumu kalendars" первым (по порядку DOM-дерева он второй), мы делаем следующее:

    1) устанавливаем родителю display:flex
    2) устанавливаем блоку order: -1
    3) ну и оборачиваем это все в @media

    пен

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

    dubr
    @dubr
    пыхарь
    Лев Розанов, а вы свою ссылку читали для разнообразия? ))

    afterMove(next_page_index)
    This callback gets called after the move animation was performed.


    $(".main").onepage_scroll({
        afterMove: function(index) {
          ...
        }
      });
    Ответ написан
  • Как на сервере вставить картинку в видео?

    dubr
    @dubr
    пыхарь
    Плюсую за ffmpeg, вот это похоже на ваш случай?
    Ответ написан
    Комментировать
  • ForEach внутри директивы v-if?

    dubr
    @dubr
    пыхарь
    В доке пишут:

    When they exist on the same node, v-for has a higher priority than v-if. That means the v-if will be run on each iteration of the loop separately.

    То есть выполняется цикл, и на каждом шаге - проверка. Чтобы об этом не думать, можно тупо не использовать эти директивы вместе, а писать явно. Для этого есть встроенный "прозрачный" тег template:

    <template v-if="shouldShowAllTags()">
       <a v-for="tag in tags">{{tag}}</a>
    </template>
    ...
    <template v-for="tag in tags">
       <a v-if="shouldShowThisTag(tag)">{{tag}}</a>
    </template>


    Теперь:
    1) мы можем добавить v-else, если понадобится
    2) человек, не читавший доку по ссылке выше, поймет как оно работает "на глаз", без экспериментов :)

    UPD: Перечитал комменты в соседнем ответе, вам оказывается надо другое =) Но все равно оставлю, в назидание будущим поколениям ))
    Ответ написан
    Комментировать
  • Смена активного класса при клике с помощью vue.js?

    dubr
    @dubr
    пыхарь
    Я бы сделал так

    1) item и active - плохие названия для переменных, хранящих класс, makeActive - плохое название метода, его меняющего. Называем все по-людски.
    data: {
        activeClass: 'container'
        ...
    },
    methods: {
        setActiveClass: function(className) { ... }
    }


    2) Хардкодить повторяющиеся штуки - это плохо, поэтому выносим список кнопок и связанных с ними классов в data, а в шаблоне ходим циклом:

    data: {
        activeClass: 'container',
        buttons: [
          ['+', 'container'],
          ['-', 'container-fluid']
        ]
    }
    <button  v-for="[label, className] in buttons">...</button>


    3) Собственно, теперь у нас есть все данные, чтобы выделить нужную кнопку. Кнопка активна, если текущий класс равен привязанному к ней классу, хранить отдельно состояние кнопки в data нет необходимости.
    Дописываем шаблон:

    <button 
             v-for="[label, className] in buttons"
             v-on:click="setActiveClass(className)"
             v-bind:class="{ active: className === activeClass }">
            {{label}}
          </button>
    Ответ написан
    Комментировать
  • Как можно реализовать такую задумку?

    dubr
    @dubr
    пыхарь
    Могу посоветовать, с чего начать.

    1) кладем картинку на canvas
    2) получаем при помощи getImageData() массив пикселов
    3) пытаемся тыкать в него палочкой

    Пункт 3 как бы самый интересный, но тут программировать надо.

    Я ради фана соорудил вот такую тупую демку на CodePen, называется "Png to Html". Оттуда можно скопипастить первые два пункта и примерно понять, чо делать с третьим. Оно читает картинку из file-input, кладет на канву, затем считывает попиксельно, и для пикселов, у которых альфа-канал не равен 1 и цвет не белый (точнее avg от rgb < 250) создает DOM-узел, раскрашенный нужным цветом и спозиционированный в нужное место. И обязательно с css-анимацией! +) Так что берегите свои браузеры )))

    Дальше вам надо эти пиксели как-то сгруппировать. Я бы начал с чтения статьи Connected-component labeling и гугления слов оттуда с приставкой "js". Придумаете реализацию - расскажите нам =)

    А, ну и вместо канвы можно изучить png-декодеры, они бывают для браузера (если у вас только сервер - соответственно, с них и начинаем). Должно работать шустрее, но не так наглядно.
    Ответ написан
    3 комментария
  • UMI.CMS верстка/интеграция/XSLT проблемы с меню, есть кто поможет?

    dubr
    @dubr
    пыхарь
    Последний пункт - это вот "УСГУЛИ" который? Для начала хорошо бы разобраться, как именно он исчезает - в смысле посмотреть не как это выглядит, а что в результирующем html происходит. Может он есть, но его перекрывает что-то другое, например. Или ссылка есть, а текст пустой. Если таки нету - я бы распечатал кол-во узлов, которые должны отрендериться, типа так:

    <xsl:value-of select="count(item)" />
    <ul> ...


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

    dubr
    @dubr
    пыхарь
    В этом сезоне модно создавать конструкторы вот так!

    Если серьезно - вы объясните, в чем проблема - в части devops, в смысле как БД создать / nginx перегрузить и т.д., или в части того, что на сайте будет и как юзер будет этим управлять? Если первое - надо понимать ваши масштабы, сколько сайтов, сколько серверов, размер бд, нагрузки. Если второе - то начать надо явно с тз и дизайна, а то ишь приноровились все на кодера сваливать )))

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

    Вообще алгоритм довольно тупой - сначала сделать все руками, а потом написать скрипт, который делает то же самое =)

    Для начала определитесь, будут ли все ваши сайтики работать на одной кодовой базе (скорее всего да, если нет - это уже ближе к шаред-хостингу). Дальше решите, нужен ли каждому свой персональный docroot - это зависит от того, как вы храните / раздаете статику. Если статика складывается куда-то далеко (типа на s3) - можно обойтись одним на всех, но ИМХО все-таки проще, когда он у каждого свой.

    Получится какая-то такая структура:

    app
    public
        1
            static
            index.php
            config.php
        2
        ...


    index.php подключает конфиг и запускает приложение.

    Дальше вам надо сделать, чтобы public/1 открывался по хосту типа 1.hosting.com - это nginx с регулярками.

    server {
        server_name   ~^(?<site_id>.+)\.hosting\.com$;
        root    /var/www/public/$site_id;
        ...
    }


    Кстати, если пыхе понадобится идентификатор сайта, его туда легко забросить:
    fastcgi_param SITE_ID $site_id;

    Есть нюанс с запуском PHP. По уму надо, чтобы на каждого был свой юзер, свой fpm-пул и т.д. Но у php-fpm в свое время не работал graceful reload, после добавления пула и перезапуска все клиенты получали 502. Я в итоге плюнул и стал всех обслуживать одним пулом, ограничившись open_basedir, но если у юзера есть хотя бы гипотетическая возможность добраться до кода (например какой-нибудь редактор шаблонов) - так делать не надо =) open_basedir передаем в конфиге нгинкса как-то так:

    fastcgi_param  PHP_ADMIN_VALUE "open_basedir = $document_root"


    Для подключения собственного домена юзайте map, он в нгинксе хороший =)
    map $http_host $site_id {
        site.com    1;
        site2.com  2;
    }

    Эту конструкцию можно вытащить в отдельный файл и генерить автоматом.

    С БД все просто: если можете сделать, чтобы все сидели в одной БД - так и делайте =) Если нет - делайте эталонный дамп и скрипт, который из него создает новую БД. И потом ломаем голову, как раскатывать миграции по куче баз и машин =)

    С управляющим скриптом поступаем так: фигачим сами скрипты (на чем удобно, пхп вполне справится) и http api к ним, когда юзер что-то делает на "главном" сайте, дергается этот api, это облегчит жизнь, когда перестанете влезать на один сервер.

    Для перезагрузки нгинкса и прочих стремных операций я завел отдельные sh-скрипты и засунул их в sudoers для того юзера, от которого работает api.

    Между "главным" сайтом и api полезно поставить очередь, но для начала можно и синхронно работать.

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

    dubr
    @dubr
    пыхарь
    https://codepen.io/dubrowsky/pen/oGMomN
    Это конечно не ваша задача, зато на флексбоксах из плоского списка, труъ-адаптив, остается шахматной при четном количестве колонок, и я вспомнил, как программировать на LESS :)
    Ответ написан
    Комментировать
  • Где купить работающие ссылки?

    dubr
    @dubr
    пыхарь
    Массово - кажется нигде такого формата нет, да и работать не будет, если массово. Так что выбирайте площадки, которые нравятся, и руками договаривайтесь как в старые добрые времена :) у меня например есть площадка, с которой я продавал такой баннер, потом рекл отвалился, а нового искать лень, но если бы предложили - я бы обсудил ))
    Ответ написан
    Комментировать
  • Как разделить динамический вывод элементов на группы?

    dubr
    @dubr
    пыхарь
    <?php
    function group_by_number($arr, $number) {
       $res = [];
       $counter = 0;
       foreach ($arr as $item) {
           if ($counter % $number === 0) {
               $res []= [];
           }
           $res[ count($res) - 1] []= $item;
           $counter++;
       }
       return $res;
    }
    
    $arr = ['a','b','c','d','e','f','g','h'];
    
    $groupped = group_by_number($arr, 3);
    foreach ($groupped as $group) {
       ?><div class="group"><?php
       foreach ($group as $item) {
           ?><span><?= $item ?></span><?php
       }
       ?></div><?php
    }


    Но вообще я бы сперва подумал, нельзя ли поправить верстку =)
    Ответ написан
    Комментировать
  • Как запретить рассылку спама в форме?

    dubr
    @dubr
    пыхарь
    Спам-боты (пока) не выполняют JS. При показе формы пишите в сессию код, передавайте на клиент в любом виде, на клиенте пишите из JS в скрытое поле. Пока оно не оформлено в массово используемый плагин, будет работать =)

    Вот наивная реализация в 40 строчек. Здесь генерируется два числа - секретное значение и множитель, в атрибут формы пишется множитель и произведение чисел, в JS вычисляется частное и подставляется в скрытое поле.

    <?php
    session_start();
    $secret_error = false;
    $is_sent = count($_POST);
    if (
        $is_sent && 
        (
            !isset($_POST['secret']) || 
            !isset($_SESSION['secret']) || 
            $_POST['secret'] !== $_SESSION['secret']
        )
    ) {
        $secret_error = true;
    }
    
    if ($is_sent && !$secret_error) {
        // обрабатываем, шлем письмо
        ?>
        Ваш звонок очень важен для нас!
        <?php
    } else {
        if ($secret_error) {
            ?>
            <p>Вы бот или у вас не включен JavaScript, сделайте с этим что-нибудь!</p>
            <?php
        }
        $multiplier = rand(10, 99);
        $secret = (string) rand(1000,9999);
        $_SESSION['secret'] = $secret;
        ?>
        <form action="" method="post" data-secret="<?= $secret * $multiplier ?>" data-multiplier="<?= $multiplier ?>">
            <label>Ваше имя <input name="name" /></label>
            <input type="hidden" name="secret" />
            <input type="submit" />
        </form>
        <!-- вот это можно вынести в отдельный файл -->
        <script type="text/javascript">
            document.querySelectorAll('form[data-secret]').forEach(function(form) {
                var secret = form.getAttribute('data-secret') / form.getAttribute('data-multiplier');
                form.querySelector('[name="secret"]').value = secret;
            });
        </script>
        <?php
    }


    В принципе можно с тем же успехом написать

    <script type="text/javascript">
            document.querySelector('[name="secret"]').value = "<?= $secret ?>";
    </script>


    Скорее всего кодеру, который делает бота, будет лень разбираться, как оно у вас работает, если оно работает только у вас (то есть не является тиражным решением). Магия со множителями или чем-то таким просто не позволяет вытащить значение одной регуляркой, еще немного снижая шансы заинтересовать злодея =)
    Ответ написан
    1 комментарий
  • PHP: Почему Class not found если use в другом файле?

    dubr
    @dubr
    пыхарь
    Почитайте доку для разнообразия.
    Неймспейсы и директивы use работают на уровне файлов. То есть use связывает полное имя с кратким/алиасом только в том файле, где его написали.
    Ответ написан
    Комментировать