• Html to pdf js?

    @nikfakel
    Веб-разработчик
    https://github.com/MrRio/jsPDF, с кириллицей все нормально
    Ответ написан
    9 комментариев
  • Какие задачи решает реактивное программирование?

    @kttotto
    пофиг на чем писать
    Есть два варианта получить данные. Можно пассивным способом, это когда мы сами делаем запрос на получение и нам приходит ответ (вариант pull). И есть второй вариант, когда данные сами нас уведомляют об изменениях и выталкивают данные нам (вариант push). Реактивное приложение, это когда приложение само извещает нас об изменении своего состояния. Не мы делаем запрос и проверяем, а не изменилось ли там что-то, а приложение само нам сигнализирует. Ну и конечно эти события, эти сигналы мы соответственно можем обрабатывать.

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

    @Hydro
    C#/.NET Developer
    Надеюсь, что правильно понял Ваш вопрос.

    Пример

    Храню в БД фото с марса в формате HD, делаю запрос на 100 фотографии, задача - показать 100 фоток последовательно на экране.

    Стандартный поход: делаю запрос к базе на 100 фотографии, жду 2 секунды, получаю массив из 100 фотографии,
    итератором бегаю по коллекции и показываю картинки на экране
    псевдокод:

    pics = GetPicsFromDatabase();
    foreach(var pic in pics)
      ShowPic(pic)


    Реактивный подход: делаю запрос к базе на 100 фотографии и обработчику запроса задаю коллбек, обрабатывающий следующий элемент коллекции

    псевдокод:
    // somecode
    GetPicsFromDatabaseReactive(NextPictureHandler);
    // somecode
    NextPictureHandler(Image pic)
    {
      ShowPic(pic)
    }

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

    Что это нам дает?
    Асинхронность - в UI например это дает отзывчивость)
    Масштабируемость - источник данных (коллекция картинок) и приемник (наш псевдкод, показывающий картинки) не связаны, отсутствие связи дает нам возможность подключить хоть 10 обработчиков картинок (пример один в черно-белом выводит, другой сепию накладывает и т.п.)
    Отказоустойчивость достигается тем, что если сдох первый обработчик, например в его треде вылетел эксепшн, который повалил тред (прошу прощения за грубый пример), то действие выполнится резервным обработчиком (мы же их можем навешивать хоть 10, правда?)
    Ответ написан
    3 комментария
  • Vue-JS: как менять вьюшки в зависимости от типа пользователя?

    @kartio
    <component :is="view"></component>

    соответственно параметр view менять в зависимости от состояния пользователя
    Ответ написан
    3 комментария
  • Спрайт svg - как правильно варить?

    Совсем недавно отвечал на вопросы
    про генерацию нескольких спрайтов: Способы генерации нескольких спрайтов?
    и про подход к хранению графики вообще: Шрифты или картинки для иконок что оптимальнее?

    Послушайте как делают в 2гис: 2014.codefest.ru/lecture/677 (правда сейчас судя по всему от ase64 отказываются)

    По вашим вопросам:

    1. К сожалению, используя спрайт мы жестко привязаны к размерам иконки. Т.е. если у нас одинаковая иконка 16*16 и 32*32 - придется добавить в спрайт обе. Если у нас серая по умолчанию и синяя по ховеру - придется добавить обе.
    Решают эту проблему шрифты (но со своими, на мой взгляд критичными, недостатками) и svg symbols (тоже есть минусы, внедрять планирую начинать в следующем году).

    2. Да, https://github.com/jkphl/gulp-svg-sprite - всё положительно, мощная штука. Конечно нужно будет заморочиться со своим шаблоном файла стилей, чтобы всё по красоте.

    Подводный камень есть со спрайтами вообще. Когда сделаете - попробуйте подвигать масштаб страницы. Иконки на некоторых уровнях"подрежутся". Погуглите про эту проблему.

    3. Ответ в первом абзаце

    4. Использую https://www.npmjs.com/package/gulp-imagemin для пожатия всей графики, включая svg
    Ответ написан
    Комментировать
  • Как сделать так, чтобы функция выполнялась только после того, как другая завершится?

    alexey-m-ukolov
    @alexey-m-ukolov Куратор тега JavaScript
    Дисклеймер
    Кому не нравится название "обещания", мысленно заменяйте его на то, которое считаете подходящим. Я выбрал именно его, чтобы концепция, лежащая в их основе, была интуитивно понятна.

    Если функция асинхронная, то лучше всего использовать обещания, что вы и попытались сделать (интерактивный пример).
    one().done(two);
    
    function one() {
        var dfd = new $.Deferred();
    
        // Запускаем асинхронную задачу. Например, ajax-запрос.
        setTimeout(function () {
            var foo = 'bar';
    
            // "Выполняем обещание", передавая в него какую-то информацию.
            // Передавать аргументы, разумеется, не обязательно.
            dfd.resolve(foo);
        }, 2000);
    
        // Возвращаем из функции обещание, на которое могут подписаться другие функции.
        // Обратите внимание, этот код выполнится до того, как завершится асинхронная задача.
        return dfd.promise();
    }
    
    function two(foo) {
        // Обрабатываем данные, полученные внутри асинхронной функции one.
        console.log('two', foo);
    }

    Для трех функций расклад немного сложнее, но принцип такой же.
    Есть и более элегантный способ запуска цепочки из трех функций:
    код
    one().then(two, onOneError).then(three, onTwoError);
    
    function one() {
        var dfd = new $.Deferred();
    
        setTimeout(function () {
            console.log('one');
            
            if (Math.round(Math.random() * 10) >= 5)
            {
                dfd.resolve();
            }
            else
            {
                dfd.reject();
            }
        }, 1000);
    
        return dfd.promise();
    }
    
    function two() {
        var dfd = new $.Deferred();
    
        setTimeout(function () {
            console.log('two');
            
            if (Math.round(Math.random() * 10) >= 5)
            {
                dfd.resolve();
            }
            else
            {
                dfd.reject();
            }
        }, 1000);
    
        return dfd.promise();
    }
    
    function three() {
        setTimeout(function () {
            console.log('three');
        }, 1000);
    }
    
    function onTwoError() {
        console.log('twoError', arguments);
    }
    
    function onOneError() {
        console.log('oneError', arguments);
    }

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


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

    Другой вариант - передавать callback, но это прямой путь в callback hell. Для запуска трех и более функций подряд я его не рекомендую - смотрите сами, на что становится похож код:
    one(function () {
        two(three)
    });
    
    function one(callback) {
        console.log('one');
        setTimeout(callback, 1000);
    }
    
    function two(callback) {
        console.log('two');
        setTimeout(callback, 1000);
    }
    
    function three() {
        console.log('three');
    }


    Есть еще один (очень, очень, очень плохой) вариант, основанный на таймерах и внешних флагах. Никогда так не делайте (код для системы из трех функций еще хуже).

    Если внутри функций ничего асинхронного нет, то можно просто вызвать их друг за другом - следующая и так запустится после предыдущей (пример).
    Ответ написан
    5 комментариев
  • Git: объясните «на пальцах» разницу между rebase и cherry-pick?

    @Nkly777
    git chery-pick - ты забираешь комиты из одной ветки в другую, это бывает полезно когда изменения сделаные другим разработчиком в его ветке, прямо сейчас нужны тебе в твоей ветке, и что бы не писать этот код заново, ты забираешь его комит себе в ветку

    git rebase master - ты синхронизируешься с главной веткой в которую коммитят все разработчики проекта, это полезно когда кто-то изменил участок кода с которым ты сейчас работаешь в своей ветке, дабы через неделю ты смог без проблем смержиться с master веткой. Обычно делается каждое утро перед началом рабочего дня и в конце когда фича готова.

    git merge - обычно используется когда у вас 2 и более master ветки (к примеру master и prototype) в этих ветках очень много комитов (и rebase здесь не подходит) и обчно через пару недель, maintainer репозитория наработки из prototype ветки "сливает" в master ветку по средствам этого самого git merge

    P.S. Что бы легче предствить разницу между git merge и git rebase. Представь что merge как собачка на молнии у одежды - "сшивает" комиты по дате их создания.
    В то время как git rebase как пожарная лестница - при применении твои коммиты крепится на конец родительской ветки

    git merge используйте для мержа фич и фиксов в master ветку (как и делает это Github)
    а git rebase используется для своей ветку в которой вы работаете над фичей что бы забрать последние изменения с master ветку (для этого есть очень удобная команда `git pull --rebase origin master`, аналог 3х команд (`git checkout master; git pull origin master; git checkout mybrach; git rebase master`)
    Ответ написан
    2 комментария
  • Что я неверно понимаю в команде git log -p --grep ?

    @mshakurov Автор вопроса
    git log -G отлично справляется с задачей
    Спасибо Scorpi за наводящую подсказку!
    Ответ написан
    Комментировать
  • Что я неверно понимаю в команде git log -p --grep ?

    Scorpi
    @Scorpi
    Вам нужно искать по названию и описанию коммита или по содержанию?
    Если по содержанию то
    git log -SprAfterEdit
    Ответ написан
    4 комментария
  • Как отправить сообщение к конкретным пользователям?

    Aliansys
    @Aliansys
    Из документации socket.io (отправка сообщений)
    // отправить текущему сокету сформировавшему запрос (туда откуда пришла)
    socket.emit('message', "this is a test");
    
    // отправить всем пользователям, включая отправителя
    io.sockets.emit('message', "this is a test");
    
    // отправить всем, кроме отправителя
    socket.broadcast.emit('message', "this is a test");
    
    // отправить всем клиентам в комнате (канале) 'game', кроме отправителя
    socket.broadcast.to('game').emit('message', 'nice game');
    
    // отправить всем клиентам в комнате (канале) 'game', включая отправителя
    io.sockets.in('game').emit('message', 'cool game');
    
    // отправить конкретному сокету, по socketid
    io.sockets.socket(socketid).emit('message', 'for your eyes only');
    Ответ написан
    19 комментариев
  • Как отправить сообщение к конкретным пользователям?

    @Burgul
    Чтобы отправить конкретному клиенту используй:
    io.sockets.sockets[id].emit('message', 'Hello!');
    Где id - sid клиента socket.io.
    Чтобы оправить данные с сервера отправителю используй аргумент функции callback:
    Сервер:
    socket.on('message', function (data,callback) {
            socket.broadcast.emit('message', data);
            callback("Send");
        });

    Клиент:
    socket.emit('message',msg,function(data) {
            console.log(data);
    });
    Ответ написан
    2 комментария
  • PHP Simple HTML DOM Parser. Почему не могу получить элемент?

    alekciy
    @alekciy
    Вёбных дел мастер
    Use XPath, Luke.
    <?php
    
    // [1- Скачиваем файл
    // Создаем поток
    $opts = array(
    	'http' => array(
    		'method'  => 'GET',
    		'timeout' => 10,
    	),
    );
    
    $context = stream_context_create($opts);
    
    // Открываем файл с помощью установленных выше HTTP-заголовков
    $page_content = file_get_contents('http://lubematch.shell.com/ru/ru/equipment/100_2_8i_avant_001755', false, $context);
    // -1]
    
    // [2- Парсим данные
    // [3- Строим DOM
    // по сути - отключаем вывод ошибок валидации
    libxml_use_internal_errors(true);
    $page_dom = new \DOMDocument();
    
    $page_dom->strictErrorChecking = false;
    $page_dom->preserveWhiteSpace  = false;
    $page_dom->validateOnParse     = true;
    
    $page_dom = new \DOMDocument();
    
    // [4- loadHTML не дает использовать utf-8, делаем хаком http://php.net/manual/en/domdocument.loadhtml.php#95251
    $page_dom->loadHTML('<?xml encoding="UTF-8">' . $page_content);
    
    foreach ($page_dom->childNodes as $node) {
    	if ($node->nodeType == XML_PI_NODE) {
    		$page_dom->removeChild($node);
    	}
    }
    $page_dom->encoding = 'UTF-8';
    // -4]
    
    $page_xpath = new \DOMXPath($page_dom);
    // -3]
    
    // Вытаскиваем Standard
    $param_1 = $page_xpath->query('//table[@id="recommendation"]//tr[2]/th')->item(0)->nodeValue;
    // Вытаскиваем Spirax S4 ATF HDX
    $param_2 = $page_xpath->query('//table[@id="recommendation"]//tr[5]/td[1]')->item(0)->nodeValue;
    // -2]
    
    var_dump($param_1, $param_2);
    Ответ написан
  • Как лечить ошибку "mkdir: cannot create directory `/home/domen.ru/log': File exists"?

    rednager
    @rednager Автор вопроса
    Да, извините меня, была ошибка в написании и понимании, вообщем, рабочим для моего VPS стал скрипт:

    cd /home
    for dir in `ls -1 `; do
    mkdir -p /home/$dir/log
    mkdir -p /home/$dir/html
    chown -R $dir:apache $dir
    chmod ug+rX $dir
    done;


    или можно его так переделать, спасибо avalak:

    cd /home
    for dir in `ls -1 `; do
    mkdir -p /home/$dir/{html,log}
    chown -R $dir:apache $dir
    chmod ug+rX $dir
    done;


    Всем спасибо, разобрался!
    Ответ написан
    Комментировать
  • Что плохого в вёрстке таблицами?

    @egorinsk
    Начнем с того, что все, что делается таблицами, делается и CSS (просто надо не лениться и прочитать соответствующие руководства). У таблиц есть недостатки:

    — нельзя перегруппировать блоки для узких страниц или в версии для печати только с помощью CSS
    — если мы выводим список картинок таблицей, каждая картинка в ячейке, то при добавлении или удалении картинки оставшиеся не сдвигаются, а остается пустое место
    — у ячеек width работает как min-width, при этом алгоритмы ратяжения ячеек не документированы и ведут себя непредсказуемо, из-за этого они могут непредсказуемо растягиваться, и хуже того, при динамической замене контента они не всегда сжимаются обратно и остаются дыры. Одно длинное слово или картинка может растянуть всю страницу.
    — фиксированное, абсолютное и относительное позиционирование неюзабельно в таблицах
    — ячейки не получится перетаскивать drag-n-drop
    — трудно манипулировать DOM (надо хитро вставлять и убирать дополнительные элменеты)
    — верстка получается замусоренная кучей лишних тегов, которые тяжело читать и в которых тяжело разобраться. Это не HTML, а лапша. Особенно тяжело, когда таблицы вложены друг в друга и раскиданы по куче шаблонов.
    — нельзя поместить контент в коде первым, а меню в шапке — вторым (некоторые сеошники считают, что это улучшает индексацию)
    — верстка таблицами всегда была костылем (и это несемантично), с поддержкой CSS2 (появилась более 10 лет назад) таблицы стали не нужны. 10 лет назад они уже стали ненужными.

    Давайте, расскажите хоть одну причину использовать устаревшую много лет назад технологию. Поддержка IE4? Верстальщик-пенсионер?
    Ответ написан
    4 комментария
  • Что плохого в вёрстке таблицами?

    @Otkrick
    Насколько я помню, ее ругали только из-за того, что для рендеринга браузер ждет закрывающего тэга. То есть таблица будет отображаться только когда полностью загрузится. Блоки отображаются по мере загрузки.
    Ответ написан
    1 комментарий
  • Что плохого в вёрстке таблицами?

    EugeneOZ
    @EugeneOZ
    stackoverflow.com/questions/83073/why-not-use-tables-for-layout-in-html
    думаю, не стоит копипастить сюда ответ, так что просто ссылка :)
    Ответ написан
    Комментировать
  • Что плохого в вёрстке таблицами?

    tmikwid
    @tmikwid
    Вопрос в семантичности разметки
    Ответ написан
    3 комментария
  • RDP-клиент под linux с возможностью работы через rdp-шлюз

    DmZ
    @DmZ
    Для Linux стандартными клиентами являются rdesktop и его форк freerdp. Последний обещает поддержку TS Gateway заимплементить с версии 1.1

    PS.
    — Из костылей можно попробовать запустить родной виндовый клиент под wine. В базе wine вроде как 7й запустили, но нужно пробовать, законнектится ли к win2k8 TS Gateway.
    — Также wine-костылем можно попробовать запустить RD Tabs у него обещается полная поддержка win2k8 r2 фич. (Но он завязан на .NET 2.0, который тоже нужно ставить с бубном)
    — Ну и совсем странный костыль — поставить ReactOS в виртуалку и попробовать с родным клиентом и RD Tabs…
    Ответ написан
    2 комментария
  • Удаленное управление android-устройством с компьютера?

    4NATIC
    @4NATIC
    Не пробовали Remote Web Desktop?
    Там есть режим удаленного рабочего стола, режим веб-камеры, клавиатуры, терминала и многое другое.
    И все это просто через браузер.
    Ответ написан
    1 комментарий
  • Как в GIT получить коммулятивный патч

    Xakki
    @Xakki Автор вопроса
    PHP-backendчик
    Решение —
    git diff --name-status commit1 commit2 | awk '{ if ($1 != «D») print $2 }' | xargs git archive -o output.zip HEAD

    где commit1 commit2, указывается между какими комитами нужны изменения, либо указать хешкод одного комита начиная с которого и до HEAD будут в архиве измененные фаилы.
    git diff --name-status — выдает список фаилов которые были изменнены, а git archive — загоняет это дело в архив. Что делает awk '{ if ($1 != «D») print $2 }' — я так и не понял.

    Спасибо Chaitanya Gupta из stackoverflow.com, за практический мгновенный ответ.
    Ответ написан
    2 комментария