Задать вопрос
  • Как выравнивать несколько элементов в строке, при смене размера экрана?

    alexey-m-ukolov
    @alexey-m-ukolov Куратор тега CSS
    <div class="parent">
        <div class="child"></div>
        <div class="child"></div>
        <div class="child"></div>
        <div class="child"></div>
        <div class="child"></div>
    </div>

    .parent {
        width: 170px;
        text-align: center;    
    }
    .child {
        display: inline-block;
        width: 50px;
        height: 50px;
        background: black;
        border-radius: 50%;
    }
    Посмотреть вживую.

    Ну или стильный, модный, молодежный flexbox:
    .parent {
        width: 170px;
        display: flex;
        justify-content: center;
        flex-wrap: wrap;
    }
    .child {
        width: 50px;
        height: 50px;
        background: black;
        border-radius: 50%;
    }
    Поиграться.
    Ответ написан
    Комментировать
  • Как оптимизировать данный код (открытие/закрытие всплывающих окон)?

    alexey-m-ukolov
    @alexey-m-ukolov Куратор тега JavaScript
    У вас по сути N систем из трех взаимосвязанных элементов.
    Сами системы между собой никак не связаны, а вот элементы внутри системы между собой нужно как-то связать.
    Самый простой вариант - использовать индексы (интерактивный пример):
    var buttons = document.querySelectorAll('.js-btn-item'),
        popups = document.querySelectorAll('.js-products-popup'),
        closers = document.querySelectorAll('.js-btn-close'),
        index, button, popup, closer;
    
    for (index = 0; index < buttons.length; index++) {
        button = buttons[index];
        popup = popups[index];
        closer = closers[index];
    
        button.addEventListener('click', buttonHandler(popup));
        closer.addEventListener('click', closerHandler(popup))
    }
    
    function buttonHandler(popup) {
        return function (event) {
            event.preventDefault();
            popup.classList.add('js-popup-show');
        }
    }
    
    function closerHandler(popup) {
        return function (event) {
            event.preventDefault();
            popup.classList.remove('js-popup-show');
        }
    }

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

    Для того, чтобы этот вариант работал, естественно, элементы каждого типа должны идти в строго одинаковом порядке.
    Чтобы этого избежать, можно использовать родителя-обертку, внутри которого содержатся все 3 элемента системы (пример). Такой подход, помимо всего прочего, за счет делегирования позволяет устанавливать N обработчиков, а не N*2, как в первом случае. Но код обработчика слегка усложняется - добавляется проверка целевого элемента.

    Третий способ показал Алексей Зуев - он более декларативный, как видите, javascript-кода там совсем немного - одна универсальная функция. Но этот вариант требует использования id вместо классов, это не всегда возможно.
    Ответ написан
    Комментировать
  • Как использовать where для коллекции в цикле?

    alexey-m-ukolov
    @alexey-m-ukolov Куратор тега Laravel
    Вы, судя по всему, метод get используете не по назначению.
    Так должно работать:
    $clothes_col->where('category_id', $category)->random()->toArray();


    $category += 0;
    Что за ужас? Вы уж либо типы приводите нормально, либо используйте whereLoose
    Ответ написан
  • Подключение/отключение CSS стилей по кнопке, с прямым изменением в файле css?

    alexey-m-ukolov
    @alexey-m-ukolov Куратор тега PHP
    Как вам уже сказали, это серверная логика, для этого придется написать php-скрипт.
    При нажатии на кнопку отправлять ajax-запрос на этот скрипт (ну или просто переходить на него, а в конце редиректить куда нужно), а в самом скрипте изменять css-файл и перезаписывать его. Проще всего, разумеется, воспользоваться готовыми библиотеками.
    Ответ написан
    1 комментарий
  • Как отменить событие после его выполнения?

    alexey-m-ukolov
    @alexey-m-ukolov Куратор тега JavaScript
    $(e).one('click', function () {
      в следующий раз не вызывать эту функцию при клике на $(e)
    })

    Документация
    Ответ написан
    Комментировать
  • Какой вес сайта считается нормальным?

    alexey-m-ukolov
    @alexey-m-ukolov Куратор тега Веб-разработка
    Норм, конечно, никаких нет, все зависит от аудитории сайта и того, с каких устройств и каналов она этот сайт посещает.
    Если много посетителей с мобильных устройств, страница должна быть как можно меньше и 2Мб - это перебор.
    Если это какое-то корпоративное веб-приложение, которое лежит в локальной сети (да еще и запускается один раз в начале рабочего дня), то экономить трафик смысла нет.
    Например, недавно нам фрилансер-верстальщик сверстал одностраничный лендинг, размером 5 мб с сотней http-запросов и удивлялся, чего мы возмущаемся.
    Ответ написан
    1 комментарий
  • Owlcarousel 1.3. Как получить индекс активного слайда?

    alexey-m-ukolov
    @alexey-m-ukolov Куратор тега JavaScript
    Ведь прямо на той странице написано:
    updateResult(".currentItem", this.owl.currentItem);
    Ответ написан
  • Почему на некоторых фотографиях Google chrome отображает hover с задержкой?

    alexey-m-ukolov
    @alexey-m-ukolov Куратор тега CSS
    Это как-то связано с transition на .caption. При его отключении все работает как нужно. Но вот в чем конкретно причина пока сообразить не могу.
    Ответ написан
  • Сталкивались ли вы с расчетом дедлайна с учетом доработок?

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

    alexey-m-ukolov
    @alexey-m-ukolov Куратор тега CSS
    На ваш вопрос нет правильного ответа.

    Логика определения того, нужно ли выносить общие стили в какой-то общий селектор проста:
    если это действительно общие стили, то есть изменять их в будущем тоже нужно будет для всех селекторов разом, то лучше написать их так, как во втором варианте;
    если это просто совпадение (например, какие-то одинаковые отступы у двух элементов), то лучше правила продублировать.

    Есть и лучший вариант - использовать препроцессор, например, SCSS, тогда можно будет вынести общие правила в миксин или в переменные или просто наследовать селекторы.

    Вот пара примеров соглашений о стиле:
    www.phpied.com/css-coding-conventions
    google-styleguide.googlecode.com/svn/trunk/htmlcss...
    Вообще, по запросу "css styleguide" много всего находится, выбирайте соглашение по вкусу.

    По поводу порядка объявления селекторов, рекомендую почитать ответы к этому вопросу.
    Ответ написан
    Комментировать
  • Почему Angular не работает с циклом?

    Насколько я понял из вашего описания проблемы, дело в document.write - он просто перезаписывает все, что есть на странице (подробнее).
    Вам нужно писать в innerHtml какого-то конкретного элемента - вот так:
    var myNumber = 10;
    
    function newFunc(number) {
        var el = document.getElementById('bar'),
            content = '';
        
        for (var i = 1; i <= number; i++) {
            content += 'Number: ' + i + '<br />';
        }
        
        el.innerHTML = content;
    }
    
    newFunc(myNumber);


    А с массивами лучше работать так (вот почему):
    var myNumber = 10;
    
    function newFunc(number) {
        var newArray = [],
              str;
    
        for (var i = 0; i < number; i++) {
            str = 'Number: ' + (i + 1) + '<br />';
            newArray.push(str);
            console.log(str);
        }
    }
    
    newFunc(myNumber);


    Это при условии, что вам действительно потом нужен этот массив, и вы не используете его как кривую замену обычному оператору for:
    var myNumber = 10;
    
    function newFunc(number) {
        for (var i = 1; i <= number; i++) {
            console.log('Number: ' + i + '<br />');
        }
    }
    
    newFunc(myNumber);
    Ответ написан
    Комментировать
  • Почему многим программистам платят почасово?

    У вас в заголовке вопроса про почасовую оплату, а в тексте - про фиксированное время на выполнение работы. Это совершенно разные вещи.

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

    А мне вот не совсем понятно, что значит "не нужно было БД ставить" - тот же SQLite нужно ставить (хотя он идет сразу во многих операционках), у него хранилище файловое.
    NoSql-аналог SQLite с описанными характеристиками - это, пожалуй, CouchDB.
    Ответ написан
  • Как правильно сделать выборку sql?

    SELECT c.id_category as id, n.name as name, p.name as parent_name
    FROM category as c
    LEFT JOIN cat_info as n USING(id_category)
    LEFT JOIN cat_info as p ON c.id_parent = p.id_category

    Документация.
    Ответ написан
    Комментировать
  • Есть ли аналог phpmyadmin на GO?

    alexey-m-ukolov
    @alexey-m-ukolov Куратор тега MySQL
    Pma не для php, а на php. Никто не мешает его использовать вне зависимости от того, на чем вы пишете.
    Если не хочется разворачивать lamp/wamp для pma, можно использовать самостоятельные приложения - HeidiSQL (легкий инструмент, запускается под Wine) или Mysql Workbench (есть несколько уникальных или редких функций, но часто глючит и имеет ужасно кривой интерфейс).
    Ответ написан
    Комментировать
  • Как навесить обработчик на коллекцию элементов?

    alexey-m-ukolov
    @alexey-m-ukolov Куратор тега JavaScript
    Проблема в том, что вы пытаетесь навесить обработчик на коллекцию элементов, которая возвращается функцией querySelectorAll. Такой возможности нет, нужно обходить эту коллекцию и навешивать обработчик на каждый элемент отдельно:
    var buttonItems = document.querySelectorAll('.button-item'),
        index, button;
    
    for (index = 0; index < buttonItems.length; index++) {
        button = buttonItems[index];
        button.addEventListener('click', function (event) {
            console.log('click');
            event.preventDefault();
        });
    }

    Пример

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

    Лучше делать так:
    var buttons = document.querySelectorAll('.button-item'),
        index, button;
    
    for (index = 0; index < buttons.length; index++) {
        button = buttons[index];
        button.addEventListener('click', clickHandler);
        button.addEventListener('dblclick', doubleClickHandler);
    }
    
    function clickHandler(event) {
        console.log('click', this.innerText);
        event.preventDefault();
    }
    
    function doubleClickHandler(event) {
        console.log('doubleclick', this.innerText);
        this.removeEventListener('click', clickHandler);    
        this.removeEventListener('dblclick', doubleClickHandler);
    }
    Ответ написан
  • Сайт оффлайн, как сделать Laravel 4?

    alexey-m-ukolov
    @alexey-m-ukolov Куратор тега Laravel
    Есть же стандартный механизм.
    Если хотите запускать команду программно а не через терминал, в документации подробно описано как это сделать (документация для 5.1, но работает и в 4-ой версии).
    Ответ написан
    Комментировать
  • Как сделать так, чтобы функция выполнялась только после того, как другая завершится?

    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 комментариев
  • Как конкатенировать все скрипты bower через grunt в нужном порядке?

    grunt-bower-concat прекрасно с этим справляется, документация там достаточно подробная и понятная. Вдобавок, он очень гибко настраивается.
    Вы хотя бы пробовали его запускать? Опишите свои проблемы конкретно.
    Ответ написан
    4 комментария
  • JS API и REST API - это разные понятия?

    alexey-m-ukolov
    @alexey-m-ukolov Куратор тега JavaScript
    Вы путаете теплое с мягким.
    REST - это методология, работа с таким апи может быть реализована на любых технологиях (включая js), реализация на стороне сервера - тоже.
    JS API - это уже конкретная реализация клиентской библиотеки. На сервере, с которым работает эта библиотека, при этом может быть REST апи.
    Ответ написан
    2 комментария