• Как вставить текст туда куда мне нужно?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    В первой строке лишний бэк-тик в конце:
    textpayload = message.user.bonusNew ? `"{\"button\": \"дуэль\"}"` : "{\"button\": \"бонус_новичка\"}`"

    См. последние 2 символа: удалите `
    Бэк-тики (обратные кавычки) там вообще-то все не нужны, т.к. не используются их преимущества.

    Неблагодарное дело вручную писать JSON со всем эти кавычками – тут обычными, тут экранированные обратными слешами. Лучше сделать обычный объект, и потом его перевести в строку JSON:
    const bonusButton = { button: message.user.bonusNew ? 'дуэль' : 'бонус_новичка' };
    textpayload = JSON.stringify(bonusButton);
    Ответ написан
    Комментировать
  • Как избавиться от большого количества else if?

    Adamos
    @Adamos
    let variants = [
      { condition: (tries === 0), alert: 'У вас закончились попытки' },
      { condition: (value == number), alert: 'Поздравляю, вы угадали', returnValue: true },
      { decreaseTries: true }
    ];
    for(let i = 0; i < variants.length; ++i) {
      let v = variants[i];
      if(typeof v.condition === 'undefined' || v.condition) {
        if(v.alert) {
          alert(v.alert);
        }
        if(v.decreaseTries) {
          tries--;
          triesSpan.textContent = declOfNum(tries, ['попытка', 'попытки', 'попыток']);
          triesTitle.textContent = `У вас осталось ${tries} ${triesSpan.textContent}`;
        }
        return v.returnValue || false;
      }
    }

    Все варианты перечислять не стал, нужные добавляются по аналогии.
    Ответ написан
    Комментировать
  • Как объединить несколько объектов в один?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const merge = (target, ...sources) =>
      sources.reduce((acc, n) => (
        Object.entries(n).forEach(([ k, v ]) =>
          acc[k] = v instanceof Object
            ? merge(acc[k] instanceof Object ? acc[k] : {}, v)
            : v
        ),
        acc
      ), target);
    
    
    const result = merge({}, ...arrayObj);
    Ответ написан
    3 комментария
  • Как избавиться от неспособности придумать адекватное название блокам?

    mayton2019
    @mayton2019
    Bigdata Engineer
    Я где-то читал что астрономы уже давно не дают названия планетам и звездам. Закончились у них названия. Они их нумеруют. Может быть в какой-то степени это оправдано. Если для блоков веб-дизайна нет названий то возможно им стоит давать хотя-бы номера из sequence. Или если есть указание на относительную ориентацию (север-юг или слева внизу) то можно добавлять там какой-то символ. Вот. А если у автора возникнет именно задача тесной работы со слайдером - то тогда он его просто переименует в slider и будет работать. Похоже конечно на обфускацию больше чем на конвенцию по именам. Но может быть имена не так уж важны в данном процессе.
    Ответ написан
    Комментировать
  • Как в js указать все числа находящиеся в определенном диапазоне?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    В JS есть клевая штука: генераторы.
    Чтобы не забивать сразу память всеми значениями (что, если понадобится от 1 до 1050), можно их получать по одному:
    // эта функция - Генератор. Он создаёт итерируемые штуки
    function* makeRangeIterator(start = 0, end = 100, step = 1) {
        let iterationCount = 0;
        for (let i = start; i < end; i += step) {
            iterationCount++;
            yield i;
        }
        return iterationCount;
    }
    
    // вот сделаем итератор от 1 и до 10 (исключая конец)
    var r1_10 = makeRangeIterator(1, 10);
    
    // в цикле получим из итератора значения
    for (i of r1_10) {
      console.log(i); // выведет от 1 до 9
    }
    Ответ написан
    Комментировать
  • Какой набор библиотек используют в веб-геймдве?

    vabka
    @vabka
    Токсичный шарпист
    Не существует какого-то одного набора библиотек - всё подбирается исходя из задачи. Некоторые библиотеки, которые могут использоваться ты уже назвал. Некоторые другие - ты можешь узнать из описания вакансий.

    А почему обязательно JavaScript? Браузерные игры вполне могут делаться и на юнити.

    Что-то может и под Wasm делаться, а там уже и C++ и Rust живут со своими экосистемами.

    А некоторые браузерки и не требуют 3d вообще - там может использоваться и какой-нибудь кастомный 2д движок, а часть логики может обрабатываться на сервере, который вообще написано на php.
    Ответ написан
    Комментировать
  • Как выводить варианты ответов в случайном порядке?

    0xD34F
    @0xD34F Куратор тега Vue.js
    function shuffle(arr) {
      for (let i = arr.length; i > 1; ) {
        const j = Math.random() * (i--) | 0;
        [ arr[i], arr[j] ] = [ arr[j], arr[i] ];
      }
    
      return arr;
    }

    computed: {
      shuffledAnswers() {
        return shuffle(Object.entries(this.questions[this.idx].answers));
      },
      ...

    <div v-for="[ key, answer ] in shuffledAnswers">
      ...
    Ответ написан
    1 комментарий
  • Как провалидировать форму в которой несколько инпутов и селектов?

    0xD34F
    @0xD34F Куратор тега JavaScript
    document.querySelector('form').addEventListener('input', e => {
      document.querySelector('button').disabled = ![
        [  'input', el => el.value         ],
        [ 'select', el => el.selectedIndex ],
      ].every(([ selector, validator ]) => {
        return [...e.currentTarget.querySelectorAll(selector)].every(validator);
      });
    });
    Ответ написан
    2 комментария
  • Какая есть библиотека для создания кастомных круглых диаграмм?

    0xD34F
    @0xD34F Куратор тега React
    Ответ написан
    Комментировать
  • Как заменить данные карты на звездочки?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const hidden = (str, count = 4) => '*'.repeat(count) + str.slice(-4);

    или

    const hidden = (str, count = 4) => str.replace(/.*?(?=.{0,4}$)/, Array(count + 1).join('*'));
    Ответ написан
    1 комментарий
  • Как реализовать фильтрацию на vue.js по нескольким параметрам одновременно?

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

    data: () => ({
      filterColumns: [
        [     'name',        'имя', 'string' ],
        [    'count', 'количество', 'number' ],
        [ 'distance', 'расстояние', 'number' ],
      ],
      operations: [
        [    'equal',    'равно' ],
        [ 'contains', 'содержит' ],
        [  'greater',   'больше' ],
        [     'less',   'меньше' ],
      ],
      ...

    Тип данных указываем потому, что значения различных типов сравниваются по-разному. Кстати, определим, как именно:

    data: () => ({
      types: {
        string: {
          equal: (a, b) => a.toLowerCase() === b,
          contains: (a, b) => a.toLowerCase().includes(b),
          greater: (a, b) => a.toLowerCase() > b,
          less: (a, b) => a.toLowerCase() < b,
        },
        number: {
          equal: (a, b) => a === +b,
          contains: (a, b) => `${a}`.includes(b),
          greater: (a, b) => a > +b,
          less: (a, b) => a < +b,
        },
      },
      ...

    На основе описаний столбцов и способов фильтрации создадим select'ы:

    <select v-model="column">
      <option v-for="n in filterColumns" :value="n[0]">{{ n[1] }}</option>
    </select>
    <select v-model="operation">
      <option v-for="n in operations" :value="n[0]">{{ n[1] }}</option>
    </select>

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

    computed: {
      filteredItems() {
        const { items, column } = this;
        const type = this.filterColumns.find(n => n[0] === column)?.[2];
        const filterFn = this.types[type]?.[this.operation];
        const filterVal = this.filterVal.toLowerCase();
    
        return filterFn && filterVal
          ? items.filter(n => filterFn(n[column], filterVal))
          : items;
      },
      ...

    https://jsfiddle.net/8df3z1un/1/
    Ответ написан
    Комментировать
  • Как повторить каждый символ, чтобы количество повторений было равно его позиции в строке?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const xxx = str => Array
      .from(str, (n, i) => n.toUpperCase() + n.toLowerCase().repeat(i))
      .join('-');

    или

    const xxx = str => str
      .toUpperCase()
      .split('')
      .reduce((acc, n, i) => `${acc}${i ? '-' : ''}${n}${Array(-~i).join(n.toLowerCase())}`, '');

    или

    const xxx = str => str
      .toUpperCase()
      .replace(/(?<=.)./g, (m, i) => '-'.concat(m, ...Array(i).fill(m.toLowerCase())));
    Ответ написан
    Комментировать
  • Почему при перезагрузке страницы мои данные пропадают?

    0xD34F
    @0xD34F Куратор тега React
    Встречный вопрос: почему вы решили, что должно быть иначе? Код, который бы доставал данные из localStorage и клал их в todos, где он, почему его нет? Должен быть, например:

    const [ todos, setTodos ] = useState(() => {
      let todos = null;
    
      try {
        todos = JSON.parse(localStorage.getItem('todos'));
      } catch (e) {};
    
      return Array.isArray(todos) ? todos : [];
    });

    Уверен, здесь вы ждёте, что добавляемый объект окажется в localStorage:

    setTodos([
      ...todos,
      {
        id: Date.now(),
        complete: false,
        title: value,
      },
    ]);
    localStorage.setItem("todos", JSON.stringify(todos));

    Этого происходить не будет (ну, пока ещё что-то не добавите, и это "ещё что-то" тоже попадёт в localStorage не сразу). Вы не понимаете, что происходит при вызове setTodos. Откройте документацию и разберитесь. Сохранение в localStorage следует делать через useEffect:

    useEffect(() => {
      localStorage.setItem('todos', JSON.stringify(todos));
    }, [ todos ]);
    Ответ написан
    7 комментариев
  • Как выглядит правильный процесс тестирования?

    M23
    @M23
    Привет.
    1) Заводить баги и тест-кейсы/чек-листы надо отдельно от задач, так как правиться и проверяться они могут сильно позже, когда задачу давно уже закрыли. Например, регресс. Писать в комментах к задаче - плохая практика :)
    2) Кейсы пишутся на документацию к задаче, а не на то, как реализовали. То есть тестовая документация пишется еще до того, как ты приступила к тестированию.
    3) Написанные кейсы можно прилинковать к задачам и наоборот.
    4) Тестовая документация, баги и задачи могут находиться в разных TMS. Например, кейсы/чек-листы в Allure, а задачи и баги в Jira. Или все в Jira, но в отдельном плагине. Тут уж как в компании заведено или какие вы используете TMS.
    5) Баги заводятся как отдельные таски в бэклог. Если это новый функционал, который в работе, то может будет удобнее, если напрямую передашь разработчику и он сразу поправит.

    P.S. Сходи к коллегам из других команд (если такие есть) и посоветуйся с ними. В дальнейшем разговоре с лидом можно будет ссылаться на их мнение. Но менять процесс определенно стоит.
    Ответ написан
    Комментировать
  • Как сделать сортировку HTML объектов в зависимости от чисел внутри элемента?

    0xD34F
    @0xD34F Куратор тега JavaScript
    <button data-order="-1">От большего к меньшему</button>
    <button data-order="+1">От меньшего к большему</button>

    const wrapper = document.querySelector('.catalog-items');
    const buttons = document.querySelectorAll('[data-order]');
    
    buttons.forEach(n => n.addEventListener('click', onClick));
    
    function onClick({ target: t }) {
      const order = +t.dataset.order;
      sortChildren(wrapper, el => parseInt(el.innerText) * order);
      buttons.forEach(n => n.classList.toggle('active', n === t));
    }
    
    function sortChildren(parent, value) {
      parent.append(...Array
        .from(parent.children, n => [ n, value(n) ])
        .sort((a, b) => a[1] - b[1])
        .map(n => n[0])
      );
    }
    Ответ написан
    3 комментария
  • Требования к самописной CRM?

    Jeer
    @Jeer
    уверенный пользователь
    Аж жуть берет от таких заданий ) Покупка готового инструмента обычно дешевле, чем разработка с нуля. Особенно если разработка осуществляется одним человеком. Особенно если опыта мало. Особенно, если на поддержке будет тот же человек, что и на разработке ) безумие :) проект полетит в помойку, но у вас будет строчка в резюме по созданию проекта, можете обкатывать любые технологии за счет глупого работодателя.

    По делу без брюзжания:
    Писать под винду моветон - лицензии дорогие
    Вин формс зачем? - делайте веб апи с фронтом на вью/реакте/ангуляре. Нужна кроссплатформенность, чтобы хоть с телефона можно было зайти и нажать нужную кнопку в системе.
    Апи нужно, потому что будет много интеграций с другими системами, загрузка/выгрузка в 1с, не дай бог будете телефонию подключать
    Внутренняя сеть решается с помощью впн сервера.
    Помимо функциональных требований существуют еще технические, должен быть мониторинг, вы должны всегда знать сколько ресурсов потребляет ваш сервер, сколько данных занимает на дисках, логи и трейсы - гуглится по слову Observability, обычно не закладывается в смету, но к этим вопросам приходят рано или поздно
    Что еще, ну, по функционалу тут проще, открываете презентации в популярных CRMках, смотрите, что они могут, выписываете списком и идете к заказчику, чтобы он указал галочками, что будете делать, что не будете
    потом прикидываете по трудозатратам и озвучиваете сроки из которых можно понять примерную стоимость проекта. Часто одно маленькое предложение, типа того же "выгрузить данные в 1с" грозит несколькими десяткми часов работы, потому что другой отдел, с ними нужно договориться и сделать интеграцию. Или "должен быть отчет такой-то", а там как начнешь разбираться, еще 5 раз посовещаться сначала надо ))
    Ответ написан
    Комментировать
  • Как отследить изменения?

    oshliaer
    @oshliaer Куратор тега Google Sheets
    Google Products Expert
    Одним из основных способов является подписка на триггер изменений в Таблице, который реализуется в Google Apps Script.

    Вы можете построить свое решение на основе примера https://qna.habr.com/q/1207030#answer_2234340
    Ответ написан
    Комментировать
  • Вопроса нет, и все?

    ThunderCat
    @ThunderCat
    {PHP, MySql, HTML, JS, CSS} developer
    Uncaught SyntaxError: Unexpected token < in JSON at position 0
    Читаем. Переводим.
    Открываем инструменты разработчика, вкладку нетворк. Отправляем наш гениальный запрос - смотрим в неменее гениальный ответ от сервера, в котором наверняка что-то типа "ой-вей, ваш пхп код полный шлак, в котором ошибок больше чем на помойной кошке блох". Исправляем ошибки, и - о чудо! Все заработало!
    Ответ написан
    Комментировать
  • Как добавить условие в регулярное выражение?

    0xD34F
    @0xD34F Куратор тега Регулярные выражения
    ^(?!.*__)@[a-z][a-z\d_]{4,34}$
    Ответ написан
    1 комментарий
  • Почему мы имеем право решать уравнения методом замены переменной?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Ну, это просто подстановка. Если, как в моем примере, предположить, что z=x^2, то из-за равенства получается и x^2=z. А дальше можно каждый x^2 переписать как z, ведь они равны.

    Или это можно еще понимать как абстрактное мышление. Вот есть у вас уравнение на x. Вы можете заметить какое-то повторяющееся выражение. Оно имеет какое-то значение. Вот это значение можно обозначить новой буквой. Вот вы же можете буквой x обозначить "сколько у вас яблок". Вы точно также можете обозначить буквой z "сколько у вас яблок в квадрате".

    Это можно делать всегда, но в результате этого могут получиться лишние корни. Как например тут, если есть решения с отрицательными z, то никакой x ему не соответствует. Надо аккуратно проверять все значения z и искать соответсвующие им x.

    Кто это придумал, я хз. Наверно примерно тогда же, когда догадались вообще буквы в уравнения вставлять, там же и придумали вставлять их по мере надобности.
    Ответ написан
    1 комментарий