Задать вопрос
  • Как двигать блок по квадрату?

    0xD34F
    @0xD34F
    Как сделать, чтобы третье условие работало?

    Усилить первое условие так, чтобы оно не становилось истинным после того, как перестаёт быть истинным второе.

    Только вам это мало чем поможет - кривое условие не только первое, но и третье.
    А всего их должно быть четыре.

    const rectLeftTop = [ 50, 50 ];
    const rectSize = 450;
    const step = 15;
    let [ x, y ] = rectLeftTop;
    
    setInterval(() => {
      if (rectLeftTop[1] <= y && x === rectLeftTop[0]) {
        y = Math.min(y + step, rectLeftTop[1] + rectSize);
      }
    
      if (rectLeftTop[0] <= x && y === rectLeftTop[1] + rectSize) {
        x = Math.min(x + step, rectLeftTop[0] + rectSize);
      }
    
      if (rectLeftTop[1] < y && x === rectLeftTop[0] + rectSize) {
        y = Math.max(y - step, rectLeftTop[1]);
      }
    
      if (rectLeftTop[0] < x && y === rectLeftTop[1]) {
        x = Math.max(x - step, rectLeftTop[0]);
      }
    
      block.style.left = `${x}px`;
      block.style.top = `${y}px`;
    }, rectSize / step);

    https://jsfiddle.net/efzcpda7/

    Хотя есть вариант обойтись одним.

    const directions = [
      [  0, -1 ],
      [ -1,  0 ],
      [  0,  1 ],
      [  1,  0 ],
    ];
    let iDirection = 0;
    
    const coords = [ 50, 50 ];
    const step = 15;
    const rectSize = 450;
    const rect = [ [...coords], coords.map(n => n + rectSize) ];
    
    (function move() {
      const d = directions[iDirection].map(n => n * step);
      coords.forEach((n, i, a) => a[i] = Math.max(rect[0][i], Math.min(rect[1][i], n + d[i])));
    
      if (coords.every((n, i) => rect.some(m => m[i] === n))) {
        iDirection = (iDirection + 1) % directions.length;
      }
    
      block.style.left = `${coords[0]}px`;
      block.style.top = `${coords[1]}px`;
    
      requestAnimationFrame(move);
    })();

    https://jsfiddle.net/efzcpda7/1/

    Но вообще - никакие условия не нужны.

    Можно задать блоку transition, определить массив конечных координат и устанавливать следующие после достижения предыдущих (событие transitionend):

    .block {
      transition: all 750ms linear;
    }

    const positions = [
      [  50,  50 ],
      [  50, 500 ],
      [ 500, 500 ],
      [ 500,  50 ],
    ];
    let iPosition = -1;
    
    move();
    block.addEventListener('transitionend', move);
    setTimeout(move, 0);
    
    function move() {
      iPosition = (iPosition + 1) % positions.length;
      const [ x, y ] = positions[iPosition].map(n => `${n}px`);
      block.style.left = x;
      block.style.top = y;
    }

    https://jsfiddle.net/efzcpda7/2/

    Да и в целом, JS не нужен - перемещения блока можно описать в CSS.

    .block {
      animation: move 3s infinite linear;
    }
    
    @keyframes move {
      0%, 100% {
        left: 50px;
        top: 50px;
      }
      25% {
        left: 50px;
        top: 500px;
      }
      50% {
        left: 500px;
        top: 500px;
      }
      75% {
        left: 500px;
        top: 50px;
      }
    }

    https://jsfiddle.net/efzcpda7/3/

    Если подумать, то и стили тоже лишние - с задачей отлично справляется SVG.

    <svg viewBox="0 0 550 550" xmlns="http://www.w3.org/2000/svg" width="550" height="550">
      <rect width="50" height="50" fill="red">
        <animateMotion
          dur="3s"
          repeatCount="indefinite"
          path="M50,50 L50,500 L500,500 L500,50 L50,50 z"
        />
      </rect>
    </svg>

    https://jsfiddle.net/efzcpda7/4/
    Ответ написан
    Комментировать
  • Как сложить значения массива по условию?

    0xD34F
    @0xD34F
    $grouped = [];
    
    foreach ($items as $n) {
      $grouped[$n['type']] ??= [
        'type' => $n['type'],
        'typeAmount' => 0,
        'amount' => 0,
      ];
    
      $grouped[$n['type']]['typeAmount'] += $n['typeAmount'];
      $grouped[$n['type']]['amount'] += $n['amount'];
    }
    
    $grouped = array_values($grouped);
    Ответ написан
    Комментировать
  • Как в React Native Calendars от wix сделать начало недели с понедельника?

    0xD34F
    @0xD34F
    Неужели было так трудно заглянуть в документацию самостоятельно?
    Ответ написан
    Комментировать
  • Почему не передаются данные через V-model?

    0xD34F
    @0xD34F Куратор тега Vue.js
    V-model="filterPriceFrom"

    V-model="filterPriceTo"

    props:['FilterPriceFrom', 'FilterPriceTo', "FilterCategoryId"],

    Во-первых - серьёзно? Не видите разницы между большими и маленькими буквами?

    Во-вторых, если бы вы составили себе труд открыть документацию, и прочесть, что там написано, то знали бы, что использовать v-model совместно с входными параметрами особого смысла нет. Потому что

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

    Вот вам и ответ на ваш вопрос: данные не передаются потому, что не могут передаваться избранным вами способом, так уж устроен vue.

    Теперь, что делать.

    Внутри компонента заменяете все v-model="параметр" на

    :value="параметр" @input="$emit('update:параметр', $event.target.value)"

    Снаружи - привязываете значения с использованием модификатора sync, если используете вторую версию vue.
    Или, через v-model с указанием имени параметра, в случае vue 3.
    Ответ написан
    Комментировать
  • Как добавить или отнять 1 по клику на кнопки?

    0xD34F
    @0xD34F Куратор тега JavaScript
    let count = 0;
    const countEl = document.querySelector('.text');
    const buttons = [...document.querySelectorAll('.click')];
    const onClick = e => updateCount(e.target.classList.toggle('clicked') ? 1 : -1);
    const updateCount = change => countEl.innerText = count += change;
    buttons.forEach(n => n.addEventListener('click', onClick));
    updateCount(buttons.reduce((acc, n) => acc + n.classList.contains('clicked'), 0));
    Ответ написан
    1 комментарий
  • Как найти произведения элементов массива и сумм столбцов матрицы?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const result = arr.map((n, i) => n * matrix.reduce((acc, row) => acc + row[i], 0));

    или

    const result = Array(arr.length).fill(0);
    
    for (const row of matrix) {
      for (const [ i, n ] of row.entries()) {
        result[i] += n * arr[i];
      }
    }
    Ответ написан
    Комментировать
  • Как вывести результат "на лету"?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Вместо click'а у кнопки обрабатывайте input у формы:

    - document.querySelector('.calculate').addEventListener('click', function () {
    + document.querySelector('form').addEventListener('input', function () {

    UPD. Сам обработчик - как-то не круто всё выглядит:

    let select = document.querySelector('select').selectedIndex;
    let selectValue = select + 1; // selectedIndex считается с 0, поэтому +1

    Зачем индекс? У option'ов указаны value, так что можно смотреть значение select'а.

    let dateStart = document.querySelector('.start_date').value;
    let dateEnd = document.querySelector('.end_date').value;

    Ради получения значений нет необходимости искать элементы - ссылки на них есть в свойстве elements формы, в качестве ключа выступают значения атрибутов id и name. Также можно создать FormData, и доставать нужное уже оттуда.

    let out_3 = document.querySelector('.out_3');

    Аналогично - искать элемент не надо, ссылка на output внутри него есть в elements формы.

    for (let i = dateStart; i <= dateEnd; i = i + 24 * 60 * 60 * 1000) {

    Цикл не нужен. Вычитаем одну дату из другой, делим на количество миллисекунд в дне, получаем таким образом количество дней.

    Исправляем:

    document.querySelector('form').addEventListener('input', function() {
      const { elements } = this;
      const data = new FormData(this);
      const keys = [ 'enterDate', 'outDate', 'countRooms', 'prepayment' ];
    
      const basePayment = 2000;
      const [ enter, out, rooms, prepayment ] = keys.map(k => data.get(k) /* или elements[k].value */);
      const days = enter && out && enter < out
        ? (new Date(out) - new Date(enter)) / (24 * 60 * 60 * 1000)
        : 0;
    
      elements.payment.textContent = `${basePayment * days * rooms - prepayment} р`;
    });
    Ответ написан
    6 комментариев
  • Как избавиться от двойных кавычек, выводя текущее количество введенных символов?

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

    .min(6, passwordMessage) ---> .min(6, () => passwordMessage.value)
    Ответ написан
    5 комментариев
  • Почему нет двусторонний привязки v-model?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Потому что объект не реактивный. Надо в reactive завернуть.
    Ответ написан
    1 комментарий
  • Как рекурсивно обойти объект и выполнить get_object_vars?

    0xD34F
    @0xD34F
    public function expose() {
      return array_map(fn($n) => $n instanceof Text ? $n->expose() : $n, get_object_vars($this));
    }
    Ответ написан
    1 комментарий
  • Как передать в filter массив аргументов?

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

    data: () => ({
      items: [ ... ],
      filters: [
        item => item.status === 'hello, world!!',
        item => item.price > 666,
        item => item.text.includes('fuck the world'),
      ],
    }),
    computed: {
      filteredItems() {
        return this.filters.reduce((items, filterFn) => items.filter(filterFn), this.items);
      },
    },
    Ответ написан
    Комментировать
  • Как, имея строку с ключами, получить массив значений из вложенных объектов?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const result = Array
      .from(letter, n => soundParts[Number.isNaN(+n) ? 'letter' : 'number'][n])
      .filter(Boolean);

    или

    const result = Object
      .entries(Object.assign({}, ...Object.values(soundParts)))
      .reduce((acc, n) => (letter.includes(n[0]) && acc.push(n[1]), acc), []);
    Ответ написан
  • Как сортировать такой массив?

    0xD34F
    @0xD34F
    usort($lots, function($a, $b) use($currencyLists) {
      $ia = array_search($a['currency'], $currencyLists);
      $ib = array_search($b['currency'], $currencyLists);
      $t = $ia - $ib;
    
      return $t ? $t : ($a['lotSize'] - $b['lotSize']);
    });
    Ответ написан
  • Как получить подстроку в данном случае?

    0xD34F
    @0xD34F Куратор тега JavaScript
    str.match(/\]\s*(.+?)\s*#/)?.[1] ?? '< unknown >'
    Ответ написан
    Комментировать
  • Как обновить данные в vuex state?

    0xD34F
    @0xD34F Куратор тега Vue.js
    data(){
      return{
        Item: {
          ...

    v-model="item.name"

    Ну и как там у вас имя свойства начинается - с большой буквы или маленькой? Вы определитесь.

    ADD_TO_PRODUCTS({commit}, item){
        commit('SET_PRODUCT_TO_STATE', item)
    },

    methods:{
      ...mapActions([
          'ADD_TO_PRODUCTS',
      ]),

    @click="ADD_TO_PRODUCTS"

    В экшене ожидается параметр, но вы ничего не передаёте. Точнее, не передаёте в явном виде - передаётся объект события клика. А надо item (Item?).

    После того, как исправите косяки выше, у вас, вероятно, вылезет ещё один. С ним разбираться будете здесь.
    Ответ написан
    Комментировать
  • Как освоить vue.js?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Читая документацию - сложно полностью понять её.

    Это потому что вы js не знаете. Если знать язык - понимать в документации нечего, всё становится ясно на ходу.

    Может ли это означать, что frontend не мое

    Может.

    либо это стандартная ситуация и стоить продолжать?

    Стандартная. Для не знающих js.

    Освоение фреймворков без знания языка - прямая дорога к превращению в говнокодера. Который никому на рынке труда конкуренции не составит. Если ваша цель такая - конечно продолжайте.

    Короче, хотите освоить vue - освойте js.
    Ответ написан
    Комментировать
  • Как сгруппировать расположенные последовательно элементы массива с одинаковыми значениями одного из свойств?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const groupAdjacent = (arr, newGroup) =>
      arr.reduce((acc, n, i, a) => (
        (!i || newGroup(n, a[~-i])) && acc.push([]),
        acc.at(-1).push(n),
        acc
      ), []);
    
    
    const result = groupAdjacent(arr, (c, p) => c.name !== p.name);
    Ответ написан
  • Как сделать, чтобы выбранная дата была подсвечена в календаре?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Оставить в datepicker'e просто дату, а дату с временем оформить как вычисляемое свойство.
    Ответ написан
    Комментировать
  • Почему в корзине считается только последний discount?

    0xD34F
    @0xD34F Куратор тега JavaScript
    for (let i in goods) {
      if (discounts.length === 0) {
        count = goods[i].value * goods[i].amount;
      }
      for (let j in discounts) {
        if (goods[i].name === discounts[j].name) {
          count =
            (goods[i].value - goods[i].value * discounts[j].discount) *
            goods[i].amount;
        } else {
          count = goods[i].value * goods[i].amount;
        }
      }
      sum += count;
      console.log(count, goods[i].name);
    }

    Зачем на каждой итерации цикла, ищущего скидку, пересчитывать цену? Предположим, нашли скидку для текущего товара, что дальше? Дальше, на следующей итерации, цена будет рассчитана заново, но уже без скидки - ведь объект скидки будет другим, будет соответствовать другому товару. Исключение - если скидка найдена на последней итерации.

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

    for (const n of goods) {
      let s = n.value * n.amount;
      for (const m of discounts) {
        if (n.name === m.name) {
          s *= 1 - m.discount;
          break;
        }
      }
      sum += s;
    }

    Возможно есть лучший способ для решения такой задачи.

    function totalCost(goods, discounts) {
      discounts = Object.fromEntries(discounts.map(n => [ n.name, 1 - parseFloat(n.discount) / 100 ]));
      return goods.reduce((acc, n) => acc + n.value * n.amount * (discounts[n.name] ?? 1), 0);
    }
    Ответ написан
    3 комментария