Задать вопрос
  • Как сделать переключение по адресам для яндекс карты?

    0xD34F
    @0xD34F Куратор тега Яндекс.Карты
    document.querySelector('.items').addEventListener('click', function(e) {
      const t = e.target;
      if (t.classList.contains('item')) {
        map.setCenter([ t.dataset.lat, t.dataset.lng ]);
      }
    });
    Ответ написан
  • Как внутри компонента получить параметр из root?

    0xD34F
    @0xD34F Куратор тега Vue.js
    :curPage="defineCurPage"

    Нет, так это работать не будет. В DOM-шаблоне. Из-за нечувствительности к регистру. Замените на :cur-page="defineCurPage".
    Ответ написан
  • Как правильно воспользоваться async await?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const getImg = url => fetch(url)
      .then(r => r.blob())
      .then(blob => new Promise(resolve => {
        const reader = new FileReader();
        reader.addEventListener('loadend', () => resolve({ image: reader.result }));
        reader.readAsDataURL(blob);
      }));
    
    
    document.querySelector('button').addEventListener('click', async () => {
      const arrImg = await Promise.all(arr.map(n => getImg(`./images/${n}`)));
      console.log(arrImg);
    });
    Ответ написан
    Комментировать
  • Как сделать, чтобы добавленные данные не пропадали при обновлении страницы?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Выкидываем jquery / jquery-ui, вместо них используем что-то более уместное - например, Vue.Draggable. Следим за изменениями списков с помощью watch, в обработчике пишем значение в localStorage. При загрузке, соответственно - достаём (если есть). Как-то так:

    data: () => ({
      newTask: '',
      items: {},
    }),
    watch: {
      items: {
        deep: true,
        handler: val => localStorage.setItem('items', JSON.stringify(val)),
      },
    },
    methods: {
      addTask() {
        const title = this.newTask.trim();
        if (title) {
          const id = 1 + Math.max(0, ...Object.values(this.items).flat().map(n => n.id));
          this.items.A.push({ id, title });               
        } else {
          alert('Введите текст задачи');
        }
        this.newTask = '';
      },
    },
    created() {
      let items = null;
      try {
        items = JSON.parse(localStorage.getItem('items'));
      } catch (e) {}
      this.items = items || дефолтное значение;
    },

    <div>
      <input placeholder="текст задачи" v-model="newTask">
      <button @click="addTask">+</button>
    </div>
    <draggable
      v-for="(v, k) in items"
      v-model="items[k]"
      :key="k"
      :options="{ group: 'tasks' }"
      element="ul"
      class="connectedSortable"
    >
      <li v-for="item in v" :key="item.id">{{ item.title }}</li>
    </draggable>
    Ответ написан
    Комментировать
  • Как изменить класс каждого div по очереди с помощью setTimeout?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const $items = $('.card');
    const openedClass = 'card--opened';
    const closedClass = 'card--closed';
    const delay = 500;
    const flip = $item => $item.removeClass(closedClass).addClass(openedClass);

    Вариант раз - назначаем таймауты на переключение классов сразу всем элементам, с временем задержки, зависящим от индекса элемента:

    $items.each((i, n) => setTimeout(flip, (i + 1) * delay, $(n)));

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

    (function next(i) {
      if (i < $items.length) {
        setTimeout(() => {
          flip($items.eq(i));
          next(-~i);
        }, delay);
      }
    })(0);

    Вариант три - вместо таймаутов назначаем интервал:

    let i = -1;
    const intervalID = setInterval(() => {
      if (++i >= $items.length) {
        clearInterval(intervalID);
      } else {
        flip($items.eq(i));
      }
    }, delay);
    Ответ написан
    2 комментария
  • Как внутри объекта размапить неограниченное количество других объектов?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const obj = array.reduce((acc, n, i) => (
      acc[`filter${i + 1}`] = { ...baseFilter, prop: n },
      acc
    ), {});

    или

    const obj = {};
    for (const [ i, n ] of array.entries()) {
      (obj['filter' + (-~i)] = Object.assign({}, baseFilter)).prop = n;
    }

    или

    const obj = {};
    for (let i = 0; i < array.length;) {
      const subobj = { prop: array[i] };
      for (const k in baseFilter) {
        subobj[k] = baseFilter[k];
      }
      obj['filter'.concat(++i)] = subobj;
    }
    Ответ написан
    Комментировать
  • Как отслеживать изменение атрибута src у img на чистом JS?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Ответ написан
    Комментировать
  • Каким регулярным выражением можно обернуть все + и - после букв в тег sup?

    0xD34F
    @0xD34F Куратор тега Регулярные выражения
    (?<=[a-zA-Z])(\+|\-)
    <sup>$1</sup>
    Ответ написан
    Комментировать
  • Как задать родительский элемент тегам?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Чьих next'ов надо обернуть и во что:

    const itemsSelector = '.block';
    const wrapperTag = 'div';
    const wrapperClass = 'parent';

    Оборачиваем:

    const $items = $(itemsSelector);
    $items.each(i => $items
      .eq(i)
      .nextUntil($items.get(i + 1))
      .wrapAll(`<${wrapperTag} class="${wrapperClass}">`)
    );

    или

    document.querySelectorAll(itemsSelector).forEach((n, i, a) => {
      const elems = [];
      for (let el = n; (el = el.nextElementSibling) != a[-~i]; elems.push(el)) ;
      n.after(document.createElement(wrapperTag));
      n.nextSibling.classList.add(wrapperClass);
      n.nextSibling.append(...elems);
    });
    Ответ написан
    8 комментариев
  • Как выбрать первые 5 элементов массива соответвующие условию?

    0xD34F
    @0xD34F
    $filtered = array_slice(array_filter($search_results, function($n) {
      return условие;
    }), 0, 5);

    или

    $filtered = [];
    
    foreach ($search_results as $n) {
      if (условие) {
        $filtered[] = $n;
      }
    
      if (count($filtered) === 5) {
        break;
      }
    }
    Ответ написан
  • Как правильно разделить массив?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const [ arr1, arr2 ] = arr.list
      .map(n => [ n, +n.pos.dv.slice(1) ])
      .sort((a, b) => a[1] - b[1])
      .reduce((acc, n) => (acc[+(n[1] >= 38)].push(n[0]), acc), [ [], [] ])
      .map(n => ({ list: n }));
    Ответ написан
    1 комментарий
  • Как проверить циклом таблицу с двумя условиями?

    0xD34F
    @0xD34F Куратор тега JavaScript
    .red {
      background: red;
    }

    $('.table').on('change', function(e) {
      const $tr = $(e.target).closest('tr');
      const ajaxdata = $tr.find('.ajaxdata').val();
      const subcat = $tr.find('.subcat').val();
    
      $tr.toggleClass('red', ajaxdata === 'none' && subcat === 'none');
    }).find('tr').change();
    
    // или
    
    const table = document.querySelector('table');
    
    table.addEventListener('change', e => {
      const tr = e.target.closest('tr');
      const ajaxdata = tr.querySelector('.ajaxdata').value;
      const subcat = tr.querySelector('.subcat').value;
    
      tr.classList.toggle('red', ajaxdata === 'none' && subcat === 'none');
    })
    
    table.querySelectorAll('tr').forEach(n => {
      n.dispatchEvent(new Event('change', { bubbles: true }));
    });
    Ответ написан
    2 комментария
  • Почему может не обновлятся динамически свойство?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Я бы предположил, что свойства isShow изначально отсутствуют в объектах requests - ну, не просто же так вы их выставляете в created. Чтобы они были реактивными, замените

    item.isShow = false;

    на

    this.$set(item, 'isShow', false);

    UPD. А-а-а, это у вас не свойство, а параметр. Нет, тогда надо иначе, модифицировать параметры не следует - делайте копию и работайте с ней, вместо возни в created будет как-то так:

    data() {
      return {
        apiCopy: this.api.map(n => ({
          ...n,
          requests: n.requests.map(m => ({
            ...m,
            isShow: false,
          })),
        })),
      };
    },
    Ответ написан
    8 комментариев
  • Как удалить вложенные массивы по условию?

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

    const mustStay = arr => arr.every(n => n.value !== '-');

    Собираем новый массив:

    const newArr = arr.filter(mustStay);
    
    // или
    
    const newArr = [];
    for (const n of arr) {
      if (mustStay(n)) {
        newArr.push(n);
      }
    }
    
    // или
    
    const newArr = [];
    for (let i = 0; i < arr.length; i++) {
      if (mustStay(arr[i])) {
        newArr[newArr.length] = arr[i];
      }
    }
    
    // или
    
    const newArr = (function get(i, n = arr[i]) {
      return n
        ? [ mustStay(n) ? [ n ] : [], get(i + 1) ].flat()
        : [];
    })(0)

    Изменяем существующий:

    for (let i = 0; i < arr.length; i++) {
      if (!mustStay(arr[i])) {
        for (let j = i--; ++j < arr.length; arr[j - 1] = arr[j]) ;
        arr.pop();
      }
    }
    
    // или
    
    arr.reduceRight((_, n, i, a) => mustStay(n) || a.splice(i, 1), null);
    
    // или
    
    arr.splice(0, arr.length, ...arr.filter(mustStay));
    
    // или
    
    arr.length -= arr.reduce((acc, n, i, a) => (
      a[i - acc] = n,
      acc + !mustStay(n)
    ), 0);
    Ответ написан
    Комментировать
  • Как правильно заполнить массив данными?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Вычисляем максимальную длину вложенных массивов:

    const length = Math.max(...arr.map(n => n.length));
    
    // или
    
    const length = arr.reduce((max, { length: n }) => max > n ? max : n, 0);

    Дополняем существующие массивы:

    for (const n of arr) {
      const id = 1 + Math.max(0, ...n.map(m => m.id));
      n.push(...Array.from(
        { length: length - n.length },
        (_, i) => ({ id: id + i, value: '_' })
      ));
    }

    Или собираем новые:

    const newArr = arr.map(n => Array.from({ length }, (_, i) => ({
      id: i + 1,
      value: i < n.length ? n[i].value : '-',
    })));
    Ответ написан
  • Как найти количество повторяющихся элементов массива?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Формулировка вопроса какая-то расплывчатая. Непонятно, о каком количестве повторяющихся элементов идёт речь - взятых в единственном экземпляре, или с учётом повторений. Т.е., каким должен быть результат для, например, такого массива - [ 7, 7, 7, 0, 1, 1 ]? В первом случае 2 - повторяются семёрка и единица, во втором 5 - три семёрки плюс две единицы.

    Количество уникальных дубликатов:

    const duplicateCount = Object
      .values(arr.reduce((acc, n) => (acc[n] = (acc[n] || 0) + 1, acc), {}))
      .filter(n => n > 1)
      .length;
    
    // или
    
    const duplicateCount = Array
      .from(arr.reduce((acc, n) => acc.set(n, acc.has(n)), new Map).values())
      .reduce((acc, n) => acc + n, 0);
    
    // или
    
    const duplicateCount = new Set(arr.filter((n, i, a) => i !== a.indexOf(n))).size;

    С учётом повторений:

    const duplicateCount = Object
      .values(arr.reduce((acc, n) => (acc[n] = acc.hasOwnProperty(n), acc), {}))
      .reduce((acc, n) => acc - !n, arr.length);
    
    // или
    
    const duplicateCount = Array
      .from(arr.reduce((acc, n) => acc.set(n, -~acc.get(n)), new Map).values())
      .reduce((acc, n) => acc + (n > 1) * n, 0);
    
    // или
    
    const duplicateCount = arr
      .filter((n, i, a) => a.indexOf(n) !== a.lastIndexOf(n))
      .length;
    Ответ написан
    5 комментариев
  • Как достать вложенные массивы, элементы которых удовлетворяют условию?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Как будем проверять, что массив нам подходит:

    const isArrOK = arr => arr.length && arr.every(n => n.value !== '-');

    Достаём вложенные массивы:

    const newArr = arr.reduce((acc, { arr: n }) => (
      isArrOK(n) && acc.push(n),
      acc
    ), []);
    
    // или
    
    const newArr = arr.map(n => n.arr).filter(isArrOK);
    
    // или
    
    const newArr = [];
    for (const n of arr) {
      if (isArrOK(n.arr)) {
        newArr[newArr.length] = n.arr;
      }
    }
    Ответ написан
    1 комментарий
  • Как узнать имя файла до загрузки JQUERY?

    0xD34F
    @0xD34F Куратор тега JavaScript
    $('#file').on('change', ({ target: { files: [ file ] } }) => {
      $('#info-file').html([ 'name', 'size', 'type' ]
        .map(n => `<div>${n}: ${file[n]}</div>`)
        .join('')
      );
    });
    Ответ написан
    1 комментарий
  • Как в slick сделать индикатор полосу вместо пагинации?

    0xD34F
    @0xD34F
    "Полоса" будет состоять из двух div'ов, вложенных один в другой. Цвет фона разный, у второго анимируется изменение ширины:

    <div class="nav">
      <div class="nav-inner"></div>
    </div>

    .nav {
      height: 20px;
      background: #ddd;
    }
    .nav-inner {
      height: 100%;
      background: red;
      transition: width 0.5s;
    }

    Метод обновления "полосы" - принимает номер слайда, устанавливает ширину внутреннего div'а:

    const updateNav = slide => $navInner.width(`${(slide + 1) / slidesCount * 100}%`);

    Этот метод используется при инициализации слайдера и изменении слайда:

    $slick.on({
      init: (e, slick) => updateNav(slick.currentSlide),
      beforeChange: (e, slick, currSlide, nextSlide) => updateNav(nextSlide),
    })

    Клик по "полосе" - из отношения положения курсора и ширины "полосы" вычисляется индекс слайда, к которому надо перейти:

    $nav.on('click', function(e) {
      $slick.slick('slickGoTo', e.offsetX / $nav.width() * slidesCount | 0);
    });

    https://jsfiddle.net/u7s2r3p4/2/

    UPD. Вынесено из комментариев:

    как сделать так, чтобы width полосы высчитывался в зависимости от slidesToShow

    Вычитайте лишнее, при расчётах ширины и номера слайда, к которому надо перейти, slidesCount надо заменить на slidesCount - slidesToShow + 1.
    Ответ написан
    2 комментария
  • Как синхронизировать store и back-end?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Насколько хороши варианты:
    1. интервалом синхронить стейт корзины.
    2. Синхронить стейт при событии onunload
    3. Писать обработчик кликов, который будет регулировать частоту запросов (очень не хочется)

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

    Надо как-то сразу сохранять состояние корзины, после любого действия пользователя, немедленно. Пишите его в localstorage. Под это дело есть плагины для vuex - например. При загрузке приложения синхронизируйте.

    Как синхронизировать в процессе работы - я бы предпочёл третий вариант. Только конечно не клики надо обрабатывать, а состояние корзины в хранилище. Делаете watch, в обработчике - запрос на синхронизацию с сервером, обёрнутый в debounce (лень писать - можете легко нагуглить готовый вариант).

    Т.е., будет что-то вроде

    methods: {
      syncCart: debounce(function() {
        ...
      }),
    },
    watch: {
      '$store.state.cart': {
        immediate: true,
        deep: true,
        handler: 'syncCart',
      },
    },
    Ответ написан
    Комментировать