Задать вопрос
  • Как отмечать определенные checkbox при клике по ссылке?

    0xD34F
    @0xD34F Куратор тега JavaScript
    document.addEventListener('click', function(e) {
      const el = document.getElementById(e.target.dataset.id);
      if (el) {
        el.checked = !el.checked;
      }
    });

    или

    const buttons = document.querySelectorAll('[data-id]');
    const onClick = e => checkboxes[e.target.dataset.id].checked ^= 1;
    const checkboxes = Array
      .from(buttons, n => n.dataset.id)
      .reduce((acc, n) => (acc[n] = document.querySelector(`#${n}`), acc), {});
    
    buttons.forEach(n => n.addEventListener('click', onClick));
    Ответ написан
    Комментировать
  • Можно ли строку перевести в объект?

    0xD34F
    @0xD34F Куратор тега JavaScript
    $('.tab__list').on('click', '.tab__item', function() {
      const
        $this = $(this),
        { label, ...attrs } = text[$this.data('tab')];
    
      $this.siblings().removeClass('tab__item--active');
      $this.addClass('tab__item--active');
      $('#formField').attr(attrs);
      $('#formLabel').text(label);
    });
    Ответ написан
    6 комментариев
  • Как воспользоваться функцией, переданной в props?

    0xD34F
    @0xD34F Куратор тега React
    onNoteAdd = {this.handleNoteAdd.bind(this)}

    this.props.onNodeAdd(newNote)

    Так как всё-таки правильно - Note или Node? Вы уж разберитесь.

    UPD. А что так многословно?

    Можно и покороче, вместо

    const newNote = {
      title: this.state.title,
      text: this.state.text,
      color: this.state.color
    };
    
    this.props.onNodeAdd(newNote);

    пусть будет this.props.onNoteAdd({ ...this.state });.

    Также нет необходимости в двух методах для обновления стейта, можно сделать общий, а какое свойство должно быть обновлено - указывать через атрибут name:

    onChange = ({ target: { name, value } }) => {
      this.setState({ [name]: value });
    }

    <input
      name="title"
      onChange={this.onChange}
      ...
    />
    <textarea
      name="text"
      onChange={this.onChange}
      ...
    />

    Ответ написан
  • Как на jQuery поменять стиль у label с активным input radio?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Вместо

    .red{border:3px solid red;;}
    .green{border:3px solid red;;}

    пусть будет

    .items-list-item-colors label {
      border: 3px solid red;
    }
    
    .items-list-item-colors label.active {
      border-color: green;
    }

    Соответственно, из разметки class="red" вырезаете.

    Где, кому и какой класс будем переключать:

    const containerSelector = '.items-list-item-colors';
    const itemSelector = 'label';
    const activeClass = 'active';

    Такие есть варианты:

    $(containerSelector).change(function() {
      $(itemSelector, this)
        .removeClass(activeClass)
        .has(':checked')
        .addClass(activeClass);
    });
    
    // или
    
    document.querySelectorAll(containerSelector).forEach(n => {
      n.addEventListener('change', onChange);
    });
    
    function onChange({ target: t }) {
      this.querySelectorAll(itemSelector).forEach(n => {
        n.classList.toggle(activeClass, n.contains(t));
      });
    }
    
    // или
    
    document.addEventListener('change', e => {
      const item = e.target.closest(itemSelector);
      if (item) {
        item.closest(containerSelector).querySelectorAll(itemSelector).forEach(n => {
          n.classList.toggle('active', n === item);
        });
      }
    });
    Ответ написан
    Комментировать
  • Как удалить копии добавленного блока?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Добавляете блок в случае, если его нет:

    const $inner = $('.inner');
    if (!$inner.find('.butt_back').length) {
      $inner.append(...);
    }


    Или, если вам действительно надо удалять предыдущие:

    $('.inner')
      .find('.butt_back').remove()
      .end()
      .append(...);
    Ответ написан
    Комментировать
  • Почему не работает клонирование canvas?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Что не так ?

    Да всё не так.

    Что за clone? - у DOM-узлов такого метода нет. Есть cloneNode. Или используйте jquery (судя по тому, что контекст вы пытаетесь получить у clone[0], так и предполагалось), там clone есть: $(canvas).clone().

    Копировать содержимое оригинала вы пытаетесь до того, как оно вообще будет загружено. Выполняйте копирование в onload.

    Копируете непонятно откуда:

    canvas = document.getElementById('myCanvas');
    <...>
    drawImage(canvas[0],

    Опять же - либо canvas = $('#myCanvas'), либо drawImage(canvas,.

    UPD. Должно было быть так?
    Ответ написан
    3 комментария
  • Как запустить функцию только один раз?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Удаляйте обработчик после того, как он выполнил нужное действие:

    $(window).scroll(function onScroll() {
      const $this = $(this);
      if ($this.scrollTop() > scrollToElem) {
        $('#popup-item').addClass('popup-open');
        $this.off('scroll', onScroll);
      }
    });
    Ответ написан
    Комментировать
  • Как правильно отрендерить данные на react с разрывом?

    0xD34F
    @0xD34F Куратор тега React
    Сделайте отдельный компонент для вывода данных и создайте два его экземпляра: первому передаёте первые три элемента, а второму - все оставшиеся. Как-то так:

    const DataList = ({ data }) => (
      <div>
        {data.map((item) => (
          <div key={item.id}>
            {item.title}
            {item.round.map((r) => <div key={r.id}>{r.total}</div>)}
          </div>
        ))}
      </div>
    );

    <DataList data={props.data.slice(0, 3)} />
    <Separator />
    <DataList data={props.data.slice(3)} />
    Ответ написан
    Комментировать
  • Как добавить слепок текущего состояния?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Проблема в реактивности, при изменении текстов в инпуте, меняются старые записанные обьекты

    Ну да, ну да. Вот так и получается: JS не учи, фреймворки используй.

    Сохраняйте копию вместо оригинала. Типа так:

    state.filter_list.push({ ...state.filter })

    Это если объект плоский. Если есть вложенность, используйте _.cloneDeep, например (или какой-либо иной аналог, или сами можете попробовать реализовать рекурсивную функцию копирования).
    Ответ написан
    3 комментария
  • Как остановить setInterval из другой функции?

    0xD34F
    @0xD34F Куратор тега JavaScript
    document.addEventListener('mouseover', ({ target: t }) => {
      if (t.classList.contains('pic') && !t.dataset.interval) {
        t.dataset.interval = bgRotate(t);
      }
    });
    
    document.addEventListener('mouseout', ({ target: t }) => {
      const { interval } = t.dataset;
      if (interval) {
        clearInterval(interval);
        delete t.dataset.interval;
      }
    });

    или

    document.querySelectorAll('.pic').forEach(n => {
      n.addEventListener('mouseenter', onHover);
      n.addEventListener('mouseleave', onHover);
    });
    
    function onHover({ type, target: t }) {
      const d = t.dataset;
      if (type === 'mouseenter' && !d.interval) {
        d.interval = bgRotate(t);
      } else if (type === 'mouseleave') {
        clearInterval(d.interval);
        delete d.interval;
      }
    }
    Ответ написан
  • Как сделать смену картинок на jquery с помощью радиокнопок?

    0xD34F
    @0xD34F Куратор тега JavaScript
    .images_box a {
      display: none;
    }
    
    .images_box a.active {
      display: inline;
    }

    const containerSelector = '.items-list-item-wrapper';
    const buttonSelector = '.items-list-item-colors input';
    const contentSelector = '.images_box a';
    const activeClass = 'active';
    
    
    // jquery, как вы и хотели
    $(containerSelector).on('change', buttonSelector, function(e) {
      $(contentSelector, e.delegateTarget)
        .removeClass(activeClass)
        .eq($(buttonSelector, e.delegateTarget).index(this))
        .addClass(activeClass);
    }).each((i, n) => $(buttonSelector, n).first().click());
    
    // или, к чёрту jquery
    document.querySelectorAll(containerSelector).forEach(n => {
      n.addEventListener('change', onChange);
      n.querySelector(buttonSelector).click();
    });
    
    function onChange({ target: t }) {
      if (t.matches(buttonSelector)) {
        const buttons = this.querySelectorAll(buttonSelector);
        const index = Array.prototype.indexOf.call(buttons, t);
        this.querySelectorAll(contentSelector).forEach((n, i) => {
          n.classList.toggle(activeClass, i === index);
        });
      }
    }
    Ответ написан
    Комментировать
  • Как скрыть блок при повторном нажатии на javascript?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Как заставить работать по-быстрому:
    function navFunction(id) {
      for (const n of document.querySelectorAll('.dropdown2-content')) {
        n.classList[n.id === id ? 'toggle' : 'remove']('show');
      }
    }

    Но вообще, тут многое можно изменить:

    Разметка - вырезать инлайновые обработчики клика и атрибуты id.

    Стили - будем плясать от корневых элементов (так удобнее; кроме того, если в будущем захотите стилизовать в "открытом" дропдауне что-то кроме контента, то не будет необходимости добавлять этим элементам классы, и, соответственно, не придётся переписывать код):

    .dropdown2 .dropdown2-content {
      display: none;
    }
    
    .dropdown2.show .dropdown2-content {
      display: block;
    }

    Код - вместо id будет смотреть на взаимное расположение элементов (переключаем класс у предка нажатой кнопки, у остальных удаляем):

    const containerSelector = '.dropdown2';
    const buttonSelector = `${containerSelector} .dropbtn2`;
    const activeClass = 'show';
    
    
    // делегирование, назначаем обработчик клика один раз для всех кнопок
    document.addEventListener('click', e => {
      const button = e.target.closest(buttonSelector);
      if (button) {
        document.querySelectorAll(containerSelector).forEach(function(n) {
          n.classList[n === this ? 'toggle' : 'remove'](activeClass);
        }, button.closest(containerSelector));
      }
    });
    
    // или, назначаем обработчик клика каждой кнопке индивидуально
    const onClick = function({ currentTarget: t }) {
      this.forEach((n, i) => n.classList[n.contains(t) ? 'toggle' : 'remove'](activeClass));
    }.bind(document.querySelectorAll(containerSelector));
    
    document.querySelectorAll(buttonSelector).forEach(n => {
      n.addEventListener('click', onClick);
    });
    Ответ написан
    Комментировать
  • Как создать группу радио кнопок?

    0xD34F
    @0xD34F Куратор тега React
    const RadioGroup = props => (
      <div>
        {props.items.map(n => (
          <label className={`radio ${n.val == props.value ? 'selected' : ''}`}>
            <input 
              type="radio"
              name={props.name}
              value={n.val}
              checked={n.val === props.value}
              onChange={props.onChange}
            />
            <img src={n.img} />
          </label>
        ))}
      </div>
    );

    https://jsfiddle.net/jt2ybfrq/
    Ответ написан
  • Почему на другой странице снова хочет пароль?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Потому что в sessionStorage хранятся строки. Т.е., реально сравниваются "true" и true.
    Ответ написан
    1 комментарий
  • Как сократить код используя цикл?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const inputSelector = '#icons_care';
    const checkboxSelector = '.check_care';
    const checkboxCheckedSelector = `${checkboxSelector}:checked`;
    const dataAttr = 'icon';
    const separator = ', ';

    $(document).on('change', checkboxSelector, () => {
      $(inputSelector).val($(checkboxCheckedSelector)
        .get()
        .map(n => $(n).data(dataAttr))
        .join(separator)
      );
    });
    
    // или
    
    document.addEventListener('change', e => {
      if (e.target.matches(checkboxSelector)) {
        const input = document.querySelector(inputSelector);
        const cb = document.querySelectorAll(checkboxCheckedSelector);
        input.value = Array.from(cb, n => n.dataset[dataAttr]).join(separator);
      }
    });
    Ответ написан
    3 комментария
  • Как исправить "You are using the runtime-only build of Vue where the template compiler is not available"?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Читаем документацию внимательнее.
    Ответ написан
    Комментировать
  • Как отображать дополнительный контент только в одном из экземпляров вложенного компонента?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Делаете у компонента параметр, отвечающий за раскрытость списка. При необходимости список открыть делаете emit. В родителе по событию устанавливаете индекс открытого компонента (он же и используется при передаче параметра открытости списка - проверяете, что равен индексу текущего экземпляра). Всё.
    Ответ написан
    Комментировать
  • Как удалить один маркер с карты?

    0xD34F
    @0xD34F Куратор тега Vue.js
    У вас маркеры дублируются - вы их добавляете по событию places_changed и повторно при построении polyline. Так что один вы удалили, а другой в том же месте (другие - дублируются многократно) остался.

    Что конкретно следует предпринять:

    1. Сделайте infowindow свойством компонента. Инициализируйте его там же где и саму карту.
    2. Перенесите назначение обработчика клика маркера из updateMap в обработчик places_changed, туда, где маркер создаётся впервые. Должно получится как-то так:

      const marker = new google.maps.Marker({
        map: this.map,
        title: place.name,
        position: place.geometry.location,
      });
      google.maps.event.addListener(marker, 'click', () => {
        this.infowindow.setContent(marker.title);
        this.infowindow.open(this.map, marker);
      });
      this.markers.push(marker);

    3. Сам метод updateMap должен сильно сократиться в размерах (да и имя ему сменить не помешает - на updatePolyline, например):

      updateMap() {
        if (this.polyline) {
          this.polyline.setMap(null);
        }
      
        this.polyline = new google.maps.Polyline({
          path: this.markers.map(n => n.getPosition()),
          geodesic: true,
          strokeColor: '#FF0000',
          strokeOpacity: 1.0,
          strokeWeight: 2,
          map: this.map,
        });
      },

    4. Что касается работы с элементами DOM-дерева:

      document.getElementById('map')
      <...>
      document.getElementById('inputPlace')

      Так дела не делаются. Стоит переписать с использованием ref.
    Ответ написан
    1 комментарий