Задать вопрос
  • Как вывести массив объектов в виде таблицы?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const columns = [ '#', ...new Set(persons.flatMap(Object.keys)) ];

    Собираем разметку:

    document.body.insertAdjacentHTML('beforeend', `
      <table>
        <thead>
          <tr>${columns.map(col => `
            <th>${col}</th>`).join('')}
          </tr>
        </thead>
        <tbody>${persons.map((person, i) => `
          <tr>${columns.map((col, j) => `
            <td>${j ? person[col] ?? '-' : i}</td>`).join('')}
          </tr>`).join('')}
        </tbody>
      </table>
    `);

    Или, создаём элементы напрямую:

    const table = document.createElement('table');
    
    table.createTHead().insertRow().append(...columns.reduce((acc, col) => (
      (acc[acc.length] = document.createElement('th')).textContent = col,
      acc
    ), []));
    
    persons.forEach(function(person, i) {
      const tr = this.insertRow();
      columns.forEach((col, j) => tr.insertCell().textContent = j ? person[col] ?? '-' : i);
    }, table.createTBody());
    
    document.body.append(table);
    Ответ написан
    2 комментария
  • Как изменить input value vue.js компонента из другого js?

    0xD34F
    @0xD34F Куратор тега Vue.js
    $addres.val("Мои данные").change();

    Во-первых - события jquery и нативные не являются взаимозаменяемыми. Само собой, про первые Vue не в курсе.

    Во-вторых - по умолчанию Vue слушает событие input (change - это если v-model используется с модификатором lazy).

    Так что попробуйте заменить .change() на [0].dispatchEvent(new Event('input')).
    Ответ написан
    Комментировать
  • Как получить путь к каталогу из пути к файлу?

    0xD34F
    @0xD34F Куратор тега Регулярные выражения
    Получаем .+(?=\/[^\/]+), или удаляем \/[^\/]+$.
    Ответ написан
    Комментировать
  • Как заставить функцию ждать выполнения события click?

    0xD34F
    @0xD34F Куратор тега JavaScript
    async function Func() {
      console.log('START');
    
      await new Promise(r => {
        $('div').one('click', () => (console.log('CLICK'), r()));
      });
    
      console.log('END');
    }
    Ответ написан
    Комментировать
  • Как найти значение по ключу в объекте с неизвестной глубиной вложенности?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Рекурсия есть:

    const find = (data, key) => Object
      .entries(data instanceof Object ? data : {})
      .reduce((found, [ k, v ]) => found ?? (k === key ? v : find(v, key)), null);

    Рекурсии нет:

    function find(data, key) {
      for (const stack = [ data ]; stack.length;) {
        const n = stack.pop();
        if (n?.hasOwnProperty(key)) {
          return n[key];
        }
    
        stack.push(...Object.values(n ?? {}));
      }
    
      return null;
    }
    Ответ написан
    Комментировать
  • Почему не срабатывает функция при нажатии?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Брехня, всё срабатывает.

    Бегом гуглить, что такое всплытие событий.

    Надо его останавливать:

    const $section = $('.section').on('click', () => $section.addClass('opened'));
    $section.find('.close').on('click', e => {
      e.stopPropagation();
      $section.removeClass('opened');
    });
    
    // или
    
    const section = document.querySelector('.section');
    
    section.addEventListener('click', () => section.classList.add('opened'));
    section.querySelector('.close').addEventListener('click', e => (
      e.stopPropagation(),
      section.classList.remove('opened')
    ));

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

    const $section = $('section').click(e => {
      $section.toggleClass('opened', !$(e.target).is('.close'));
    });
    
    // или
    
    document.querySelector('.section').addEventListener('click', e => {
      e.currentTarget.classList.toggle('opened', !e.target.matches('.close'));
    });
    Ответ написан
    1 комментарий
  • Как сгруппировать массив объектов по двум свойствам?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Object.values(orders.reduce((acc, n) => {
      const date = n.date.split(' ')[0];
    
      ((acc[date] ??= {
        date,
        documents: {},
      }).documents[n.docTypesName] ??= {
        date: n.date,
        docId: n.docId,
        docTypesName: n.docTypesName,
        products: [],
      }).products.push({
        name: n.name,
        price: n.price,
        image: n.image,
        qunatity: n.quantity,
      });
    
      return acc;
    }, {})).map(n => (n.documents = Object.values(n.documents), n))
    Ответ написан
  • Как избавиться от утечек памяти при самовызове промисов?

    0xD34F
    @0xD34F Куратор тега JavaScript
    С каждым "неудачным" вызовом функции camel у вас добавляется ещё один промис, ждущий разрешения. 10 "неудачных" вызовов - 10 промисов в режиме ожидания. 1000 попыток - 1000 промисов. И т.д. Каждый съедает немного памяти.

    Не нужно вам тут никакого "самовызова". Вместо рекурсии сделайте цикл:

    async function test() {
      let result = null;
    
      do {
        result = await camel() || await new Promise(r => setTimeout(r, 1000));
      } while (!result);
    
      return result;
    }
    Ответ написан
    3 комментария
  • Как в Swiper Slider реализовать Lazy Load на React?

    0xD34F
    @0xD34F Куратор тега React
    Надо импортировать модуль Lazy: import { Lazy } from 'swiper';. Этого вы не сделали.

    Подключить его: SwiperCore.use([ Lazy ]);. Этого вы не сделали.

    Экземпляру слайдера указать, что необходима ленивая загрузка: <Swiper lazy={true}>. Этого вы не сделали.

    Изображениям добавить класс swiper-lazy, атрибут src заменить на data-src. Ну, хоть это у вас есть.
    Ответ написан
    1 комментарий
  • Как определить дату, отстоящую от другой даты на определённое количество дней?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const days = 46330;
    const date = new Date();
    date.setDate(date.getDate() + days);
    const dateStr = date.toLocaleDateString('ru-RU', {
      day: 'numeric',
      month: 'short',
      year: 'numeric',
    });
    
    console.log(dateStr);
    Ответ написан
    Комментировать
  • Почему мои вопросы блокируют?

    0xD34F
    @0xD34F
    Очевидно же - они правила нарушают. Будете продолжать в том же духе - заблокируют не только вопросы, но и вас самого. Так что на вашем месте, я бы сейчас перешел по ссылке и ознакомился с тем, как тут принято себя вести.

    И, кстати, здесь не форум.
    Ответ написан
    Комментировать
  • Как заставить работать пагинацию?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Пусть в сторе кроме собственно массива данных также хранятся текущая страница и общее количество страниц; действие fetchCharacters - пусть загружает не дефолтную первую страницу, а какую будет указано:

    state: {
      characters: [],
      page: 0,
      pages: 0,
    },
    mutations: {
      setCharacters: (state, { characters, pages, page }) =>
        Object.assign(state, { characters, pages, page }),
    },
    actions: {
      async fetchCharacters({ commit }, page = 1) {
        try {
          const { data: { info, results } } = await axios.get(`${BASE_URL}?page=${page}`);
          commit('setCharacters', {
            page,
            pages: info.pages,
            characters: results,
          });
        } catch (e) {
          console.error(e);
        }
      },
    },

    В компоненте, где используется пагинация, делаем вычисляемое свойство, которое будет отвечать за текущую страницу - геттер достаёт значение из стора, сеттер вызывает действие fetchCharacters:

    computed: {
      currentPage: {
        get() {
          return this.$store.state.page;
        },
        set(page) {
          this.$store.dispatch('fetchCharacters', page);
        },
      },
    },

    Привязываем это вычисляемое свойство к экземпляру компонента пагинации:

    <el-pagination
      v-model:current-page="currentPage"
      :page-count="$store.state.pages"
      layout="prev, pager, next"
      background
    />

    https://jsfiddle.net/qbjc9onm/
    Ответ написан
    Комментировать
  • Как превратить вложенный массив в плоский?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Рекурсия есть:

    const flatten = arr => [].concat(...arr.map(n => Array.isArray(n) ? flatten(n) : n));
    
    // или
    
    function flatten(arr) {
      const result = [];
    
      for (const n of arr) {
        if (n?.constructor === Array) {
          [].push.apply(result, flatten(n));
        } else {
          result.push(n);
        }
      }
    
      return result;
    }

    Рекурсии нет:

    function flatten(arr) {
      const result = [];
      const stack = [];
    
      for (let i = 0; i < arr.length || stack.length; i++) {
        if (i === arr.length) {
          [ i, arr ] = stack.pop();
        } else if (arr[i] instanceof Array) {
          stack.push([ i, arr ]);
          [ i, arr ] = [ -1, arr[i] ];
        } else {
          result.push(arr[i]);
        }
      }
      
      return result;
    }
    
    // или
    
    function flatten([...arr]) {
      for (let i = 0; i < arr.length; i++) {
        const n = arr[i];
        if (n?.[Symbol.iterator] && typeof n !== 'string') {
          arr.splice(i--, 1, ...n);
        }
      }
    
      return arr;
    }
    Ответ написан
    Комментировать
  • Как при вызове return из функции в функции остановить функцию?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Никак, forEach прервать нельзя. Да и не надо тут никаких forEach'ей, больше подойдёт some. И функция не нужна, код совсем короткий получается:

    words.some(n => str.includes(n))
    Ответ написан
    1 комментарий
  • Как по клику на кнопку окрывать нужный попап ( класс в дата атрибуте)?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const openSelector = '.block__item';
    const closeSelector = '.close';
    const itemSelector = '.popup';
    const activeClass = 'popup--active';
    
    
    // делегирование, общий обработчик клика - для открытия и закрытия сразу,
    // назначается один раз для всех элементов;
    // связь кнопок открытия попапов с попапами через data-атрибут
    document.addEventListener('click', ({ target: t }) => {
      let item = t.closest(closeSelector)?.closest(itemSelector);
      if (!item) {
        const open = t.closest(openSelector);
        if (open) {
          item = document.querySelector(`${itemSelector}.${open.dataset.popup}`);
        }
      }
    
      item?.classList.toggle(activeClass);
    });
    
    // или, отдельные обработчики клика для открытия и закрытия,
    // назначаются каждому элементу индивидуально;
    // связь кнопок открытия попапов с попапами через индексы
    const open = [...document.querySelectorAll(openSelector)];
    const close = document.querySelectorAll(closeSelector);
    const items = document.querySelectorAll(itemSelector);
    
    const onOpenClick = e => items[open.indexOf(e.currentTarget)].classList.add(activeClass);
    open.forEach(n => n.addEventListener('click', onOpenClick));
    
    const onCloseClick = e => e.currentTarget.closest(itemSelector).classList.remove(activeClass);
    close.forEach(n => n.addEventListener('click', onCloseClick));
    Ответ написан
    Комментировать
  • Почему не работает код?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Вопрос бессмысленный - код работает. Между "не работает" и "работает не так, как задумано" есть существенная разница. Попытайтесь её осознать.

    params = format({

    Зачем здесь вызов format? Не нужен.

    params_list = Object.values(params)
    console.log(params_list)
    for (var v in params_list) {s=s+v+'='+params[v]+'&'}

    Вот это конечно дичь дикая. Чтобы такое написать, надо не знать, как работает цикл for-in. Разберитесь. Не нужен тут массив значений, перебирать надо было сразу params.

    А вообще, всё это делается гораздо проще:

    function format(params, method) {
      return `https://api.vk.com/method/${method}?${new URLSearchParams(params)}`;
    }
    
    console.log(format({ access_token, version }, method));
    Ответ написан
    4 комментария
  • Как просуммировать элементы массива, расположенные до нуля?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const sum = arr.reduceRight((acc, n) => n && acc + n, 0);

    или

    let sum = 0;
    for (let i = 0; arr[i]; sum += arr[i++]) ;

    или

    let sum = 0;
    for (const n of arr) {
      if (!n) {
        break;
      }
      sum += n;
    }

    или

    const sum = (function sum(arr, i = 0) {
      return arr[i] ? arr[i] + sum(arr, i + 1) : 0;
    })(arr);
    Ответ написан
    1 комментарий
  • Vue, vuetify, компонент list-item-group: как привязать активный list-item?

    0xD34F
    @0xD34F Куратор тега Vue.js
    При указании to элемент списка начинает работать как ссылка - внутри v-list-item будет создаваться router-link, который в вашем случае создать невозможно, по причине отсутствия роутера. Ну и всё, дальше выяснять, что конкретно и почему не работает - не интересно.

    Определитесь, как вы хотите управлять активностью элементов списка. Если действительно с помощью роутера - ну так добавьте его, определите маршруты, уберите v-model. Если через v-model - не надо пытаться указывать to.
    Ответ написан
    Комментировать
  • Как заменить элемент в кортеже, вложенном в список?

    0xD34F
    @0xD34F
    for i, n in enumerate(result):
      if n[3] == 10640:
        n = list(n)
        n[3] = 'Вход'
        result[i] = tuple(n)

    или

    result = [ (*n[:3], 'Вход') if n[3] == 10640 else n for n in result ]
    Ответ написан
    1 комментарий
  • Как тут происходит сложение a и b?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Это "сложение" (не сложение) работает только для целых чисел >= 0.

    Если передать в Array одно число, будет создан (будет попытка создания - отрицательные и нецелые числа приведут к ошибке) массив указанной длины. Метод push может принимать несколько значений, а возвращает - новую длину массива, после добавления элементов. Т.е., в массив из трёх элементов добавили ещё четыре, и получили длину.
    Ответ написан
    Комментировать