Homepage update (#2663)
# Description Please provide a summary of the changes, including relevant motivation and context. Closes #(issue_number) ## Checklist - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have performed a self-review of my own code - [ ] I have attached images of the change if it is UI based - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] If my code has heavily changed functionality I have updated relevant docs on [Stirling-PDFs doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) - [ ] My changes generate no new warnings - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) --------- Co-authored-by: Reece Browne <reece@stirling.pdf>
This commit is contained in:
@@ -1,53 +1,65 @@
|
||||
function updateFavoritesDropdown() {
|
||||
var dropdown = document.querySelector("#favoritesDropdown");
|
||||
|
||||
if (!dropdown) {
|
||||
console.error('Dropdown element with ID "favoritesDropdown" not found!');
|
||||
return;
|
||||
}
|
||||
dropdown.innerHTML = "";
|
||||
|
||||
var hasFavorites = false;
|
||||
var addedFeatures = new Set();
|
||||
const favoritesList = JSON.parse(localStorage.getItem('favoritesList')) || [];
|
||||
|
||||
for (var i = 0; i < localStorage.length; i++) {
|
||||
var key = localStorage.key(i);
|
||||
var value = localStorage.getItem(key);
|
||||
|
||||
if (value === "favorite") {
|
||||
var navbarEntry = document.querySelector(`a[href='${key}']`);
|
||||
if (value === 'favorite') {
|
||||
const index = favoritesList.indexOf(key);
|
||||
if (index === -1) {
|
||||
favoritesList.push(key);
|
||||
localStorage.removeItem(key);
|
||||
console.log(`Added to favorites: ${key}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var dropdown = document.querySelector('#favoritesDropdown');
|
||||
|
||||
if (!dropdown) {
|
||||
console.error('Dropdown element with ID "favoritesDropdown" not found!');
|
||||
return;
|
||||
}
|
||||
dropdown.innerHTML = '';
|
||||
|
||||
var hasFavorites = false;
|
||||
var addedFeatures = new Set();
|
||||
|
||||
for (var i = 0; i < favoritesList.length; i++) {
|
||||
var value = favoritesList[i];
|
||||
if (value) {
|
||||
var navbarEntry = document.querySelector(`a[data-bs-link='${value}']`);
|
||||
if (navbarEntry) {
|
||||
var featureName = navbarEntry.textContent.trim();
|
||||
|
||||
if (!addedFeatures.has(featureName)) {
|
||||
var dropdownItem = document.createElement("div");
|
||||
dropdownItem.className = "dropdown-item d-flex justify-content-between align-items-center";
|
||||
var dropdownItem = document.createElement('div');
|
||||
dropdownItem.className = 'dropdown-item d-flex justify-content-between align-items-center';
|
||||
|
||||
// Create a wrapper for the original content
|
||||
var contentWrapper = document.createElement("div");
|
||||
contentWrapper.className = "d-flex align-items-center flex-grow-1";
|
||||
contentWrapper.style.textDecoration = "none";
|
||||
contentWrapper.style.color = "inherit";
|
||||
var contentWrapper = document.createElement('div');
|
||||
contentWrapper.className = 'd-flex align-items-center flex-grow-1';
|
||||
contentWrapper.style.textDecoration = 'none';
|
||||
contentWrapper.style.color = 'inherit';
|
||||
|
||||
// Clone the original content
|
||||
var originalContent = navbarEntry.querySelector('div').cloneNode(true);
|
||||
contentWrapper.appendChild(originalContent);
|
||||
|
||||
// Create the remove button
|
||||
var removeButton = document.createElement("button");
|
||||
removeButton.className = "btn btn-sm btn-link p-0 ml-2";
|
||||
var removeButton = document.createElement('button');
|
||||
removeButton.className = 'btn btn-sm btn-link p-0 ml-2';
|
||||
removeButton.innerHTML = '<i class="material-symbols-rounded close-icon" style="font-size: 18px;">close</i>';
|
||||
removeButton.onclick = function(itemKey, event) {
|
||||
removeButton.onclick = function (itemKey, event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
localStorage.removeItem(itemKey);
|
||||
updateFavoritesSection();
|
||||
addToFavorites(itemKey);
|
||||
updateFavoritesDropdown();
|
||||
filterCards();
|
||||
}.bind(null, key);
|
||||
}.bind(null, value);
|
||||
|
||||
// Add click event to the content wrapper
|
||||
contentWrapper.onclick = function(itemHref, event) {
|
||||
contentWrapper.onclick = function (itemHref, event) {
|
||||
event.preventDefault();
|
||||
window.location.href = itemHref;
|
||||
}.bind(null, navbarEntry.href);
|
||||
@@ -58,16 +70,67 @@ function updateFavoritesDropdown() {
|
||||
hasFavorites = true;
|
||||
addedFeatures.add(featureName);
|
||||
}
|
||||
} else {
|
||||
console.warn(`Navbar entry not found for key: ${key}`);
|
||||
}
|
||||
} else {
|
||||
console.warn(`Navbar entry not found for : ${value}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasFavorites) {
|
||||
var defaultItem = document.createElement("a");
|
||||
defaultItem.className = "dropdown-item";
|
||||
defaultItem.textContent = noFavourites || "No favorites added";
|
||||
var defaultItem = document.createElement('a');
|
||||
defaultItem.className = 'dropdown-item';
|
||||
defaultItem.textContent = noFavourites || 'No favorites added';
|
||||
dropdown.appendChild(defaultItem);
|
||||
}
|
||||
}
|
||||
|
||||
function updateFavoriteIcons() {
|
||||
const favoritesList = JSON.parse(localStorage.getItem('favoritesList')) || [];
|
||||
|
||||
// Select all favorite icons
|
||||
document.querySelectorAll('.favorite-icon').forEach((icon) => {
|
||||
const endpoint = icon.getAttribute('data-endpoint');
|
||||
const parent = icon.closest('.dropdown-item');
|
||||
|
||||
// Determine if the icon belongs to groupRecent or groupFavorites
|
||||
const isInGroupRecent = parent?.closest('#groupRecent') !== null;
|
||||
const isInGroupFavorites = parent?.closest('#groupFavorites') !== null;
|
||||
|
||||
if (isInGroupRecent) {
|
||||
icon.style.display = 'none';
|
||||
} else if (isInGroupFavorites) {
|
||||
icon.textContent = 'close_small';
|
||||
icon.style.color = 'palevioletred';
|
||||
} else {
|
||||
icon.textContent = favoritesList.includes(endpoint) ? 'close_small' : 'add';
|
||||
icon.className = favoritesList.includes(endpoint)
|
||||
? 'material-symbols-rounded favorite-icon close-icon'
|
||||
: 'material-symbols-rounded favorite-icon add-icon';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function addToFavorites(entryId) {
|
||||
if (entryId) {
|
||||
const favoritesList = JSON.parse(localStorage.getItem('favoritesList')) || [];
|
||||
const index = favoritesList.indexOf(entryId);
|
||||
|
||||
if (index === -1) {
|
||||
favoritesList.push(entryId);
|
||||
console.log(`Added to favorites: ${entryId}`);
|
||||
} else {
|
||||
favoritesList.splice(index, 1);
|
||||
console.log(`Removed from favorites: ${entryId}`);
|
||||
}
|
||||
|
||||
localStorage.setItem('favoritesList', JSON.stringify(favoritesList));
|
||||
updateFavoritesDropdown();
|
||||
updateFavoriteIcons();
|
||||
const currentPath = window.location.pathname;
|
||||
if (currentPath.includes('home-legacy')) {
|
||||
syncFavoritesLegacy();
|
||||
} else {
|
||||
initializeCards();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
259
src/main/resources/static/js/homecard-legacy.js
Normal file
259
src/main/resources/static/js/homecard-legacy.js
Normal file
@@ -0,0 +1,259 @@
|
||||
function filterCardsLegacy() {
|
||||
var input = document.getElementById('searchBar');
|
||||
var filter = input.value.toUpperCase();
|
||||
|
||||
let featureGroups = document.querySelectorAll('.feature-group-legacy');
|
||||
const collapsedGroups = getCollapsedGroups();
|
||||
|
||||
for (const featureGroup of featureGroups) {
|
||||
var cards = featureGroup.querySelectorAll('.feature-card');
|
||||
|
||||
let groupMatchesFilter = false;
|
||||
for (var i = 0; i < cards.length; i++) {
|
||||
var card = cards[i];
|
||||
var title = card.querySelector('h5.card-title').innerText;
|
||||
var text = card.querySelector('p.card-text').innerText;
|
||||
|
||||
// Get the navbar tags associated with the card
|
||||
var navbarItem = document.querySelector(`a.dropdown-item[href="${card.id}"]`);
|
||||
var navbarTags = navbarItem ? navbarItem.getAttribute('data-bs-tags') : '';
|
||||
|
||||
var content = title + ' ' + text + ' ' + navbarTags;
|
||||
|
||||
if (content.toUpperCase().indexOf(filter) > -1) {
|
||||
card.style.display = '';
|
||||
groupMatchesFilter = true;
|
||||
} else {
|
||||
card.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
if (!groupMatchesFilter) {
|
||||
featureGroup.style.display = 'none';
|
||||
} else {
|
||||
featureGroup.style.display = '';
|
||||
resetOrTemporarilyExpandGroup(featureGroup, filter, collapsedGroups);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getCollapsedGroups() {
|
||||
return localStorage.getItem('collapsedGroups') ? JSON.parse(localStorage.getItem('collapsedGroups')) : [];
|
||||
}
|
||||
|
||||
function resetOrTemporarilyExpandGroup(featureGroup, filterKeywords = '', collapsedGroups = []) {
|
||||
const shouldResetCollapse = filterKeywords.trim() === '';
|
||||
if (shouldResetCollapse) {
|
||||
// Resetting the group's expand/collapse to its original state (as in collapsed groups)
|
||||
const isCollapsed = collapsedGroups.indexOf(featureGroup.id) != -1;
|
||||
expandCollapseToggle(featureGroup, !isCollapsed);
|
||||
} else {
|
||||
// Temporarily expands feature group without affecting the actual/stored collapsed groups
|
||||
featureGroup.classList.remove('collapsed');
|
||||
featureGroup.querySelector('.header-expand-button').classList.remove('collapsed');
|
||||
}
|
||||
}
|
||||
|
||||
function updateFavoritesSectionLegacy() {
|
||||
const favoritesContainer = document.getElementById('groupFavorites').querySelector('.feature-group-container');
|
||||
favoritesContainer.innerHTML = '';
|
||||
const cards = Array.from(document.querySelectorAll('.feature-card:not(.duplicate)'));
|
||||
const addedCardIds = new Set();
|
||||
let favoritesAmount = 0;
|
||||
|
||||
cards.forEach((card) => {
|
||||
const favouritesList = JSON.parse(localStorage.getItem('favoritesList') || '[]');
|
||||
|
||||
if (favouritesList.includes(card.id) && !addedCardIds.has(card.id)) {
|
||||
const duplicate = card.cloneNode(true);
|
||||
duplicate.classList.add('duplicate');
|
||||
favoritesContainer.appendChild(duplicate);
|
||||
addedCardIds.add(card.id);
|
||||
favoritesAmount++;
|
||||
}
|
||||
});
|
||||
|
||||
if (favoritesAmount === 0) {
|
||||
document.getElementById('groupFavorites').style.display = 'none';
|
||||
} else {
|
||||
document.getElementById('groupFavorites').style.display = 'flex';
|
||||
}
|
||||
reorderCards(favoritesContainer);
|
||||
}
|
||||
|
||||
function syncFavoritesLegacy() {
|
||||
const cards = Array.from(document.querySelectorAll('.feature-card'));
|
||||
cards.forEach((card) => {
|
||||
const isFavorite = localStorage.getItem(card.id) === 'favorite';
|
||||
const starIcon = card.querySelector('.favorite-icon span.material-symbols-rounded');
|
||||
if (starIcon) {
|
||||
if (isFavorite) {
|
||||
starIcon.classList.remove('no-fill');
|
||||
starIcon.classList.add('fill');
|
||||
card.classList.add('favorite');
|
||||
} else {
|
||||
starIcon.classList.remove('fill');
|
||||
starIcon.classList.add('no-fill');
|
||||
card.classList.remove('favorite');
|
||||
}
|
||||
}
|
||||
});
|
||||
updateFavoritesSectionLegacy();
|
||||
updateFavoritesDropdown();
|
||||
filterCardsLegacy();
|
||||
}
|
||||
|
||||
function reorderCards(container) {
|
||||
var cards = Array.from(container.querySelectorAll('.feature-card'));
|
||||
cards.forEach(function (card) {
|
||||
container.removeChild(card);
|
||||
});
|
||||
cards.sort(function (a, b) {
|
||||
var aIsFavorite = localStorage.getItem(a.id) === 'favorite';
|
||||
var bIsFavorite = localStorage.getItem(b.id) === 'favorite';
|
||||
if (a.id === 'update-link') {
|
||||
return -1;
|
||||
}
|
||||
if (b.id === 'update-link') {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (aIsFavorite && !bIsFavorite) {
|
||||
return -1;
|
||||
} else if (!aIsFavorite && bIsFavorite) {
|
||||
return 1;
|
||||
} else {
|
||||
return a.id > b.id;
|
||||
}
|
||||
});
|
||||
cards.forEach(function (card) {
|
||||
container.appendChild(card);
|
||||
});
|
||||
}
|
||||
|
||||
function reorderAllCards() {
|
||||
const containers = Array.from(document.querySelectorAll('.feature-group-container'));
|
||||
containers.forEach(function (container) {
|
||||
reorderCards(container);
|
||||
});
|
||||
}
|
||||
|
||||
function initializeCardsLegacy() {
|
||||
reorderAllCards();
|
||||
updateFavoritesSectionLegacy();
|
||||
updateFavoritesDropdown();
|
||||
filterCardsLegacy();
|
||||
}
|
||||
|
||||
function showFavoritesOnly() {
|
||||
const groups = Array.from(document.querySelectorAll('.feature-group-legacy'));
|
||||
if (localStorage.getItem('favoritesOnly') === 'true') {
|
||||
groups.forEach((group) => {
|
||||
if (group.id !== 'groupFavorites') {
|
||||
group.style.display = 'none';
|
||||
}
|
||||
});
|
||||
} else {
|
||||
groups.forEach((group) => {
|
||||
if (group.id !== 'groupFavorites') {
|
||||
group.style.display = 'flex';
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function toggleFavoritesOnly() {
|
||||
if (localStorage.getItem('favoritesOnly') === 'true') {
|
||||
localStorage.setItem('favoritesOnly', 'false');
|
||||
} else {
|
||||
localStorage.setItem('favoritesOnly', 'true');
|
||||
}
|
||||
showFavoritesOnly();
|
||||
}
|
||||
|
||||
// Expands a feature group on true, collapses it on false and toggles state on null.
|
||||
function expandCollapseToggle(group, expand = null) {
|
||||
if (expand === null) {
|
||||
group.classList.toggle('collapsed');
|
||||
group.querySelector('.header-expand-button').classList.toggle('collapsed');
|
||||
} else if (expand) {
|
||||
group.classList.remove('collapsed');
|
||||
group.querySelector('.header-expand-button').classList.remove('collapsed');
|
||||
} else {
|
||||
group.classList.add('collapsed');
|
||||
group.querySelector('.header-expand-button').classList.add('collapsed');
|
||||
}
|
||||
|
||||
const collapsed = localStorage.getItem('collapsedGroups') ? JSON.parse(localStorage.getItem('collapsedGroups')) : [];
|
||||
const groupIndex = collapsed.indexOf(group.id);
|
||||
|
||||
if (group.classList.contains('collapsed')) {
|
||||
if (groupIndex === -1) {
|
||||
collapsed.push(group.id);
|
||||
}
|
||||
} else {
|
||||
if (groupIndex !== -1) {
|
||||
collapsed.splice(groupIndex, 1);
|
||||
}
|
||||
}
|
||||
|
||||
localStorage.setItem('collapsedGroups', JSON.stringify(collapsed));
|
||||
}
|
||||
|
||||
function expandCollapseAll(expandAll) {
|
||||
const groups = Array.from(document.querySelectorAll('.feature-group-legacy'));
|
||||
groups.forEach((group) => {
|
||||
expandCollapseToggle(group, expandAll);
|
||||
});
|
||||
}
|
||||
|
||||
window.onload = function () {
|
||||
initializeCardsLegacy();
|
||||
syncFavoritesLegacy(); // Ensure everything is in sync on page load
|
||||
};
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const materialIcons = new FontFaceObserver('Material Symbols Rounded');
|
||||
|
||||
materialIcons
|
||||
.load()
|
||||
.then(() => {
|
||||
document.querySelectorAll('.feature-card.hidden').forEach((el) => {
|
||||
el.classList.remove('hidden');
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
console.error('Material Symbols Rounded font failed to load.');
|
||||
});
|
||||
|
||||
Array.from(document.querySelectorAll('.feature-group-header-legacy')).forEach((header) => {
|
||||
const parent = header.parentNode;
|
||||
const container = header.parentNode.querySelector('.feature-group-container');
|
||||
if (parent.id !== 'groupFavorites') {
|
||||
// container.style.maxHeight = container.scrollHeight + 'px';
|
||||
}
|
||||
header.onclick = () => {
|
||||
expandCollapseToggle(parent);
|
||||
};
|
||||
});
|
||||
|
||||
const collapsed = localStorage.getItem('collapsedGroups') ? JSON.parse(localStorage.getItem('collapsedGroups')) : [];
|
||||
const groupsArray = Array.from(document.querySelectorAll('.feature-group-legacy'));
|
||||
|
||||
groupsArray.forEach((group) => {
|
||||
if (collapsed.indexOf(group.id) !== -1) {
|
||||
expandCollapseToggle(group, false);
|
||||
}
|
||||
});
|
||||
|
||||
// Necessary in order to not fire the transition animation on page load, which looks wrong.
|
||||
// The timeout isn't doing anything visible to the user, so it's not making the page load look slower.
|
||||
setTimeout(() => {
|
||||
groupsArray.forEach((group) => {
|
||||
const container = group.querySelector('.feature-group-container');
|
||||
container.classList.add('animated-group');
|
||||
});
|
||||
}, 500);
|
||||
|
||||
showFavoritesOnly();
|
||||
});
|
||||
@@ -1,159 +1,90 @@
|
||||
function filterCards() {
|
||||
var input = document.getElementById("searchBar");
|
||||
var filter = input.value.toUpperCase();
|
||||
var input = document.getElementById('searchBar');
|
||||
var filter = input.value.toUpperCase().trim();
|
||||
|
||||
let featureGroups = document.querySelectorAll(".feature-group");
|
||||
const collapsedGroups = getCollapsedGroups();
|
||||
// Split the input filter into individual words for multi-word matching
|
||||
var filterWords = filter.split(/[\s,;.\-]+/);
|
||||
|
||||
let featureGroups = document.querySelectorAll('.feature-group');
|
||||
for (const featureGroup of featureGroups) {
|
||||
var cards = featureGroup.querySelectorAll(".feature-card");
|
||||
var cards = featureGroup.querySelectorAll('.dropdown-item');
|
||||
|
||||
let groupMatchesFilter = false;
|
||||
for (var i = 0; i < cards.length; i++) {
|
||||
var card = cards[i];
|
||||
var title = card.querySelector("h5.card-title").innerText;
|
||||
var text = card.querySelector("p.card-text").innerText;
|
||||
var title = card.getAttribute('title') || '';
|
||||
|
||||
// Get the navbar tags associated with the card
|
||||
var navbarItem = document.querySelector(`a.dropdown-item[href="${card.id}"]`);
|
||||
var navbarTags = navbarItem ? navbarItem.getAttribute("data-bs-tags") : "";
|
||||
var navbarTags = navbarItem ? navbarItem.getAttribute('data-bs-tags') : '';
|
||||
var navbarTags = navbarItem ? navbarTags + ',' + navbarItem.getAttribute('data-bs-title') : '';
|
||||
|
||||
var content = title + " " + text + " " + navbarTags;
|
||||
var content = (title + ' ' + navbarTags).toUpperCase();
|
||||
|
||||
if (content.toUpperCase().indexOf(filter) > -1) {
|
||||
card.style.display = "";
|
||||
// Check if all words in the filter match the content
|
||||
var matches = filterWords.every((word) => content.includes(word));
|
||||
|
||||
if (matches) {
|
||||
card.style.display = '';
|
||||
groupMatchesFilter = true;
|
||||
} else {
|
||||
card.style.display = "none";
|
||||
card.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
if (!groupMatchesFilter) {
|
||||
featureGroup.style.display = "none";
|
||||
featureGroup.style.display = 'none';
|
||||
} else {
|
||||
featureGroup.style.display = "";
|
||||
resetOrTemporarilyExpandGroup(featureGroup, filter, collapsedGroups);
|
||||
featureGroup.style.display = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getCollapsedGroups() {
|
||||
return localStorage.getItem("collapsedGroups") ? JSON.parse(localStorage.getItem("collapsedGroups")) : [];
|
||||
}
|
||||
|
||||
function resetOrTemporarilyExpandGroup(featureGroup, filterKeywords = "", collapsedGroups = []) {
|
||||
const shouldResetCollapse = filterKeywords.trim() === "";
|
||||
if (shouldResetCollapse) {
|
||||
// Resetting the group's expand/collapse to its original state (as in collapsed groups)
|
||||
const isCollapsed = collapsedGroups.indexOf(featureGroup.id) != -1;
|
||||
expandCollapseToggle(featureGroup, !isCollapsed);
|
||||
} else {
|
||||
// Temporarily expands feature group without affecting the actual/stored collapsed groups
|
||||
featureGroup.classList.remove("collapsed");
|
||||
featureGroup.querySelector(".header-expand-button").classList.remove("collapsed");
|
||||
}
|
||||
}
|
||||
|
||||
function updateFavoritesSection() {
|
||||
const favoritesContainer = document.getElementById("groupFavorites").querySelector(".feature-group-container");
|
||||
favoritesContainer.style.maxHeight = "none";
|
||||
favoritesContainer.innerHTML = ""; // Clear the container first
|
||||
const cards = Array.from(document.querySelectorAll(".feature-card:not(.duplicate)"));
|
||||
const addedCardIds = new Set(); // To keep track of added card IDs
|
||||
const favoritesContainer = document.getElementById('groupFavorites').querySelector('.nav-group-container');
|
||||
favoritesContainer.innerHTML = '';
|
||||
let favoritesAmount = 0;
|
||||
const favouritesList = JSON.parse(localStorage.getItem('favoritesList') || '[]');
|
||||
const isFavoritesView = JSON.parse(localStorage.getItem('favoritesView') || 'false');
|
||||
|
||||
cards.forEach(card => {
|
||||
if (localStorage.getItem(card.id) === "favorite" && !addedCardIds.has(card.id)) {
|
||||
const duplicate = card.cloneNode(true);
|
||||
duplicate.classList.add("duplicate");
|
||||
favouritesList.forEach((value) => {
|
||||
var navbarEntry = document.querySelector(`a[data-bs-link='${value}']`);
|
||||
if (navbarEntry) {
|
||||
const duplicate = navbarEntry.cloneNode(true);
|
||||
favoritesContainer.appendChild(duplicate);
|
||||
addedCardIds.add(card.id); // Mark this card as added
|
||||
favoritesAmount++;
|
||||
}
|
||||
favoritesAmount++;
|
||||
});
|
||||
|
||||
if (favoritesAmount === 0) {
|
||||
document.getElementById("groupFavorites").style.display = "none";
|
||||
if (favoritesAmount === 0 || !isFavoritesView) {
|
||||
document.getElementById('groupFavorites').style.display = 'none';
|
||||
} else {
|
||||
document.getElementById("groupFavorites").style.display = "flex";
|
||||
document.getElementById('groupFavorites').style.display = 'flex';
|
||||
}
|
||||
reorderCards(favoritesContainer);
|
||||
favoritesContainer.style.maxHeight = favoritesContainer.scrollHeight + "px";
|
||||
}
|
||||
|
||||
function toggleFavorite(element) {
|
||||
var span = element.querySelector("span.material-symbols-rounded");
|
||||
var card = element.closest(".feature-card");
|
||||
var cardId = card.id;
|
||||
|
||||
// Prevent the event from bubbling up to parent elements
|
||||
event.stopPropagation();
|
||||
|
||||
if (span.classList.contains("no-fill")) {
|
||||
span.classList.remove("no-fill");
|
||||
span.classList.add("fill");
|
||||
card.classList.add("favorite");
|
||||
localStorage.setItem(cardId, "favorite");
|
||||
} else {
|
||||
span.classList.remove("fill");
|
||||
span.classList.add("no-fill");
|
||||
card.classList.remove("favorite");
|
||||
localStorage.removeItem(cardId);
|
||||
}
|
||||
|
||||
// Use setTimeout to ensure this runs after the current call stack is clear
|
||||
setTimeout(() => {
|
||||
reorderCards(card.parentNode);
|
||||
updateFavoritesSection();
|
||||
updateFavoritesDropdown();
|
||||
filterCards();
|
||||
}, 0);
|
||||
}
|
||||
|
||||
function syncFavorites() {
|
||||
const cards = Array.from(document.querySelectorAll(".feature-card"));
|
||||
cards.forEach(card => {
|
||||
const isFavorite = localStorage.getItem(card.id) === "favorite";
|
||||
const starIcon = card.querySelector(".favorite-icon span.material-symbols-rounded");
|
||||
if (starIcon) {
|
||||
if (isFavorite) {
|
||||
starIcon.classList.remove("no-fill");
|
||||
starIcon.classList.add("fill");
|
||||
card.classList.add("favorite");
|
||||
} else {
|
||||
starIcon.classList.remove("fill");
|
||||
starIcon.classList.add("no-fill");
|
||||
card.classList.remove("favorite");
|
||||
}
|
||||
}
|
||||
});
|
||||
updateFavoritesSection();
|
||||
updateFavoritesDropdown();
|
||||
filterCards();
|
||||
//favoritesContainer.style.maxHeight = favoritesContainer.scrollHeight + 'px';
|
||||
}
|
||||
|
||||
function reorderCards(container) {
|
||||
var cards = Array.from(container.querySelectorAll(".feature-card"));
|
||||
var cards = Array.from(container.querySelectorAll('.dropdown-item'));
|
||||
cards.forEach(function (card) {
|
||||
container.removeChild(card);
|
||||
});
|
||||
cards.sort(function (a, b) {
|
||||
var aIsFavorite = localStorage.getItem(a.id) === "favorite";
|
||||
var bIsFavorite = localStorage.getItem(b.id) === "favorite";
|
||||
if (a.id === "update-link") {
|
||||
var aIsFavorite = localStorage.getItem(a.id) === 'favorite';
|
||||
var bIsFavorite = localStorage.getItem(b.id) === 'favorite';
|
||||
if (a.id === 'update-link') {
|
||||
return -1;
|
||||
}
|
||||
if (b.id === "update-link") {
|
||||
if (b.id === 'update-link') {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (aIsFavorite && !bIsFavorite) {
|
||||
return -1;
|
||||
}
|
||||
else if (!aIsFavorite && bIsFavorite) {
|
||||
} else if (!aIsFavorite && bIsFavorite) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return a.id > b.id;
|
||||
}
|
||||
});
|
||||
@@ -162,136 +93,165 @@ function reorderCards(container) {
|
||||
});
|
||||
}
|
||||
|
||||
function reorderAllCards() {
|
||||
const containers = Array.from(document.querySelectorAll(".feature-group-container"));
|
||||
containers.forEach(function (container) {
|
||||
reorderCards(container);
|
||||
})
|
||||
}
|
||||
|
||||
function initializeCards() {
|
||||
var cards = document.querySelectorAll(".feature-card");
|
||||
cards.forEach(function (card) {
|
||||
var cardId = card.id;
|
||||
var span = card.querySelector(".favorite-icon span.material-symbols-rounded");
|
||||
if (localStorage.getItem(cardId) === "favorite") {
|
||||
span.classList.remove("no-fill");
|
||||
span.classList.add("fill");
|
||||
card.classList.add("favorite");
|
||||
}
|
||||
});
|
||||
reorderAllCards();
|
||||
updateFavoritesSection();
|
||||
updateFavoritesDropdown();
|
||||
filterCards();
|
||||
}
|
||||
|
||||
function showFavoritesOnly() {
|
||||
const groups = Array.from(document.querySelectorAll(".feature-group"));
|
||||
if (localStorage.getItem("favoritesOnly") === "true") {
|
||||
groups.forEach((group) => {
|
||||
if (group.id !== "groupFavorites") {
|
||||
group.style.display = "none";
|
||||
};
|
||||
})
|
||||
} else {
|
||||
groups.forEach((group) => {
|
||||
if (group.id !== "groupFavorites") {
|
||||
group.style.display = "flex";
|
||||
};
|
||||
})
|
||||
};
|
||||
}
|
||||
function updateFavoritesView() {
|
||||
const isFavoritesView = JSON.parse(localStorage.getItem('favoritesView') || 'false');
|
||||
const textElement = document.getElementById('toggle-favourites-text');
|
||||
const iconElement = document.getElementById('toggle-favourites-icon');
|
||||
const favoritesGroup = document.querySelector('#groupFavorites');
|
||||
const favoritesList = JSON.parse(localStorage.getItem('favoritesList')) || [];
|
||||
document.getElementById('favouritesVisibility').style.display = 'flex';
|
||||
|
||||
function toggleFavoritesOnly() {
|
||||
if (localStorage.getItem("favoritesOnly") === "true") {
|
||||
localStorage.setItem("favoritesOnly", "false");
|
||||
if (isFavoritesView && favoritesList.length > 0) {
|
||||
iconElement.textContent = 'visibility_off';
|
||||
favoritesGroup.style.display = 'flex';
|
||||
} else {
|
||||
localStorage.setItem("favoritesOnly", "true");
|
||||
}
|
||||
showFavoritesOnly();
|
||||
}
|
||||
|
||||
// Expands a feature group on true, collapses it on false and toggles state on null.
|
||||
function expandCollapseToggle(group, expand = null) {
|
||||
if (expand === null) {
|
||||
group.classList.toggle("collapsed");
|
||||
group.querySelector(".header-expand-button").classList.toggle("collapsed");
|
||||
} else if (expand) {
|
||||
group.classList.remove("collapsed");
|
||||
group.querySelector(".header-expand-button").classList.remove("collapsed");
|
||||
} else {
|
||||
group.classList.add("collapsed");
|
||||
group.querySelector(".header-expand-button").classList.add("collapsed");
|
||||
}
|
||||
|
||||
const collapsed = localStorage.getItem("collapsedGroups") ? JSON.parse(localStorage.getItem("collapsedGroups")) : [];
|
||||
const groupIndex = collapsed.indexOf(group.id);
|
||||
|
||||
if (group.classList.contains("collapsed")) {
|
||||
if (groupIndex === -1) {
|
||||
collapsed.push(group.id);
|
||||
}
|
||||
} else {
|
||||
if (groupIndex !== -1) {
|
||||
collapsed.splice(groupIndex, 1);
|
||||
if (favoritesList.length > 0) {
|
||||
iconElement.textContent = 'visibility';
|
||||
favoritesGroup.style.display = 'none';
|
||||
} else {
|
||||
document.getElementById('favouritesVisibility').style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
localStorage.setItem("collapsedGroups", JSON.stringify(collapsed));
|
||||
}
|
||||
|
||||
function expandCollapseAll(expandAll) {
|
||||
const groups = Array.from(document.querySelectorAll(".feature-group"));
|
||||
groups.forEach((group) => {
|
||||
expandCollapseToggle(group, expandAll);
|
||||
})
|
||||
}
|
||||
function toggleFavoritesMode() {
|
||||
const favoritesMode = !document.querySelector('.toggle-favourites').classList.contains('active');
|
||||
document.querySelector('.toggle-favourites').classList.toggle('active', favoritesMode);
|
||||
|
||||
window.onload = function() {
|
||||
initializeCards();
|
||||
syncFavorites(); // Ensure everything is in sync on page load
|
||||
};
|
||||
document.querySelectorAll('.favorite-icon').forEach((icon) => {
|
||||
const endpoint = icon.getAttribute('data-endpoint');
|
||||
const parent = icon.closest('.dropdown-item');
|
||||
const isInGroupRecent = parent.closest('#groupRecent') !== null;
|
||||
const isInGroupFavorites = parent.closest('#groupFavorites') !== null;
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const materialIcons = new FontFaceObserver('Material Symbols Rounded');
|
||||
if (isInGroupRecent) {
|
||||
icon.style.display = 'none';
|
||||
} else if (isInGroupFavorites) {
|
||||
icon.style.display = favoritesMode ? 'inline-block' : 'none';
|
||||
icon.textContent = 'close_small';
|
||||
} else {
|
||||
icon.style.display = favoritesMode ? 'inline-block' : 'none';
|
||||
|
||||
materialIcons.load().then(() => {
|
||||
document.querySelectorAll('.feature-card.hidden').forEach(el => {
|
||||
el.classList.remove('hidden');
|
||||
});
|
||||
}).catch(() => {
|
||||
console.error('Material Symbols Rounded font failed to load.');
|
||||
const favoritesList = JSON.parse(localStorage.getItem('favoritesList')) || [];
|
||||
icon.textContent = favoritesList.includes(endpoint) ? 'close_small' : 'add';
|
||||
}
|
||||
});
|
||||
|
||||
Array.from(document.querySelectorAll(".feature-group-header")).forEach(header => {
|
||||
const parent = header.parentNode;
|
||||
const container = header.parentNode.querySelector(".feature-group-container");
|
||||
if (parent.id !== "groupFavorites") {
|
||||
container.style.maxHeight = container.scrollHeight + "px";
|
||||
document.querySelectorAll('.dropdown-item').forEach((link) => {
|
||||
if (favoritesMode) {
|
||||
link.dataset.originalHref = link.getAttribute('href');
|
||||
link.setAttribute('href', '#');
|
||||
link.classList.add('no-hover');
|
||||
} else {
|
||||
link.setAttribute('href', link.dataset.originalHref || '#');
|
||||
link.classList.remove('no-hover');
|
||||
}
|
||||
});
|
||||
|
||||
const isFavoritesView = JSON.parse(localStorage.getItem('favoritesView') || 'false');
|
||||
if (favoritesMode && !isFavoritesView) {
|
||||
toggleFavoritesView();
|
||||
}
|
||||
}
|
||||
|
||||
function toggleFavoritesView() {
|
||||
const isFavoritesView = JSON.parse(localStorage.getItem('favoritesView') || 'false');
|
||||
localStorage.setItem('favoritesView', !isFavoritesView);
|
||||
updateFavoritesView();
|
||||
}
|
||||
window.onload = function () {
|
||||
initializeCards();
|
||||
};
|
||||
|
||||
function sortNavElements(criteria) {
|
||||
document.querySelectorAll('.nav-group-container').forEach((container) => {
|
||||
const items = Array.from(container.children);
|
||||
|
||||
items.sort((a, b) => {
|
||||
if (criteria === 'alphabetical') {
|
||||
const titleA = a.querySelector('.icon-text')?.textContent.trim().toLowerCase() || '';
|
||||
const titleB = b.querySelector('.icon-text')?.textContent.trim().toLowerCase() || '';
|
||||
return titleA.localeCompare(titleB);
|
||||
} else if (criteria === 'global') {
|
||||
const popularityA = parseInt(a.dataset.popularity, 10) || 1000;
|
||||
const popularityB = parseInt(b.dataset.popularity, 10) || 1000;
|
||||
return popularityA - popularityB;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
container.innerHTML = '';
|
||||
items.forEach((item) => container.appendChild(item));
|
||||
});
|
||||
}
|
||||
|
||||
async function fetchPopularityData(url) {
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
return await response.text();
|
||||
}
|
||||
|
||||
function applyPopularityData(popularityData) {
|
||||
document.querySelectorAll('.dropdown-item').forEach((item) => {
|
||||
const endpoint = item.getAttribute('data-bs-link');
|
||||
const popularity = popularityData['/' + endpoint];
|
||||
if (endpoint && popularity !== undefined) {
|
||||
item.setAttribute('data-popularity', popularity);
|
||||
}
|
||||
});
|
||||
const currentSort = localStorage.getItem('homepageSort') || 'alphabetical';
|
||||
const sortDropdown = document.getElementById('sort-options');
|
||||
if (sortDropdown) {
|
||||
sortDropdown.value = currentSort;
|
||||
``;
|
||||
}
|
||||
sortNavElements(currentSort);
|
||||
}
|
||||
document.addEventListener('DOMContentLoaded', async function () {
|
||||
const sortDropdown = document.getElementById('sort-options');
|
||||
if (sortDropdown) {
|
||||
sortDropdown.addEventListener('change', (event) => {
|
||||
const selectedOption = event.target.value;
|
||||
localStorage.setItem('homepageSort', selectedOption);
|
||||
|
||||
sortNavElements(selectedOption);
|
||||
});
|
||||
}
|
||||
try {
|
||||
const response = await fetch('files/popularity.txt');
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
const popularityData = await response.json();
|
||||
applyPopularityData(popularityData);
|
||||
} catch (error) {
|
||||
console.error('Error loading popularity data:', error);
|
||||
}
|
||||
|
||||
const materialIcons = new FontFaceObserver('Material Symbols Rounded');
|
||||
|
||||
materialIcons
|
||||
.load()
|
||||
.then(() => {
|
||||
document.querySelectorAll('.dropdown-item.hidden').forEach((el) => {
|
||||
el.classList.remove('hidden');
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
console.error('Material Symbols Rounded font failed to load.');
|
||||
});
|
||||
|
||||
Array.from(document.querySelectorAll('.feature-group-header')).forEach((header) => {
|
||||
const parent = header.parentNode;
|
||||
header.onclick = () => {
|
||||
expandCollapseToggle(parent);
|
||||
};
|
||||
})
|
||||
|
||||
const collapsed = localStorage.getItem("collapsedGroups") ? JSON.parse(localStorage.getItem("collapsedGroups")) : [];
|
||||
const groupsArray = Array.from(document.querySelectorAll(".feature-group"));
|
||||
|
||||
groupsArray.forEach(group => {
|
||||
if (collapsed.indexOf(group.id) !== -1) {
|
||||
expandCollapseToggle(group, false);
|
||||
}
|
||||
})
|
||||
|
||||
// Necessary in order to not fire the transition animation on page load, which looks wrong.
|
||||
// The timeout isn't doing anything visible to the user, so it's not making the page load look slower.
|
||||
setTimeout(() => {
|
||||
groupsArray.forEach(group => {
|
||||
const container = group.querySelector(".feature-group-container");
|
||||
container.classList.add("animated-group");
|
||||
})
|
||||
}, 500);
|
||||
|
||||
showFavoritesOnly();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -81,7 +81,7 @@ class DragDropManager {
|
||||
}
|
||||
|
||||
onDragEl(mouseEvent) {
|
||||
const {clientX, clientY} = mouseEvent;
|
||||
const { clientX, clientY } = mouseEvent;
|
||||
if (this.draggedImageEl) {
|
||||
this.draggedImageEl.style.visibility = 'visible';
|
||||
this.draggedImageEl.style.left = `${clientX}px`;
|
||||
@@ -174,7 +174,7 @@ class DragDropManager {
|
||||
this.elementTimeouts.set(element, timeoutId);
|
||||
}
|
||||
|
||||
setActions({movePageTo}) {
|
||||
setActions({ movePageTo }) {
|
||||
this.movePageTo = movePageTo;
|
||||
}
|
||||
|
||||
|
||||
@@ -129,32 +129,37 @@ class PdfActionsManager {
|
||||
|
||||
const moveUp = document.createElement("button");
|
||||
moveUp.classList.add("pdf-actions_move-left-button", "btn", "btn-secondary");
|
||||
moveUp.innerHTML = `<span class="material-symbols-rounded">arrow_${leftDirection}_alt</span><span class="btn-tooltip">${window.translations.moveLeft}</span>`;
|
||||
moveUp.setAttribute('title', window.translations.moveLeft);
|
||||
moveUp.innerHTML = `<span class="material-symbols-rounded">arrow_${leftDirection}_alt</span>`;
|
||||
moveUp.onclick = this.moveUpButtonCallback;
|
||||
buttonContainer.appendChild(moveUp);
|
||||
|
||||
const moveDown = document.createElement("button");
|
||||
moveDown.classList.add("pdf-actions_move-right-button", "btn", "btn-secondary");
|
||||
moveDown.innerHTML = `<span class="material-symbols-rounded">arrow_${rightDirection}_alt</span><span class="btn-tooltip">${window.translations.moveRight}</span>`;
|
||||
moveDown.setAttribute('title', window.translations.moveRight);
|
||||
moveDown.innerHTML = `<span class="material-symbols-rounded">arrow_${rightDirection}_alt</span>`;
|
||||
moveDown.onclick = this.moveDownButtonCallback;
|
||||
buttonContainer.appendChild(moveDown);
|
||||
|
||||
|
||||
const rotateCCW = document.createElement("button");
|
||||
rotateCCW.classList.add("btn", "btn-secondary");
|
||||
rotateCCW.innerHTML = `<span class="material-symbols-rounded">rotate_left</span><span class="btn-tooltip">${window.translations.rotateLeft}</span>`;
|
||||
rotateCCW.setAttribute('title', window.translations.rotateLeft);
|
||||
rotateCCW.innerHTML = `<span class="material-symbols-rounded">rotate_left</span>`;
|
||||
rotateCCW.onclick = this.rotateCCWButtonCallback;
|
||||
buttonContainer.appendChild(rotateCCW);
|
||||
|
||||
const rotateCW = document.createElement("button");
|
||||
rotateCW.classList.add("btn", "btn-secondary");
|
||||
rotateCW.innerHTML = `<span class="material-symbols-rounded">rotate_right</span><span class="btn-tooltip">${window.translations.rotateRight}</span>`;
|
||||
rotateCW.setAttribute('title', window.translations.rotateRight);
|
||||
rotateCW.innerHTML = `<span class="material-symbols-rounded">rotate_right</span>`;
|
||||
rotateCW.onclick = this.rotateCWButtonCallback;
|
||||
buttonContainer.appendChild(rotateCW);
|
||||
|
||||
const deletePage = document.createElement("button");
|
||||
deletePage.classList.add("btn", "btn-danger");
|
||||
deletePage.innerHTML = `<span class="material-symbols-rounded">delete</span><span class="btn-tooltip"></span><span class="btn-tooltip">${window.translations.delete}</span>`;
|
||||
deletePage.setAttribute('title', window.translations.delete);
|
||||
deletePage.innerHTML = `<span class="material-symbols-rounded">delete</span>`;
|
||||
deletePage.onclick = this.deletePageButtonCallback;
|
||||
buttonContainer.appendChild(deletePage);
|
||||
|
||||
@@ -194,19 +199,22 @@ class PdfActionsManager {
|
||||
|
||||
const insertFileButton = document.createElement("button");
|
||||
insertFileButton.classList.add("btn", "btn-primary", "pdf-actions_insert-file-button");
|
||||
insertFileButton.innerHTML = `<span class="material-symbols-rounded">add</span></span><span class="btn-tooltip">${window.translations.addFile}</span>`;
|
||||
moveUp.setAttribute('title', window.translations.addFile);
|
||||
insertFileButton.innerHTML = `<span class="material-symbols-rounded">add</span>`;
|
||||
insertFileButton.onclick = this.insertFileButtonCallback;
|
||||
insertFileButtonContainer.appendChild(insertFileButton);
|
||||
|
||||
const splitFileButton = document.createElement("button");
|
||||
splitFileButton.classList.add("btn", "btn-primary", "pdf-actions_split-file-button");
|
||||
splitFileButton.innerHTML = `<span class="material-symbols-rounded">cut</span></span><span class="btn-tooltip">${window.translations.split}</span>`;
|
||||
splitFileButton.setAttribute('title', window.translations.split);
|
||||
splitFileButton.innerHTML = `<span class="material-symbols-rounded">cut</span>`;
|
||||
splitFileButton.onclick = this.splitFileButtonCallback;
|
||||
insertFileButtonContainer.appendChild(splitFileButton);
|
||||
|
||||
const insertFileBlankButton = document.createElement("button");
|
||||
insertFileBlankButton.classList.add("btn", "btn-primary", "pdf-actions_insert-file-blank-button");
|
||||
insertFileBlankButton.innerHTML = `<span class="material-symbols-rounded">insert_page_break</span></span><span class="btn-tooltip">${window.translations.insertPageBreak}</span>`;
|
||||
insertFileBlankButton.setAttribute('title', window.translations.insertPageBreak);
|
||||
insertFileBlankButton.innerHTML = `<span class="material-symbols-rounded">insert_page_break</span>`;
|
||||
insertFileBlankButton.onclick = this.insertFileBlankButtonCallback;
|
||||
insertFileButtonContainer.appendChild(insertFileBlankButton);
|
||||
|
||||
@@ -261,10 +269,8 @@ class PdfActionsManager {
|
||||
document.addEventListener("selectedPagesUpdated", () => {
|
||||
window.updateSelectedPagesDisplay();
|
||||
});
|
||||
|
||||
return div;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default PdfActionsManager;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import {MovePageUpCommand, MovePageDownCommand} from './commands/move-page.js';
|
||||
import {RemoveSelectedCommand} from './commands/remove.js';
|
||||
import {RotateAllCommand, RotateElementCommand} from './commands/rotate.js';
|
||||
import {SplitAllCommand} from './commands/split.js';
|
||||
import {UndoManager} from './UndoManager.js';
|
||||
import {PageBreakCommand} from './commands/page-break.js';
|
||||
import {AddFilesCommand} from './commands/add-page.js';
|
||||
import {DecryptFile} from '../DecryptFiles.js';
|
||||
import { MovePageUpCommand, MovePageDownCommand } from './commands/move-page.js';
|
||||
import { RemoveSelectedCommand } from './commands/remove.js';
|
||||
import { RotateAllCommand, RotateElementCommand } from './commands/rotate.js';
|
||||
import { SplitAllCommand } from './commands/split.js';
|
||||
import { UndoManager } from './UndoManager.js';
|
||||
import { PageBreakCommand } from './commands/page-break.js';
|
||||
import { AddFilesCommand } from './commands/add-page.js';
|
||||
import { DecryptFile } from '../DecryptFiles.js';
|
||||
|
||||
class PdfContainer {
|
||||
fileName;
|
||||
@@ -144,6 +144,8 @@ class PdfContainer {
|
||||
await addFilesCommand.execute();
|
||||
|
||||
this.undoManager.pushUndoClearRedo(addFilesCommand);
|
||||
window.tooltipSetup();
|
||||
|
||||
}
|
||||
|
||||
async addFilesAction(nextSiblingElement) {
|
||||
@@ -212,7 +214,7 @@ class PdfContainer {
|
||||
}
|
||||
|
||||
if (decryptedFile.type === 'application/pdf') {
|
||||
const {renderer, pdfDocument} = await this.loadFile(decryptedFile);
|
||||
const { renderer, pdfDocument } = await this.loadFile(decryptedFile);
|
||||
pageCount = renderer.pageCount || 0;
|
||||
pages = await this.addPdfFile(renderer, pdfDocument, nextSiblingElement, pages);
|
||||
} else if (decryptedFile.type.startsWith('image/')) {
|
||||
@@ -247,14 +249,14 @@ class PdfContainer {
|
||||
pdf_pages: pageCount,
|
||||
});
|
||||
}
|
||||
} catch {}
|
||||
} catch { }
|
||||
}
|
||||
|
||||
async addFilesBlank(nextSiblingElement, pages) {
|
||||
let doc = await PDFLib.PDFDocument.create();
|
||||
let docBytes = await doc.save();
|
||||
|
||||
const url = URL.createObjectURL(new Blob([docBytes], {type: 'application/pdf'}));
|
||||
const url = URL.createObjectURL(new Blob([docBytes], { type: 'application/pdf' }));
|
||||
|
||||
const renderer = await this.toRenderer(url);
|
||||
pages = await this.addPdfFile(renderer, doc, nextSiblingElement, pages);
|
||||
@@ -324,7 +326,7 @@ class PdfContainer {
|
||||
var objectUrl = URL.createObjectURL(file);
|
||||
var pdfDocument = await this.toPdfLib(objectUrl);
|
||||
var renderer = await this.toRenderer(objectUrl);
|
||||
return {renderer, pdfDocument};
|
||||
return { renderer, pdfDocument };
|
||||
}
|
||||
|
||||
async toRenderer(objectUrl) {
|
||||
@@ -350,7 +352,7 @@ class PdfContainer {
|
||||
// render the page onto the canvas
|
||||
var renderContext = {
|
||||
canvasContext: canvas.getContext('2d'),
|
||||
viewport: page.getViewport({scale: 1}),
|
||||
viewport: page.getViewport({ scale: 1 }),
|
||||
};
|
||||
|
||||
await page.render(renderContext).promise;
|
||||
@@ -604,7 +606,7 @@ class PdfContainer {
|
||||
|
||||
let firstPage = splitterIndex === 0 ? 0 : splitters[splitterIndex - 1];
|
||||
|
||||
const pageIndices = Array.from({length: splitterPosition - firstPage}, (value, key) => firstPage + key);
|
||||
const pageIndices = Array.from({ length: splitterPosition - firstPage }, (value, key) => firstPage + key);
|
||||
|
||||
const copiedPages = await subDocument.copyPages(baseDocument, pageIndices);
|
||||
|
||||
@@ -687,7 +689,7 @@ class PdfContainer {
|
||||
pdfDoc.setProducer(stirlingPDFLabel);
|
||||
|
||||
const pdfBytes = await pdfDoc.save();
|
||||
const pdfBlob = new Blob([pdfBytes], {type: 'application/pdf'});
|
||||
const pdfBlob = new Blob([pdfBytes], { type: 'application/pdf' });
|
||||
|
||||
const filenameInput = document.getElementById('filename-input');
|
||||
|
||||
@@ -722,7 +724,7 @@ class PdfContainer {
|
||||
const archivedDocuments = await this.nameAndArchiveFiles(splitDocuments, baseName);
|
||||
|
||||
const self = this;
|
||||
archivedDocuments.generateAsync({type: 'base64'}).then(function (base64) {
|
||||
archivedDocuments.generateAsync({ type: 'base64' }).then(function (base64) {
|
||||
const url = 'data:application/zip;base64,' + base64;
|
||||
self.downloadLink = document.createElement('a');
|
||||
self.downloadLink.href = url;
|
||||
|
||||
@@ -1,46 +1,79 @@
|
||||
function toolsManager() {
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const stackedContainer = document.getElementById('stacked');
|
||||
const convertToPDF = document.querySelector('#groupConvertTo');
|
||||
const convertFromPDF = document.querySelector('#groupConvertFrom');
|
||||
|
||||
if (stackedContainer) {
|
||||
const convertToPDF = stackedContainer.querySelector('.navbar-item:first-child');
|
||||
const convertFromPDF = stackedContainer.querySelector('.navbar-item:nth-child(2)');
|
||||
if (convertToPDF && convertFromPDF) {
|
||||
const itemsTo = Array.from(convertToPDF.querySelectorAll('.dropdown-item')).filter(
|
||||
(item) => !item.querySelector('hr.dropdown-divider')
|
||||
);
|
||||
const itemsFrom = Array.from(convertFromPDF.querySelectorAll('.dropdown-item')).filter(
|
||||
(item) => !item.querySelector('hr.dropdown-divider')
|
||||
);
|
||||
|
||||
if (convertToPDF && convertFromPDF) {
|
||||
const dropdownItemsTo = convertToPDF.querySelectorAll('.dropdown-item');
|
||||
const dropdownItemsFrom = convertFromPDF.querySelectorAll('.dropdown-item');
|
||||
const totalItems = itemsTo.length + itemsFrom.length;
|
||||
|
||||
const itemsTo = Array.from(dropdownItemsTo).filter((item) => !item.querySelector('hr.dropdown-divider'));
|
||||
const itemsFrom = Array.from(dropdownItemsFrom).filter((item) => !item.querySelector('hr.dropdown-divider'));
|
||||
if (totalItems > 12) {
|
||||
document.querySelectorAll('#convertGroup').forEach((element) => (element.style.display = 'none'));
|
||||
document.querySelectorAll('#groupConvertTo').forEach((element) => (element.style.display = 'flex'));
|
||||
document.querySelectorAll('#groupConvertFrom').forEach((element) => (element.style.display = 'flex'));
|
||||
} else {
|
||||
document.querySelectorAll('#convertGroup').forEach((element) => (element.style.display = 'flex'));
|
||||
document.querySelectorAll('#groupConvertTo').forEach((element) => (element.style.display = 'none'));
|
||||
document.querySelectorAll('#groupConvertFrom').forEach((element) => (element.style.display = 'none'));
|
||||
}
|
||||
}
|
||||
|
||||
const totalItems = itemsTo.length + itemsFrom.length;
|
||||
document.querySelectorAll('.navbar-item').forEach((element) => {
|
||||
if (!element.closest('#stacked')) {
|
||||
const dropdownItems = element.querySelectorAll('.dropdown-item');
|
||||
const items = Array.from(dropdownItems).filter((item) => !item.querySelector('hr.dropdown-divider'));
|
||||
|
||||
if (totalItems > 12) {
|
||||
stackedContainer.style.flexDirection = 'row';
|
||||
stackedContainer.classList.remove('col-lg-2');
|
||||
stackedContainer.classList.add('col-lg-4');
|
||||
convertToPDF.style.flex = '1 1 50%';
|
||||
convertFromPDF.style.flex = '1 1 50%';
|
||||
if (items.length === 0) {
|
||||
if (
|
||||
element.previousElementSibling &&
|
||||
element.previousElementSibling.classList.contains('navbar-item') &&
|
||||
element.previousElementSibling.classList.contains('nav-item-separator')
|
||||
) {
|
||||
element.previousElementSibling.remove();
|
||||
}
|
||||
element.remove();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
document.querySelectorAll('.navbar-item').forEach((element) => {
|
||||
if (!element.closest('#stacked')) {
|
||||
const dropdownItems = element.querySelectorAll('.dropdown-item');
|
||||
const items = Array.from(dropdownItems).filter((item) => !item.querySelector('hr.dropdown-divider'));
|
||||
window.tooltipSetup = () => {
|
||||
const tooltipElements = document.querySelectorAll("[title]");
|
||||
|
||||
if (items.length === 0) {
|
||||
if (
|
||||
element.previousElementSibling &&
|
||||
element.previousElementSibling.classList.contains('navbar-item') &&
|
||||
element.previousElementSibling.classList.contains('nav-item-separator')
|
||||
) {
|
||||
element.previousElementSibling.remove();
|
||||
}
|
||||
element.remove();
|
||||
}
|
||||
}
|
||||
tooltipElements.forEach((element) => {
|
||||
const tooltipText = element.getAttribute("title");
|
||||
element.removeAttribute("title");
|
||||
|
||||
const customTooltip = document.createElement("div");
|
||||
customTooltip.className = "btn-tooltip";
|
||||
customTooltip.textContent = tooltipText;
|
||||
|
||||
document.body.appendChild(customTooltip);
|
||||
|
||||
element.addEventListener("mouseenter", (event) => {
|
||||
customTooltip.style.display = "block";
|
||||
customTooltip.style.left = `${event.pageX + 10}px`; // Position tooltip slightly away from the cursor
|
||||
customTooltip.style.top = `${event.pageY + 10}px`;
|
||||
});
|
||||
|
||||
// Update the position of the tooltip as the user moves the mouse
|
||||
element.addEventListener("mousemove", (event) => {
|
||||
customTooltip.style.left = `${event.pageX + 10}px`;
|
||||
customTooltip.style.top = `${event.pageY + 10}px`;
|
||||
});
|
||||
|
||||
|
||||
// Hide the tooltip when the mouse leaves
|
||||
element.addEventListener("mouseleave", () => {
|
||||
customTooltip.style.display = "none";
|
||||
});
|
||||
});
|
||||
}
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
tooltipSetup();
|
||||
});
|
||||
|
||||
182
src/main/resources/static/js/pages/home.js
Normal file
182
src/main/resources/static/js/pages/home.js
Normal file
@@ -0,0 +1,182 @@
|
||||
/*<![CDATA[*/
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
if (window.analyticsPromptBoolean) {
|
||||
const analyticsModal = new bootstrap.Modal(document.getElementById('analyticsModal'));
|
||||
analyticsModal.show();
|
||||
}
|
||||
});
|
||||
/*]]>*/
|
||||
function setAnalytics(enabled) {
|
||||
fetchWithCsrf('api/v1/settings/update-enable-analytics', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(enabled),
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.status === 200) {
|
||||
console.log('Analytics setting updated successfully');
|
||||
bootstrap.Modal.getInstance(document.getElementById('analyticsModal')).hide();
|
||||
} else if (response.status === 208) {
|
||||
console.log('Analytics setting has already been set. Please edit /config/settings.yml to change it.', response);
|
||||
alert('Analytics setting has already been set. Please edit /config/settings.yml to change it.');
|
||||
} else {
|
||||
throw new Error('Unexpected response status: ' + response.status);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Error updating analytics setting:', error);
|
||||
alert('An error occurred while updating the analytics setting. Please try again.');
|
||||
});
|
||||
}
|
||||
|
||||
updateFavoriteIcons();
|
||||
|
||||
const defaultView = localStorage.getItem('defaultView') || 'home'; // Default to "home"
|
||||
if (defaultView === 'home-legacy') {
|
||||
window.location.href = '/home-legacy'; // Redirect to legacy view
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const surveyVersion = '2.0';
|
||||
const modal = new bootstrap.Modal(document.getElementById('surveyModal'));
|
||||
const dontShowAgain = document.getElementById('dontShowAgain');
|
||||
const takeSurveyButton = document.getElementById('takeSurvey');
|
||||
|
||||
const viewThresholds = [5, 10, 15, 22, 30, 50, 75, 100, 150, 200];
|
||||
|
||||
// Check if survey version changed and reset page views if it did
|
||||
const storedVersion = localStorage.getItem('surveyVersion');
|
||||
if (storedVersion && storedVersion !== surveyVersion) {
|
||||
localStorage.setItem('pageViews', '0');
|
||||
}
|
||||
|
||||
let pageViews = parseInt(localStorage.getItem('pageViews') || '0');
|
||||
|
||||
pageViews++;
|
||||
localStorage.setItem('pageViews', pageViews.toString());
|
||||
|
||||
function shouldShowSurvey() {
|
||||
if (localStorage.getItem('dontShowSurvey') === 'true' || localStorage.getItem('surveyTaken') === 'true') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If survey version changed and we hit a threshold, show the survey
|
||||
if (localStorage.getItem('surveyVersion') !== surveyVersion && viewThresholds.includes(pageViews)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return viewThresholds.includes(pageViews);
|
||||
}
|
||||
|
||||
if (shouldShowSurvey()) {
|
||||
modal.show();
|
||||
}
|
||||
|
||||
dontShowAgain.addEventListener('change', function () {
|
||||
if (this.checked) {
|
||||
localStorage.setItem('dontShowSurvey', 'true');
|
||||
localStorage.setItem('surveyVersion', surveyVersion);
|
||||
} else {
|
||||
localStorage.removeItem('dontShowSurvey');
|
||||
localStorage.removeItem('surveyVersion');
|
||||
}
|
||||
});
|
||||
|
||||
takeSurveyButton.addEventListener('click', function () {
|
||||
localStorage.setItem('surveyTaken', 'true');
|
||||
localStorage.setItem('surveyVersion', surveyVersion);
|
||||
modal.hide();
|
||||
});
|
||||
|
||||
if (localStorage.getItem('dontShowSurvey')) {
|
||||
modal.hide();
|
||||
}
|
||||
|
||||
if (window.location.pathname === '/') {
|
||||
const navItem = document.getElementById('navItemToHide');
|
||||
if (navItem) {
|
||||
navItem.style.display = 'none';
|
||||
}
|
||||
}
|
||||
updateFavoritesDropdown();
|
||||
});
|
||||
function setAsDefault(value) {
|
||||
localStorage.setItem('defaultView', value);
|
||||
console.log(`Default view set to: ${value}`);
|
||||
}
|
||||
|
||||
function adjustVisibleElements() {
|
||||
const container = document.querySelector('.recent-features');
|
||||
const subElements = Array.from(container.children);
|
||||
|
||||
let totalWidth = 0;
|
||||
const containerWidth = container.offsetWidth;
|
||||
|
||||
subElements.forEach((element) => {
|
||||
totalWidth += 12 * parseFloat(getComputedStyle(document.documentElement).fontSize);
|
||||
|
||||
if (totalWidth > window.innerWidth) {
|
||||
element.style.display = 'none';
|
||||
} else {
|
||||
element.style.display = 'block';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function adjustContainerAlignment() {
|
||||
console.log('Adjusting container alignment');
|
||||
|
||||
document.querySelectorAll('.features-container').forEach((parent) => {
|
||||
parent.querySelectorAll('.feature-rows').forEach((container) => {
|
||||
const childElements = Array.from(container.children);
|
||||
|
||||
const containerWidth = parent.offsetWidth;
|
||||
console.log(containerWidth < 32 * parseFloat(getComputedStyle(document.documentElement).fontSize));
|
||||
if (containerWidth < 32 * parseFloat(getComputedStyle(document.documentElement).fontSize)) {
|
||||
container.classList.add('single-column');
|
||||
} else {
|
||||
container.classList.remove('single-column');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
function toolsManager() {
|
||||
const convertToPDF = document.querySelector('#groupConvertTo');
|
||||
const convertFromPDF = document.querySelector('#groupConvertFrom');
|
||||
|
||||
if (convertToPDF && convertFromPDF) {
|
||||
const itemsTo = Array.from(convertToPDF.querySelectorAll('.dropdown-item')).filter(
|
||||
(item) => !item.querySelector('hr.dropdown-divider')
|
||||
);
|
||||
const itemsFrom = Array.from(convertFromPDF.querySelectorAll('.dropdown-item')).filter(
|
||||
(item) => !item.querySelector('hr.dropdown-divider')
|
||||
);
|
||||
|
||||
const totalItems = itemsTo.length + itemsFrom.length;
|
||||
|
||||
if (totalItems > 12) {
|
||||
document.querySelectorAll('#convertGroup').forEach((element) => element.remove());
|
||||
document.querySelectorAll('#groupConvertTo').forEach((element) => (element.style.display = 'flex'));
|
||||
document.querySelectorAll('#groupConvertFrom').forEach((element) => (element.style.display = 'flex'));
|
||||
} else {
|
||||
document.querySelectorAll('#convertGroup').forEach((element) => (element.style.display = 'flex'));
|
||||
document.querySelectorAll('#groupConvertTo').forEach((element) => element.remove());
|
||||
document.querySelectorAll('#groupConvertFrom').forEach((element) => element.remove());
|
||||
}
|
||||
}
|
||||
}
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
toolsManager();
|
||||
});
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
adjustContainerAlignment();
|
||||
adjustVisibleElements();
|
||||
});
|
||||
window.addEventListener('resize', () => {
|
||||
adjustContainerAlignment();
|
||||
adjustVisibleElements();
|
||||
});
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user