Задать вопрос
  • Как получить ключи объекта вместе с типами их значений?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const result = [];
    
    for (const k in obj) {
      if (obj.hasOwnProperty(k)) {
        result.push([ k, typeof obj[k] ]);
      }
    }

    или (памятуя о некоторой ограниченности оператора typeof):

    const result = Object
      .entries(obj)
      .map(function(n) {
        return [ n[0], this(n[1]) ];
      }, x => x?.constructor.name ?? `${x}`);
    Ответ написан
    1 комментарий
  • Как вложенные массивы объединить в один при совпадении id в родительских объектах?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const groupSubarrays = (arr, idKey, subarrKey) =>
      Object.values(arr.reduce((acc, n) => (
        (acc[n[idKey]] ??= { ...n, [subarrKey]: [] })[subarrKey].push(...n[subarrKey]),
        acc
      ), {}));

    const result = groupSubarrays(arr, 'id', 'array1');
    Ответ написан
    Комментировать
  • Как разбить на адекватные vue компоненты?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Сделать общий компонент с параметром, который будет определять количество значений, доступных для выбора:

    props: {
      multiple: Boolean,
      ...
    },
    computed: {
      placeholder() {
        return `Выберите ${this.multiple ? 'несколько значений' : 'одно значение'}`;
      },
      innerValue: {
        get() {
          const v = this.value;
          return this.multiple || this.options.includes(v) ? v : '';
        },
        set(val) {
          this.$emit('input', val);
        },
      },
    },

    <select v-model="innerValue" :multiple="multiple">
      <option disabled value="" v-text="placeholder"></option>
      <option v-for="n in options">{{ n }}</option>
    </select>

    https://jsfiddle.net/cgknyLd0/2/
    Ответ написан
    Комментировать
  • Как упростить код с условием?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Прежде чем упрощать, следует исправить - тот код, что есть, выдаёт некорректные результаты, если среди элементов массива есть 0 (например, для [ -1, 0, 0.1, 2 ] выдаёт 2 вместо 0.1). В первой части условия следует вместо предыдущего элемента массива смотреть индекс текущего - единственным неподходящим является нулевой.

    Если планируете получать единственное значение, то фильтрация плюс извлечение нулевого элемента результата избыточны - хватит метода find. Для подмены undefined на null вообще не нужно никаких проверок делать - с этим справится nullish coalescing. Так что вот:

    const firstNonConsecutive = arr => arr.find((n, i, a) => i && a[i - 1] !== n - 1) ?? null;
    Ответ написан
    Комментировать
  • Как через каждые N элементов удалить N элементов из списка?

    0xD34F
    @0xD34F
    N = 1000
    M = 300
    NM = N + M
    
    newArr = sum((arr[i * NM:(i + 1) * NM - M] for i in range(ceil(len(arr) / NM))), [])
    Ответ написан
  • Как после добавления объекта в стор избежать ошибки "do not mutate vuex store state outside mutation handlers"?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Error: [vuex] do not mutate vuex store state outside mutation handlers.

    Ну да, как и должно быть. Вы же помещаете в массив, находящийся в хранилище, ссылку на объект, с которым работаете в компоненте с формой.

    Добавляя объект в хранилище, создавайте копию:

    this.$store.commit('vehicles/addVehicle', { ...this.vehicle });
    // или
    addVehicle: (state, payload) => state.vehicles.push({ ...payload }),


    Или заменяйте оригинал. Добавляете в компонент метод, создающий объект с дефолтными значениями свойств:

    methods: {
      createNewVehicle: () => ({
        name: '',
        description: '',
        rent: '',
        type: 'custom',
      }),
      ...

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

    data() {
      return {
        vehicle: this.createNewVehicle(),
      };
    },

    this.$store.commit('vehicles/addVehicle', this.vehicle);
    this.vehicle = this.createNewVehicle();
    Ответ написан
    1 комментарий
  • Как и кому ябедничать на пользователей, нарушающих пункт правил 6.4. (накрутка)?

    0xD34F
    @0xD34F
    Внизу страницы есть ссылка "Обратная связь". По ссылке - форма. В форме - выпадающий список. В выпадающем списке пункт - "Нарушение правил сайта". Вот его и выбираете. Чуть пониже поле - "Текст сообщения". Там излагаете суть вопроса - кто, чего и как. Ещё ниже кнопка - "Отправить сообщение". Жмёте её.
    Ответ написан
    1 комментарий
  • Как сделать переключение слайда по шагу в карусели?

    0xD34F
    @0xD34F Куратор тега React
    nextSlide = ({ target: { dataset: { step } } }) => {
      this.setState(({ images: { length }, currentImageIndex: i }) => ({
        currentImageIndex: Math.max(0, Math.min(length - this.props.slidesToShow, i + +step)),
      }));
    };

    <button onClick={this.nextSlide} data-step="-1">PREV</button>
    <button onClick={this.nextSlide} data-step="+2">NEXT</button>
    Ответ написан
  • Как правильно выводить данные при выборе radio?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Из массива с ценами надо выдернуть элемент, соответствующий выбранному индексу:

    <span>{{ result.prices[result.indexOfSize] }}</span>


    А вообще, что-то не могу никак понять - зачем раскладывать данные, относящиеся к одной сущности, по разным массивам? Я бы сделал массив объектов:

    items: [
      { size: '256GB', price:  '99 999' },
      { size: '512GB', price: '105 999' },
    ],
    index: 0,

    <label v-for="(n, i) in result.items">
      <input type="radio" :value="i" v-model.number="result.index">
      <span>{{ n.size }}</span>
    </label>

    Выбранный элемент которого можно оформить как вычисляемое свойство:

    computed: {
      selectedItem() {
        return this.result.items[this.result.index];
      },
      ...

    Ну и вывод цены станет выглядеть так:

    <span>{{ selectedItem.price }}</span>
    Ответ написан
    Комментировать
  • Почему исчезает плавный скролл, если добавить закрытие меню?

    0xD34F
    @0xD34F Куратор тега Vue.js
    @click="menuShow=!menuShow,goToBlock"

    Добавив переключение menuShow, вы превратили значение v-on из имени метода в inline-выражение. Так что goToBlock теперь не вызывается. Вызовем: @click="menuShow = !menuShow, goToBlock($event)". Ну а лучше бы конечно сделать новый метод (если goToBlock действительно нужен как отдельный метод, в противном случае достаточно унести в него переключение menuShow), как-то так:

    methods: {
      goToBlock(selector) {
        document.querySelector(selector).scrollIntoView({
          behavior: 'smooth',
        });
      },
      onMenuItemClick(e) {
        this.menuShow = false;
        this.goToBlock(e.target.getAttribute('href'));
      },
    },

    @click.prevent="onMenuItemClick"
    Ответ написан
  • Как решить задачку, сохранив предыдущий элемент массива в замыкании?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Не надо никуда ничего сохранять:

    arr.splice(0, arr.length, ...arr.map((n, i, a) => (a[i - 1] ?? 0) + (a[i + 1] ?? 0)));
    Ответ написан
    6 комментариев
  • Как заменить символы посередине строки?

    0xD34F
    @0xD34F Куратор тега Регулярные выражения
    preg_replace('~(?<=.{2}).(?=.*@)~', '*', $str)
    Ответ написан
    3 комментария
  • Как сделать кнопки в галерее рабочими?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const $links = $('.small a');
    let currentIndex = null;
    
    function setActiveImage(index) {
      currentIndex = (index + $links.length) % $links.length;
      $('.big img').attr('src', $links.eq(currentIndex).attr('href'));
      $('.photo').text(`${currentIndex + 1} / ${$links.length}`);
    }
    
    $links.click(e => (e.preventDefault(), setActiveImage($links.index(e.currentTarget))));
    $('#prev').click(() => setActiveImage(currentIndex - 1));
    $('#next').click(() => setActiveImage(currentIndex + 1));
    
    setActiveImage(0);
    Ответ написан
    3 комментария
  • Как отследить изменение во вложенном объекте data в vue2?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Сделать вычисляемое свойство, содержащее в себе все need_watch:

    computed: {
      needWatch() {
        return Object.fromEntries(Object.entries(this.obj_lev_1).map(n => [ n[0], n[1].need_watch ]));
      },
    },

    И следить за ним:

    watch: {
      needWatch(newVal, oldVal) {
        const [ k, v ] = Object.entries(newVal).find(n => n[1] !== oldVal[n[0]]);
        alert(`${k}.need_watch changed from ${oldVal[k]} to ${v}`);
      },
    },

    Или, сделать компонент, который будет получать вложенные объекты или их need_watch в качестве параметра. Создавать новое значение внутри и отправлять его наверх (v-model/sync). Подписаться в родителе на соответствующее событие (вместо использования watch).
    Ответ написан
    Комментировать
  • Как передать значние input и изменить его в модальном окне?

    0xD34F
    @0xD34F Куратор тега Vue.js
    editTask (task, index) {

    v-model="editidTask.title"

    task.title = this.editTask.title

    Вижу, имена свойств/методов подобраны грамотно - перепутать невозможно.

    this.tasks.map((task, index) => {
      if (index === this.editidTask.id) {

    Во-первых - зачем перебирать массив, если вам известен индекс элемента? Кстати, очень умно - хранить индекс в свойстве с именем "id".

    Во-вторых - не боитесь обновить что-то не то? Работаете с массивом tasks, используя индекс, полученный при работе с tasksFiltered.

    UPD. Исправляем:

    При сохранении копируем свойства редактируемого объекта, а не метода, начинающего процесс редактирования (серьёзно, как можно было перепутать?).

    К чёрту индекс, всё равно удалять с его помощью не получится - для этого нужен индекс в исходном массиве, а не отфильтрованном. Ищем нужный элемент непосредственно в момент сохранения.

    Напрямую к заявленной проблеме не относится, но сказать стоит:

    Имеет смысл оформить модальное окно как отдельный компонент - упрощаем компонент с таблицей, получаем возможность переиспользовать окно в других местах. Содержимое (текстовые поля) передаём внутрь через слот.

    <list

    Почему list, если этот компонент работает с одним элементом массива? Не понимаете, в чём разница между "один" и "несколько"?

    :tasks="task"

    Почему tasks, если передаёте один объект? Повторю свой вопрос - не понимаете, в чём разница между "один" и "несколько"?

    :key="task.title"

    Что, одинаковых title'ов быть не может? Может. Пусть здесь вместо вводимого пользователем текста будет автоматически генерируемый id.

    v-show="isModal"

    Отдельное свойство для управления состоянием модального окна не нужно, достаточно редактируемого объекта - окно открывается, если он не null.

    task.date = this.editTask.date
    task.title = this.editTask.title

    Завтра потребуется редактировать третье свойство - будете копипастить? Перечислять вручную ничего не надо, есть же Object.assign.
    Ответ написан
  • Регулярка для проверки select, как правильно?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const select = document.querySelector('select');
    const reg = /^\d\d\. /;

    Как проверить, что option должен быть скрыт:

    const mustBeHidden = el => !reg.test(el.text);
    // или
    const mustBeHidden = el => el.textContent.search(reg) !== 0;
    // или
    const mustBeHidden = el => el.innerText.match(reg) === null;
    // или
    const mustBeHidden = el => !~-el.innerHTML.split(reg).length;

    Как переключать видимость option'а:

    const toggle = el => el.hidden = mustBeHidden(el);
    // или
    const toggle = el => el.style.display = mustBeHidden(el) ? 'none' : '';
    // или
    const toggle = el => el.style.setProperty('display', mustBeHidden(el) ? 'none' : '');
    // или
    const toggle = el => el.style.cssText += `display: ${mustBeHidden(el) ? 'none' : 'block'}`;
    // или
    const toggle = el => el.setAttribute('style', mustBeHidden(el) ? 'display: none' : '');
    // или (надо будет добавить в стили .hidden { display: none; })
    const toggle = el => el.classList.toggle('hidden', mustBeHidden(el));

    Переключаем:

    Array.prototype.forEach.call(select.options, toggle);
    
    // или
    
    for (const n of select.children) {
      toggle(n);
    }
    
    // или
    
    for (let i = 0; i < select.length; i++) {
      toggle(select[i]);
    }
    
    // или
    
    (function next(i, n = select.item(i)) {
      n && (toggle(n), next(-~i));
    })(0);
    
    // или
    
    select.querySelectorAll('option').forEach(toggle);
    Ответ написан
    Комментировать
  • Как правильно преобразовать данные (массивы)?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const newData = data
      .reduce((acc, { type, ...n }) => (
        acc[acc.length - 1]?.[0] !== type && acc.push([ type, [] ]),
        acc[acc.length - 1][1].push(n),
        acc
      ), [])
      .map(([ type, children ]) => children.length - 1
        ? { type: `Section${type}`, children }
        : { type, ...children[0] }
      );
    Ответ написан
    Комментировать
  • Как получить каждый элемент списка в отдельной строке?

    0xD34F
    @0xD34F
    [ [ *n.values() ] for n in list_1 ]
    Ответ написан
    Комментировать