• Как сделать чтоб при клике на кнопку появлялся div,при клике вне его чтоб закрывался?

    nowm
    @nowm
    Обычно, если вы хотите добавить какую-то вещь, вам нужно полностью понимать её логику работы, чтобы это описать в коде. То есть, если вы можете описать весь функционал с помощью алгоритма, есть смысл самостоятельно это писать. В противном случае, лучше воспользоваться готовым решением, вроде Dropdowns или Modals из Bootstrap, потому что это поможет сэкономить время и обеспечит определённую надёжность работы за счёт использования дополнительных ресурсов (нужно подгружать CSS- и JS-файлы бутстрапа).

    Самостоятельное понимание обычно приходит с опытом. То есть, например, если я хочу написать модал, я сначала должен понять, что такое этот мой модал и как он себя должен вести в различных ситуациях. По сути, это какой-то элемент, который выводится на переднем плане и блокирует всё остальное. То есть, мне нужно создать один полноэкранный элемент (1), который будет блокировать всё остальное, а потом поместить в него другой элемент (2), который будет отображать нужный мне контент. При клике по элементу 1 мне нужно скрывать оба элемента, освобождая всё, что находится на заднем плане. При этом, если я кликаю внутри элемента 2, ничего не должно происходить. Дальше, мне нужно показывать элементы 1 и 2 после определённого события, например, если я кликаю по кнопке (3).

    Вот простейший код который работает как АК-47 (так же доступно на JsFiddle для тестирования):

    HTML
    <span id="element-3">Open modal</span>
    <div id="element-1">
      <div id="element-2">
        Modal content
      </div>
    </div>


    CSS:
    body {  
      width: 100vw;
      height: 100vh;
      background-color: green;
      margin: 0;
      padding: 0;
    }
    
    #element-3 {
      border: 1px solid black;
      background-color: white;
    }
    
    #element-1 {
      display: none;
      position: fixed;
      background-color: blue;
      width: 100vw;
      height: 100vh;
      top: 0;
      left: 0;
    }
    
    #element-1.show {
      display: block;
    }
    
    #element-2 {
      background-color: red;
      width: 50vw;
      height: 50vh;
      margin: 0 auto;
    }


    JS
    var element1 = document.getElementById('element-1');
    var element2 = document.getElementById('element-2');
    var element3 = document.getElementById('element-3');
    
    element3.onclick = function() {
    	element1.classList.add('show');
    };
    
    element1.onclick = function(event) {
    	if (event.target !== event.currentTarget) {
      	return;
      }
    	element1.classList.remove('show');
    };


    После того, как вы сделали стабильно работающий функционал, можно начать его развивать. Например, нужно сделать, чтобы элемент 1 был прозрачным. Или нужно сделать, чтобы он и элемент2 появлялись/исчезали, используя анимацию, а не мгновенно. Или нужно избавиться от этих красно-сине-зелёных цветов и отображать у элемента 2 закруглённые уголки и центрировать его по вертикали. Это уже задачи другого уровня, которые решаются другими методами, которые тоже можно разбить на подзадачи и решать их так, чтобы они не ломали задачи более высокого уровня. В таком случае у вас всегда всё будет работать надёжно и предсказуемо.

    А ваш код я не видел, так что помочь ничем не могу. Причин, по которым происходят глюки, может быть много, и нужно быть телепатом, чтобы угадать, что именно происходит в вашей реализации кода. Но я видел много примеров, когда люди что-то делали, не понимая полностью логики явления, которое они разрабатывают. (Например, модальный диалог, или галлерею, или кнопку. Или космический корабль.) Из-за этого их код превращается в запутанный клубок, который глючит в самые неожиданные моменты.
    Ответ написан
    Комментировать
  • Как вывести текст из одной строки в формате "артист - песня" с помощью JS без багов?

    nowm
    @nowm
    Можно вместо split("-") сделать split(" - "), но, вообще, лучше использовать JSON, чтобы название трека и артист были в отдельных полях. Это будет надёжнее работать, потому что входные данные могут быть непредсказуемыми. Например, название артиста будет содержать «–» с пробелами, и всё опять сломается.
    Ответ написан
  • Как изменить место placeholder?

    nowm
    @nowm
    У input-элементов есть CSS-свойство ::placeholder. Можно сделать так:

    #my-phone-input::placeholder {
        padding-left: 2em;
    }


    Просто замените #my-phone-input на корректный селектор для инпута, который у вас на скриншоте. Но, вообще, обычно у плейсхолдера такой же отступ, как и у текста в поле ввода, так что если вы для самого input зададите отступы с помощью padding, плейсхолдер это унаследует.
    Ответ написан
  • Как назначить метод обработки на input в Sweetalert2?

    nowm
    @nowm
    Можно прослушивать события на уровне документа:

    const myMethod = event => {
        if (event.target && event.target.id === 'swal-input1') {
            // Поймали событие "input" для элемента #swal-input1
        }
    };
    
    document.addEventListener('input', myMethod);
    
    const { value: formValues } = await Swal.fire({/* . . . */});
    
    document.removeEventListener('input', myMethod);


    Кстати, если вы используете ReactJS, то можно использовать sweetalert2-react-content. С ним у вас будет возможность в качестве HTML использовать компоненты ReactJS, в которых можно делать всё, что угодно, включая кастомные обработчики событий, привязанные к конкретным элементам. Можно делать примерно такую вещь:

    import SwalRaw from "sweetalert2";
    import withReactContent from 'sweetalert2-react-content';
    
    const Swal = withReactContent(SwalRaw);
    
    Swal.fire({
        html: (
            <div>
                <input onInput={console.log} id="swal-input1" className="swal2-input">
                <input id="swal-input2" className="swal2-input">
            </div>
        ),
    });


    Swal вызывается как обычно, но можно дополнительно использовать компоненты ReactJS для таких options как: title, html, confirmButtonText, denyButtonText, cancelButtonText, footer и closeButtonHtml.
    Ответ написан
  • Как остановить ratchet из php?

    nowm
    @nowm
    Можно это сделать двумя способами:

    1. Доработать PHP-код, чтобы он реагировал на сигналы, переданные через вебсокет. Например, если ему послать команду «stop», то он должен останавливаться и, соответственно, процесс завершается, освобождая TTY или тот скрипт, который запускал этот вебсокет.
    2. Скрипт с вебсокетом можно запускать в фоновом режиме, а потом, если нужно его завершить, просто убивать процесс по его PID. Чтобы запустить скрипт в фоновом режиме, нужно добавить & в конце команды. Для примера: php bin/chat-server.php &


    Судя по вашей терминологии («перезагрузка php») вы из скрипта PHP вызываете команду php bin/chat-server.php, а сам этот скрипт вызывается с помощью HTTP-запроса из браузера. В этом случае имеется ввиду перезагрузка PHP-FPM, так? Если так, то самое простое решение проблемы с подвисанием скрипта — это способ 2.
    Ответ написан
    6 комментариев
  • Почему gulp uglify выдаёт ошибку?

    nowm
    @nowm
    Uglify не поддерживает ES6 и следующие версии JavaScript. Это значит, что он будет падать с ошибкой, если в коде используются такие вещи:

    const alertLangs = langs => alert(langs);
    
    localStorage.getItem(key: "langs");


    Чтобы Uglify не ругался, нужно либо писать код, который соответствует стандарту «ECMAScript 5», либо использовать препроцессоры, вроде gulp-babel до вызова .pipe(uglify()).

    const babel = require('gulp-babel');
    
    ...
    return src(path.src.js, {base: './src/assets/js/'})
        .pipe(...)
        .pipe(...)
        .pipe(babel({
            presets: ['@babel/preset-env']
        }))
        .pipe(uglify())
        .pipe(...)
        .pipe(...)
    
    ...
    Ответ написан
    Комментировать
  • Как организовать структуру хранения javascrirpt-файлов для многостраничного сайта?

    nowm
    @nowm
    Лично мне понравилось использование webpack. Я прописываю в конфиге все entry-файлы, а webpack потом за меня генерирует итоговый JS-файл. При этом, webpack во время генерации выдёргивает только тот код, который реально используется. Например, у меня есть файл functions.js:

    export function function1() {
        alert('function 1');
    }
    
    export function function2 () {
        alert('function 2);
    }


    Далее, я создаю файл landing.js:

    import {function1} from './functions';
    
    function1();


    После работы webpack будет создан файл, который содержит код из landing.js и functions.js, при этом function2 там не будет, потому что этот код не использовался.

    Посоветовать хорошее руководство по конфигурации webpack не могу, потому что я разбирался с ним сам — по документации. Сразу предупреждаю, что это не самая простая технология для освоения, и у вас может уйти несколько часов на одно только написание конфига. Но его плюсы перевешивают минусы, так что советую попробовать.

    P.S. На хабре есть много статей про webpack. Есть смысл начать поиски там. Я уверен, что среди over 900 статей там есть что-нибудь для новичков. Ну, или, гугл в помощь.
    Ответ написан
    Комментировать
  • Возможно ли с помощью Node.js/php получить скрытый контент определенной странице определенного сайта?

    nowm
    @nowm
    Я обычно пользуюсь DOM в PHP. Конечно, можно отдельные поля регулярными выражениями отловить, если знаешь их название, но есть большая вероятность, что у одного инпута сначала будет идти `type`, потом `name`, а у другого наоборт, и придётся для каждого инпута писать отдельный код, который будет из него вытаскивать значение. Проще воспринимать их как сущности с одинаковыми признаками и переложить парсинг на специализированные билиотеки.

    Насколько я понял, судя по особенностям наименования инпутов, это был форум на базе hoop.la (не путать с hoopla). Я бы примерно так организовал парсинг:

    $dom = new \DOMDocument();
    
    libxml_use_internal_errors(true);
    if (!@$dom->loadHTML('содержимое страницы в виде HTML')) {
        /** @var \LibXMLError $error */
        $error = libxml_get_last_error();
        if ($error->level > LIBXML_ERR_ERROR) {
            throw new \Exception($error->message);
        }
    }
    
    $xpath = new \DOMXPath($dom);
    
    /** @var \DOMNodeList $form */
    $form = $xpath->query('//form[@name="mainLoginForm"]');
    if (!$form->length) {
        throw new \Exception('Форма не найдена');
    }
    
    $post_data = [];
    
    /** @var \DOMElement $input */
    foreach ($xpath->query('.//input', $form->item(0)) as $input) {
        $post_data[$input->getAttribute('name')] = $input->getAttribute('value');
    }
    
    $post_data['email'] = 'логин';
    $post_data['password'] = 'пароль';
    
    // В $post_data находятся все данные которые нужно отправлять


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

    В каких-то других ситуациях, кроме инпутов нужно будет искать ещё и селекты, или предусматривать ситуации, когда нужно делать выбор из нескольких radio-элементов, либо предусматривать ещё более комплексные ситуации, но конкретно в случае с hoopla этого не потребуется — там одни инпуты, и они динамически с помощью JS вроде бы не модифицируются (сильно не тестировал).

    Код может быть нерабочим. Я его наполовину копипастил из собственных разработок, наполовину писал прямо на Тостере. Главное, из него понятен смысл.
    Ответ написан
    5 комментариев
  • Насколько сильно облегчились условия работы для разработчиков/тестеров и т.п. по сравнению с 1960-1970 годами?

    nowm
    @nowm
    Условия облегчились в 42 раза по сравнению с 60-70-ми годами. Если не верите и хотите пересчитать самостоятельно, советую почитать книгу Гленфорда Майерса — «Надёжность программного обеспечения» — Издательство «Мир». Москва, 1980. Почти треть книги посвящена тестированию. Там (что мне нравится в старых книгах) очень много ссылок и на другие книги, если вдруг заинтересует эта тема. В университетской библиотеке можно найти. Я свой экземпляр именно так и «нашёл» сколько-то лет назад.

    Вкратце, в те года к тестированию был более научный подход, были всякие методологии, было намного больше видов тестирования и требовалось больше мыслить. Сейчас для тестирования часто пользуются готовыми библиотеками. Раньше тестирование было процессом, явно нацеленным на поиск ошибок. Сейчас тестирование — это, скорее, создание набора спецификаций для программы, которым она должна соответствовать. Если сделать небольшое допущение, то тесты сегодня — это то же самое, что технические задания вчера. Поэтому естественно, что сейчас условия стали в 42 раза легче.

    Ну, и всякие штуки, вроде удобных кресел, свободного графика, кучи информации в Интернете, которую легко прогуглить и пр. — это тоже облегчает работу.
    Ответ написан
    Комментировать
  • Как правильно сравнить массивы и оценить их схожесть?

    nowm
    @nowm
    Если два массива имеют одинаковую длину, можно просто двигать по кругу первый массив и сравнивать его элементы с элементами второго. Потом можно просто выбрать максимальное совпадение и перегнать в проценты. Примерно так:

    $arr1 = [1,2,3,4,5,7,2,8];
    $arr2 = [2,9,5,5,7,2,8,1];
    
    $len = count($arr1);
    $conformity = [];
    
    for($i = 0; $i < $len; $i++) {
    	/**
    	 * $temp содержит нули в позициях, где числа в двух массивах 
    	 * по одному и тому же индексу не равны. Единицы — там, где равны.
    	 */
    	$temp = array_map(function($x,$y){return intval($x==$y);}, $arr1, $arr2);
    	
    	// Элементы полученного массива суммируются и добавляются в отчётный массив
    	$conformity[] = array_sum($temp);
    	
    	// Массив прокручивается на одну позицию
    	$arr1[] = array_shift($arr1);
    }
    
    //С помощью max($conformity) выбирается максимальное совпадение элементов
    echo sprintf("Max conformity is %s%%\n", number_format(100*(max($conformity)/$len), 2));


    Это конкретно для ситуации, когда длина «колец» одинаковая.

    Update: ещё один вариант:

    $arr1 = [1,2,3,4,5,7,2,8];
    $arr2 = [2,9,5,5,7,2,8,1];
    
    function conformity($arr1, $arr2) {
    	$len = count($arr1);
    	$max = $curr = 0;
    	
    	for($i = 0; $i < $len; $i++) {
    		array_map(function($x,$y)use(&$curr){$curr += intval($x==$y);}, $arr1, $arr2);
    		
    		if($curr == $len) {
    			return 100;
    		}
    
    		$max = $max > $curr ? $max : $curr;
    		$curr = 0;
    		
    		$arr1[] = array_shift($arr1);
    	}
    	
    	return 100*($max/$len);
    };
    
    echo sprintf("Max conformity is %s%%\n", number_format(conformity($arr1, $arr2), 2));
    Ответ написан
    6 комментариев
  • Зачем в PHP ссылки?

    nowm
    @nowm
    Если что, «в методах объекта, $this всегда является ссылкой на вызывающий объект»

    Если вы можете обойтись без использования $this в коде, то, определённо, ссылки вам не принесут пользы. :)

    class MyModel {
        private $db;
    
        public function __construct($db) {
            $this->db = $db;
        }
    }


    В коде выше тоже используется механизм ссылок — $db, которая передаётся в конструктор и свойство «db» класса MyModel указывают на один и тот же экземпляр объекта после того, как отработал конструктор MyModel.

    как это может помочь в работе с БД или на примере контроллера/модели что нибудь повседневное такое для PHP программиста , было бы очень полезно для меня!!

    Я думаю, что механизм ссылок самым непосредственным образом помогает вам работать с БД. Но, так как ядро PHP само занимается оптимизациями, связанными со ссылками, от кодера не очень часто требуется их использовать явно.

    Это тоже самое, что жёсткие ссылки в файловой системе. От них может быть большая польза, но рядовой пользователь не очень часто их использует осознанно.
    Ответ написан
  • Что это за sublime?

    nowm
    @nowm
    Это Seti UI.

    Оригинальная версия, если не ошибаюсь, работает только на версии 2. Есть порт для ST3, который требует ST3 Build 3062 и выше.
    Ответ написан
    5 комментариев
  • Заказчик вместо обещаных 3 часов моего времени делает правки уже 4й день, что делать?

    nowm
    @nowm
    Возвращайте деньги, если он вам что-то платил, закрывайте проект и ставьте заказчику отрицательный отзыв. Это будет проще всего. Перед тем, как закрывать проект, озаботьтесь тем, чтобы из переписки на сайте биржи было понятно, что он требует что-то ещё дополнительное, но не хочет за это дополнительно платить. Если я не ошибаюсь, то закрытый проект, за который не уплачено ни цента, в вашей истории не появится. Во всяком случае, так обстоит дело на oDesk.

    Так же, на oDesk есть правило, по которому заказчик не может быть агентством, если он зарегистрировался как заказчик. Если он «проксирует» работу, то он — агенство, а агенство не может публиковать заказы. Он нарушает правила. Это ещё один момент, который вам может помочь, если вы вступите с клиентом в какой-то диспут. Опять же, важно, чтобы он упоминал в личной переписке на сайте биржи, что он, дескать, посредник, а не заказчик — если он этого не упоминал, то нужно его как-то на это развести.

    В остальном, я в похожих ситуациях обычно упираюсь и говорю, что никак не могу продолжать работу, пока не получу оплату за то, что было оговорено. Приплетаю всякие фантастические истории, что, как будто, меня недавно так кинули и я никому не могу доверять и т.д. и т.п. — тут всё ограничено фантазией. Главное: ни в коем случае не грубите человеку, на три буквы можно и вежливо посылать, закрутив всё ещё таким образом, что заказчик останется в восторге.

    Главное, и не только в подобных ситуациях, не тянуть резину. Чем вы будете мягче и податливее, чем дольше вы будете откладывать «неприятные» для клиента вопросы, тем чаще этим будут пользоваться окружающие, продавливая вас насколько это возможно. Это не значит, что нужно всем направо и налево грубить и посылать, это значит, что нужно сразу же сообщать окружающим, что вас что-то не устраивает — вежливо, но твёрдо.

    Я могу только посочувствовать вашей ситуации, но рано или поздно каждый человек с таким сталкивается. Со временем просто развивается чуйка, которая позволяет сразу видеть что конкретный проект публикует неадекватный клиент. Как говорил alexgilev (полчаса назад :) ), всякие фразы, вроде: «срочно», «мне мой знакомый программист сказал, что тут дел — на пять минут», «час-два для тех, кто в теме», «быстрые деньги» и т.п. — это один из признаков неадекватности.
    Ответ написан
    1 комментарий
  • Где лежит каркас страницы index на движке Opencart?

    nowm
    @nowm
    Я сначала пытался объяснить, как устроен Opencart, чтобы вам было легко потом находить, какие шаблоны используются на конкретной странице, но получается, что это будет слишком объёмно. Поэтому я представлю ситуацию, когда используется стандартная установка Opencart.

    Заголовочная часть HTML-кода, шапка страницы, плюс выпадающее меню категорий, плюс уведомления — <корень сайта>/catalog/view/theme/<название шаблона>/template/common/header.tpl

    Футер — <корень сайта>/catalog/view/theme/<название шаблона>/template/common/footer.tpl

    Контент — зависит от текущего пути. Например, если текущий путь — product/product (страница товара), то шаблон можно найти в <корень сайта>/catalog/view/theme/<название шаблона>/template/product/product.tpl. Если корневая страница сайта (вы её назвали index), то её шаблон лежит в <корень сайта>/catalog/view/theme/<название шаблона>/template/common/home.tpl.

    Левая колонка — <корень сайта>/catalog/view/theme/<название шаблона>/template/common/column_left.tpl

    Правая колонка — <корень сайта>/catalog/view/theme/<название шаблона>/template/common/column_right.tpl

    Служебная часть перед контентом — <корень сайта>/catalog/view/theme/<название шаблона>/template/common/content_top.tpl

    Служебная часть после контента — <корень сайта>/catalog/view/theme/<название шаблона>/template/common/content_bottom.tpl

    <название шаблона> можно узнать на странице настройки магазина в админке: Админка → Меню «Система» → пункт «Настройки» → ссылка «Изменить» напротив текущей конфигурации → вкладка «Магазин» → пункт «Шаблон».

    Всё содержимое обычно компонуется из этих кусков.

    Правая и левая колонки, а так же служебные части перед и после контента обычно заполняются модулями — в зависимости от настроек модулей. Эти четыре шаблона лучше не трогать, если вы не уверены до конца, что делаете.
    Ответ написан
    4 комментария
  • Почему try..catch не отлавливает ошибку?

    nowm
    @nowm
    Проблема в том, что XMLHttpRequest выкидывает только два исключения:

    exception XMLHttpRequestException {
      unsigned short     code;
    };
    const unsigned short NETWORK_ERR = 101;
    const unsigned short ABORT_ERR = 102;


    NETWORK_ERR — ошибка сети.
    ABORT_ERR — пользователь отменил запрос.

    Ещё один немаловажный момент: NETWORK_ERR и ABORT_ERR не выкидываются в асинхронном режиме.

    Всё остальное отлавливаться не будет, и нужно писать свой обработчик, который, например, будет реагировать на код ответа 404 от сервера и т.д.

    function test(data) {
     // taking care of data
    }
    
    function handler() {
     if(this.readyState == 4 && this.status == 200) {
      // so far so good
      if(this.responseXML != null && this.responseXML.getElementById('test').firstChild.data)
         // success!
       test(this.responseXML.getElementById('test').firstChild.data);
      else
       test(null);
     } else if (this.readyState == 4 && this.status != 200) {
      // fetched the wrong page or network error...
      test(null);
     }
    }
    
    var client = new XMLHttpRequest();
    client.onreadystatechange = handler;
    client.open("GET", "test.xml");
    client.send();


    Здесь function handler() — обработчик, а client.onreadystatechange = handler; — привязка этого обработчика к экземпляру XMLHttpRequest.

    Просто ответ от сервера с кодом «404 Страница не найдена» не считается за NETWORK_ERR, потому что сервер ответил на запрос. А то, с каким он кодом ответил — это уже на другом уровне обрабатывается.
    Ответ написан
    6 комментариев
  • Как добавить комплектации товара с разными ценами?

    nowm
    @nowm
    Это организовывается с помощью опций на странице редактирования товара. При добавлении опции можно указать сумму, которая прибавится/вычтется из стоимости при её выборе.

    Инструкция: Опции товара
    Ответ написан
    2 комментария
  • Почему не срабатывает:last-child?

    nowm
    @nowm
    Так происходит потому, что :last-child — это последний элемент родительского контейнера. Совсем последний. После него не должно быть никаких элементов. Не получится использовать и :last-of-type, так как last-of-type подразумевает последний элемент по имени, а не по классу (и если после последнего div.blog-item будет хотя бы один div на этом же уровне иерархии, этот div.blog-item перестанет быть last-of-type).

    Вообще, я разделители меду элементами делал бы так:

    .blog-item + .blog-item {
        /* В ситуации с 5-ю элементами с классом .blog-item, которые строго 
         * следуют друг за другом, этот селектор применится
         * к элементам со второго по пятый. Первый будет проигнорирован.
         */
    }
    Ответ написан
    Комментировать
  • Есть ли API перевода средств с одного электронного кошелька на другой в ЯД, qiwi, WM и PayPal?

    nowm
    @nowm


    Там есть и примеры реализации на различных языках программирования.
    Ответ написан
    Комментировать
  • Принцип работы буфферизированного вывода в php?

    nowm
    @nowm
    Чтобы ничего не выводилось, нужно вызывать функцию ob_end_clean.

    Я обычно с буфером так работаю:

    ob_start();
    
    // Тут какой-нибудь вывод
    
    // В переменную $output заносится весь буфер, и её можно потом где-то использовать
    $output = ob_get_contents();
    
    // Очистка буфера
    ob_end_clean();


    Хотя, можно ещё проще делать: вместо связки ob_get_contents + ob_end_clean можно использовать ob_get_clean, которая очищает буфер и при этом возвращает его содержимое.

    ob_start();
    
    // Тут какой-нибудь вывод
    
    // В переменную $output заносится весь буфер, и её можно потом где-то использовать.
    // При этом происходит очистка буфера.
    $output = ob_get_clean();
    Ответ написан
    Комментировать
  • Какой применить способ вывода символа рубля на сайте?

    nowm
    @nowm
    Самый элегантный способ — подключить и использовать шрифт, в котором есть знак рубля. PT Sans, например. Это шрифт без засечек (sans-serif family) — выглядит вполне нормально для веба (единственное, мне в нём не нравится «Q» (заглавная) — как-то неестественно смотрится). Подключение шрифтов поддерживается в данный момент большинством браузеров. Так что не придётся дополнительно танцевать с разными марками бубнов.
    Ответ написан
    Комментировать