mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2025-09-08 17:51:20 +02:00
Merge branch 'main' into main
This commit is contained in:
commit
1cc66fb9b1
15
.github/workflows/PR-Demo-cleanup.yml
vendored
15
.github/workflows/PR-Demo-cleanup.yml
vendored
@ -47,7 +47,7 @@ jobs:
|
||||
const owner = context.repo.owner;
|
||||
const repo = context.repo.repo;
|
||||
|
||||
// Hole alle Labels auf dem PR
|
||||
// Get all labels on the PR
|
||||
const { data: labels } = await github.rest.issues.listLabelsOnIssue({
|
||||
owner,
|
||||
repo,
|
||||
@ -68,14 +68,13 @@ jobs:
|
||||
console.log("Label 'pr-deployed' not found. Nothing to do.");
|
||||
}
|
||||
|
||||
// Find existing comment
|
||||
const comments = await github.rest.issues.listComments({
|
||||
// Find existing bot comments about the deployment
|
||||
const { data: comments } = await github.rest.issues.listComments({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: prNumber
|
||||
});
|
||||
|
||||
const deploymentComments = comments.data.filter(c =>
|
||||
const deploymentComments = comments.filter(c =>
|
||||
c.body?.includes("## 🚀 PR Test Deployment") &&
|
||||
c.user?.type === "Bot"
|
||||
);
|
||||
@ -92,7 +91,11 @@ jobs:
|
||||
} else {
|
||||
console.log("No matching deployment comments found.");
|
||||
}
|
||||
core.setOutput('present', hasLabel || deploymentComment ? 'true' : 'false');
|
||||
|
||||
// Set flag if either label or comment was present
|
||||
const hasDeploymentComment = deploymentComments.length > 0;
|
||||
core.setOutput('present', (hasLabel || hasDeploymentComment) ? 'true' : 'false');
|
||||
|
||||
|
||||
- name: Set up SSH
|
||||
if: steps.remove-label-comment.outputs.present == 'true'
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -128,6 +128,9 @@ SwaggerDoc.json
|
||||
/app/core/build
|
||||
/app/common/build
|
||||
/app/proprietary/build
|
||||
common/build
|
||||
proprietary/build
|
||||
stirling-pdf/build
|
||||
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
|
@ -28,7 +28,8 @@ FROM alpine:3.22.0@sha256:8a1f59ffb675680d47db6337b49d22281a139e9d709335b492be02
|
||||
COPY scripts /scripts
|
||||
COPY pipeline /pipeline
|
||||
COPY app/core/src/main/resources/static/fonts/*.ttf /usr/share/fonts/opentype/noto/
|
||||
COPY --from=build /app/core/build/libs/*.jar app.jar
|
||||
# first /app directory is for the build stage, second is for the final image
|
||||
COPY --from=build /app/app/core/build/libs/*.jar app.jar
|
||||
|
||||
ARG VERSION_TAG
|
||||
|
||||
|
@ -43,7 +43,11 @@ public class AutoJobAspect {
|
||||
// This aspect will run before any audit aspects due to @Order(0)
|
||||
// Extract parameters from the request and annotation
|
||||
boolean async = Boolean.parseBoolean(request.getParameter("async"));
|
||||
log.debug("AutoJobAspect: Processing {} {} with async={}", request.getMethod(), request.getRequestURI(), async);
|
||||
log.debug(
|
||||
"AutoJobAspect: Processing {} {} with async={}",
|
||||
request.getMethod(),
|
||||
request.getRequestURI(),
|
||||
async);
|
||||
long timeout = autoJobPostMapping.timeout();
|
||||
int retryCount = autoJobPostMapping.retryCount();
|
||||
boolean trackProgress = autoJobPostMapping.trackProgress();
|
||||
@ -219,10 +223,9 @@ public class AutoJobAspect {
|
||||
resourceWeight);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Processes arguments in-place to handle file resolution and async file persistence.
|
||||
* This approach avoids type mismatch issues by modifying the original objects directly.
|
||||
* Processes arguments in-place to handle file resolution and async file persistence. This
|
||||
* approach avoids type mismatch issues by modifying the original objects directly.
|
||||
*
|
||||
* @param originalArgs The original arguments
|
||||
* @param async Whether this is an async operation
|
||||
|
@ -30,8 +30,7 @@ public class JobResult {
|
||||
private String error;
|
||||
|
||||
/** List of result files for jobs that produce files */
|
||||
@JsonIgnore
|
||||
private List<ResultFile> resultFiles;
|
||||
@JsonIgnore private List<ResultFile> resultFiles;
|
||||
|
||||
/** Time when the job was created */
|
||||
private LocalDateTime createdAt;
|
||||
|
@ -40,7 +40,7 @@
|
||||
</root>
|
||||
|
||||
<!-- Specific Logger -->
|
||||
<logger name="stirling.software.SPDF.config.security.CustomAuthenticationFailureHandler"
|
||||
<logger name="stirling.software.proprietary.security.CustomAuthenticationFailureHandler"
|
||||
level="ERROR" additivity="false">
|
||||
<appender-ref ref="CONSOLE"/>
|
||||
<appender-ref ref="AUTHLOG"/>
|
||||
|
@ -159,41 +159,36 @@
|
||||
|
||||
.scalable-languages-container {
|
||||
display: grid;
|
||||
/* Auto-fill columns, with a minimum width of 180px */
|
||||
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
|
||||
grid-template-columns: repeat(1, 1fr);
|
||||
}
|
||||
|
||||
@media (min-width: 400px) {
|
||||
#languageSelection.scalable-languages-container {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
#languageSelection.scalable-languages-container {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
}
|
||||
@media (min-width: 900px) {
|
||||
#languageSelection.scalable-languages-container {
|
||||
grid-template-columns: repeat(4, 1fr) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.scalable-languages-container:not(:has(> :nth-child(4))) .lang-dropdown-item-wrapper:last-child {
|
||||
border: 0px !important
|
||||
}
|
||||
|
||||
.scalable-languages-container:has(> *:nth-child(1)) {
|
||||
--count: 1;
|
||||
html[dir="ltr"] #languageSelection .lang-dropdown-item-wrapper:last-child {
|
||||
border-right: none !important;
|
||||
}
|
||||
|
||||
.scalable-languages-container:has(> *:nth-child(2)) {
|
||||
--count: 2;
|
||||
#languageSelection .lang-dropdown-item-wrapper:last-child {
|
||||
border: 0px !important;
|
||||
}
|
||||
|
||||
.scalable-languages-container:has(> *:nth-child(3)) {
|
||||
--count: 3;
|
||||
}
|
||||
|
||||
html[dir="ltr"] .lang-dropdown-item-wrapper {
|
||||
border-right: 2px solid var(--md-nav-color-on-separator);
|
||||
}
|
||||
|
||||
html[dir="rtl"] .lang-dropdown-item-wrapper {
|
||||
border-left: 2px solid var(--md-nav-color-on-separator);
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (min-width: 1200px) {
|
||||
.lang-dropdown-item-wrapper .dropdown-item {
|
||||
min-width: 200px
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.scalable-languages-container {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
@ -236,6 +231,41 @@ html[dir="rtl"] .lang-dropdown-item-wrapper {
|
||||
}
|
||||
}
|
||||
|
||||
.scalable-languages-container:has(> *:nth-child(1)) {
|
||||
--count: 1;
|
||||
}
|
||||
|
||||
.scalable-languages-container:has(> *:nth-child(2)) {
|
||||
--count: 2;
|
||||
}
|
||||
|
||||
.scalable-languages-container:has(> *:nth-child(3)) {
|
||||
--count: 3;
|
||||
}
|
||||
|
||||
html[dir="ltr"] .lang-dropdown-item-wrapper {
|
||||
border-right: 2px solid var(--md-nav-color-on-separator);
|
||||
}
|
||||
|
||||
html[dir="rtl"] .lang-dropdown-item-wrapper {
|
||||
border-left: 2px solid var(--md-nav-color-on-separator);
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (min-width: 1200px) {
|
||||
.lang-dropdown-item-wrapper .dropdown-item {
|
||||
min-width: 200px
|
||||
}
|
||||
|
||||
.scroll-lock-y {
|
||||
overflow-y: auto;
|
||||
max-height: 80vh;
|
||||
overscroll-behavior-y: contain;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.dropdown-item .icon-text {
|
||||
text-wrap: wrap;
|
||||
word-break: break-word;
|
||||
@ -290,6 +320,21 @@ span.icon-text::after {
|
||||
color: var(--md-sys-color-on-surface-variant);
|
||||
}
|
||||
|
||||
.nav-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
max-width: 98vw;
|
||||
}
|
||||
|
||||
.chevron-icon {
|
||||
margin-left: auto;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
[aria-expanded="true"] > .chevron-icon {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
position: relative;
|
||||
}
|
||||
@ -473,6 +518,7 @@ html[dir="rtl"] .dropdown-menu {
|
||||
box-shadow: var(--md-sys-elevation-2);
|
||||
}
|
||||
|
||||
|
||||
.dropdown-menu-tp {
|
||||
color: transparent;
|
||||
background-color: transparent;
|
||||
@ -484,27 +530,119 @@ html[dir="rtl"] .dropdown-menu {
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
@media (min-width:992px) {
|
||||
@media (max-width:1199.98px) {
|
||||
.navbar-collapse .dropdown-menu {
|
||||
width: 100%;
|
||||
}
|
||||
.navbar-collapse .dropdown-menu-wrapper {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.navbar-collapse .dropdown-mw-28 {
|
||||
min-width: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width:1200px) {
|
||||
/* This CSS-based hover is disabled because it conflicts with Bootstrap's JavaScript.
|
||||
Hover functionality is now handled in navbar.js and search.js */
|
||||
/*
|
||||
.dropdown:hover .dropdown-menu {
|
||||
display: block;
|
||||
margin-top: 0;
|
||||
}
|
||||
*/
|
||||
|
||||
/* .icon-hide {
|
||||
display: none;
|
||||
} */
|
||||
}
|
||||
|
||||
@media (max-width:1199px) {
|
||||
.icon-hide {
|
||||
display: inline-flex;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width:1200px) {
|
||||
.icon-hide {
|
||||
display: none;
|
||||
}
|
||||
.chevron-icon {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1199.98px) {
|
||||
.navbar-collapse .dropdown-menu {
|
||||
width: 100vw !important;
|
||||
max-width: 100vw !important;
|
||||
left: 0 !important;
|
||||
right: 0 !important;
|
||||
transform: none !important;
|
||||
transform-origin: none !important;
|
||||
}
|
||||
|
||||
.navbar .navbar-expand-xl .dropdown-menu,
|
||||
.navbar-expand .dropdown-menu {
|
||||
transform: none !important;
|
||||
transform-origin: none !important;
|
||||
left: 0 !important;
|
||||
right: 0 !important;
|
||||
}
|
||||
|
||||
.navbar-collapse .dropdown-mega .dropdown-menu {
|
||||
max-height: 60vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.navbar-collapse .dropdown-mega .dropdown-menu-wrapper {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
#favoritesDropdown,
|
||||
#languageDropdown + .dropdown-menu .dropdown-menu-wrapper,
|
||||
#searchDropdown + .dropdown-menu .dropdown-menu-wrapper {
|
||||
padding: 1.5rem 1rem;
|
||||
}
|
||||
|
||||
#favoritesDropdown, #languageSelection, #searchResults {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.navbar-collapse .dropdown-menu-wrapper {
|
||||
width: 95vw;
|
||||
box-sizing: border-box;
|
||||
margin-left: 0 !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
.navbar-collapse .dropdown-mw-28 {
|
||||
min-width: 0;
|
||||
}
|
||||
.icon-hide {
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.navbar-collapse .dropdown-item {
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
|
||||
.container {
|
||||
margin-left: auto !important;
|
||||
margin-right: auto !important;
|
||||
padding-left: 4px !important;
|
||||
}
|
||||
|
||||
#mainNavbarDropdownMenu {
|
||||
transform: none !important;
|
||||
transform-origin: none !important;
|
||||
left: 0 !important;
|
||||
right: 0 !important;
|
||||
width: 100vw !important;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.dropdown-menu,
|
||||
.dropdown-menu-tp,
|
||||
.dropdown-menu-tp.show {
|
||||
transform: none !important;
|
||||
transform-origin: none !important;
|
||||
max-width: 95vw !important;
|
||||
width: 100vw !important;
|
||||
left: 0 !important;
|
||||
right: 0 !important;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
.go-pro-link {
|
||||
@ -558,6 +696,12 @@ html[dir="rtl"] .dropdown-menu {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.feature-group {
|
||||
min-width: 10rem;
|
||||
}
|
||||
}
|
||||
|
||||
.feature-rows {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
@ -40,7 +40,7 @@ textarea {
|
||||
}
|
||||
|
||||
*::-webkit-scrollbar-corner {
|
||||
background-color: var(--md-sys-color-surface);
|
||||
background-color: var(--md-sys-color-surface);
|
||||
}
|
||||
|
||||
/* Alerts */
|
||||
@ -66,6 +66,9 @@ td {
|
||||
background-color: var(--md-sys-color-surface-5);
|
||||
border-radius: 3rem;
|
||||
padding: 2.5rem;
|
||||
|
||||
max-width: 95vw;
|
||||
margin-left: 2vw;
|
||||
}
|
||||
|
||||
.card {
|
||||
|
@ -44,8 +44,16 @@ function updateFavoritesDropdown() {
|
||||
contentWrapper.style.color = 'inherit';
|
||||
|
||||
// Clone the original content
|
||||
var originalContent = navbarEntry.querySelector('div').cloneNode(true);
|
||||
contentWrapper.appendChild(originalContent);
|
||||
var divElement = navbarEntry.querySelector('div');
|
||||
if (divElement) {
|
||||
var originalContent = divElement.cloneNode(true);
|
||||
contentWrapper.appendChild(originalContent);
|
||||
} else {
|
||||
// Fallback: create content manually if div is not found
|
||||
var fallbackContent = document.createElement('div');
|
||||
fallbackContent.innerHTML = navbarEntry.innerHTML;
|
||||
contentWrapper.appendChild(fallbackContent);
|
||||
}
|
||||
|
||||
// Create the remove button
|
||||
var removeButton = document.createElement('button');
|
||||
|
@ -42,6 +42,39 @@ function toolsManager() {
|
||||
});
|
||||
}
|
||||
|
||||
function setupDropdowns() {
|
||||
const dropdowns = document.querySelectorAll('.navbar-nav > .nav-item.dropdown');
|
||||
|
||||
dropdowns.forEach((dropdown) => {
|
||||
const toggle = dropdown.querySelector('[data-bs-toggle="dropdown"]');
|
||||
if (!toggle) return;
|
||||
|
||||
// Skip search dropdown, it has its own logic
|
||||
if (toggle.id === 'searchDropdown') {
|
||||
return;
|
||||
}
|
||||
|
||||
dropdown.addEventListener('show.bs.dropdown', () => {
|
||||
// Find all other open dropdowns and hide them
|
||||
const openDropdowns = document.querySelectorAll('.navbar-nav .dropdown-menu.show');
|
||||
openDropdowns.forEach((menu) => {
|
||||
const parentDropdown = menu.closest('.dropdown');
|
||||
if (parentDropdown && parentDropdown !== dropdown) {
|
||||
const parentToggle = parentDropdown.querySelector('[data-bs-toggle="dropdown"]');
|
||||
if (parentToggle) {
|
||||
// Get or create Bootstrap dropdown instance
|
||||
let instance = bootstrap.Dropdown.getInstance(parentToggle);
|
||||
if (!instance) {
|
||||
instance = new bootstrap.Dropdown(parentToggle);
|
||||
}
|
||||
instance.hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
window.tooltipSetup = () => {
|
||||
const tooltipElements = document.querySelectorAll('[title]');
|
||||
|
||||
@ -56,23 +89,54 @@ window.tooltipSetup = () => {
|
||||
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`;
|
||||
if (window.innerWidth >= 1200) {
|
||||
customTooltip.style.display = 'block';
|
||||
customTooltip.style.left = `${event.pageX + 10}px`;
|
||||
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`;
|
||||
if (window.innerWidth >= 1200) {
|
||||
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';
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// Override the bootstrap dropdown styles for mobile
|
||||
function fixNavbarDropdownStyles() {
|
||||
if (window.innerWidth < 1200) {
|
||||
document.querySelectorAll('.navbar .dropdown-menu').forEach(function(menu) {
|
||||
menu.style.transform = 'none';
|
||||
menu.style.transformOrigin = 'none';
|
||||
menu.style.left = '0';
|
||||
menu.style.right = '0';
|
||||
menu.style.maxWidth = '95vw';
|
||||
menu.style.width = '100vw';
|
||||
menu.style.marginBottom = '0';
|
||||
});
|
||||
} else {
|
||||
document.querySelectorAll('.navbar .dropdown-menu').forEach(function(menu) {
|
||||
menu.style.transform = '';
|
||||
menu.style.transformOrigin = '';
|
||||
menu.style.left = '';
|
||||
menu.style.right = '';
|
||||
menu.style.maxWidth = '';
|
||||
menu.style.width = '';
|
||||
menu.style.marginBottom = '';
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
tooltipSetup();
|
||||
setupDropdowns();
|
||||
fixNavbarDropdownStyles();
|
||||
});
|
||||
window.addEventListener('resize', fixNavbarDropdownStyles);
|
||||
|
@ -56,8 +56,16 @@ document.querySelector("#navbarSearchInput").addEventListener("input", function
|
||||
contentWrapper.style.textDecoration = "none";
|
||||
contentWrapper.style.color = "inherit";
|
||||
|
||||
var originalContent = item.querySelector("div").cloneNode(true);
|
||||
contentWrapper.appendChild(originalContent);
|
||||
var divElement = item.querySelector("div");
|
||||
if (divElement) {
|
||||
var originalContent = divElement.cloneNode(true);
|
||||
contentWrapper.appendChild(originalContent);
|
||||
} else {
|
||||
// Fallback: create content manually if div is not found
|
||||
var fallbackContent = document.createElement("div");
|
||||
fallbackContent.innerHTML = item.innerHTML;
|
||||
contentWrapper.appendChild(fallbackContent);
|
||||
}
|
||||
|
||||
contentWrapper.onclick = function () {
|
||||
window.location.href = itemHref;
|
||||
@ -77,35 +85,52 @@ document.querySelector("#navbarSearchInput").addEventListener("input", function
|
||||
|
||||
const searchDropdown = document.getElementById('searchDropdown');
|
||||
const searchInput = document.getElementById('navbarSearchInput');
|
||||
const dropdownMenu = searchDropdown.querySelector('.dropdown-menu');
|
||||
|
||||
// Handle dropdown shown event
|
||||
searchDropdown.addEventListener('shown.bs.dropdown', function () {
|
||||
searchInput.focus();
|
||||
});
|
||||
// Check if elements exist before proceeding
|
||||
if (searchDropdown && searchInput) {
|
||||
const dropdownMenu = searchDropdown.querySelector('.dropdown-menu');
|
||||
|
||||
// Handle hover opening
|
||||
searchDropdown.addEventListener('mouseenter', function () {
|
||||
// Create a single dropdown instance
|
||||
const dropdownInstance = new bootstrap.Dropdown(searchDropdown);
|
||||
dropdownInstance.show();
|
||||
|
||||
setTimeout(() => {
|
||||
searchInput.focus();
|
||||
}, 100);
|
||||
});
|
||||
// Handle click for mobile
|
||||
searchDropdown.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
const isOpen = dropdownMenu.classList.contains('show');
|
||||
// Close all other open dropdowns
|
||||
document.querySelectorAll('.navbar-nav .dropdown-menu.show').forEach((menu) => {
|
||||
if (menu !== dropdownMenu) {
|
||||
const parentDropdown = menu.closest('.dropdown');
|
||||
if (parentDropdown) {
|
||||
const parentToggle = parentDropdown.querySelector('[data-bs-toggle="dropdown"]');
|
||||
if (parentToggle) {
|
||||
let instance = bootstrap.Dropdown.getInstance(parentToggle);
|
||||
if (!instance) {
|
||||
instance = new bootstrap.Dropdown(parentToggle);
|
||||
}
|
||||
instance.hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
if (!isOpen) {
|
||||
dropdownInstance.show();
|
||||
setTimeout(() => searchInput.focus(), 150);
|
||||
} else {
|
||||
dropdownInstance.hide();
|
||||
}
|
||||
});
|
||||
|
||||
// Handle mouse leave
|
||||
searchDropdown.addEventListener('mouseleave', function () {
|
||||
// Check if current value is empty (including if user typed and then deleted)
|
||||
if (searchInput.value.trim().length === 0) {
|
||||
searchInput.blur();
|
||||
const dropdownInstance = new bootstrap.Dropdown(searchDropdown);
|
||||
dropdownInstance.hide();
|
||||
}
|
||||
});
|
||||
// Hide dropdown if it's open and user clicks outside
|
||||
document.addEventListener('click', function(e) {
|
||||
if (!searchDropdown.contains(e.target) && dropdownMenu.classList.contains('show')) {
|
||||
dropdownInstance.hide();
|
||||
}
|
||||
});
|
||||
|
||||
searchDropdown.addEventListener('hidden.bs.dropdown', function () {
|
||||
if (searchInput.value.trim().length === 0) {
|
||||
searchInput.blur();
|
||||
}
|
||||
});
|
||||
// Keep dropdown open if search input is clicked
|
||||
searchInput.addEventListener('click', function (e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
}
|
||||
|
@ -29,8 +29,40 @@
|
||||
|
||||
// Determine if this is actually a high DPI screen at page load
|
||||
const isHighDPI = systemDPR > 1.4;
|
||||
|
||||
// Reset all navbar and dropdown scaling styles
|
||||
function resetNavScaling() {
|
||||
const navbarElement = document.querySelector('.navbar');
|
||||
if (navbarElement) {
|
||||
navbarElement.style.transform = '';
|
||||
navbarElement.style.transformOrigin = '';
|
||||
navbarElement.style.width = '';
|
||||
navbarElement.style.left = '';
|
||||
navbarElement.style.right = '';
|
||||
navbarElement.style.marginBottom = '';
|
||||
navbarElement.classList.remove('navbar-expand-lg');
|
||||
navbarElement.classList.remove('navbar-expand-xl');
|
||||
}
|
||||
// Reset dropdown scaling
|
||||
const dropdowns = document.querySelectorAll('.dropdown-menu');
|
||||
dropdowns.forEach(dropdown => {
|
||||
dropdown.style.transform = '';
|
||||
dropdown.style.transformOrigin = '';
|
||||
});
|
||||
// Reset CSS custom property
|
||||
document.documentElement.style.setProperty('--navbar-height', '');
|
||||
}
|
||||
|
||||
function scaleNav() {
|
||||
resetNavScaling();
|
||||
if (window.innerWidth < 1200) {
|
||||
const navbarElement = document.querySelector('.navbar');
|
||||
if (navbarElement) {
|
||||
navbarElement.classList.remove('navbar-expand-lg');
|
||||
navbarElement.classList.add('navbar-expand-xl');
|
||||
}
|
||||
return;
|
||||
}
|
||||
const currentDPR = window.devicePixelRatio || 1;
|
||||
const browserZoom = currentDPR / systemDPR;
|
||||
|
||||
|
@ -45,9 +45,10 @@
|
||||
apps
|
||||
</span>
|
||||
<span class="icon-text" th:data-text="#{navbar.allTools}" th:text="#{navbar.allTools}"></span>
|
||||
<span class="material-symbols-rounded chevron-icon">expand_more</span>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-tp" aria-labelledby="navbarDropdown-1">
|
||||
<div class="dropdown-menu-wrapper" style="justify-content: center; display:flex">
|
||||
<div class="dropdown-menu-wrapper scroll-lock-y" style="max-width: 95vw !important;">
|
||||
<div class="feature-rows">
|
||||
|
||||
<th:block th:insert="~{fragments/navElements.html :: navElements}"></th:block>
|
||||
@ -117,9 +118,10 @@
|
||||
star
|
||||
</span>
|
||||
<span class="icon-text icon-hide" th:data-text="#{navbar.favorite}" th:text="#{navbar.favorite}"></span>
|
||||
<span class="material-symbols-rounded chevron-icon">expand_more</span>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-tp dropdown-mw-28" aria-labelledby="navbarDropdown-5">
|
||||
<div class="dropdown-menu-wrapper px-xl-2 px-2" id="favoritesDropdown">
|
||||
<div class="dropdown-menu dropdown-menu-tp dropdown-mw-28" role="menu" aria-labelledby="navbarDropdown-5">
|
||||
<div class="dropdown-menu-wrapper px-xl-2 px-2 scroll-lock-y" id="favoritesDropdown" style="max-width: 95vw !important; ">
|
||||
<!-- Dropdown items will be added here by JavaScript -->
|
||||
</div>
|
||||
</div>
|
||||
@ -140,9 +142,10 @@
|
||||
language
|
||||
</span>
|
||||
<span class="icon-text icon-hide" th:data-text="#{navbar.language}" th:text="#{navbar.language}"></span>
|
||||
<span class="material-symbols-rounded chevron-icon">expand_more</span>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-tp" aria-labelledby="languageDropdown">
|
||||
<div class="dropdown-menu-wrapper px-xl-2 px-2">
|
||||
<div class="dropdown-menu-wrapper px-xl-2 px-2 scroll-lock-y" style="max-width: 95vw !important;">
|
||||
<div id="languageSelection" class="scrollable-y lang_dropdown-mw scalable-languages-container">
|
||||
<th:block th:insert="~{fragments/languages :: langs}"></th:block>
|
||||
</div>
|
||||
@ -157,15 +160,16 @@
|
||||
search
|
||||
</span>
|
||||
<span class="icon-text icon-hide">Search</span>
|
||||
<span class="material-symbols-rounded chevron-icon">expand_more</span>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-tp" aria-labelledby="searchDropdown">
|
||||
<div class="dropdown-menu-wrapper px-xl-2 px-2">
|
||||
<div class="dropdown-menu-wrapper px-xl-2 px-2 scroll-lock-y" style="max-width: 95vw !important;">
|
||||
<form th:action="@{''}" class="d-flex p-2 search-form" id="searchForm">
|
||||
<input class="form-control search-input" type="search" th:placeholder="#{navbar.search}"
|
||||
aria-label="Search" id="navbarSearchInput">
|
||||
</form>
|
||||
<!-- Search Results -->
|
||||
<div id="searchResults" class="search-results scrollable-y dropdown-mw-20"></div>
|
||||
<div id="searchResults" class="search-results scroll-lock-y dropdown-mw-20"></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
@ -30,10 +30,6 @@ See https://github.com/adobe-type-tools/cmap-resources
|
||||
<meta name="google" content="notranslate">
|
||||
<title>PDF.js viewer</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<script th:src="@{'/js/thirdParty/popper.min.js'}"></script>
|
||||
<script th:src="@{'/js/thirdParty/bootstrap.min.js'}"></script>
|
||||
|
||||
<link rel="stylesheet" th:href="@{'/css/theme/componentes.css'}">
|
||||
<link rel="stylesheet" th:href="@{'/css/navbar.css'}">
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user