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

    0xD34F
    @0xD34F Куратор тега JavaScript
    Как проверить наличие элементов:

    const card = document.querySelector('.card');
    const itemsExists = () => !!card.querySelector('.item');

    Кому надо изменить видимость:

    const nav = document.querySelector('.navigation');
    
    // или, если слова про соседа являются правдой
    
    const nav = card.nextElementSibling;

    Скрываем/показываем:

    nav.hidden = !itemsExists();
    
    // или
    
    nav.style.display = itemsExists() ? 'block' : 'none';

    UPD. Наконец-то дождались. Теперь использовать js тут не обязательно:

    .card:not(:has(.item)) + .navigation {
      display: none;
    }
    Ответ написан
    Комментировать
  • Cоздать компонент Vue и событие внутри него?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Вариант раз, размер шрифта делаем свойством компонента, ну и v-model + watch:

    data: () => ({
      size: ...
    }),
    watch: {
      size: {
        immediate: true,
        handler(val) {
          fontSize(this.target, val);
        },
      },
    },

    <input type="range" v-model="size">

    Вариант два - слушаем событие input:

    methods: {
      onInput(e) {
        fontSize(this.target, e.target.value);
      },
    },
    mounted() {
      this.$el.querySelector('input').dispatchEvent(new Event('input'));
    },

    <input type="range" @input="onInput">
    Ответ написан
    Комментировать
  • Какая должна быть регулярка для проверки чисел в строке?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const isPositiveInteger = RegExp.prototype.test.bind(/^\d+$/);
    
    // или
    
    const isPositiveInteger = str =>
      !(!str || str.replace(/\d/g, ''));
    
    // или
    
    const isPositiveInteger = str =>
      Boolean(str) && !str.match(/\D/);

    Нужна именно регулярка, т.к. числа большой длины.

    Нет, не "т.к.". Т.к. строку можно проверить и без регулярных выражений:

    const isPositiveInteger = str =>
      str !== '' && [...str].every(n => Number.isInteger(+n));
    
    // или
    
    function isPositiveInteger(str) {
      for (const n of str) {
        if (!'0123456789'.includes(n)) {
          return false;
        }
      }
    
      return str.length > 0;
    }
    
    // или
    
    function isPositiveInteger(str) {
      let result = !!str;
    
      for (let i = 0; i < str.length && result; i++) {
        const n = str.charCodeAt(i);
        result = 47 < n && n < 58;
      }
    
      return result;
    }
    Ответ написан
    1 комментарий
  • Как менять класс родителя при выборе радиокнопки?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const containerSelector = '.form-fields';
    const itemSelector = `${containerSelector} .wrapper-from-field`;
    const activeClass = 'active';
    const toggle = item => item
      .closest(containerSelector)
      .querySelectorAll(itemSelector)
      .forEach(n => n.classList.toggle(activeClass, n === item));

    document.querySelectorAll(itemSelector).forEach(function(n) {
      n.addEventListener('change', this);
    }, e => toggle(e.currentTarget));
    
    // или
    
    document.addEventListener('change', ({ target: t }) =>
      (t = t.closest(itemSelector)) && toggle(t)
    );
    Ответ написан
  • Как конвертировать дату в unix?

    0xD34F
    @0xD34F Куратор тега JavaScript
    берёте moment.js и: moment(dateStr, 'MMM D, YYYY at hh:mm A').unix()

    или, если подрезать строку, можно будет обойтись без сторонних библиотек:

    Date.parse(dateStr.replace('at', '')) / 1000
    Ответ написан
    Комментировать
  • Как сделать код короче?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const getCard = button => $(`#card${button.id.match(/\d+/).pop()}`);
    
    $('[id^="button"]').hover(
      e => getCard(e.target).fadeIn(),
      e => getCard(e.target).fadeOut(),
    );

    или

    const $buttons = $('[id^=button]').hover(function(e) {
      this.eq($buttons.index(e.target))[e.type === 'mouseenter' ? 'fadeIn' : 'fadeOut']();
    }.bind($('[id^=card]')));
    Ответ написан
    Комментировать
  • Как при добавлении новой строки, к элементу крепить виджет datepicker?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Правильный вариант: отказаться от использования jquery, и взять какой-нибудь готовый компонент для vue. Можете заглянуть на awesome-vue, там есть список, может присмотрите себе что-нибудь.

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

    <input ref="datepicker" v-model="item.date">

    watch: {
      items() {
        this.$nextTick(() => {
          this.$refs.datepicker
            .filter(n => !n.classList.contains('hasDatepicker'))
            .forEach(n => $(n).datepicker({
              onSelect: () => n.dispatchEvent(new Event('input')),
            }));
        });
      },
    },

    Или можно директиву сделать:

    <input v-datepicker v-model="item.date">

    Vue.directive('datepicker', {
      inserted: el => $(el).datepicker({
        onSelect: () => el.dispatchEvent(new Event('input')),
      }),
    });

    Или даже целый компонент:

    <v-datepicker v-model="item.date"></v-datepicker>

    Vue.component('v-datepicker', {
      template: `<input :value="value" readonly="readonly">`,
      props: [ 'value' ],
      mounted() {
        $(this.$el).datepicker({
          onSelect: date => this.$emit('input', date),
        });
      },
    });


    Кстати, вам ещё в шаблоне надо будет добавить key в список пользователей.
    Ответ написан
  • Как передать значение из data в атрибут html во vue?

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

    Само значение собирайте с использованием обычных javascript-выражений:

    :src="`/img/${imgName}.jpg`"

    или

    :src="'/img/' + imgName + '.jpg'"

    Также можно сделать вычисляемое свойство, если imgName является свойством компонента:

    computed: {
      imgSrc() {
        return `/img/${this.imgName}.jpg`;
      },
    },

    :src="imgSrc"

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

    methods: {
      imgSrc: name => `/img/${name}.jpg`,
    },

    :src="imgSrc(imgName)"
    Ответ написан
    Комментировать
  • Как сделать фильтрацию по нескольким параметрам?

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

    filters: [
      { field: 'bg', value: '', options: [ 'black', 'white' ] },
      { field: 'color', value: '', options: [ 'red', 'green' ] },
    ],

    На основе этого массива создать элементы фильтров:

    filters.map((n, i) => (
      <label>
        {n.field}:
        <select data-index={i} onChange={this.onChange}>
          <option value="">none</option>
          {n.options.map(n => <option>{n}</option>)}
        </select>
      </label>
    ))

    onChange = e => {
      const index = +e.target.dataset.index;
      const value = e.target.value;
    
      this.setState(prevState => ({
        filters: prevState.filters.map((n, i) => index === i ? { ...n, value } : n)
      }));
    }

    Получить отфильтрованные данные:

    const filteredData = filters.reduce((acc, n) => {
      return n.value
        ? acc.filter(m => m[n.field].includes(n.value))
        : acc;
    }, data);

    Вместо полных данных отобразить отфильтрованные.
    Ответ написан
    1 комментарий
  • Как исключить из массива текст?

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

    // смотрим, что скажет оператор typeof
    const isString = x => typeof x === 'string';
    
    // сравниваем значение и результат его преобразования в строку
    const isString = x => x === `${x}`;
    
    // проверяем конструктор (помимо примитивов, выдаёт true и для строковых объектов)
    const isString = x => x != null && x.constructor === String;

    Избавляемся от строк:

    // cобираем новый массив
    const newArr = arr.filter(n => !isString(n));
    
    // удаляем элементы существующего
    arr.length -= arr.reduce((acc, n, i, a) => (
      a[i - acc] = n,
      acc + isString(n)
    ), 0);
    Ответ написан
    1 комментарий
  • Почему не работает кнопка?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Потому что у вас имя переменной - top, и она глобальная. Но глобальной переменной с таким именем быть не может, место уже занято. Так что когда вы делаете top += 2, вы вовсе не с числом работаете. Меняйте имя переменной или выполняйте свой код в области видимости, отличной от глобальной или сделайте свой top свойством какого-нибудь объекта или...
    Ответ написан
  • Исполнение JS, полученного с сервера в компоненте VUE. Можно ли?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Можно. Только это называется не "исполнение js", а компиляция шаблона. Смотрите Vue.compile.
    Ответ написан
  • Как реализовать фильтр в react-table?

    0xD34F
    @0xD34F Куратор тега React
    Сделайте кастомный фильтр, с обработчиками onChange и onKeyPress, в которых и будет происходить переключение функции фильтрации. Например, так (поле lastName, посмотреть в деле можно вбивая короткие слова, которые являются частью более длинных - такие как war, son, comb, sign, child, work, can и т.п.).

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

    у меня много столбцов, плюс к этому много таблиц, и логику фильтра нужно применить ко всему

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

    UPD. https://codesandbox.io/s/nn1z53jn4l (только первые три поля, у последнего фильтр оставлен переопределённым).
    Ответ написан
    5 комментариев
  • Как сделать, чтобы отображаемый select'ом текст отличался от текста выбранного option'а?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Продублировать option'ы. Первый в каждой из полученных пар будет содержать текст, отображаемый в качестве выбранного, при этом сам он должен быть скрыт, чтобы не отображаться в выпадающем списке. При выборе следует присвоить select'у его текущее значение, чтобы выбранным option'ом (т.е. тем, чей текст будет показан в select'е) вместо видимого второго оказался скрытый первый.

    select.innerHTML = [
      { val:  69, optionText:  'hello, world!!', selectText:  'HELLO, WORLD!!' },
      { val: 187, optionText:  'fuck the world', selectText:  'FUCK THE WORLD' },
      { val: 666, optionText: 'fuck everything', selectText: 'FUCK EVERYTHING' },
    ].map(n => `
      <option value="${n.val}" hidden>${n.selectText}</option>
      <option value="${n.val}">${n.optionText}</option>
    `).join('');
    
    select.addEventListener('change', e => e.target.value = e.target.value);
    Ответ написан
  • Как вывести элементы htmlcollection в цикле на странице?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Откуда и куда копируем:

    const source = document.querySelector('.menu');
    const target = document.querySelector('#parent');

    • Вариант раз - cloneNode.

      Можно перебирать элементы и копировать их по одному:

      for (const n of source.children) {
        target.appendChild(n.cloneNode(true));
      }
      
      // или
      
      source.querySelectorAll(':scope > *').forEach(n => {
        target.insertAdjacentElement('beforeend', n.cloneNode(true));
      });

      А можно скопировать их родителя:

      // вложенные узлы копии добавляем в целевой элемент
      target.append(...source.cloneNode(true).children);
      
      // или, заменяем целевой элемент копией исходного
      target.replaceWith(source.cloneNode(true));

    • Вариант два - копируем не сами элементы, а разметку:

      target.innerHTML = source.innerHTML;
      
      // или
      
      target.outerHTML = source.outerHTML;

    Ответ написан
    Комментировать
  • Как выводить день недели и месяц зная порядковый номер дня года?

    0xD34F
    @0xD34F Куратор тега JavaScript
    function getDate(day, year = new Date().getFullYear()) {
      const date = new Date(year, 0, day);
      return [
        date.getDate(),
        [
          'январь', 'февраль', 'март', 'апрель', 'май', 'июнь',
          'июль', 'август', 'сентябрь', 'октябрь', 'ноябрь', 'декабрь'
        ][date.getMonth()],
        [ 'вс', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб' ][date.getDay()],
      ].join(' ');
    }
    
    getDate(115, 2019) // "25 апрель чт"

    или

    const getDate = (day, year = new Date().getFullYear()) =>
      new Date(year, 0, day).toLocaleString('ru-RU', {
        day: 'numeric',
        month: 'long',
        weekday: 'short',
      });
    
    getDate(115, 2019) // "чт, 25 апреля"
    Ответ написан
  • Почему не срабатывает скрипт jquery?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Останавливайте всплытие события при клике на .close-panel, чтобы только что удалённый класс не добавлялся обратно (при обработке события в родительском элементе):

    $('.close-panel').on('click', function(e) {
      e.stopPropagation();
      $('.add-caption').removeClass('active');
    });

    Или, уберите отдельный обработчик клика по .close-panel, а в обработчике клика по .add добавляйте или убирайте класс в зависимости от того, откуда пришло событие:

    $('.add').on('click', function(e) {
      $('.add-caption').toggleClass('active', !$(e.target).hasClass('close-panel'));
    });
    Ответ написан
  • Как из родителя запустить метод в ребенке Vue?

    0xD34F
    @0xD34F Куратор тега Vue.js
    через ref:

    <button @click="$refs.child.someMethod()">call child method</button>
    <child-component ref="child"></child-component>
    Ответ написан
    2 комментария
  • Как найти телефонные номера в строке?

    0xD34F
    @0xD34F Куратор тега JavaScript
    text.match(/8 \(495\) \d{3}-\d{2}-\d{2}/g)
    Ответ написан
    2 комментария
  • Как найти совпадения координат и удалить их?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const toDelX = new Set;
    const toDelY = new Set;
    
    X.forEach((n, i) => {
      if (X2.includes(n) && Y2.includes(Y[i])) {
        toDelX.add(n);
        toDelY.add(Y[i]);
      }
    });
    
    X2.splice(0, X2.length, ...X2.filter(n => !toDelX.has(n)));
    Y2.splice(0, Y2.length, ...Y2.filter(n => !toDelY.has(n)));
    Ответ написан
    Комментировать