docbrown/app/assets/javascripts/initializers/initializeCommentDropdown.js
Yash Dave d307ce7469 Fix JavaScript Console errors in /Comments sub-page of any article (#4446)
* Fix JavaScript Console errors in /Comments sub-page of any article

- Make use of `document.body.contains()` to check if the element is present before trying to Add or Remove Event listeners or assign attribute values to the same.

* Implement recommendations for changes

- Switch String.match() to Regex.test() in order to have consistent Boolean return.
- Switch if(document.body.contains(element)) to if(element) as no need to check if the element is in visible context, only whether present or not.

* Implement recommendations for changes

- Switch String.match() to Regex.test() in order to have consistent Boolean return for isIOSDevice().
- Switch if(document.body.contains(element)) to if(element) as no need to check if the element is in visible context, only whether present or not.
2019-10-16 09:06:28 -04:00

124 lines
3.5 KiB
JavaScript

'use strict';
function initializeCommentDropdown() {
const announcer = document.getElementById('article-copy-link-announcer');
function isIOSDevice() {
return (
/iPhone|CriOS|iPad/i.test(navigator.userAgent) ||
navigator.userAgent === 'DEV-Native-ios'
);
}
function removeClass(className) {
return element => element.classList.remove(className);
}
function getAllByClassName(className) {
return Array.from(document.getElementsByClassName(className));
}
function showAnnouncer() {
const { activeElement } = document;
const input =
activeElement.localName === 'clipboard-copy'
? activeElement.querySelector('input')
: activeElement;
input.focus();
input.setSelectionRange(0, input.value.length);
announcer.hidden = false;
}
function hideAnnouncer() {
if (announcer) {
announcer.hidden = true;
}
}
function iOSCopyText() {
const input = document.getElementById('article-copy-link-input');
input.setSelectionRange(0, input.value.length);
document.execCommand('copy');
showAnnouncer();
}
function shouldCloseDropdown(event) {
return !(
event.target.matches('.dropdown-icon') ||
event.target.matches('.dropbtn') ||
event.target.matches('clipboard-copy') ||
event.target.matches('clipboard-copy input') ||
event.target.matches('clipboard-copy img') ||
event.target.parentElement.classList.contains('dropdown-link-row')
);
}
function removeClickListener() {
// disabling this rule because `removeEventListener` needs
// a reference to the specific handler. The function is hoisted.
// eslint-disable-next-line no-use-before-define
document.removeEventListener('click', outsideClickListener);
}
function removeCopyListener() {
if (isIOSDevice()) {
const clipboardCopyElement = document.getElementsByTagName(
'clipboard-copy',
)[0];
if (clipboardCopyElement) {
clipboardCopyElement.removeEventListener('click', iOSCopyText);
}
} else {
document.removeEventListener('clipboard-copy', showAnnouncer);
}
}
function removeAllShowing() {
getAllByClassName('showing').forEach(removeClass('showing'));
}
function outsideClickListener(event) {
if (shouldCloseDropdown(event)) {
removeAllShowing();
hideAnnouncer();
removeClickListener();
}
}
function dropdownFunction(e) {
var button = e.target.parentElement;
var dropdownContent = button.parentElement.getElementsByClassName(
'dropdown-content',
)[0];
if (dropdownContent.classList.contains('showing')) {
dropdownContent.classList.remove('showing');
removeClickListener();
removeCopyListener();
hideAnnouncer();
} else {
removeAllShowing();
dropdownContent.classList.add('showing');
if (isIOSDevice()) {
const clipboardCopyElement = document.getElementsByTagName(
'clipboard-copy',
)[0];
document.addEventListener('click', outsideClickListener);
if (clipboardCopyElement) {
clipboardCopyElement.addEventListener('click', iOSCopyText);
}
} else {
document.addEventListener('click', outsideClickListener);
document.addEventListener('clipboard-copy', showAnnouncer);
}
}
}
function addDropdownListener(dropdown) {
dropdown.addEventListener('click', dropdownFunction);
}
setTimeout(function addListeners() {
getAllByClassName('dropbtn').forEach(addDropdownListener);
}, 100);
}