Не учитывать клик, при выделении

380
25 ноября 2017, 11:56

Обработчик висит на элементе main. При клике по элементам внутри main, если элемент (цель клика) является потомком блока message, к соответствующему блоку message добавляется/удаляется класс checked.

Таким образом можно помечать сообщения, например для удаления.

Но вот в чем проблема: если я выделяю текст сообщения, то это считается за клик и сообщение выделяется. Я хочу чтобы при выделении текста в блоке message или его потомках (например body) блок message не обособлялся классом checked.

То есть если я кликаю по любому содержимому блока message, то блок message выделяется (классом), а если я выделяю текст в блоке message, то ничего происходить не должно.

function hasClass(element, cls) { 
  return (' ' + element.className + ' ').indexOf(' ' + cls + ' ') > -1; 
} 
 
document.querySelector('.main').addEventListener('click', function(e) { 
  var found = false; 
  for (var i = 0; i < e.path.length; i++) { 
    var elm = e.path[i]; 
    if (hasClass(elm, 'message')) { 
      found = true; 
      break; 
    } 
  } 
 
  if (!found) { 
    return; 
  } 
 
  if (hasClass(elm, 'checked')) { 
    elm.classList.remove('checked'); 
  } else { 
    elm.classList.add('checked'); 
  } 
 
});
.message { 
  background: yellow; 
} 
 
.checked { 
  background: red; 
}
<div class="main"> 
  <div class="message"> 
    <div class="body">Lorem ipsum, qwerty! Если текст выделен - цвет не должен переключиться</div> 
  </div> 
</div>

JsFiddle

Answer 1

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

Определить это можно с помощью свойства isCollapsed объекта Selection, который возвращает функция getSelection()

Например:

function hasClass(element, cls) { 
  return (' ' + element.className + ' ').indexOf(' ' + cls + ' ') > -1; 
} 
 
document.querySelector('.main').addEventListener('click', function(e) { 
  if (!getSelection().isCollapsed) return; 
  var found = false; 
  for (var i = 0; i < e.path.length; i++) { 
    var elm = e.path[i]; 
    if (hasClass(elm, 'message')) { 
      found = true; 
      break; 
    } 
  } 
 
  if (!found) { 
    return; 
  } 
 
  if (hasClass(elm, 'checked')) { 
    elm.classList.remove('checked'); 
  } else { 
    elm.classList.add('checked'); 
  } 
 
});
.message { 
  background: yellow; 
} 
 
.checked { 
  background: red; 
}
<div class="main"> 
  <div class="message"> 
    <div class="body">Lorem ipsum, qwerty! Если текст выделен - <span>клик</span> отменен</div> 
  </div> 
</div>

READ ALSO
как сделать UNIT тесты

как сделать UNIT тесты

Готовлюсь к собеседованию, помогите плиз разобраться с тестамиНапример как можно протестить эту функцию

262
Аккордеон в обратную сторону

Аккордеон в обратную сторону

Все аккордеоны открывают контент вниз методом next(), как мне сделать чтобы кнопка всегда была внизу, а текст скрытый аккордеоном открывался...

371
Эффект искажения, параллакс?

Эффект искажения, параллакс?

Как сделать такой же эффект как здесь? Особенно видно на слайде "loftec"?

387
Разбор js скрипта

Разбор js скрипта

Есть скрип(ниже) в который я привел читабельному виду и закоментировл eval( вместо него поместил documentwrite)

264