Задать вопрос
  • Identifier has already been declared как исправить?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Точка с запятой должна быть, а у вас только запятая, точку забыли, забыли точку, вот здесь:

    let money,
        price,

    Ну пожалуйста, добавьте точку, не хватает точки, добавьте-добавьте-добавьте, чтобы стало так:

    let money,
        price;
    Ответ написан
    1 комментарий
  • Как применять IonRangeSlider только что генерированным полям?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Есть ли что-то типо delegate() для такого случая?

    Нет.

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

    0xD34F
    @0xD34F
    Почему ключи заменяются? - потому что так работает array_merge:

    В результирующем массиве значения исходного массива с числовыми ключами будут перенумерованы в возрастающем порядке, начиная с нуля.


    Используйте оператор +, чтобы значения ключей остались неизменными:

    $result = $array1 + $array2;
    Ответ написан
    Комментировать
  • Почему drag and drop некорректно работает при быстром перемещении?

    0xD34F
    @0xD34F Куратор тега JavaScript
    У вас обработчик mousemove вешается на перемещаемый элемент - естественно, что при выходе курсора за пределы элемента перемещение прекращается. А во втором примере, где всё окей - там обработчик mousemove вешается на document.
    Ответ написан
    1 комментарий
  • Как написать такой SQL запрос (подробности внутри)?

    0xD34F
    @0xD34F
    рейтинг для каждой книги - COUNT записей

    Не COUNT. Если есть две записи по одной книге, у которых rating равен 1 и -1, то COUNT вернёт 2. А должно быть 0. Количество записей и сумма значений в столбце - не одно и то же.

    SELECT b.*, COALESCE(SUM(br.rating), 0) rating
    FROM books b
    LEFT JOIN books_rating br ON br.book_id = b.id
    GROUP BY b.id
    Ответ написан
    2 комментария
  • Как правильно реализовать админ-панель в SPA?

    0xD34F
    @0xD34F
    можно открыть в конце концов build.js и увидеть там...

    Да плевать. Главное, чтобы ваш бэкенд не позволял делать лишнего пользователям с недостаточными правами.

    Другое дело что загружать код, который заведомо не должен исполняться - излишне, так что имеет смысл разбить ваш build.js на несколько частей.
    Ответ написан
    1 комментарий
  • Почему не происходит вывод данных?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Консоль говорит, что не может найти product, потому что я не правильно использую хуки.

    Нет. Консоль вам говорит что-то другое.

    Вот эта вот строка,

    var prod = product;

    - что вы хотели ею сказать? Что ещё за product? Это который в data лежит? Тогда должно быть this.product. Почему вы пытаетесь определить переменную с таким же именем как и у параметра? А при вызове в хуке mounted - почему ничего не передаёте в метод results, у него же определён параметр?

    Думаю, должно быть так: строку, процитированную выше - просто удаляете, а в mounted при вызове results передавайте ему product - this.results(this.product). Или так: строку удаляете, удаляете параметр prod, в вызове axios.get вместо prod используете this.product.
    Ответ написан
  • Как во vuejs при событии в изолированном компоненте - потушить свойство в братских компонентах на одном уровне?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Пусть за видимость всплывающего сообщения отвечает не свойство, а параметр, значение которого будет назначаться в зависимости от равенства индекса текущего элемента индексу активного. При клике эмитите событие, в родительском компоненте это событие ловите, соответствующим образом изменяете индекс активного элемента. На всё про всё - пара строк. Как-то так.
    Ответ написан
    1 комментарий
  • Javascript как зациклить вывод дней недели?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Собираем массив с днями:

    const days = ['Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота', 'Воскресенье'];
    
    // или
    
    const days = Array.from({ length: 7 }, (_, i) => new Date(1, 0, i)
      .toLocaleString('ru', { weekday: 'long' })
      .replace(/./, m => m.toUpperCase()
    ));

    Зацикливаем вывод:

    for (
      let iDay = 0;
      confirm(`${days[iDay]}. Хотите увидеть следующий день?`);
      iDay = (iDay + 1) % days.length
    ) ;
    Ответ написан
    Комментировать
  • Как найти последний элемент массива с нужный свойством?

    0xD34F
    @0xD34F Куратор тега JavaScript
    сделал это так, но мне кажется, это не совсем производительно и есть решение получше

    "Производительно" далеко не всегда значит "лучше". Бывает так, что производительностью можно пренебречь в пользу краткости и читаемости (шутка, являются ли варианты ниже более читаемыми, вопрос спорный). Код - он не только для компьютеров, но и для людей.

    Вот, смотрите - одна строка вместо шести ваших:

    const lastId = arr.reduce((id, n) => n.glob_id || id, null);
    // или
    const lastId = (arr.filter(n => n.glob_id).pop() || {}).glob_id;
    // или
    const lastId = ([...arr].reverse().find(n => n.glob_id) || {}).glob_id;
    // или
    const lastId = arr.map(n => n.glob_id).filter(Boolean).pop();

    Ну а если говорить более серьёзно, то можно перебирать массив от конца к началу, и прерывать цикл после того, как будет обнаружен первый подходящий элемент:

    let lastId = null;
    for (let i = arr.length; i--;) {
      if (arr[i].glob_id) {
        lastId = arr[i].glob_id;
        break;
      }
    }

    UPD. Наконец-то подъехал метод, позволяющий решить задачу и коротко, и без стояния на голове. И трёх с половиной лет ждать не пришлось:

    const lastId = arr.findLast(n => n.glob_id)?.glob_id;
    Ответ написан
  • Как сделать, чтобы Яндекс.Карты на сайте изначально отображались черно-белыми?

    0xD34F
    @0xD34F Куратор тега CSS
    <div id="map" class="black-and-white"></div>

    .black-and-white {
      filter: grayscale(100%);
    }

    document.querySelector('#map').addEventListener('click', function() {
      this.classList.remove('black-and-white');
    }, { once: true });

    jsfiddle.net/0uays3d7
    Ответ написан
    2 комментария
  • Как узнать какой по счёту элемент в dom дереве имеет определённый класс?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Определимся с элементом, у которого будем узнавать индекс - внутри кого он находится, что это за элемент, какой у него должен быть класс:

    const parentSelector = 'div';
    const childSelector = 'p';
    const className = 'there';
    
    const siblingsSelector = `${parentSelector} > ${childSelector}`;
    const elementSelector = `${siblingsSelector}.${className}`;

    Дальше есть варианты:

    const index = Array.prototype.findIndex.call(
      document.querySelectorAll(siblingsSelector),
      n => n.classList.contains(className)
    );

    или

    let index = -1;
    for (
      let el = document.querySelector(elementSelector);
      el;
      index++, el = el.previousElementSibling
    ) ;

    или

    const el = document.querySelector(elementSelector);
    const index = el ? [...el.parentNode.children].indexOf(el) : -1;

    Если вдруг у элемента могут быть другие соседи, не соответствующие childSelector, и они не должны учитываться, то третий вариант не подходит, а во втором надо заменить index++ на index += el.matches(childSelector).
    Ответ написан
    Комментировать
  • Как сделать так, чтобы при прокрутке колеса мыши инициировалось нажатие какое-нибудь клавиши на клавиатуре?

    0xD34F
    @0xD34F Куратор тега JavaScript
    document.addEventListener('keypress', function(e) {
      if (e.keyCode === 32) {
        console.log('space pressed');
      }
    });
    
    document.addEventListener('wheel', function(e) {
      const event = new Event('keypress');
      event.keyCode = 32;
      document.dispatchEvent(event);
    });
    Ответ написан
    7 комментариев
  • Как корректно динамически обновлять несколько серий графиков?

    0xD34F
    @0xD34F
    Вместо того, чтобы создавать отдельные переменные под каждый набор данных, просто обходите массив series с помощью forEach. Надо ли перерисовывать график сразу, как только в какой-либо из наборов данных добавлена новая точка - не уверен. Лично я бы дожидался получения новых данных по всем наборам и только потом делал перерисовку. Конечно, если хотите, перерисовывать можно и при каждом получении новых данных.

    Также следует обратить внимание на ваш выбор использовать setInterval для организации постоянного обновления - что если один из запросов займёт сильно больше времени, чем вы ожидаете? Не получится ли так, что более новые данные будут добавлены раньше старых? Возможно, стоит делать так: запрос, по получении ответа - setTimeout на следующий запрос.

    Что до

    работает, но не всегда корректно <...> точно есть ошибки

    - это разговор ни о чём. Информации примерно ноль. Вам следовало рассказать, как проявляется эта некорректность.
    Ответ написан
    Комментировать
  • Как написать запрос MySQL или обработать в PHP для получения массива нужного вида?

    0xD34F
    @0xD34F
    Вариантов тут несколько:
    • Так как значения у вас парные - измените структуру БД, пусть оба значения лежат в одной строке
    • Путь дурака: два запроса в PHP и ручное объединение их результатов - цикл по первому массиву, вложенный цикл по второму, как встретился элемент с таким же значением time, его value добавляется в элемент из первого массива
    • Получить данные одним запросом:
      SELECT t1.time, t1.value AS temp_val, t2.value AS hum_val
      FROM topics t1
      JOIN topics t2 ON t2.time = t1.time
      WHERE
        t1.topic = 'tempinroom' AND
        t2.topic = 'huminroom'

    Ответ написан
  • Как сделать множественное поле редактирования на Vue?

    0xD34F
    @0xD34F Куратор тега Vue.js
    при вводе каждого символа с поля слетает фокус

    Потому что при изменении значения поле создаётся заново - ведь вы в качестве key это значение и указали. Что само по себе является дичью несусветной, кроме того, так у вас могут быть поля с одинаковыми key.

    Генерируйте уникальные значения для key в момент добавления нового элемента в массив company_ids. Если удаление элементов из массива не предполагается, это может быть просто количество элементов / индекс элемента в массиве:

    this.form.company_ids.push({
      key: this.form.company_ids.length,
    });

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

    this.form.company_ids.push({
      key: ++this.currKey,
    });

    Или можно брать текущее максимальное значение key + 1:

    this.form.company_ids.push({
      key: Math.max(0, ...this.form.company_ids.map(n => n.key)) + 1,
    });
    Ответ написан
    1 комментарий
  • Как из набора элементов удалить определённое количество из начала и конца?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Где элементы находятся, и сколько с какого конца надо удалить:

    const selector = 'div p';
    const removeFirst = 5;
    const removeLast = 3;

    Удаляем:

    document.querySelectorAll(selector).forEach((n, i, a) => {
      if (i < removeFirst || i > a.length - removeLast - 1) {
        n.remove();
      }
    });

    Или, если родитель действительно общий, то можно и так:

    document.querySelectorAll([
      `${selector}:nth-child(-n+${removeFirst})`,
      `${selector}:nth-last-child(-n+${removeLast})`,
    ]).forEach(n => n.replaceWith());
    Ответ написан
    Комментировать
  • Заменить все совпадения в тексте на ссылку?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Режете текст на куски регуляркой, соответствующей ссылкам (важный момент: надо поместить всё выражение в скобки, это позволит получить в результирующем массиве и сами разделители - будущие ссылки), обходите полученный массив - если элемент соответствует регулярке, делаете ссылку, нет - оставляете как есть. Типа так.
    Ответ написан
    Комментировать
  • Как сделать ограничение на уменьшение числа в input?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Добавить input'у атрибуты min/max; всем трём элементам добавить общую обёртку (уверен, на странице подобных блоков будет больше одного):

    <div class="counter">
      <button class="minus">-</button>
      <input type="number" min="2" max="17" value="5">
      <button class="plus">+</button>
    </div>

    При обновлении input'а ограничивать новое значение значениями атрибутов min/max (если где-то ограничений быть не должно, то вместо отсутствующих значений атрибутов подставлять +/- бесконечность). Кроме того, неплохо бы обрабатывать пользовательский ввод в input - а ну как кто захочет его напрямую отредактировать, мимо кнопок.

    Как это может выглядеть:

    const updateInput = change => e =>
      $('input', e.delegateTarget).val(function(i, v) {
        const min = this.min || -Infinity;
        const max = this.max || Infinity;
        return Math.max(min, Math.min(max, (v | 0) + change));
      });
    
    $('.counter')
      .on('click', '.minus', updateInput(-1))
      .on('click', '.plus', updateInput(1))
      .on('input', updateInput(0));

    Или, к чёрту jquery:

    const updateInput = change => e => {
      const input = e.target.closest('.counter').querySelector('input');
      const min = input.min || -Infinity;
      const max = input.max || Infinity;
      input.value = Math.min(max, Math.max(min, (input.value | 0) + change));
    };
    
    document.querySelectorAll('.counter').forEach(function(n) {
      n.querySelector('.minus').addEventListener('click', this[0]);
      n.querySelector('input').addEventListener('input', this[1]);
      n.querySelector('.plus').addEventListener('click', this[2]);
    }, [ -1, 0, 1 ].map(updateInput));

    Или, не обязательно назначать обработчики событий каждому элементу индивидуально, достаточно по одному делегированному на тип события:

    document.addEventListener('click', ({ target: t }) => {
      const change = -t.matches('.plus') || +t.matches('.minus');
      if (change) {
        const input = t.closest('.counter').querySelector('input');
        input.value -= change;
        input.dispatchEvent(new Event('input', { bubbles: true }));
      }
    });
    
    document.addEventListener('input', ({ target: t }) => {
      if (t.closest('.counter')) {
        t.value = Math.min(t.max || Infinity, Math.max(t.min || -Infinity, t.value | 0));
      }
    });

    А ещё можно добавить кнопкам data-атрибуты, указывающие, на сколько должно быть изменено значение input'а, и тогда проверять у кнопок наличие классов будет не надо:

    <button class="minus" data-change="-1">-</button>
    <button class="plus" data-change="+1">+</button>

    document.addEventListener('input', updateInput);
    document.addEventListener('click', updateInput);
    
    function updateInput({ target: t }) {
      const counter = t.closest('.counter');
      if (counter) {
        const input = counter.querySelector('input');
        const min = input.min || -Infinity;
        const max = input.max || Infinity;
        input.value = Math.min(max, Math.max(min, (input.value | 0) + (t.dataset.change | 0)));
      }
    }
    Ответ написан
    Комментировать