Skip to content

Commit

Permalink
Remove innerHMTL and adjacentHTML
Browse files Browse the repository at this point in the history
  • Loading branch information
nikitahl committed Aug 20, 2024
1 parent eb27f11 commit 430b56a
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 67 deletions.
28 changes: 20 additions & 8 deletions js/content.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
}
});

const { DOMParser } = window;
const parser = new DOMParser();
const popupStyle = `<style id="save-popup-styles">
.save-btn,.close-btn{display:block;border:none;cursor:pointer;padding:10px 24px;color:#333;background:transparent;}
.save-btn{display:block;width:100%;margin:0 0 8px;text-align:left;}
Expand All @@ -29,7 +31,7 @@ const popupStyle = `<style id="save-popup-styles">
const channelsBtn = `<div class="option">
<button class="save-btn" id="saveChannel">Save Channel</button>
</div>`;
const playlistBtn = `<div class="option">
const playlistBtn = `<div><div class="option">
<button class="save-btn" id="saveToPlaylist">Save to playlist</button>
<div id="playlistOptions" style="display: none;">
<div class="playlist-container">
Expand All @@ -41,8 +43,9 @@ const playlistBtn = `<div class="option">
</div>
<div class="option">
<button class="save-btn" id="saveToWatchLater">Save to Watch later</button>
</div>`;
</div></div>`;
const closeBtn = '<button class="close-btn" id="closePopup" title="Close"><svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="18" viewBox="0 0 24 24" width="18" focusable="false" style="pointer-events: none; display: inherit;" aria-hidden="true"><path d="m12.71 12 8.15 8.15-.71.71L12 12.71l-8.15 8.15-.71-.71L11.29 12 3.15 3.85l.71-.71L12 11.29l8.15-8.15.71.71L12.71 12z"></path></svg></button>';
const closeBtnElement = parser.parseFromString(closeBtn, 'text/html').body.firstChild;

function createPopup(link, type, linkText, linkMeta) {
const existingPopup = document.getElementById('extension-popup');
Expand All @@ -67,16 +70,21 @@ function createPopup(link, type, linkText, linkMeta) {
popup.style.width = '300px';

const isChannel = type === 'channel';
popup.innerHTML = closeBtn;
popup.appendChild(closeBtnElement);
if (linkText === 'No text available') {
popup.innerHTML += `<b class="save-text">Could not get the name of the ${type}. Please input the name:</b><br>
const noText = `<b class="save-text">Could not get the name of the ${type}. Please input the name:</b><br>
<input class="save-input" id="linkName" type="text" placeholder="No text available">`;
const noTextElement = parser.parseFromString(noText, 'text/html').body.firstChild;
popup.appendChild(noTextElement);
}

popup.innerHTML += isChannel ? channelsBtn : playlistBtn;
const content = isChannel ? channelsBtn : playlistBtn;
const contentElement = parser.parseFromString(content, 'text/html').body.firstChild;
popup.appendChild(contentElement);

const styleElement = parser.parseFromString(popupStyle, 'text/html').head.firstChild;
document.body.appendChild(styleElement);
document.body.appendChild(popup);
popup.insertAdjacentHTML('beforebegin', popupStyle);

