Задать вопрос
  • Как в react работать с событием ресайза и как при загрузке определить ширину экрана и поменять стейт?

    0xD34F
    @0xD34F Куратор тега React
    onResize = () => {
      this.setState(() => ({
        /* ... */
      }));
    }
    
    componentDidMount() {
      window.addEventListener('resize', this.onResize);
      this.onResize();
    }
    
    componentWillUnmount() {
      window.removeEventListener('resize', this.onResize);
    }

    https://jsfiddle.net/jmz39vwo/
    Ответ написан
  • Как сделать, чтобы выбранное значение в списке заменяло собой список?

    0xD34F
    @0xD34F Куратор тега JavaScript
    $('table').on('change', 'select', ({ target: t }) => {
    
      $(t).replaceWith(t.value);
    
      // или
    
      $(t).prop('outerText', t.value);
    
      // или
    
      $(t).after(t.value).remove();
    });

    или

    const isSelect = el => el.tagName === 'SELECT';
    // или
    const isSelect = el => el.nodeName === 'SELECT';
    // или
    const isSelect = el => el.matches('select');
    // или
    const isSelect = el => el instanceof HTMLSelectElement;

    document.querySelector('table').addEventListener('change', ({ target: t }) => {
      if (isSelect(t)) {
    
        t.replaceWith(t.value);
    
        // или
    
        t.parentNode.replaceChild(new Text(t.value), t);
    
        // или
    
        t.outerText = t.value;
    
        // или
    
        t.after(t.value);
        t.remove();
    
        // или
    
        t.parentNode.replaceChildren(...Array.from(
          t.parentNode.childNodes,
          n => n === t ? t.value : n
        ));
      }
    });
    Ответ написан
    Комментировать
  • Как более компактно получить тексты ошибок и выводить цвета?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Цвета:

    progress.css('background-color', [
      { min: 100, color: '#47C965' },
      { min:  40, color: '#f5dd30' },
      { min:   0, color: '#bf4542' },
    ].find(n => n.min <= strength).color);

    Тексты ошибок: не надо никаких атрибутов, сразу положите их в объекты.
    Но если всё же хотите идти путём говнокодера, то
    const tests = [ здесь перечисляете регулярные выражения ].map((n, i) => ({
      regex: n,
      message: error_wrap.attr(`data-error_${i + 1}`),
    }));
    Ответ написан
    1 комментарий
  • Как найти дубликаты в массиве?

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

    const newArr = Object
      .values(arr.reduce((acc, n, i) => ((acc[n] ??= []).push(i), acc), {}))
      .reduce((acc, n) => (n.forEach(i => acc[i] = n.length > 1), acc), []);
    
    // или
    
    const newArr = arr.map(function(n) {
      return this[n];
    }, arr.reduce((acc, n) => (acc[n] = acc.hasOwnProperty(n), acc), {}));
    
    // или
    
    const count = arr.reduce((acc, n) => (acc[n] = (acc[n] ?? 0) + 1, acc), {});
    const newArr = arr.map(n => count[n] > 1);
    
    // или
    
    const newArr = arr.map((n, i, a) => a.indexOf(n) !== a.lastIndexOf(n));

    Обновить существующий:

    arr.forEach(function(n, i, a) {
      a[i] = this.get(n) > 1;
    }, arr.reduce((acc, n) => acc.set(n, -~acc.get(n)), new Map));
    
    // или
    
    const duplicates = arr.reduce((acc, n) => acc.set(n, acc.has(n)), new Map);
    arr.splice(0, arr.length, ...arr.map(n => duplicates.get(n)));
    Ответ написан
    2 комментария
  • Почему появляется две галочки?

    0xD34F
    @0xD34F Куратор тега CSS
    input[type=checkbox], label{

    Вместо , должен быть +.

    А чекбоксу надо задать display; none;.
    Ответ написан
    Комментировать
  • Как получить текст выбранного option'а?

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

    Ну а вообще:

    $('select').change(function() {
      const text = $(':checked', this).text();
      console.log(text);
    });

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

    document.querySelector('select').addEventListener('change', function(e) {
      const select = this;
      // или
      // const select = e.target;
      // const select = e.currentTarget;
    
      const [ option ] = select.selectedOptions;
      // или
      // const option = select[select.selectedIndex];
      // const option = select.querySelector(':checked');
      // const option = [...select.options].find(n => n.selected);
    
      const text = option.text;
      // или
      // const text = option.textContent;
      // const text = option.innerText;
    
      console.log(text);
    });
    Ответ написан
    Комментировать
  • Как сделать фильтрацию результатов по поиску?

    0xD34F
    @0xD34F Куратор тега JavaScript
    document.querySelector('#filter-input').addEventListener('input', e => {
      const val = e.target.value.toLowerCase();
    
      container.querySelectorAll('.title').forEach(n => {
        n.closest('.card').style.display = n.innerText.toLowerCase().includes(val)
          ? 'block'
          : 'none';
      });
    });

    или

    document.getElementById('filter-input').oninput = function() {
      const val = this.value.toLowerCase();
    
      for (const n of container.getElementsByClassName('title')) {
        let card = n;
        while (!(card = card.parentNode).classList.contains('card')) ;
        card.hidden = n.textContent.toLowerCase().indexOf(val) === -1;
      }
    };
    Ответ написан
    1 комментарий
  • Как из компонента обновлять объект в хранилище?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Когда в хранилище появится новое свойство, будете вручную его добавлять в компонент? Хранилище доступно в data (если, конечно, не будете делать её стрелочной), так что можно просто скопировать объект; в наблюдателе вместо проверок конкретных свойств можно сделать цикл по всем:

    rangeValues: { ...this.$store.state.CarSetup },

    Object.entries(newValue).forEach(([ k, v ]) => {
      if (v !== oldValue[k]) {
        this.$store.commit('setCarInfo', { to: k, value: v });
      }
    });


    А вообще, не надо ни копии объекта из хранилища, ни наблюдателя. Вырезаете returnValue, свойство rangeValues из обычного делаете вычисляемым:

    computed: {
      rangeValues() {
        return new Proxy(this.$store.state.carSetup, {
          set: (target, key, val) => {
            this.$store.commit('setCarInfo', { [key]: val });
            return true;
          },
        });
      },
    },

    Мутацию переписываете следующим образом:

    setCarInfo: (state, payload) => Object.assign(state.carSetup, payload),
    Ответ написан
  • Как динамично сформировать объект?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const obj = Object.fromEntries(arr.map((n, i) => [ `answer${i + 1}`, n ]));

    или

    const obj = arr.reduce((acc, n, i) => (acc['answer' + ++i] = n, acc), {});

    или

    const obj = {};
    for (const [ i, n ] of arr.entries()) {
      obj['answer'.concat(-~i)] = n;
    }
    Ответ написан
    5 комментариев
  • Как перепарсить словарь python?

    0xD34F
    @0xD34F
    keys = list(data.keys())
    result = [ { k: data[k][i] for k in keys } for i in range(len(data[keys[0]])) ]
    Ответ написан
    Комментировать
  • Как сделать фильтр списка, если у элемента несколько категорий массивом?

    0xD34F
    @0xD34F Куратор тега Vue.js
    computed: {
      filteredProducts() {
        const keyword = this.keyword.toLowerCase();
    
        return this.products.filter(item => (
          (item.name.toLowerCase().includes(keyword)) &&
          (!this.colors.length || this.colors.includes(item.color)) &&
          (!this.sizes.length || this.sizes.some(n => item.size.includes(n))) &&
          (!this.categories.length || this.categories.includes(item.category))
        ));
      },
      ...

    UPD. Вопрос конечно был не об этом, но уж как-то сильно глаз режет... Размеры ладно, какие они бывают известно заранее и их немного, но вот, скажем, цвета - когда изменится список товаров, будете вручную его просматривать и обновлять список цветов? Можно вычислять автоматически:

    computed: {
      colorFilter() {
        return Array
          .from(new Set(this.products.map(n => n.color)))
          .sort((a, b) => a.localeCompare(b));
      },
      ...
    Ответ написан
    Комментировать
  • Как получить данные элемента по клику в итерации?

    0xD34F
    @0xD34F Куратор тега React
    onChange = {(event, userItem)=>handleChange(event, userItem)}

    Убрать userItem из списка параметров: onChange={e => handleChange(e, userItem)}.

    Или, onChange={handleChange.bind(userItem)},

    function handleChange(e) {
      console.log('userItem', this);
      console.log('value', e.target.value);
    }
    Ответ написан
    Комментировать
  • Как проверить регистр первой буквы?

    0xD34F
    @0xD34F Куратор тега JavaScript
    str[0] === str[0].toUpperCase()

    или

    /^[A-Z]/.test(str)

    или

    (c => 64 < c && c < 91)(str.charCodeAt(0))

    или

    'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.includes(str.at(0))

    Но что если там вообще не буква?
    Если такое может быть, то...
    ...ни хрена тут больше не скажу, тщательнее надо было вопрос продумывать.
    Ответ написан
    Комментировать
  • Как собирать строку из нескольких кусков на питоне?

    0xD34F
    @0xD34F
    from random import sample
    
    arr = [ 'AAA', 'BBB', 'CCC', 'DDD', 'EEE', 'FFF', 'GGG', 'HHH' ]
    string = ''.join(sample(arr, k=len(arr)))
    Ответ написан
    1 комментарий
  • Как поменять класс, если выбран checkbox?

    0xD34F
    @0xD34F Куратор тега JavaScript
    $('.filter').change(({ target: t }) => {
      $(`[name="${$(t).closest('.button').data('size')}"]`)
        .closest('.product-box')
        .toggleClass('hidden', !t.checked);
    }).find(':checked').change();

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

    const filter = document.querySelector('.filter');
    
    filter.addEventListener('change', ({ target: t }) => {
      const size = t.closest('.button').dataset.size;
      document.querySelectorAll(`[name="${size}"]`).forEach(n => {
        n.closest('.product-box').classList.toggle('hidden', !t.checked);
      });
    });
    
    filter.querySelectorAll(':checked').forEach(n => {
      n.dispatchEvent(new Event('change', { bubbles: true }));
    });
    Ответ написан
    1 комментарий
  • Как посчитать суммы соседних элементов в списке?

    0xD34F
    @0xD34F
    arr = [ int(n) for n in input().split() ]
    arrLen = len(arr)
    result = arr if arrLen == 1 else [ arr[i - 1] + arr[(i + 1) % arrLen] for i in range(arrLen) ]
    
    print(' '.join(map(str, result)))
    Ответ написан
    Комментировать
  • Как сделать рендер таблицы React js?

    0xD34F
    @0xD34F Куратор тега React
    Функция группировки массива по значениям одного из свойств его элементов, она нам ниже не раз понадобится:

    const group = (arr, key) =>
      arr.reduce((acc, n) => (
        (acc[n[key]] = acc[n[key]] || []).push(n),
        acc
      ), {});

    Имена свойств группируемых данных, они тоже понадобятся:

    const groupItemKeys = [ 'kurs', 'contract', 'credit' ];

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

    const groupedData = useMemo(() => {
      return Object.entries(group(data, 'country'));
    }, [ data ]);

    <tbody>{groupedData.map(([ country, items ], i) =>
      <tr>
        <td>{i + 1}</td>
        <td>{country}</td>
        {groupItemKeys.map(k =>
          <td>{items.map(n => <div>{n[k]}</div>)}</td>
        )}
      </tr>)}
    </tbody>

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

    const groupedData = useMemo(() => {
      return Object.values(group(data, 'country'));
    }, [ data ]);

    <tbody>{groupedData.map((n, i) => n.map((m, j) =>
      <tr>
        {!j && <React.Fragment>
          <td rowSpan={n.length}>{i + 1}</td>
          <td rowSpan={n.length}>{m.country}</td>
        </React.Fragment>}
        {groupItemKeys.map(k => <td>{m[k]}</td>)}
      </tr>))}
    </tbody>

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

    const rowsData = useMemo(() => {
      return Object
        .values(group(data, 'country'))
        .flatMap((items, i) => items.map((n, j) => (j
          ? []
          : [ i + 1, n.country ].map(m => [ m, items.length ])
        ).concat(groupItemKeys.map(k => [ n[k] ]))));
    }, [ data ]);

    <tbody>{rowsData.map(n =>
      <tr>{n.map(m => (
        <td rowSpan={m[1]}>{m[0]}</td>))}
      </tr>)}
    </tbody>
    Ответ написан
    Комментировать
  • Как создать список словарей из заданного списка?

    0xD34F
    @0xD34F
    result = [ { arr[i]: arr[i + 1] } for i in range(0, len(arr), 2) ]
    Ответ написан
    Комментировать
  • Как валидировать пароль?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Складываем в массив описания проверок, которым должен быть подвергнут пароль - это будут объекты, состоящие из функции, проверяющей соответствие пароля одному конкретному условию, и сообщения, демонстрируемого пользователю в случае, если проверка прошла неудачно.

    Добавляем элементу с паролем обработчик события input, в котором бежим по массиву проверок, передаём функциям текущий пароль, собираем в массив сообщения о допущенных пользователем ошибках.

    Как посчитать процент успеха в деле сочинения пароля - это будет отношение количества успешно пройденных проверок к общему количеству проверок, умноженное на сто.

    Ну и всё, дальше остаётся только вывести результаты.

    <div>
      <input id="password">
    </div>
    <div>
      <div>Сложность пароля: <span id="strength_percent">0</span>%</div>
      <progress id="strength_progress" max="100" value="0"></progress>
    </div>
    <div id="errors"></div>

    const validations = [
      {
        test: val => val.length >= 8,
        message: 'пароль должен содержать хотя бы 8 символов',
      },
      {
        test: val => /[A-ZА-ЯЁ]/.test(val),
        message: 'пароль должен содержать хотя бы 1 большую букву',
      },
      {
        test: val => /[a-zа-яё]/.test(val),
        message: 'пароль должен содержать хотя бы 1 маленькую букву',
      },
      {
        test: val => /[^\s\da-zа-яё]/i.test(val),
        message: 'пароль должен содержать хотя бы 1 спецсимвол (не пробел, букву или цифру)',
      },
      {
        test: val => /\d/.test(val),
        message: 'пароль должен содержать хотя бы 1 цифру',
      },
    ];
    
    document.querySelector('#password').addEventListener('input', e => {
      const errors = validations.reduce((acc, n) => (
        n.test(e.target.value) || acc.push(n.message),
        acc
      ), []);
    
      const strength = (validations.length - errors.length) / validations.length * 100;
    
      document.querySelector('#strength_progress').value = strength;
      document.querySelector('#strength_percent').innerText = strength | 0;
      document.querySelector('#errors').innerHTML = errors
        .map(n => `<p>${n}</p>`)
        .join('');
    });
    Ответ написан
    1 комментарий