Задать вопрос
  • Как при нажатии на блок с id="какой-то текст" добавить стили к блоку, у которого class="такой же текст"?

    0xD34F
    @0xD34F Куратор тега JavaScript
    По каким элементам надо кликать и где они находятся:

    const container = document.querySelector('ul');
    const itemSelector = 'li';

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

    const randomStyles = () => ({
      'background-color': `#${(Math.random() * 0xFFFFFF | 0).toString(16).padStart(6, 0)}`,
      'padding-left': `${Math.random() * 100 | 0}px`,
    });

    .active {
      border: 3px dashed blue;
    }

    const update = (el, styles) => (
      Object.assign(el.style, styles),
      el.classList.toggle('active')
    );

    Ловить клики можно непосредственно на интересующих нас элементах:

    container.querySelectorAll(itemSelector).forEach(function(n) {
      n.addEventListener('click', this);
    }, function() {
      document.querySelectorAll(`.${this.id}`).forEach(function(n) {
        update(n, this);
      }, randomStyles());
    });

    Или добавлять обработчик события один раз - их общему предку:

    container.addEventListener('click', ({ target: t }) => {
      if ((t = t.closest(itemSelector)) && container.contains(t)) {
        const styles = randomStyles();
        for (const n of document.getElementsByClassName(t.getAttribute('id'))) {
          update(n, styles);
        }
      }
    });
    Ответ написан
    1 комментарий
  • Как запускать воспроизведение аудио только тогда, когда предыдущий звук был проигран полностью?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Сделайте очередь:

    const audio = new Audio();
    const queue = [];
    
    audio.onended = function() {
      if (queue.length) {
        audio.src = queue.shift();
        audio.play();
      }
    };
    
    function play(srcArray) {
      queue.push(...srcArray);
    
      if (audio.paused) {
        audio.onended();
      }
    }
    
    play([ '1.mp3', '2.mp3', '3.mp3' ]);
    Ответ написан
    2 комментария
  • Почему строка не меняется?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Нельзя строки в JS менять, строки неизменны, хотите строку с другим значением - создавайте новую.

    Ну и этот поиск индексов... Ерунда какая-то. Правильно так - сделать объект вида { 'символ': 'на что его надо заменить' }:

    const combine = (keys, values) =>
      keys.reduce((acc, n, i) => (acc[n] = values[i], acc), {});
    
    const enToRu = combine(trans[0], trans[1]);
    const ruToEn = combine(trans[1], trans[0]);

    Тогда "перевод" сведётся к чтению свойства объекта:

    const translate = (str, charset) => Array
      .from(str, n => charset[n] || n)
      .join('');
    
    translate(';jgf', enToRu) // 'жопа'
    translate('руддщб цщкдв!!', ruToEn) // 'hello, world!!'
    Ответ написан
    Комментировать
  • Почему атрибут selected не срабатывает?

    0xD34F
    @0xD34F
    Неправильно задаёте начальное значение. Вырезаем [selected], а в методе createSubForm вместо массива всех возможных значений в конструктор FormControl передаём одно. Типа так.
    Ответ написан
    Комментировать
  • Как отследить изменение свойства объекта?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Вешаю на него сеттер...

    Не-а, не на него. Созданное ранее свойство вы перетёрли вызовом defineProperty, кроме того, вы не определяете геттер - отсюда и undefined.

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

    function test(m) {
      let money = m;
    
      Object.defineProperty(this, 'money', {
        get() {
          return money;
        },
        set(val) {
          alert(`Значение свойства money меняется с ${money} на ${val}`);
          money = val;
        },
      });
    }

    Или можно воспользоваться Proxy:

    function test(m) {
      this.money = m;
    
      return new Proxy(this, {
        set(target, prop, val) {
          alert(`Значение свойства ${prop} меняется с ${target[prop]} на ${val}`);
          target[prop] = val;
          return true;
        },
      });
    }
    Ответ написан
    4 комментария
  • Можно ли вызывать хук из кода?

    0xD34F
    @0xD34F
    Есть ли причины так не делать?

    Уместнее спросить - есть ли причины так делать? Мне таковые не известны. Если хотите повторно выполнить какой-то код из хука в произвольный момент - вынесите его в отдельный метод, и вызывайте этот метод.

    А то, что вы показали в качестве примера, при назначении рейтинга дёргаете ngOnInit - это что же, компонент повторно инициализируется при изменении рейтинга? Нет, это не правда. Зачем же тогда вводить в заблуждение себя и тех людей, которые будут читать ваш код? Не просто же так переменным, методам, классам и т.д. дают человекопонятные имена, описывающие их назначение.
    Ответ написан
    1 комментарий
  • Пропал элемент в html после указания родителя в объекте el: '#app'?

    0xD34F
    @0xD34F Куратор тега Vue.js
    @click="pushNumbars() reader.push(*)"

    Вот из-за подобных художеств шаблон и не рендерится.

    Между выражениями должна быть точка с запятой, и ещё кавычек не хватает - попробуйте догадаться где. Ну а по-хорошему - вместо этого позорища надо бы метод сделать, так и ошибки будут очевиднее.
    Ответ написан
    3 комментария
  • Как повесить обработчик на несколько элементов?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Вместо img класс лучше переключать у article - максимально дальних не общих предков картинок. Если вдруг захотите при кликах на кнопки стилизовать ещё что-то помимо картинок, или измените взаимное расположение элементов, то не придётся переписывать js-код. Стили, конечно, придётся немного поправить, вместо .active будет .active img.

    const container = document.querySelector('.container');
    const itemSelector = 'article';
    const buttonSelector = `${itemSelector} .btn`;
    const activeClass = 'active';

    Делегирование, назначаем обработчик один раз:

    container.addEventListener('click', e => {
      const button = e.target.closest(buttonSelector);
      if (button) {
        button.closest(itemSelector).classList.toggle(activeClass);
      }
    });

    Или каждой кнопке индивидуально:

    container.querySelectorAll(buttonSelector).forEach(function(n) {
      n.addEventListener('click', this);
    }, e => e.currentTarget.closest(itemSelector).classList.toggle(activeClass));
    Ответ написан
    Комментировать
  • Как исправить мерцание блока при наведении?

    0xD34F
    @0xD34F Куратор тега CSS
    Достаточно добавить :hover и самой кнопке тоже:

    .btn:hover {
      display: block;
    }
    Ответ написан
  • Как собрать слово из букв?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Будем вставлять вместо текста элементы, каждый из которых содержит по одной букве.

    Куда: <div id="container"></div>.

    Как анимировать появление элементов:

    #container span {
      display: inline-block;
      white-space: pre;
      font-size: 40px;
      animation: span .2s ease-out;
    }
    @keyframes span {
      from {
        transform: translateX(500px);
        opacity: 0;
      }
      to {
        transform: translateX(0);
        opacity: 1;
      }
    }

    Как перебирать с задержкой массивоподобный объект:

    const forEachWithDelay = (arr, delay, callback) =>
      (function next(i) {
        if (i < arr.length) {
          setTimeout(() => (callback(arr[i]), next(-~i)), delay);
        }
      })(0);
    
    // или
    
    async function forEachWithDelay(arr, delay, callback) {
      for (let i = 0; i < arr.length; i++) {
        await new Promise(r => setTimeout(r, delay));
        callback(arr[i]);
      }
    }

    Вот так всё просто получается:

    forEachWithDelay(
      'hello, world!!',
      69,
      n => document
        .querySelector('#container')
        .insertAdjacentHTML('beforeend', `<span>${n}</span>`)
    );
    
    // или
    
    forEachWithDelay(
      'fuck the world',
      187,
      function(n) {
        this.appendChild(document.createElement('span'));
        this.lastChild.textContent = n;
      }.bind(document.getElementById('container'))
    );
    Ответ написан
    2 комментария
  • Как создать новый объект в VueJS?

    0xD34F
    @0xD34F Куратор тега Vue.js
    // хочу добавить в list_appointments_drugs новый объект drug, но получается что добавляю модель
    this.list_appointments_drugs.unshift(this.drug)

    Надо делать копию объекта:

    this.list_appointments_drugs.unshift({ ...this.drug })

    А вообще, раз уж сказали "модель"... Добавьте в компонент свойство - объект, который будет содержать дефолтные значения. И копируйте его в drug, когда необходимо начать редактирование нового объекта (т.е., при создании экземпляра компонента и после добавления в массив):

    data: () => ({
      drug: null,
      defaultDrugData: {
        ...
      },
      ...
    }),
    created() {
      this.resetDrug();
    },
    methods: {
      addDrug() {
        this.list_appointments_drugs.unshift(this.drug);
        this.resetDrug();
      },
      resetDrug() {
        this.drug = { ...this.defaultDrugData };
      },
      ...
    },
    Ответ написан
    Комментировать
  • Как стилизовать чекбоксы созданные в цикле v-for не нарушив их работу?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Должно быть так?

    Во-первых - v-for должен быть у элемента li, а не ul. Во-вторых - чтобы динамически назначать значения атрибутов (у вас это id и for), надо всё-таки использовать v-bind, а не просто вписывать строку, совпадающую с именем индекса из v-for.
    Ответ написан
    1 комментарий
  • Почему не работает lodash debounce в vue?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Этот код не работает. Совсем.

    Разумеется, всё работает. Между "не работает" и "работает не так, как бы мне хотелось" существенная разница. Допускаю, что для вас она трудноуловима, но она всё-таки есть. Попытайтесь её осознать.

    test: function() {
        _.debounce(function() {
                console.log('test222');
            }, 500);
    }

    В debounce должен был быть обёрнут сам метод:

    test: _.debounce(function() {
      console.log('test222');
    }, 500)
    Ответ написан
    2 комментария
  • Как удалить все спецсимволы из строки?

    0xD34F
    @0xD34F
    str.replaceAll("[^\\w ]", "")
    Ответ написан
    Комментировать
  • Как объединить уникальные значения в массиве объектов?

    0xD34F
    @0xD34F
    - var data = [ { "title": "Артем" }, { "title": "Аня" }, { "title": "Виталик" }, { "title": "Гена" }, { "title": "Дима" }, { "title": "Вася" }, { "title": "Гриша" }, { "title": "Андрей" } ]
    
    mixin sort(data)
      - var grouped = data.reduce((acc, n) => {
      -   var name = n.title[0];
      -   acc[name] = acc[name] || [];
      -   acc[name].push(n);
      -   return acc;
      - }, {});
      each group, name in grouped
        div
          h3= name
          each obj in group
            div= obj.title
    
    div
      +sort(data)
    Ответ написан
    1 комментарий
  • Почему происходит два клика?

    0xD34F
    @0xD34F
    Из-за элемента label - при клике по нему инициируется событие клика на связанном элементе. Вместо клика у label'а обрабатывайте change у input'а.
    Ответ написан
  • Как отсортировать массив по дате?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Сортируем существующий массив с помощью moment.js:

    arr.sort((a, b) => moment(b.date, 'DD.MM.YY') - moment(a.date, 'DD.MM.YY'));

    Собираем отсортированный новый без помощи сторонних библиотек:

    const newArr = arr
      .map(n => [ n, +n.date.split('.').reverse().join('') ])
      .sort((a, b) => b[1] - a[1])
      .map(n => n[0]);
    Ответ написан
  • Почему возникает ошибка "FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory"?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Ну, память кончилась. Потому что... так, представьте, что обрабатывается последний элемент вашего массива, и доходит очередь до вот этого:

    array[i+1]=true;

    Размер вашего массива увеличится, последний элемент перестанет быть последним, и цикл, вместо того, чтобы завершится, уйдёт на следующую итерацию. А там опять array[i+1]=true; (или array[i+1]=false;, в зависимости от условия) - массив снова увеличился, опять цикл не завершился, ну и так далее - массив будет жиреть до тех пор, пока станет невозможно выделить ему ещё памяти.

    UPD. Я так понял, речь об этой задаче.
    Решается вот прям совсем просто.

    Конечно, при использовании методов массива:

    const ops = {
      OR: arr => arr.some(Boolean),
      AND: arr => arr.every(Boolean),
      XOR: arr => !!arr.reduce((p, c) => p ^ c, 0),
    };
    
    const logicalCalc = (arr, op) => ops[op](arr);

    В противном случае код может серьёзно опухнуть:

    const ops = {
      OR(arr) {
        for (const n of arr) if (n) {
          return true;
        }
        return false;
      },
      AND(arr) {
        for (const n of arr) if (!n) {
          return false;
        }
        return true;
      },
      XOR(arr) {
        let result = false;
        for (const n of arr) if (n) {
          result = !result;
        }
        return result;
      },
    };

    Ответ написан
    Комментировать