if (isChannel) {
document.getElementById('saveChannel').addEventListener('click', () => {
Expand Down Expand Up @@ -112,8 +120,8 @@ function createPopup(link, type, linkText, linkMeta) {

function closePopup() {
const popupStyles = document.getElementById('save-popup-styles');
popupStyles.remove();
popup.remove();
popupStyles.remove();
}
}

Expand Down Expand Up @@ -179,7 +187,11 @@ function loadPlaylists() {
const playlistSelect = document.getElementById('playlistSelect');
const playlistName = document.getElementById('newPlaylistName');
const savePlaylist = document.getElementById('createPlaylist');
playlistSelect.innerHTML = '<option value="">Choose a playlist</option>';
// eslint-disable-next-line
const defaultOption = document.createElement('option');
defaultOption.setAttribute('value', '');
defaultOption.textContent = 'Choose a playlist';
playlistSelect.appendChild(defaultOption);

for (let playlist in playlists) {
let option = document.createElement('option');
Expand Down
73 changes: 51 additions & 22 deletions js/library.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,22 @@ document.addEventListener('DOMContentLoaded', () => {
const playlist = playlists[key];
const playlistContainer = document.createElement('div');
playlistContainer.classList.add('playlist');
playlistContainer.innerHTML = `<strong class="title">${playlist.playlistName}</strong>
<span class="secondary-link">${playlist.videos.length} videos</span>
<a class="primary-link view-playlist" data-playlist-id="${key}" href="library.html?playlistName=${key}">View full playlist</a>
`;
const playlistTitle = document.createElement('strong');
playlistTitle.classList.add('title');
playlistTitle.innerText = playlist.playlistName;
const playlistLength = document.createElement('span');
playlistLength.classList.add('secondary-link');
playlistLength.innerText = `${playlist.videos.length} videos`;
const playlistLink = document.createElement('a');
playlistLink.classList.add('primary-link', 'view-playlist');
playlistLink.href = `library.html?playlistName=${key}`;
playlistLink.setAttribute('data-playlist-id', key);
playlistLink.innerText = 'View full playlist';

playlistContainer.appendChild(playlistTitle);
playlistContainer.appendChild(playlistLength);
playlistContainer.appendChild(playlistLink);

playlistsContainer.appendChild(playlistContainer);
}
}
Expand All @@ -61,26 +73,43 @@ document.addEventListener('DOMContentLoaded', () => {
return;
}
savedChannels && savedChannels.forEach(channel => {
const li = document.createElement('li');
const channelLink = document.createElement('a');
const removeBtn = document.createElement('button');
const avatar = document.createElement('img');
li.dataset.link = channel.link;
li.dataset.category = 'channels';
li.dataset.type = 'channel';
channelLink.href = channel.link;
channelLink.textContent = channel.linkText;
channelLink.title = channel.linkText;
channelLink.target = '_blank';
channelLink.classList.add('secondary-link');
removeBtn.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24" viewBox="0 0 24 24" width="24" focusable="false" style="pointer-events: none; display: inherit;" aria-hidden="true"><path d="M11 17H9V8h2v9zm4-9h-2v9h2V8zm4-4v1h-1v16H6V5H5V4h4V3h6v1h4zm-2 1H7v15h10V5z"></path></svg>';
removeBtn.title = 'Remove';
removeBtn.classList.add('remove-item');
avatar.classList.add('avatar');
const liOptions = {
'data-link': channel.link,
'data-category': 'channels',
'data-type': 'channel'
};
if (playlistName) {
liOptions['data-playlistname'] = playlistName;
}
// eslint-disable-next-line
const li = createElement('li', null, liOptions);
const channelLinkOptions = {
className: 'secondary-link',
href: channel.link,
title: channel.linkText,
target: '_blank'
};
// eslint-disable-next-line
const channelLink = createElement('a', channel.linkText, channelLinkOptions);
const btnAttributes = {
title: 'Remove',
className: 'remove-item'
};
// eslint-disable-next-line
const removeBtn = createElement('button', null, btnAttributes);
const template = document.querySelector('#removeSvgTemplate');
const clone = template.content.cloneNode(true);
removeBtn.appendChild(clone);
const avatarOptions = {
className: 'avatar'
};
// avatar.classList.add('avatar');
if (channel?.linkMeta?.avatar) {
avatar.src = channel.linkMeta.avatar;
avatar.loading = 'lazy';
avatarOptions.src = channel.linkMeta.avatar;
avatarOptions.loading = 'lazy';
}
// eslint-disable-next-line
const avatar = createElement('img', null , avatarOptions);
li.appendChild(avatar);
li.appendChild(channelLink);
li.appendChild(removeBtn);
Expand Down
97 changes: 60 additions & 37 deletions js/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,44 +2,55 @@ const { URL } = window;
// eslint-disable-next-line
function renderVideos(videos, container, category, playlistName = null) { // used in library.js
videos && videos.forEach(video => {
const li = document.createElement('li');
const videoLink = document.createElement('a');
const channelLink = document.createElement('a');
const removeBtn = document.createElement('button');
const removeBtnWrapper = document.createElement('div');
const contentWrapper = document.createElement('div');
const link = video.link;
const videoId = new URL(link).searchParams.get('v');
const embedHTML = `<iframe
class="video-embed"
loading="lazy"
src="https://www.youtube.com/embed/${videoId}"
title="YouTube video player"
frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
referrerpolicy="strict-origin-when-cross-origin"
allowfullscreen></iframe>`;
li.dataset.link = link;
li.dataset.category = category;
li.dataset.type = 'video';
const embedOptions = {
className: 'video-embed',
loading: 'lazy',
src: `https://www.youtube.com/embed/${videoId}`,
title: 'YouTube video player',
frameborder: '0',
allow: 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share',
referrerPolicy: 'strict-origin-when-cross-origin',
allowFullscreen: true
};
const embed = createElement('iframe', null, embedOptions);
const liOptions = {
'data-link': link,
'data-category': category,
'data-type': 'video'
};
if (playlistName) {
li.dataset.playlistName = playlistName;
liOptions['data-playlistname'] = playlistName;
}
li.insertAdjacentHTML('afterbegin', embedHTML);
contentWrapper.classList.add('video-content');
removeBtnWrapper.classList.add('remove-wrapper');
channelLink.classList.add('secondary-link');
channelLink.href = video.linkMeta.channelLink;
channelLink.textContent = video.linkMeta.channelName;
channelLink.title = video.linkMeta.channelName;
videoLink.classList.add('primary-link');
videoLink.href = link;
videoLink.title = video.linkText || 'No video title ...';
videoLink.textContent = video.linkText || 'No video title ...';
videoLink.target = '_blank';
removeBtn.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24" viewBox="0 0 24 24" width="24" focusable="false" style="pointer-events: none; display: inherit;" aria-hidden="true"><path d="M11 17H9V8h2v9zm4-9h-2v9h2V8zm4-4v1h-1v16H6V5H5V4h4V3h6v1h4zm-2 1H7v15h10V5z"></path></svg>';
removeBtn.title = 'Remove';
removeBtn.classList.add('remove-item');
const li = createElement('li', null, liOptions);
const removeBtnWrapper = createElement('div', null, { className: 'remove-wrapper' });
const contentWrapper = createElement('div', null, { className: 'video-content' });
const channelLinkOptions = {
className: 'secondary-link',
href: video.linkMeta.channelLink,
title: video.linkMeta.channelName,
target: '_blank'
};
const channelLink = createElement('a', video.linkMeta.channelName, channelLinkOptions);
const videoName = video.linkText || 'No video title ...';
const videoLinkOptions = {
className: 'primary-link',
href: link,
title: videoName,
target: '_blank'
};
const videoLink = createElement('a', videoName, videoLinkOptions);
const btnAttributes = {
title: 'Remove',
className: 'remove-item'
};
const removeBtn = createElement('button', null, btnAttributes);
const template = document.querySelector('#removeSvgTemplate');
const clone = template.content.cloneNode(true);

removeBtn.appendChild(clone);
li.appendChild(embed);
li.appendChild(contentWrapper);
li.appendChild(removeBtnWrapper);
contentWrapper.appendChild(videoLink);
Expand All @@ -55,14 +66,14 @@ document.body.addEventListener('click', e => {
if (e.target.tagName === 'BUTTON' && e.target.classList.contains('remove-item') && window.confirm(`Do you really want to remove this ${type}?`)) {
const link = item.dataset.link;
const category = item.dataset.category;
const playlistName = item.dataset.playlistName;
const playlistName = item.dataset.playlistname;
removeFromLocalStorage(category, link, playlistName);
item.remove();
}
});

function removeFromLocalStorage(category, link, playlistName = null) {
chrome.storage.local.get([ category ], result => {
browser.storage.local.get([ category ], result => {
let items = result[category] || {};
let save = false;

Expand All @@ -80,7 +91,7 @@ function removeFromLocalStorage(category, link, playlistName = null) {
}

if (save) {
chrome.storage.local.set({ [category]: items }, () => {
browser.storage.local.set({ [category]: items }, () => {
console.log(`${category} removed:`, link);
});
} else {
Expand All @@ -95,5 +106,17 @@ function createElement (tag, content = null, attributes) { // used in library.js
if (content) {
element.textContent = content;
}

// Assign other attributes, including data-* attributes
for (const [ key, value ] of Object.entries(attributes)) {
if (key.startsWith('data-')) {
element.setAttribute(key, value);
} else {
element[key] = value;
}
}
if (tag === 'li') {
console.log('attributes', attributes)
}
return Object.assign(element, attributes);
}
7 changes: 7 additions & 0 deletions library.html
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ <h2>Playlists</h2>
</main>
</div>
</div>
<div id="templates">
<template id="removeSvgTemplate">
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24" viewBox="0 0 24 24" width="24" focusable="false" style="pointer-events: none; display: inherit;" aria-hidden="true">
<path d="M11 17H9V8h2v9zm4-9h-2v9h2V8zm4-4v1h-1v16H6V5H5V4h4V3h6v1h4zm-2 1H7v15h10V5z"></path>
</svg>
</template>
</div>
<script src="dist/js/utils.min.js"></script>
<script src="dist/js/library.min.js"></script>
</body>
Expand Down

0 comments on commit 430b56a

Please sign in to comment.