HTML, CSS, JS and JAVA corrections (#810)

* CSS corrections

* HTML corrections

* JS corrections

* JAVA corrections

* remove tab

* CSS corrections 2

* JS corrections 2

* back to the roots

* max-linie 127

* add slash hr|br

* return bootstrap-icons.css

* return bootstrap-icons.min.css

* return bootstrap.min.css

* Update bootstrap-icons.css

* Update bootstrap-icons.min.css

* Update bootstrap-icons.min.css

* Update bootstrap.min.css

* CSS corrections

* HTML corrections

* JS corrections

* JAVA corrections

* remove tab

* CSS corrections 2

* JS corrections 2

* back to the roots

* max-linie 127

* add slash hr|br

* return bootstrap-icons.css

* Update bootstrap-icons.css

* Bootstrap CSS

* Update prism.css
This commit is contained in:
Ludy
2024-02-16 22:49:06 +01:00
committed by GitHub
parent 68f582bcb9
commit e4a76e96af
124 changed files with 9025 additions and 9424 deletions

View File

@@ -0,0 +1,4 @@
.buttons-container {
margin-top: 20px;
text-align: center;
}

View File

@@ -0,0 +1,28 @@
#box-drag-container {
position: relative;
margin: 20px 0;
}
#pdf-canvas {
box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.384);
width: 100%;
}
.draggable-buttons-box {
position: absolute;
top: 0;
padding: 10px;
width: 100%;
display: flex;
gap: 5px;
}
.draggable-buttons-box > button {
z-index: 10;
background-color: rgba(13, 110, 253, 0.1);
}
.draggable-canvas {
border: 1px solid red;
position: absolute;
touch-action: none;
user-select: none;
top: 0px;
left: 0;
}

View File

@@ -1,9 +1,11 @@
/* Dark Mode Styles */
body, select, textarea {
--body-background-color: 51, 51, 51;
--base-font-color: 255, 255, 255;
background-color: rgb(var(--body-background-color)) !important;
color: rgb(var(--base-font-color)) !important;
body,
select,
textarea {
--body-background-color: 51, 51, 51;
--base-font-color: 255, 255, 255;
background-color: rgb(var(--body-background-color)) !important;
color: rgb(var(--base-font-color)) !important;
}
.card {
background-color: rgb(var(--body-background-color)) !important;
@@ -11,11 +13,11 @@ body, select, textarea {
color: rgb(var(--base-font-color)) !important;
}
a {
color: #add8e6;
}
a:hover {
color: #87ceeb; /* Slightly brighter blue on hover for accessibility */
a {
color: #add8e6;
}
a:hover {
color: #87ceeb; /* Slightly brighter blue on hover for accessibility */
}
.dark-card {
@@ -36,7 +38,7 @@ body, select, textarea {
color: rgb(var(--base-font-color)) !important;
}
#support-section {
background-color: #444 !important;
background-color: #444 !important;
}
#pages-container-wrapper {
@@ -47,89 +49,93 @@ body, select, textarea {
}
.favorite-icon img {
filter: brightness(0) invert(1) !important;
filter: brightness(0) invert(1) !important;
}
table thead {
background-color: #333 !important;
border: 1px solid #444;
background-color: #333 !important;
border: 1px solid #444;
}
table th, table td {
border: 1px solid #444 !important;
color: white;
table th,
table td {
border: 1px solid #444 !important;
color: white;
}
.btn {
background-color: #444 !important;
border: none;
color: #fff !important;
background-color: #444 !important;
border: none;
color: #fff !important;
}
.btn-primary {
background-color: #007bff !important;
border: none;
color: #fff !important;
background-color: #007bff !important;
border: none;
color: #fff !important;
}
.btn-secondary {
background-color: #6c757d !important;
border: none;
color: #fff !important;
background-color: #6c757d !important;
border: none;
color: #fff !important;
}
.btn-info {
background-color: #17a2b8 !important;
border: none;
color: #fff !important;
background-color: #17a2b8 !important;
border: none;
color: #fff !important;
}
.btn-danger {
background-color: #dc3545 !important;
border: none;
color: #fff !important;
background-color: #dc3545 !important;
border: none;
color: #fff !important;
}
.btn-warning {
background-color: #ffc107 !important;
border: none;
color: #000 !important;
background-color: #ffc107 !important;
border: none;
color: #000 !important;
}
.btn-outline-secondary {
color: #fff !important;
border-color: #fff;
color: #fff !important;
border-color: #fff;
}
.btn-outline-secondary:hover {
background-color: #444 !important;
color: #007bff !important;
border-color: #007bff;
background-color: #444 !important;
color: #007bff !important;
border-color: #007bff;
}
.blackwhite-icon {
filter: brightness(0) invert(1);
filter: brightness(0) invert(1);
}
hr {
border-color: rgba(255, 255, 255, 0.6); /* semi-transparent white */
background-color: rgba(255, 255, 255, 0.6); /* for some browsers that might use background instead of border for <hr> */
border-color: rgba(255, 255, 255, 0.6); /* semi-transparent white */
background-color: rgba(255, 255, 255, 0.6); /* for some browsers that might use background instead of border for <hr> */
}
.modal-content {
color: #fff !important;
border-color: #fff;
color: #fff !important;
border-color: #fff;
}
#global-buttons-container input {
background-color: #323948;
caret-color: #ffffff;
color: #ffffff;
background-color: #323948;
caret-color: #ffffff;
color: #ffffff;
}
#global-buttons-container input::placeholder {
color: #ffffff;
color: #ffffff;
}
#global-buttons-container input:disabled::-webkit-input-placeholder { /* WebKit browsers */
color: #6E6865;
#global-buttons-container input:disabled::-webkit-input-placeholder {
/* WebKit browsers */
color: #6e6865;
}
#global-buttons-container input:disabled:-moz-placeholder { /* Mozilla Firefox 4 to 18 */
color: #6E6865;
#global-buttons-container input:disabled:-moz-placeholder {
/* Mozilla Firefox 4 to 18 */
color: #6e6865;
}
#global-buttons-container input:disabled::-moz-placeholder { /* Mozilla Firefox 19+ */
color: #6E6865;
#global-buttons-container input:disabled::-moz-placeholder {
/* Mozilla Firefox 19+ */
color: #6e6865;
}
#global-buttons-container input:disabled:-ms-input-placeholder { /* Internet Explorer 10+ */
color: #6E6865;
#global-buttons-container input:disabled:-ms-input-placeholder {
/* Internet Explorer 10+ */
color: #6e6865;
}

View File

@@ -1,78 +1,78 @@
#drag-container {
position: fixed;
display:flex;
inset: 0;
pointer-events: none;
z-index: 10000;
visibility: hidden;
position: fixed;
display: flex;
inset: 0;
pointer-events: none;
z-index: 10000;
visibility: hidden;
}
#drag-container:not(:empty) {
visibility: visible;
visibility: visible;
}
#drag-container .dragged-img {
position: fixed;
max-width: 200px;
max-height: 200px;
box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.58);
transform-origin: top left;
position: fixed;
max-width: 200px;
max-height: 200px;
box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.58);
transform-origin: top left;
}
.drag-manager_dragging {
width: 0px;
visibility: hidden;
width: 0px;
visibility: hidden;
}
.drag-manager_draghover {
width: 375px !important;
width: 375px !important;
}
.drag-manager_draghover .insert-file-button-container {
display: none !important;
display: none !important;
}
.drag-manager_draghover .button-container {
visibility: hidden !important;
visibility: hidden !important;
}
html[lang-direction=ltr] .drag-manager_draghover img {
left: calc(50% + 62.5px) !important;
html[lang-direction="ltr"] .drag-manager_draghover img {
left: calc(50% + 62.5px) !important;
}
html[lang-direction=rtl] .drag-manager_draghover img {
left: 125px
html[lang-direction="rtl"] .drag-manager_draghover img {
left: 125px;
}
.drag-manager_dragging-container .hide-on-drag {
display: none !important;
display: none !important;
}
.drag-manager_endpoint {
width: 80px;
height: 100%;
background-color: #FFFFFF10;
transition: width 0.1s;
animation: end-drop-expand .3s ease;
display: flex;
align-items: center;
justify-content: center;
width: 80px;
height: 100%;
background-color: #ffffff10;
transition: width 0.1s;
animation: end-drop-expand 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
}
.drag-manager_endpoint svg {
width: 50px;
height: 50px;
width: 50px;
height: 50px;
}
.drag-manager_endpoint.drag-manager_draghover {
width: 150px !important;
width: 150px !important;
}
@keyframes end-drop-expand {
from {
width: 0;
}
to {
width: 80px;
}
}
from {
width: 0;
}
to {
width: 80px;
}
}

View File

@@ -0,0 +1,88 @@
h1 {
text-align: center;
margin-top: 10%;
}
p {
text-align: center;
margin-top: 2em;
}
.button:hover {
background-color: #005b7f;
}
.features-container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(21rem, 3fr));
gap: 25px 30px;
}
.feature-card {
border: 1px solid rgba(0, 0, 0, 0.125);
border-radius: 0.25rem;
padding: 1.25rem;
display: flex;
flex-direction: column;
align-items: flex-start;
}
.feature-card .card-text {
flex: 1;
}
#support-section {
background-color: #f9f9f9;
padding: 4rem;
margin-top: 1rem;
text-align: center;
}
#support-section h1 {
margin-top: 0;
}
#support-section p {
margin-top: 0;
}
#button-group {
display: flex;
justify-content: center;
flex-wrap: wrap;
}
#github-button,
#discord-button {
display: inline-block;
padding: 1rem 2rem;
margin: 1rem;
background-color: #008cba;
color: #fff;
font-size: 1.2rem;
text-align: center;
text-decoration: none;
border-radius: 3rem;
transition: all 0.3s ease-in-out;
}
#github-button:hover,
#discord-button:hover,
#home-button:hover {
background-color: #005b7f;
}
#home-button {
display: block;
width: 200px;
height: 50px;
margin: 2em auto;
background-color: #008cba;
color: white;
text-align: center;
line-height: 50px;
text-decoration: none;
font-weight: bold;
border-radius: 25px;
transition: all 0.3s ease-in-out;
}

View File

@@ -1,94 +1,97 @@
#errorContainer {
margin: 20px; /* adjust this value as needed */
margin: 20px; /* adjust this value as needed */
}
#helpModalDialog {
width: 90%;
max-width: 800px;
width: 90%;
max-width: 800px;
}
#helpModal h1 {
text-align: center;
margin-top: 10%;
text-align: center;
margin-top: 10%;
}
#helpModal p {
text-align: center;
margin-top: 2em;
text-align: center;
margin-top: 2em;
}
#helpModal .button:hover {
background-color: #005b7f;
background-color: #005b7f;
}
#helpModal .features-container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(21rem, 3fr));
gap: 25px 30px;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(21rem, 3fr));
gap: 25px 30px;
}
#helpModal .feature-card {
border: 1px solid rgba(0, 0, 0, .125);
border-radius: 0.25rem;
padding: 1.25rem;
display: flex;
flex-direction: column;
align-items: flex-start;
border: 1px solid rgba(0, 0, 0, 0.125);
border-radius: 0.25rem;
padding: 1.25rem;
display: flex;
flex-direction: column;
align-items: flex-start;
}
#helpModal .feature-card .card-text {
flex: 1;
flex: 1;
}
#support-section {
background-color: #f9f9f9;
padding: 4rem;
margin-top: 1rem;
text-align: center;
background-color: #f9f9f9;
padding: 4rem;
margin-top: 1rem;
text-align: center;
}
#support-section h1 {
margin-top: 0;
margin-top: 0;
}
#support-section p {
margin-top: 0;
margin-top: 0;
}
#button-group {
display: flex;
justify-content: center;
flex-wrap: wrap;
display: flex;
justify-content: center;
flex-wrap: wrap;
}
#github-button, #discord-button {
display: inline-block;
padding: 1rem 2rem;
margin: 1rem;
background-color: #008CBA;
color: #fff;
font-size: 1.2rem;
text-align: center;
text-decoration: none;
border-radius: 3rem;
transition: all 0.3s ease-in-out;
#github-button,
#discord-button {
display: inline-block;
padding: 1rem 2rem;
margin: 1rem;
background-color: #008cba;
color: #fff;
font-size: 1.2rem;
text-align: center;
text-decoration: none;
border-radius: 3rem;
transition: all 0.3s ease-in-out;
}
#github-button:hover, #discord-button:hover, #home-button:hover {
background-color: #005b7f;
#github-button:hover,
#discord-button:hover,
#home-button:hover {
background-color: #005b7f;
}
#home-button {
display: block;
width: 200px;
height: 50px;
margin: 2em auto;
background-color: #008CBA;
color: white;
text-align: center;
line-height: 50px;
text-decoration: none;
font-weight: bold;
border-radius: 25px;
transition: all 0.3s ease-in-out;
}
display: block;
width: 200px;
height: 50px;
margin: 2em auto;
background-color: #008cba;
color: white;
text-align: center;
line-height: 50px;
text-decoration: none;
font-weight: bold;
border-radius: 25px;
transition: all 0.3s ease-in-out;
}

View File

@@ -1,10 +1,10 @@
.custom-file-label {
padding-right: 90px;
padding-right: 90px;
}
.selected-files {
margin-top: 10px;
max-height: 150px;
overflow-y: auto;
white-space: pre-wrap;
}
margin-top: 10px;
max-height: 150px;
overflow-y: auto;
white-space: pre-wrap;
}

View File

@@ -0,0 +1,20 @@
#footer {
display: flex;
flex-direction: column; /* Stack children vertically */
justify-content: center;
align-items: center;
width: 100%;
}
.footer-center {
display: flex;
align-items: center; /* Center children horizontally */
flex-grow: 1;
}
.footer-powered-by {
margin-top: auto; /* Pushes the text to the bottom */
color: grey;
text-align: center; /* Centers the text inside the div */
width: 100%; /* Full width to center the text properly */
}

View File

@@ -1,49 +1,54 @@
#game-container {
position: relative;
width: 100vh;
height: 0;
padding-bottom: 75%; /* 4:3 aspect ratio */
background-color: transparent;
margin: auto;
overflow: hidden;
border: 2px solid black; /* Add border */
position: relative;
width: 100vh;
height: 0;
padding-bottom: 75%; /* 4:3 aspect ratio */
background-color: transparent;
margin: auto;
overflow: hidden;
border: 2px solid black; /* Add border */
}
.pdf, .player, .projectile {
position: absolute;
.pdf,
.player,
.projectile {
position: absolute;
}
.pdf {
width: 50px;
height: 50px;
width: 50px;
height: 50px;
}
.player {
width: 50px;
height: 50px;
width: 50px;
height: 50px;
}
.projectile {
background-color: black !important;
width: 5px;
height: 10px;
background-color: black !important;
width: 5px;
height: 10px;
}
#score, #level, #lives, #high-score {
color: black;
font-family: sans-serif;
position: absolute;
font-size: calc(14px + 0.25vw); /* Reduced font size */
#score,
#level,
#lives,
#high-score {
color: black;
font-family: sans-serif;
position: absolute;
font-size: calc(14px + 0.25vw); /* Reduced font size */
}
#score {
top: 10px;
left: 10px;
top: 10px;
left: 10px;
}
#lives {
top: 10px;
left: calc(7vw); /* Adjusted position */
top: 10px;
left: calc(7vw); /* Adjusted position */
}
#high-score {
top: 10px;
left: calc(14vw); /* Adjusted position */
top: 10px;
left: calc(14vw); /* Adjusted position */
}
#level {
top: 10px;
right: 10px;
}
top: 10px;
right: 10px;
}

View File

@@ -1,20 +1,20 @@
#page-container {
min-height: 100vh;
display: flex;
flex-direction: column;
min-height: 100vh;
display: flex;
flex-direction: column;
}
#content-wrap {
flex: 1;
flex: 1;
}
#footer {
bottom: 0;
width: 100%;
bottom: 0;
width: 100%;
}
.navbar {
height: auto; /* Adjusts height automatically based on content */
white-space: nowrap; /* Prevents wrapping of navbar contents */
height: auto; /* Adjusts height automatically based on content */
white-space: nowrap; /* Prevents wrapping of navbar contents */
}
/* TODO enable later
.navbar .container {
@@ -25,70 +25,70 @@
margin-right: auto;
}*/
html[lang-direction=ltr] * {
direction: ltr;
html[lang-direction="ltr"] * {
direction: ltr;
}
html[lang-direction=rtl] * {
direction: rtl;
text-align: right;
html[lang-direction="rtl"] * {
direction: rtl;
text-align: right;
}
.ignore-rtl {
direction: ltr !important;
text-align: left !important;
direction: ltr !important;
text-align: left !important;
}
.align-top {
position: absolute;
top: 0;
position: absolute;
top: 0;
}
.align-center-right {
position: absolute;
right: 0;
top: 50%;
position: absolute;
right: 0;
top: 50%;
}
.align-center-left {
position: absolute;
left: 0;
top: 50%;
position: absolute;
left: 0;
top: 50%;
}
.align-bottom {
position: absolute;
bottom: 0;
position: absolute;
bottom: 0;
}
.btn-group > label:first-of-type {
border-top-left-radius: 0.25rem !important;
border-bottom-left-radius: 0.25rem !important;
border-top-left-radius: 0.25rem !important;
border-bottom-left-radius: 0.25rem !important;
}
html[lang-direction="rtl"] input.form-check-input {
position: relative;
margin-left: 0px;
position: relative;
margin-left: 0px;
}
html[lang-direction="rtl"] label.form-check-label {
display: inline;
display: inline;
}
.margin-auto-parent {
width: 100%;
display: flex;
width: 100%;
display: flex;
}
.margin-center {
margin: 0 auto;
margin: 0 auto;
}
#pdf-canvas {
box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.384);
width: 100%;
box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.384);
width: 100%;
}
.fixed-shadow-canvas {
box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.384);
width: 100%;
box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.384);
width: 100%;
}
.shadow-canvas {
box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.384);
box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.384);
}
.hidden {
display: none;
}
display: none;
}

View File

@@ -1,64 +1,62 @@
#searchBar {
background-image: url('../images/search.svg');
background-position: 16px 16px;
background-repeat: no-repeat;
width: 100%;
font-size: 16px;
margin-bottom: 12px;
padding: 12px 20px 12px 40px;
border: 1px solid #ddd;
background-image: url("../images/search.svg");
background-position: 16px 16px;
background-repeat: no-repeat;
width: 100%;
font-size: 16px;
margin-bottom: 12px;
padding: 12px 20px 12px 40px;
border: 1px solid #ddd;
}
.dark-mode-search {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' hei… 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z'/%3E%3C/svg%3E") !important;
color: #f8f9fa !important;
background-color: #212529 !important;
border-color: #343a40 !important;
}
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' hei… 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z'/%3E%3C/svg%3E") !important;
color: #f8f9fa !important;
background-color: #212529 !important;
border-color: #343a40 !important;
}
.features-container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(15rem, 3fr));
gap: 25px 30px;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(15rem, 3fr));
gap: 25px 30px;
}
.feature-card {
border: 2px solid rgba(0, 0, 0, .25);
border-radius: 0.25rem;
padding: 1.25rem;
display: flex;
flex-direction: column;
align-items: flex-start;
background: rgba(13, 110, 253, 0.05);
transition: transform 0.3s, border 0.3s;
transform-origin: center center;
outline: 2px solid transparent;
border: 2px solid rgba(0, 0, 0, 0.25);
border-radius: 0.25rem;
padding: 1.25rem;
display: flex;
flex-direction: column;
align-items: flex-start;
background: rgba(13, 110, 253, 0.05);
transition:
transform 0.3s,
border 0.3s;
transform-origin: center center;
outline: 2px solid transparent;
}
.feature-card a {
text-decoration: none;
color: inherit;
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
text-decoration: none;
color: inherit;
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
}
.feature-card .card-text {
flex: 1;
flex: 1;
}
.feature-card:hover {
outline: 1px solid rgba(0, 0, 0, .5);
cursor: pointer;
transform: scale(1.1);
outline: 1px solid rgba(0, 0, 0, 0.5);
cursor: pointer;
transform: scale(1.1);
}
.feature-card:hover .card-title {
text-decoration: underline;
text-decoration: underline;
}
.card-title.text-primary {
color: #000; /* Replace with your desired shade of blue */
@@ -67,27 +65,27 @@
.home-card-icon {
width: 30px;
height: 30px;
transform: translateY(-5px);
transform: translateY(-5px);
}
.home-card-icon-colour {
filter: invert(0.2) sepia(2) saturate(50) hue-rotate(190deg);
filter: invert(0.2) sepia(2) saturate(50) hue-rotate(190deg);
}
.favorite-icon {
display: none;
position: absolute;
top: 10px;
right: 10px;
display: none;
position: absolute;
top: 10px;
right: 10px;
}
/* Only show the favorite icons when the parent card is being hovered over */
.feature-card:hover .favorite-icon {
display: block;
display: block;
}
.favorite-icon img {
filter: brightness(0);
filter: brightness(0);
}
.jumbotron {
padding: 3rem 3rem; /* Reduce vertical padding */
padding: 3rem 3rem; /* Reduce vertical padding */
}

View File

@@ -1,40 +1,43 @@
#image-highlighter {
position: fixed;
display:flex;
inset: 0;
z-index: 10000;
background-color: rgba(0, 0, 0, 0);
visibility: hidden;
align-items: center;
justify-content: center;
transition: visbility 0.1s linear, background-color 0.1s linear;
position: fixed;
display: flex;
inset: 0;
z-index: 10000;
background-color: rgba(0, 0, 0, 0);
visibility: hidden;
align-items: center;
justify-content: center;
transition:
visbility 0.1s linear,
background-color 0.1s linear;
}
#image-highlighter > * {
max-width: 80vw;
max-height: 80vh;
animation: image-highlight .1s linear;
transition: transform .1s linear, opacity .1s linear;
max-width: 80vw;
max-height: 80vh;
animation: image-highlight 0.1s linear;
transition:
transform 0.1s linear,
opacity 0.1s linear;
}
#image-highlighter > *.remove {
transform: scale(0.8) !important;
opacity: 0 !important;
transform: scale(0.8) !important;
opacity: 0 !important;
}
#image-highlighter:not(:empty) {
background-color: rgba(0, 0, 0, 0.37);
visibility: visible;
background-color: rgba(0, 0, 0, 0.37);
visibility: visible;
}
@keyframes image-highlight {
from {
transform: scale(0.8);
opacity: 0;
}
to {
transform: scale(1);
opacity: 1;
}
}
from {
transform: scale(0.8);
opacity: 0;
}
to {
transform: scale(1);
opacity: 1;
}
}

View File

@@ -0,0 +1,9 @@
td a {
text-decoration: none;
}
td a:hover,
td a:focus {
text-decoration: underline;
/* Adds underline on hover/focus for clarity */
}

View File

@@ -1,14 +1,13 @@
/* Dark Mode Styles */
body {
--body-background-color: 255, 255, 255;
--base-font-color: 33, 37, 41;
--body-background-color: 255, 255, 255;
--base-font-color: 33, 37, 41;
}
#global-buttons-container input {
background-color: #ffffff;
/*caret-color: #ffffff;*/
/*color: #ffffff;*/
background-color: #ffffff;
/*caret-color: #ffffff;*/
/*color: #ffffff;*/
}
/*#global-buttons-container input:disabled::-webkit-input-placeholder { !* WebKit browsers *!*/
/* color: #98A0AB;*/

View File

@@ -0,0 +1,111 @@
html,
body {
height: 100%;
}
body {
display: flex;
align-items: center;
padding-top: 40px;
padding-bottom: 40px;
background-color: #f5f5f5;
}
.form-signin {
width: 100%;
max-width: 330px;
padding: 15px;
margin: auto;
}
.form-signin .checkbox {
font-weight: 400;
}
.form-signin .form-floating:focus-within {
z-index: 2;
}
.form-signin input[type="text"] {
margin-bottom: -1px;
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
}
.form-signin input[type="password"] {
margin-bottom: 10px;
border-top-left-radius: 0;
border-top-right-radius: 0;
}
.container-flex {
display: flex;
flex-direction: column;
min-height: 100vh;
width: 100%; /* Set width to 100% */
align-items: center; /* Center its children horizontally */
}
.footer-bottom {
margin-top: auto;
}
body.light-mode input:-webkit-autofill,
body.light-mode input:-webkit-autofill:hover,
body.light-mode input:-webkit-autofill:focus,
body.light-mode input:-webkit-autofill:active {
-webkit-text-fill-color: #212529; /* Dark font color */
-webkit-box-shadow: 0 0 0 1000px #f8f9fa inset; /* Light background color */
}
/* Dark Mode */
body.dark-mode input:-webkit-autofill,
body.dark-mode input:-webkit-autofill:hover,
body.dark-mode input:-webkit-autofill:focus,
body.dark-mode input:-webkit-autofill:active {
-webkit-text-fill-color: #f8f9fa; /* Light font color */
-webkit-box-shadow: 0 0 0 1000px #212529 inset; /* Dark background color */
}
/* Light Mode */
body.light-mode .form-floating > input:focus + label {
color: #212529 !important; /* Dark text for light background */
}
/* Dark Mode */
body.dark-mode .form-floating > input:focus + label {
color: #fff !important; /* Light text for dark background */
}
body.light-mode .form-floating > label {
color: #212529 !important; /* Dark text for light background */
}
body.dark-mode .form-floating > label {
color: #fff !important; /* Light text for dark background */
}
/* Removing default styles for ul and li */
ul {
list-style: none;
padding: 0;
margin: 0;
}
li {
list-style: none;
}
/* Positioning the container of these elements to the top right */
.your-container-class {
position: absolute;
top: 0;
right: 0;
display: flex;
}
/* Styling for the dropdown */
.dropdown-menu {
min-width: 200px; /* or whatever width you prefer */
}
.navbar-icon {
width: 40px;
height: 40px;
}

View File

@@ -1,4 +1,4 @@
.list-group-item {
.list-group-item {
display: flex;
justify-content: space-between;
align-items: center;
@@ -25,5 +25,4 @@
.move-down span {
font-weight: bold;
font-size: 1.2em;
}

View File

@@ -0,0 +1,119 @@
.multi-tool-container {
max-width: 95vw;
margin: 0 auto;
}
#global-buttons-container {
display: flex;
gap: 10px;
align-items: start;
background-color: rgba(13, 110, 253, 0.1);
border: 1px solid rgba(0, 0, 0, 0.25);
backdrop-filter: blur(2px);
top: 10px;
z-index: 10;
padding: 10px;
border-radius: 8px;
}
#global-buttons-container > * {
padding: 0.6rem 0.75rem;
}
#global-buttons-container svg {
width: 20px;
height: 20px;
}
#export-button {
margin-left: auto;
}
#pages-container-wrapper {
--background-color: rgba(0, 0, 0, 0.025);
--scroll-bar-color: #f1f1f1;
--scroll-bar-thumb: #888;
--scroll-bar-thumb-hover: #555;
background-color: var(--background-color);
width: 100%;
display: flex;
flex-direction: column;
padding: 10px 25px;
border-radius: 10px;
overflow-y: hidden;
overflow-x: auto;
min-height: 275px;
margin: 0 0 30px 0;
}
#pages-container {
margin: auto;
gap: 0px;
display: flex;
align-items: center;
justify-content: center;
}
/* width */
#pages-container-wrapper::-webkit-scrollbar {
width: 10px;
height: 10px;
}
/* Track */
#pages-container-wrapper::-webkit-scrollbar-track {
background: var(--scroll-bar-color);
}
/* Handle */
#pages-container-wrapper::-webkit-scrollbar-thumb {
border-radius: 10px;
background: var(--scroll-bar-thumb);
}
/* Handle on hover */
#pages-container-wrapper::-webkit-scrollbar-thumb:hover {
background: var(--scroll-bar-thumb-hover);
}
.page-container {
height: 250px;
display: flex;
align-items: center;
flex-direction: column-reverse;
aspect-ratio: 1;
text-align: center;
position: relative;
user-select: none;
transition: width 1s linear;
}
.page-container img {
/* max-width: calc(100% - 15px); */
max-height: calc(100% - 15px);
max-width: 237px;
display: block;
position: absolute;
left: 50%;
top: 50%;
translate: -50% -50%;
box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.384);
border-radius: 4px;
transition: rotate 0.3s;
}
#add-pdf-button {
margin: 0 auto;
}
.page-number {
position: absolute;
top: 5px;
right: 5px;
color: white;
background-color: #007bff; /* Primary blue color */
padding: 3px 6px;
border-radius: 4px;
font-size: 12px;
z-index: 2;
}

View File

@@ -1,80 +1,116 @@
#navbarSearch {
top: 100%;
right: 0;
top: 100%;
right: 0;
transition: all 0.3s;
max-height: 0;
overflow: hidden;
}
#navbarSearch.show {
max-height: 300px; /* Adjust this to your desired max height */
}
#searchForm {
width: 200px; /* Adjust this value as needed */
width: 200px; /* Adjust this value as needed */
}
/* Style the search results to match the navbar */
#searchResults {
max-height: 200px; /* Adjust this value as needed */
overflow-y: auto;
width: 100%;
max-height: 200px; /* Adjust this value as needed */
overflow-y: auto;
width: 100%;
max-width: 300px; /* Adjust to your preferred width */
transition: height 0.3s ease; /* Smooth height transition */
}
#searchResults .dropdown-item {
display: flex;
align-items: center;
white-space: nowrap;
height: 50px; /* Fixed height */
overflow: hidden; /* Hide overflow */
display: flex;
align-items: center;
white-space: nowrap;
height: 50px; /* Fixed height */
overflow: hidden; /* Hide overflow */
}
#searchResults .icon {
margin-right: 10px;
margin-right: 10px;
}
#searchResults .icon-text {
display: inline;
overflow: hidden; /* Hide overflow */
text-overflow: ellipsis; /* Add ellipsis for long text */
display: inline;
overflow: hidden; /* Hide overflow */
text-overflow: ellipsis; /* Add ellipsis for long text */
}
#search-icon i {
font-size: 24px; /* Adjust this to your desired size */
transition: color 0.3s;
}
#search-icon:hover i {
color: #666; /* Adjust this to your hover color */
}
.search-input {
transition:
border 0.3s,
box-shadow 0.3s;
}
.search-input:focus {
border-color: #666; /* Adjust this to your focus color */
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); /* Adjust this to your desired shadow */
}
/* Set a fixed height and styling for each search result item */
.search-results a {
display: flex;
align-items: center;
gap: 10px; /* space between icon and text */
height: 40px; /* Adjust based on your design */
overflow: hidden; /* Prevent content from overflowing */
white-space: nowrap; /* Prevent text from wrapping to next line */
text-overflow: ellipsis; /* Truncate text if it's too long */
}
.main-icon {
width: 36px;
height: 36px;
vertical-align: middle;
transform: translateY(-2px);
width: 36px;
height: 36px;
vertical-align: middle;
transform: translateY(-2px);
}
.icon {
width: 16px;
height: 16px;
vertical-align: middle;
transform: translateY(-2px);
width: 16px;
height: 16px;
vertical-align: middle;
transform: translateY(-2px);
}
.icon+.icon {
margin-left: -4px;
.icon + .icon {
margin-left: -4px;
}
.icon-text {
margin-left: 4px;
margin-left: 4px;
}
.nav-item-separator {
position: relative;
margin: 0 4px; /* Adjust the margin as needed */
position: relative;
margin: 0 4px; /* Adjust the margin as needed */
}
.nav-item-separator::before {
content: '';
position: absolute;
left: 0;
top: 10%; /* Adjust the top and bottom margins as needed */
bottom: 10%;
width: 1px;
background-color: #ccc; /* Adjust the color as needed */
content: "";
position: absolute;
left: 0;
top: 10%; /* Adjust the top and bottom margins as needed */
bottom: 10%;
width: 1px;
background-color: #ccc; /* Adjust the color as needed */
}
.navbar-icon {
width: 20px;
height: 20px;
transform: translateY(-2px);
}
width: 20px;
height: 20px;
transform: translateY(-2px);
}

View File

@@ -1,87 +1,85 @@
.pdf-actions_button-container {
z-index: 2;
display:flex;
opacity: 0;
transition: opacity 0.1s linear;
z-index: 2;
display: flex;
opacity: 0;
transition: opacity 0.1s linear;
}
.pdf-actions_container:hover .pdf-actions_button-container {
opacity: 1;
opacity: 1;
}
.pdf-actions_button-container > * {
padding: 0.25rem 0.5rem;
margin: 3px;
display: block;
padding: 0.25rem 0.5rem;
margin: 3px;
display: block;
}
.pdf-actions_container svg {
width: 16px;
height: 16px;
width: 16px;
height: 16px;
}
.pdf-actions_container:nth-child(1) .pdf-actions_move-left-button {
display: none;
display: none;
}
.pdf-actions_container:last-child .pdf-actions_move-right-button {
display: none;
display: none;
}
/* "insert pdf" buttons that appear on the right when hover */
.pdf-actions_insert-file-button-container {
translate: 0 -50%;
width: 80px;
height: 100%;
translate: 0 -50%;
width: 80px;
height: 100%;
z-index: 1;
opacity: 0;
transition: opacity 0.2s;
z-index: 1;
opacity: 0;
transition: opacity 0.2s;
}
.pdf-actions_insert-file-button-container.left {
left: -20px;
left: -20px;
}
.pdf-actions_insert-file-button-container.right {
right: -20px;
right: -20px;
}
html[lang-direction=ltr] .pdf-actions_insert-file-button-container.right {
display:none;
html[lang-direction="ltr"] .pdf-actions_insert-file-button-container.right {
display: none;
}
html[lang-direction=rtl] .pdf-actions_insert-file-button-container.left {
display:none;
html[lang-direction="rtl"] .pdf-actions_insert-file-button-container.left {
display: none;
}
.pdf-actions_insert-file-button-container.left .pdf-actions_insert-file-button {
left: 0;
translate: 0 -50%;
left: 0;
translate: 0 -50%;
}
.pdf-actions_insert-file-button-container.right .pdf-actions_insert-file-button {
right: 0;
translate: 0 -50%;
right: 0;
translate: 0 -50%;
}
html[lang-direction=ltr] .pdf-actions_container:last-child > .pdf-actions_insert-file-button-container.right {
display: block;
html[lang-direction="ltr"] .pdf-actions_container:last-child > .pdf-actions_insert-file-button-container.right {
display: block;
}
html[lang-direction=rtl] .pdf-actions_container:last-child > .pdf-actions_insert-file-button-container.left {
display: block;
html[lang-direction="rtl"] .pdf-actions_container:last-child > .pdf-actions_insert-file-button-container.left {
display: block;
}
.pdf-actions_insert-file-button-container:hover {
opacity: 1;
transition: opacity 0.05s;
opacity: 1;
transition: opacity 0.05s;
}
.pdf-actions_insert-file-button {
position: absolute;
top: 50%;
right: 50%;
translate: 50% -50%;
aspect-ratio: 1;
border-radius: 100px;
}
position: absolute;
top: 50%;
right: 50%;
translate: 50% -50%;
aspect-ratio: 1;
border-radius: 100px;
}

View File

@@ -0,0 +1,21 @@
.btn-margin {
margin-right: 2px;
}
.bordered-box {
border: 1px solid #ddd;
padding: 20px;
margin: 20px;
width: 70%;
}
.center-element {
width: 80%;
text-align: center;
margin: auto;
}
.element-margin {
margin: 10px 0;
/* Adjust this value to increase/decrease the margin as needed */
}

View File

@@ -1,37 +1,113 @@
/* Rainbow Mode Styles */
body {
background: linear-gradient(90deg, rgba(255,0,0,1) 0%, rgba(255,154,0,1) 10%, rgba(208,222,33,1) 20%, rgba(79,220,74,1) 30%, rgba(63,218,216,1) 40%, rgba(47,201,226,1) 50%, rgba(28,127,238,1) 60%, rgba(95,21,242,1) 70%, rgba(186,12,248,1) 80%, rgba(251,7,217,1) 90%, rgba(255,0,0,1) 100%);
color: #fff !important;
--body-background-color: 255, 255, 255;
--base-font-color: 33, 37, 41;
background: linear-gradient(
90deg,
rgba(255, 0, 0, 1) 0%,
rgba(255, 154, 0, 1) 10%,
rgba(208, 222, 33, 1) 20%,
rgba(79, 220, 74, 1) 30%,
rgba(63, 218, 216, 1) 40%,
rgba(47, 201, 226, 1) 50%,
rgba(28, 127, 238, 1) 60%,
rgba(95, 21, 242, 1) 70%,
rgba(186, 12, 248, 1) 80%,
rgba(251, 7, 217, 1) 90%,
rgba(255, 0, 0, 1) 100%
);
color: #fff !important;
--body-background-color: 255, 255, 255;
--base-font-color: 33, 37, 41;
}
.dark-card {
background: linear-gradient(90deg, rgba(255,0,0,1) 0%, rgba(255,154,0,1) 10%, rgba(208,222,33,1) 20%, rgba(79,220,74,1) 30%, rgba(63,218,216,1) 40%, rgba(47,201,226,1) 50%, rgba(28,127,238,1) 60%, rgba(95,21,242,1) 70%, rgba(186,12,248,1) 80%, rgba(251,7,217,1) 90%, rgba(255,0,0,1) 100%) !important;
color: white !important;
background: linear-gradient(
90deg,
rgba(255, 0, 0, 1) 0%,
rgba(255, 154, 0, 1) 10%,
rgba(208, 222, 33, 1) 20%,
rgba(79, 220, 74, 1) 30%,
rgba(63, 218, 216, 1) 40%,
rgba(47, 201, 226, 1) 50%,
rgba(28, 127, 238, 1) 60%,
rgba(95, 21, 242, 1) 70%,
rgba(186, 12, 248, 1) 80%,
rgba(251, 7, 217, 1) 90%,
rgba(255, 0, 0, 1) 100%
) !important;
color: white !important;
}
.jumbotron {
background: linear-gradient(90deg, rgba(255,0,0,1) 0%, rgba(255,154,0,1) 10%, rgba(208,222,33,1) 20%, rgba(79,220,74,1) 30%, rgba(63,218,216,1) 40%, rgba(47,201,226,1) 50%, rgba(28,127,238,1) 60%, rgba(95,21,242,1) 70%, rgba(186,12,248,1) 80%, rgba(251,7,217,1) 90%, rgba(255,0,0,1) 100%);
color: #fff !important;
background: linear-gradient(
90deg,
rgba(255, 0, 0, 1) 0%,
rgba(255, 154, 0, 1) 10%,
rgba(208, 222, 33, 1) 20%,
rgba(79, 220, 74, 1) 30%,
rgba(63, 218, 216, 1) 40%,
rgba(47, 201, 226, 1) 50%,
rgba(28, 127, 238, 1) 60%,
rgba(95, 21, 242, 1) 70%,
rgba(186, 12, 248, 1) 80%,
rgba(251, 7, 217, 1) 90%,
rgba(255, 0, 0, 1) 100%
);
color: #fff !important;
}
.list-group {
background: linear-gradient(90deg, rgba(255,0,0,1) 0%, rgba(255,154,0,1) 10%, rgba(208,222,33,1) 20%, rgba(79,220,74,1) 30%, rgba(63,218,216,1) 40%, rgba(47,201,226,1) 50%, rgba(28,127,238,1) 60%, rgba(95,21,242,1) 70%, rgba(186,12,248,1) 80%, rgba(251,7,217,1) 90%, rgba(255,0,0,1) 100%) !important;
color: fff !important;
background: linear-gradient(
90deg,
rgba(255, 0, 0, 1) 0%,
rgba(255, 154, 0, 1) 10%,
rgba(208, 222, 33, 1) 20%,
rgba(79, 220, 74, 1) 30%,
rgba(63, 218, 216, 1) 40%,
rgba(47, 201, 226, 1) 50%,
rgba(28, 127, 238, 1) 60%,
rgba(95, 21, 242, 1) 70%,
rgba(186, 12, 248, 1) 80%,
rgba(251, 7, 217, 1) 90%,
rgba(255, 0, 0, 1) 100%
) !important;
color: fff !important;
}
.list-group-item {
background: linear-gradient(90deg, rgba(255,0,0,1) 0%, rgba(255,154,0,1) 10%, rgba(208,222,33,1) 20%, rgba(79,220,74,1) 30%, rgba(63,218,216,1) 40%, rgba(47,201,226,1) 50%, rgba(28,127,238,1) 60%, rgba(95,21,242,1) 70%, rgba(186,12,248,1) 80%, rgba(251,7,217,1) 90%, rgba(255,0,0,1) 100%) !important;
color: fff !important;
background: linear-gradient(
90deg,
rgba(255, 0, 0, 1) 0%,
rgba(255, 154, 0, 1) 10%,
rgba(208, 222, 33, 1) 20%,
rgba(79, 220, 74, 1) 30%,
rgba(63, 218, 216, 1) 40%,
rgba(47, 201, 226, 1) 50%,
rgba(28, 127, 238, 1) 60%,
rgba(95, 21, 242, 1) 70%,
rgba(186, 12, 248, 1) 80%,
rgba(251, 7, 217, 1) 90%,
rgba(255, 0, 0, 1) 100%
) !important;
color: fff !important;
}
#support-section {
background: linear-gradient(90deg, rgba(255,0,0,1) 0%, rgba(255,154,0,1) 10%, rgba(208,222,33,1) 20%, rgba(79,220,74,1) 30%, rgba(63,218,216,1) 40%, rgba(47,201,226,1) 50%, rgba(28,127,238,1) 60%, rgba(95,21,242,1) 70%, rgba(186,12,248,1) 80%, rgba(251,7,217,1) 90%, rgba(255,0,0,1) 100%) !important;
background: linear-gradient(
90deg,
rgba(255, 0, 0, 1) 0%,
rgba(255, 154, 0, 1) 10%,
rgba(208, 222, 33, 1) 20%,
rgba(79, 220, 74, 1) 30%,
rgba(63, 218, 216, 1) 40%,
rgba(47, 201, 226, 1) 50%,
rgba(28, 127, 238, 1) 60%,
rgba(95, 21, 242, 1) 70%,
rgba(186, 12, 248, 1) 80%,
rgba(251, 7, 217, 1) 90%,
rgba(255, 0, 0, 1) 100%
) !important;
}
#pages-container-wrapper {
--background-color: rgba(255, 255, 255, 0.046) !important;
--scroll-bar-color: #4c4c4c !important;
--scroll-bar-thumb: #d3d3d3 !important;
--scroll-bar-thumb-hover: #ffffff !important;
}

View File

@@ -0,0 +1,29 @@
#pdf-preview {
margin: 0 auto;
display: block;
max-width: calc(100% - 30px);
max-height: calc(100% - 30px);
box-shadow: 0 0 4px rgba(100, 100, 100, 0.25);
transition: rotate 0.3s;
position: absolute;
top: 50%;
left: 50%;
translate: -50% -50%;
}
.previewContainer {
aspect-ratio: 1;
width: 100%;
border: 1px solid rgba(0, 0, 0, 0.125);
border-radius: 0.25rem;
margin: 1rem 0;
padding: 15px;
display: block;
overflow: hidden;
position: relative;
}
.buttonContainer {
display: flex;
justify-content: space-around;
}

View File

@@ -0,0 +1,39 @@
select#font-select,
select#font-select option {
height: 60px; /* Adjust as needed */
font-size: 30px; /* Adjust as needed */
}
.drawing-pad-container {
text-align: center;
}
#drawing-pad-canvas {
background: rgba(125, 125, 125, 0.2);
width: 100%;
height: 300px;
}
#box-drag-container {
position: relative;
margin: 20px 0;
}
.draggable-buttons-box {
position: absolute;
top: 0;
padding: 10px;
width: 100%;
display: flex;
gap: 5px;
}
.draggable-buttons-box > button {
z-index: 10;
background-color: rgba(13, 110, 253, 0.1);
}
.draggable-canvas {
border: 1px solid red;
position: absolute;
touch-action: none;
user-select: none;
top: 0px;
left: 0;
}

View File

@@ -0,0 +1,10 @@
.pdf-visual-aid {
width: 150px; /* Adjust as needed */
height: 200px; /* Adjust as needed */
border: 1px solid black; /* Represents the PDF page */
position: relative;
}
.line {
position: absolute;
background-color: red; /* Line color */
}

View File

@@ -0,0 +1,41 @@
.a4container {
position: relative;
width: 50%;
aspect-ratio: 0.707;
border: 1px solid #ddd;
box-sizing: border-box;
background-color: white;
}
.pageNumber {
position: absolute;
display: flex;
justify-content: center;
align-items: center;
font-size: 1em;
color: #333;
cursor: pointer;
background-color: #ccc;
width: 15%;
height: 15%;
transform: translate(-50%, -50%);
}
.pageNumber:hover {
background-color: #eee;
}
#myForm {
display: flex;
justify-content: center;
align-items: center;
margin-top: 20px;
}
.selectedPosition {
background-color: #0a0;
}
.selectedPosition.selectedHovered {
background-color: #006600;
}

View File

@@ -1,26 +1,24 @@
.tab-group {
}
.tab-container {
display: none;
display: none;
}
.tab-container.active {
display: block;
border: 1px solid rgba(var(--base-font-color), 0.25);
padding: 15px;
display: block;
border: 1px solid rgba(var(--base-font-color), 0.25);
padding: 15px;
}
.tab-buttons > button {
margin-bottom: -1px;
background: 0 0;
border: 1px solid transparent;
color: rgb(var(--base-font-color));
margin-bottom: -1px;
background: 0 0;
border: 1px solid transparent;
color: rgb(var(--base-font-color));
border-top-left-radius: 0.25rem;
border-top-right-radius: 0.25rem;
border-top-left-radius: 0.25rem;
border-top-right-radius: 0.25rem;
}
.tab-buttons > button.active {
background-color: rgb(var(--body-background-color));
border-color: rgba(var(--base-font-color), 0.25) rgba(var(--base-font-color), 0.25) rgb(var(--body-background-color));
}
background-color: rgb(var(--body-background-color));
border-color: rgba(var(--base-font-color), 0.25) rgba(var(--base-font-color), 0.25) rgb(var(--body-background-color));
}

View File

@@ -1,5 +1,5 @@
var toggleCount = 0
var lastToggleTime = Date.now()
var toggleCount = 0;
var lastToggleTime = Date.now();
var elements = {
lightModeStyles: null,
@@ -11,18 +11,18 @@ var elements = {
navbar: null,
navIcons: null,
navDropdownMenus: null,
}
};
function getElements() {
elements.lightModeStyles = document.getElementById("light-mode-styles")
elements.darkModeStyles = document.getElementById("dark-mode-styles")
elements.rainbowModeStyles = document.getElementById("rainbow-mode-styles")
elements.darkModeIcon = document.getElementById("dark-mode-icon")
elements.searchBar = document.getElementById("searchBar")
elements.formControls = document.querySelectorAll(".form-control")
elements.navbar = document.querySelectorAll("nav.navbar")
elements.navIcons = document.querySelectorAll("nav .icon, .navbar-icon")
elements.navDropdownMenus = document.querySelectorAll("nav .dropdown-menu")
elements.lightModeStyles = document.getElementById("light-mode-styles");
elements.darkModeStyles = document.getElementById("dark-mode-styles");
elements.rainbowModeStyles = document.getElementById("rainbow-mode-styles");
elements.darkModeIcon = document.getElementById("dark-mode-icon");
elements.searchBar = document.getElementById("searchBar");
elements.formControls = document.querySelectorAll(".form-control");
elements.navbar = document.querySelectorAll("nav.navbar");
elements.navIcons = document.querySelectorAll("nav .icon, .navbar-icon");
elements.navDropdownMenus = document.querySelectorAll(".dropdown-menu");
}
function setMode(mode) {
var event = new CustomEvent("modeChanged", { detail: mode });
@@ -48,22 +48,22 @@ function setMode(mode) {
elements.searchBar.classList.add("dark-mode-search");
}
if (elements && elements.formControls) {
elements.formControls.forEach(input => input.classList.add("bg-dark", "text-white"));
elements.formControls.forEach((input) => input.classList.add("bg-dark", "text-white"));
}
if (elements && elements.navbar) {
elements.navbar.forEach(navElement => {
elements.navbar.forEach((navElement) => {
navElement.classList.remove("navbar-light", "bg-light");
navElement.classList.add("navbar-dark", "bg-dark");
});
}
if (elements && elements.navDropdownMenus) {
elements.navDropdownMenus.forEach(menu => menu.classList.add("dropdown-menu-dark"));
elements.navDropdownMenus.forEach((menu) => menu.classList.add("dropdown-menu-dark"));
}
if (elements && elements.navIcons) {
elements.navIcons.forEach(icon => (icon.style.filter = "invert(1)"));
elements.navIcons.forEach((icon) => (icon.style.filter = "invert(1)"));
}
var tables = document.querySelectorAll(".table");
tables.forEach(table => {
tables.forEach((table) => {
table.classList.add("table-dark");
});
if (jumbotron) {
@@ -78,22 +78,22 @@ function setMode(mode) {
elements.searchBar.classList.remove("dark-mode-search");
}
if (elements && elements.formControls) {
elements.formControls.forEach(input => input.classList.remove("bg-dark", "text-white"));
elements.formControls.forEach((input) => input.classList.remove("bg-dark", "text-white"));
}
if (elements && elements.navbar) {
elements.navbar.forEach(navElement => {
elements.navbar.forEach((navElement) => {
navElement.classList.remove("navbar-dark", "bg-dark");
navElement.classList.add("navbar-light", "bg-light");
});
}
if (elements && elements.navDropdownMenus) {
elements.navDropdownMenus.forEach(menu => menu.classList.remove("dropdown-menu-dark"));
elements.navDropdownMenus.forEach((menu) => menu.classList.remove("dropdown-menu-dark"));
}
if (elements && elements.navIcons) {
elements.navIcons.forEach(icon => (icon.style.filter = "none"));
elements.navIcons.forEach((icon) => (icon.style.filter = "none"));
}
var tables = document.querySelectorAll(".table-dark");
tables.forEach(table => {
tables.forEach((table) => {
table.classList.remove("table-dark");
});
if (jumbotron) {
@@ -108,43 +108,43 @@ function setMode(mode) {
}
function toggleDarkMode() {
var currentTime = Date.now()
var currentTime = Date.now();
if (currentTime - lastToggleTime < 1000) {
toggleCount++
toggleCount++;
} else {
toggleCount = 1
toggleCount = 1;
}
lastToggleTime = currentTime
lastToggleTime = currentTime;
if (toggleCount >= 18) {
localStorage.setItem("dark-mode", "rainbow")
setMode("rainbow")
localStorage.setItem("dark-mode", "rainbow");
setMode("rainbow");
} else if (localStorage.getItem("dark-mode") == "on") {
localStorage.setItem("dark-mode", "off")
setMode("off")
localStorage.setItem("dark-mode", "off");
setMode("off");
} else {
localStorage.setItem("dark-mode", "on")
setMode("on")
localStorage.setItem("dark-mode", "on");
setMode("on");
}
}
document.addEventListener("DOMContentLoaded", function () {
getElements()
getElements();
var currentMode = localStorage.getItem("dark-mode")
var currentMode = localStorage.getItem("dark-mode");
if (currentMode === "on" || currentMode === "off" || currentMode === "rainbow") {
setMode(currentMode)
setMode(currentMode);
} else if (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches) {
setMode("on")
setMode("on");
} else {
setMode("off")
setMode("off");
}
var darkModeToggle = document.getElementById("dark-mode-toggle");
if (darkModeToggle !== null) {
darkModeToggle.addEventListener("click", function (event) {
event.preventDefault();
toggleDarkMode();
});
}
})
darkModeToggle.addEventListener("click", function (event) {
event.preventDefault();
toggleDarkMode();
});
}
});

View File

@@ -1,242 +1,235 @@
function showErrorBanner(message, stackTrace) {
const errorContainer = document.getElementById("errorContainer");
errorContainer.style.display = "block"; // Display the banner
document.querySelector("#errorContainer .alert-heading").textContent = "Error";
document.querySelector("#errorContainer p").textContent = message;
document.querySelector("#traceContent").textContent = stackTrace;
const errorContainer = document.getElementById("errorContainer");
errorContainer.style.display = "block"; // Display the banner
document.querySelector("#errorContainer .alert-heading").textContent = "Error";
document.querySelector("#errorContainer p").textContent = message;
document.querySelector("#traceContent").textContent = stackTrace;
}
let firstErrorOccurred = false;
$(document).ready(function() {
$('form').submit(async function(event) {
event.preventDefault();
firstErrorOccurred = false;
const url = this.action;
const files = $('#fileInput-input')[0].files;
const formData = new FormData(this);
$(document).ready(function () {
$("form").submit(async function (event) {
event.preventDefault();
firstErrorOccurred = false;
const url = this.action;
const files = $("#fileInput-input")[0].files;
const formData = new FormData(this);
// Remove empty file entries
for (let [key, value] of formData.entries()) {
if (value instanceof File && !value.name) {
formData.delete(key);
}
// Remove empty file entries
for (let [key, value] of formData.entries()) {
if (value instanceof File && !value.name) {
formData.delete(key);
}
}
const override = $("#override").val() || "";
const originalButtonText = $("#submitBtn").text();
$("#submitBtn").text("Processing...");
console.log(override);
try {
if (remoteCall === true) {
if (override === "multi" || (!multiple && files.length > 1 && override !== "single")) {
await submitMultiPdfForm(url, files);
} else {
await handleSingleDownload(url, formData);
}
const override = $('#override').val() || '';
const originalButtonText = $('#submitBtn').text();
$('#submitBtn').text('Processing...');
console.log(override);
try {
if(remoteCall === true) {
if (override === 'multi' || (!multiple && files.length > 1) && override !== 'single' ) {
await submitMultiPdfForm(url, files);
} else {
await handleSingleDownload(url, formData);
}
}
$('#submitBtn').text(originalButtonText);
} catch (error) {
handleDownloadError(error);
$('#submitBtn').text(originalButtonText);
console.error(error);
}
});
}
$("#submitBtn").text(originalButtonText);
} catch (error) {
handleDownloadError(error);
$("#submitBtn").text(originalButtonText);
console.error(error);
}
});
});
async function handleSingleDownload(url, formData, isMulti = false, isZip = false) {
try {
const response = await fetch(url, { method: "POST", body: formData });
const contentType = response.headers.get("content-type");
if (!response.ok) {
if (contentType && contentType.includes("application/json")) {
return handleJsonResponse(response);
console.error("Throwing error banner, response was not okay");
}
throw new Error(`HTTP error! status: ${response.status}`);
}
async function handleSingleDownload(url, formData, isMulti = false , isZip = false) {
try {
const response = await fetch(url, { method: 'POST', body: formData });
const contentType = response.headers.get('content-type');
const contentDisposition = response.headers.get("Content-Disposition");
let filename = getFilenameFromContentDisposition(contentDisposition);
if (!response.ok) {
if (contentType && contentType.includes('application/json')) {
return handleJsonResponse(response);
console.error('Throwing error banner, response was not okay');
}
throw new Error(`HTTP error! status: ${response.status}`);
}
const contentDisposition = response.headers.get('Content-Disposition');
let filename = getFilenameFromContentDisposition(contentDisposition);
const blob = await response.blob();
if (contentType.includes('application/pdf') || contentType.includes('image/')) {
return handleResponse(blob, filename, !isMulti, isZip);
} else {
return handleResponse(blob, filename, false, isZip);
}
} catch (error) {
console.error('Error in handleSingleDownload:', error);
throw error; // Re-throw the error if you want it to be handled higher up.
}
const blob = await response.blob();
if (contentType.includes("application/pdf") || contentType.includes("image/")) {
return handleResponse(blob, filename, !isMulti, isZip);
} else {
return handleResponse(blob, filename, false, isZip);
}
} catch (error) {
console.error("Error in handleSingleDownload:", error);
throw error; // Re-throw the error if you want it to be handled higher up.
}
}
function getFilenameFromContentDisposition(contentDisposition) {
let filename;
let filename;
if (contentDisposition && contentDisposition.indexOf('attachment') !== -1) {
filename = decodeURIComponent(contentDisposition.split('filename=')[1].replace(/"/g, '')).trim();
} else {
// If the Content-Disposition header is not present or does not contain the filename, use a default filename
filename = 'download';
}
if (contentDisposition && contentDisposition.indexOf("attachment") !== -1) {
filename = decodeURIComponent(contentDisposition.split("filename=")[1].replace(/"/g, "")).trim();
} else {
// If the Content-Disposition header is not present or does not contain the filename, use a default filename
filename = "download";
}
return filename;
return filename;
}
async function handleJsonResponse(response) {
const json = await response.json();
const errorMessage = JSON.stringify(json, null, 2);
if (errorMessage.toLowerCase().includes('the password is incorrect') || errorMessage.toLowerCase().includes('Password is not provided') || errorMessage.toLowerCase().includes('PDF contains an encryption dictionary')) {
if (!firstErrorOccurred) {
firstErrorOccurred = true;
alert(pdfPasswordPrompt);
}
} else {
showErrorBanner(json.error + ':' + json.message, json.trace);
}
const json = await response.json();
const errorMessage = JSON.stringify(json, null, 2);
if (
errorMessage.toLowerCase().includes("the password is incorrect") ||
errorMessage.toLowerCase().includes("Password is not provided") ||
errorMessage.toLowerCase().includes("PDF contains an encryption dictionary")
) {
if (!firstErrorOccurred) {
firstErrorOccurred = true;
alert(pdfPasswordPrompt);
}
} else {
showErrorBanner(json.error + ":" + json.message, json.trace);
}
}
async function handleResponse(blob, filename, considerViewOptions = false, isZip = false) {
if (!blob) return;
const downloadOption = localStorage.getItem('downloadOption');
if (considerViewOptions) {
if (downloadOption === 'sameWindow') {
const url = URL.createObjectURL(blob);
window.location.href = url;
return;
} else if (downloadOption === 'newWindow') {
const url = URL.createObjectURL(blob);
window.open(url, '_blank');
return;
}
}
if(!isZip){
downloadFile(blob, filename);
}
return { filename, blob };
if (!blob) return;
const downloadOption = localStorage.getItem("downloadOption");
if (considerViewOptions) {
if (downloadOption === "sameWindow") {
const url = URL.createObjectURL(blob);
window.location.href = url;
return;
} else if (downloadOption === "newWindow") {
const url = URL.createObjectURL(blob);
window.open(url, "_blank");
return;
}
}
if (!isZip) {
downloadFile(blob, filename);
}
return { filename, blob };
}
function handleDownloadError(error) {
const errorMessage = error.message;
showErrorBanner(errorMessage);
const errorMessage = error.message;
showErrorBanner(errorMessage);
}
let urls = []; // An array to hold all the URLs
function downloadFile(blob, filename) {
if (!(blob instanceof Blob)) {
console.error('Invalid blob passed to downloadFile function');
return;
}
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename;
a.click();
urls.push(url); // Store the URL so it doesn't get garbage collected too soon
if (!(blob instanceof Blob)) {
console.error("Invalid blob passed to downloadFile function");
return;
}
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = filename;
a.click();
urls.push(url); // Store the URL so it doesn't get garbage collected too soon
return { filename, blob };
return { filename, blob };
}
async function submitMultiPdfForm(url, files) {
const zipThreshold = parseInt(localStorage.getItem('zipThreshold'), 10) || 4;
const zipFiles = files.length > zipThreshold;
let jszip = null;
// Show the progress bar
$('#progressBarContainer').show();
// Initialize the progress bar
const zipThreshold = parseInt(localStorage.getItem("zipThreshold"), 10) || 4;
const zipFiles = files.length > zipThreshold;
let jszip = null;
// Show the progress bar
$("#progressBarContainer").show();
// Initialize the progress bar
let progressBar = $('#progressBar');
progressBar.css('width', '0%');
progressBar.attr('aria-valuenow', 0);
progressBar.attr('aria-valuemax', files.length);
let progressBar = $("#progressBar");
progressBar.css("width", "0%");
progressBar.attr("aria-valuenow", 0);
progressBar.attr("aria-valuemax", files.length);
if (zipFiles) {
jszip = new JSZip();
}
if (zipFiles) {
jszip = new JSZip();
}
// Get the form with the method attribute set to POST
let postForm = document.querySelector('form[method="POST"]');
// Get the form with the method attribute set to POST
let postForm = document.querySelector('form[method="POST"]');
// Get existing form data
let formData;
if (postForm) {
formData = new FormData($(postForm)[0]); // Convert the form to a jQuery object and get the raw DOM element
} else {
console.log("No form with POST method found.");
}
//Remove file to reuse parameters for other runs
formData.delete('fileInput');
// Remove empty file entries
for (let [key, value] of formData.entries()) {
if (value instanceof File && !value.name) {
formData.delete(key);
}
// Get existing form data
let formData;
if (postForm) {
formData = new FormData($(postForm)[0]); // Convert the form to a jQuery object and get the raw DOM element
} else {
console.log("No form with POST method found.");
}
//Remove file to reuse parameters for other runs
formData.delete("fileInput");
// Remove empty file entries
for (let [key, value] of formData.entries()) {
if (value instanceof File && !value.name) {
formData.delete(key);
}
const CONCURRENCY_LIMIT = 8;
const chunks = [];
for (let i = 0; i < Array.from(files).length; i += CONCURRENCY_LIMIT) {
chunks.push(Array.from(files).slice(i, i + CONCURRENCY_LIMIT));
}
}
const CONCURRENCY_LIMIT = 8;
const chunks = [];
for (let i = 0; i < Array.from(files).length; i += CONCURRENCY_LIMIT) {
chunks.push(Array.from(files).slice(i, i + CONCURRENCY_LIMIT));
}
for (const chunk of chunks) {
const promises = chunk.map(async file => {
let fileFormData = new FormData();
fileFormData.append('fileInput', file);
console.log(fileFormData);
// Add other form data
for (let pair of formData.entries()) {
fileFormData.append(pair[0], pair[1]);
console.log(pair[0]+ ', ' + pair[1]);
}
for (const chunk of chunks) {
const promises = chunk.map(async (file) => {
let fileFormData = new FormData();
fileFormData.append("fileInput", file);
console.log(fileFormData);
// Add other form data
for (let pair of formData.entries()) {
fileFormData.append(pair[0], pair[1]);
console.log(pair[0] + ", " + pair[1]);
}
try {
const downloadDetails = await handleSingleDownload(url, fileFormData, true, zipFiles);
console.log(downloadDetails);
if (zipFiles) {
jszip.file(downloadDetails.filename, downloadDetails.blob);
} else {
//downloadFile(downloadDetails.blob, downloadDetails.filename);
}
updateProgressBar(progressBar, Array.from(files).length);
} catch (error) {
handleDownloadError(error);
console.error(error);
}
});
await Promise.all(promises);
try {
const downloadDetails = await handleSingleDownload(url, fileFormData, true, zipFiles);
console.log(downloadDetails);
if (zipFiles) {
jszip.file(downloadDetails.filename, downloadDetails.blob);
} else {
//downloadFile(downloadDetails.blob, downloadDetails.filename);
}
updateProgressBar(progressBar, Array.from(files).length);
} catch (error) {
handleDownloadError(error);
console.error(error);
}
});
await Promise.all(promises);
}
}
if (zipFiles) {
try {
const content = await jszip.generateAsync({ type: "blob" });
downloadFile(content, "files.zip");
} catch (error) {
console.error('Error generating ZIP file: ' + error);
}
}
progressBar.css('width', '100%');
progressBar.attr('aria-valuenow', Array.from(files).length);
if (zipFiles) {
try {
const content = await jszip.generateAsync({ type: "blob" });
downloadFile(content, "files.zip");
} catch (error) {
console.error("Error generating ZIP file: " + error);
}
}
progressBar.css("width", "100%");
progressBar.attr("aria-valuenow", Array.from(files).length);
}
function updateProgressBar(progressBar, files) {
let progress = ((progressBar.attr('aria-valuenow') / files.length) * 100) + (100 / files.length);
progressBar.css('width', progress + '%');
progressBar.attr('aria-valuenow', parseInt(progressBar.attr('aria-valuenow')) + 1);
let progress = (progressBar.attr("aria-valuenow") / files.length) * 100 + 100 / files.length;
progressBar.css("width", progress + "%");
progressBar.attr("aria-valuenow", parseInt(progressBar.attr("aria-valuenow")) + 1);
}
window.addEventListener('unload', () => {
for (const url of urls) {
URL.revokeObjectURL(url);
}
window.addEventListener("unload", () => {
for (const url of urls) {
URL.revokeObjectURL(url);
}
});

View File

@@ -1,282 +1,287 @@
const DraggableUtils = {
boxDragContainer: document.getElementById("box-drag-container"),
pdfCanvas: document.getElementById("pdf-canvas"),
nextId: 0,
pdfDoc: null,
pageIndex: 0,
documentsMap: new Map(),
boxDragContainer: document.getElementById('box-drag-container'),
pdfCanvas: document.getElementById('pdf-canvas'),
nextId: 0,
pdfDoc: null,
pageIndex: 0,
documentsMap: new Map(),
init() {
interact(".draggable-canvas")
.draggable({
listeners: {
move: (event) => {
const target = event.target;
const x = (parseFloat(target.getAttribute("data-bs-x")) || 0) + event.dx;
const y = (parseFloat(target.getAttribute("data-bs-y")) || 0) + event.dy;
init() {
interact('.draggable-canvas')
.draggable({
listeners: {
move: (event) => {
const target = event.target;
const x = (parseFloat(target.getAttribute('data-bs-x')) || 0) + event.dx;
const y = (parseFloat(target.getAttribute('data-bs-y')) || 0) + event.dy;
target.style.transform = `translate(${x}px, ${y}px)`;
target.setAttribute("data-bs-x", x);
target.setAttribute("data-bs-y", y);
target.style.transform = `translate(${x}px, ${y}px)`;
target.setAttribute('data-bs-x', x);
target.setAttribute('data-bs-y', y);
this.onInteraction(target);
},
},
})
.resizable({
edges: { left: true, right: true, bottom: true, top: true },
listeners: {
move: (event) => {
var target = event.target
var x = (parseFloat(target.getAttribute('data-bs-x')) || 0)
var y = (parseFloat(target.getAttribute('data-bs-y')) || 0)
this.onInteraction(target);
},
},
})
.resizable({
edges: { left: true, right: true, bottom: true, top: true },
listeners: {
move: (event) => {
var target = event.target;
var x = parseFloat(target.getAttribute("data-bs-x")) || 0;
var y = parseFloat(target.getAttribute("data-bs-y")) || 0;
// check if control key is pressed
if (event.ctrlKey) {
const aspectRatio = target.offsetWidth / target.offsetHeight;
// preserve aspect ratio
let width = event.rect.width;
let height = event.rect.height;
const aspectRatio = target.offsetWidth / target.offsetHeight;
// preserve aspect ratio
let width = event.rect.width;
let height = event.rect.height;
if (Math.abs(event.deltaRect.width) >= Math.abs(event.deltaRect.height)) {
height = width / aspectRatio;
} else {
width = height * aspectRatio;
}
if (Math.abs(event.deltaRect.width) >= Math.abs(event.deltaRect.height)) {
height = width / aspectRatio;
} else {
width = height * aspectRatio;
}
event.rect.width = width;
event.rect.height = height;
event.rect.width = width;
event.rect.height = height;
}
target.style.width = event.rect.width + 'px'
target.style.height = event.rect.height + 'px'
target.style.width = event.rect.width + "px";
target.style.height = event.rect.height + "px";
// translate when resizing from top or left edges
x += event.deltaRect.left
y += event.deltaRect.top
x += event.deltaRect.left;
y += event.deltaRect.top;
target.style.transform = 'translate(' + x + 'px,' + y + 'px)'
target.style.transform = "translate(" + x + "px," + y + "px)";
target.setAttribute('data-bs-x', x)
target.setAttribute('data-bs-y', y)
target.textContent = Math.round(event.rect.width) + '\u00D7' + Math.round(event.rect.height)
target.setAttribute("data-bs-x", x);
target.setAttribute("data-bs-y", y);
target.textContent = Math.round(event.rect.width) + "\u00D7" + Math.round(event.rect.height);
this.onInteraction(target);
},
},
},
modifiers: [
interact.modifiers.restrictSize({
min: { width: 5, height: 5 },
}),
],
inertia: true,
});
},
onInteraction(target) {
this.boxDragContainer.appendChild(target);
},
modifiers: [
interact.modifiers.restrictSize({
min: { width: 5, height: 5 },
}),
],
inertia: true,
});
},
onInteraction(target) {
this.boxDragContainer.appendChild(target);
},
createDraggableCanvas() {
const createdCanvas = document.createElement('canvas');
createdCanvas.id = `draggable-canvas-${this.nextId++}`;
createdCanvas.classList.add("draggable-canvas");
createDraggableCanvas() {
const createdCanvas = document.createElement("canvas");
createdCanvas.id = `draggable-canvas-${this.nextId++}`;
createdCanvas.classList.add("draggable-canvas");
const x = 0;
const y = 20;
createdCanvas.style.transform = `translate(${x}px, ${y}px)`;
createdCanvas.setAttribute('data-bs-x', x);
createdCanvas.setAttribute('data-bs-y', y);
const x = 0;
const y = 20;
createdCanvas.style.transform = `translate(${x}px, ${y}px)`;
createdCanvas.setAttribute("data-bs-x", x);
createdCanvas.setAttribute("data-bs-y", y);
createdCanvas.onclick = e => this.onInteraction(e.target);
createdCanvas.onclick = (e) => this.onInteraction(e.target);
this.boxDragContainer.appendChild(createdCanvas);
return createdCanvas;
},
createDraggableCanvasFromUrl(dataUrl) {
return new Promise((resolve) => {
var myImage = new Image();
myImage.src = dataUrl;
myImage.onload = () => {
var createdCanvas = this.createDraggableCanvas();
this.boxDragContainer.appendChild(createdCanvas);
return createdCanvas;
},
createDraggableCanvasFromUrl(dataUrl) {
return new Promise((resolve) => {
var myImage = new Image();
myImage.src = dataUrl;
myImage.onload = () => {
var createdCanvas = this.createDraggableCanvas();
createdCanvas.width = myImage.width;
createdCanvas.height = myImage.height;
createdCanvas.width = myImage.width;
createdCanvas.height = myImage.height;
const imgAspect = myImage.width / myImage.height;
const pdfAspect = this.boxDragContainer.offsetWidth / this.boxDragContainer.offsetHeight;
const imgAspect = myImage.width / myImage.height;
const pdfAspect = this.boxDragContainer.offsetWidth / this.boxDragContainer.offsetHeight;
var scaleMultiplier;
if (imgAspect > pdfAspect) {
scaleMultiplier = this.boxDragContainer.offsetWidth / myImage.width;
} else {
scaleMultiplier = this.boxDragContainer.offsetHeight / myImage.height;
}
var newWidth = createdCanvas.width;
var newHeight = createdCanvas.height;
if (scaleMultiplier < 1) {
newWidth = newWidth * scaleMultiplier;
newHeight = newHeight * scaleMultiplier;
}
createdCanvas.style.width = newWidth+"px";
createdCanvas.style.height = newHeight+"px";
var myContext = createdCanvas.getContext("2d");
myContext.drawImage(myImage,0,0);
resolve(createdCanvas);
}
})
},
deleteAllDraggableCanvases() {
this.boxDragContainer.querySelectorAll(".draggable-canvas").forEach(el => el.remove());
},
deleteDraggableCanvas(element) {
if (element) {
element.remove();
}
},
getLastInteracted() {
return this.boxDragContainer.querySelector(".draggable-canvas:last-of-type");
},
storePageContents() {
var pagesMap = this.documentsMap.get(this.pdfDoc);
if (!pagesMap) {
pagesMap = {};
}
const elements = [...this.boxDragContainer.querySelectorAll(".draggable-canvas")];
const draggablesData = elements.map(el => {return{element:el, offsetWidth:el.offsetWidth, offsetHeight:el.offsetHeight}});
elements.forEach(el => this.boxDragContainer.removeChild(el));
pagesMap[this.pageIndex] = draggablesData;
pagesMap[this.pageIndex+"-offsetWidth"] = this.pdfCanvas.offsetWidth;
pagesMap[this.pageIndex+"-offsetHeight"] = this.pdfCanvas.offsetHeight;
this.documentsMap.set(this.pdfDoc, pagesMap);
},
loadPageContents() {
var pagesMap = this.documentsMap.get(this.pdfDoc);
this.deleteAllDraggableCanvases();
if (!pagesMap) {
return;
}
const draggablesData = pagesMap[this.pageIndex];
if (draggablesData) {
draggablesData.forEach(draggableData => this.boxDragContainer.appendChild(draggableData.element));
}
this.documentsMap.set(this.pdfDoc, pagesMap);
},
async renderPage(pdfDocument, pageIdx) {
this.pdfDoc = pdfDocument ? pdfDocument : this.pdfDoc;
this.pageIndex = pageIdx;
// persist
const page = await this.pdfDoc.getPage(this.pageIndex+1);
// set the canvas size to the size of the page
if (page.rotate == 90 || page.rotate == 270) {
this.pdfCanvas.width = page.view[3];
this.pdfCanvas.height = page.view[2];
var scaleMultiplier;
if (imgAspect > pdfAspect) {
scaleMultiplier = this.boxDragContainer.offsetWidth / myImage.width;
} else {
this.pdfCanvas.width = page.view[2];
this.pdfCanvas.height = page.view[3];
scaleMultiplier = this.boxDragContainer.offsetHeight / myImage.height;
}
// render the page onto the canvas
var renderContext = {
canvasContext: this.pdfCanvas.getContext("2d"),
viewport: page.getViewport({ scale: 1 })
var newWidth = createdCanvas.width;
var newHeight = createdCanvas.height;
if (scaleMultiplier < 1) {
newWidth = newWidth * scaleMultiplier;
newHeight = newHeight * scaleMultiplier;
}
createdCanvas.style.width = newWidth + "px";
createdCanvas.style.height = newHeight + "px";
var myContext = createdCanvas.getContext("2d");
myContext.drawImage(myImage, 0, 0);
resolve(createdCanvas);
};
});
},
deleteAllDraggableCanvases() {
this.boxDragContainer.querySelectorAll(".draggable-canvas").forEach((el) => el.remove());
},
deleteDraggableCanvas(element) {
if (element) {
element.remove();
}
},
getLastInteracted() {
return this.boxDragContainer.querySelector(".draggable-canvas:last-of-type");
},
storePageContents() {
var pagesMap = this.documentsMap.get(this.pdfDoc);
if (!pagesMap) {
pagesMap = {};
}
const elements = [...this.boxDragContainer.querySelectorAll(".draggable-canvas")];
const draggablesData = elements.map((el) => {
return {
element: el,
offsetWidth: el.offsetWidth,
offsetHeight: el.offsetHeight,
};
});
elements.forEach((el) => this.boxDragContainer.removeChild(el));
pagesMap[this.pageIndex] = draggablesData;
pagesMap[this.pageIndex + "-offsetWidth"] = this.pdfCanvas.offsetWidth;
pagesMap[this.pageIndex + "-offsetHeight"] = this.pdfCanvas.offsetHeight;
this.documentsMap.set(this.pdfDoc, pagesMap);
},
loadPageContents() {
var pagesMap = this.documentsMap.get(this.pdfDoc);
this.deleteAllDraggableCanvases();
if (!pagesMap) {
return;
}
const draggablesData = pagesMap[this.pageIndex];
if (draggablesData) {
draggablesData.forEach((draggableData) => this.boxDragContainer.appendChild(draggableData.element));
}
this.documentsMap.set(this.pdfDoc, pagesMap);
},
async renderPage(pdfDocument, pageIdx) {
this.pdfDoc = pdfDocument ? pdfDocument : this.pdfDoc;
this.pageIndex = pageIdx;
// persist
const page = await this.pdfDoc.getPage(this.pageIndex + 1);
// set the canvas size to the size of the page
if (page.rotate == 90 || page.rotate == 270) {
this.pdfCanvas.width = page.view[3];
this.pdfCanvas.height = page.view[2];
} else {
this.pdfCanvas.width = page.view[2];
this.pdfCanvas.height = page.view[3];
}
// render the page onto the canvas
var renderContext = {
canvasContext: this.pdfCanvas.getContext("2d"),
viewport: page.getViewport({ scale: 1 }),
};
await page.render(renderContext).promise;
//return pdfCanvas.toDataURL();
},
async incrementPage() {
if (this.pageIndex < this.pdfDoc.numPages - 1) {
this.storePageContents();
await this.renderPage(this.pdfDoc, this.pageIndex + 1);
this.loadPageContents();
}
},
async decrementPage() {
if (this.pageIndex > 0) {
this.storePageContents();
await this.renderPage(this.pdfDoc, this.pageIndex - 1);
this.loadPageContents();
}
},
parseTransform(element) {},
async getOverlayedPdfDocument() {
const pdfBytes = await this.pdfDoc.getData();
const pdfDocModified = await PDFLib.PDFDocument.load(pdfBytes, {
ignoreEncryption: true,
});
this.storePageContents();
const pagesMap = this.documentsMap.get(this.pdfDoc);
for (let pageIdx in pagesMap) {
if (pageIdx.includes("offset")) {
continue;
}
console.log(typeof pageIdx);
const page = pdfDocModified.getPage(parseInt(pageIdx));
const draggablesData = pagesMap[pageIdx];
const offsetWidth = pagesMap[pageIdx + "-offsetWidth"];
const offsetHeight = pagesMap[pageIdx + "-offsetHeight"];
for (const draggableData of draggablesData) {
// embed the draggable canvas
const draggableElement = draggableData.element;
const response = await fetch(draggableElement.toDataURL());
const draggableImgBytes = await response.arrayBuffer();
const pdfImageObject = await pdfDocModified.embedPng(draggableImgBytes);
// calculate the position in the pdf document
const tansform = draggableElement.style.transform.replace(/[^.,-\d]/g, "");
const transformComponents = tansform.split(",");
const draggablePositionPixels = {
x: parseFloat(transformComponents[0]),
y: parseFloat(transformComponents[1]),
width: draggableData.offsetWidth,
height: draggableData.offsetHeight,
};
const draggablePositionRelative = {
x: draggablePositionPixels.x / offsetWidth,
y: draggablePositionPixels.y / offsetHeight,
width: draggablePositionPixels.width / offsetWidth,
height: draggablePositionPixels.height / offsetHeight,
};
const draggablePositionPdf = {
x: draggablePositionRelative.x * page.getWidth(),
y: draggablePositionRelative.y * page.getHeight(),
width: draggablePositionRelative.width * page.getWidth(),
height: draggablePositionRelative.height * page.getHeight(),
};
await page.render(renderContext).promise;
//return pdfCanvas.toDataURL();
},
async incrementPage() {
if (this.pageIndex < this.pdfDoc.numPages-1) {
this.storePageContents();
await this.renderPage(this.pdfDoc, this.pageIndex+1);
this.loadPageContents();
}
},
async decrementPage() {
if (this.pageIndex > 0) {
this.storePageContents();
await this.renderPage(this.pdfDoc, this.pageIndex-1);
this.loadPageContents();
}
},
// draw the image
page.drawImage(pdfImageObject, {
x: draggablePositionPdf.x,
y: page.getHeight() - draggablePositionPdf.y - draggablePositionPdf.height,
width: draggablePositionPdf.width,
height: draggablePositionPdf.height,
});
}
}
parseTransform(element) {
},
async getOverlayedPdfDocument() {
const pdfBytes = await this.pdfDoc.getData();
const pdfDocModified = await PDFLib.PDFDocument.load(pdfBytes, { ignoreEncryption: true });
this.storePageContents();
const pagesMap = this.documentsMap.get(this.pdfDoc);
for (let pageIdx in pagesMap) {
if (pageIdx.includes("offset")) {
continue;
}
console.log(typeof pageIdx);
const page = pdfDocModified.getPage(parseInt(pageIdx));
const draggablesData = pagesMap[pageIdx];
const offsetWidth = pagesMap[pageIdx+"-offsetWidth"];
const offsetHeight = pagesMap[pageIdx+"-offsetHeight"];
for (const draggableData of draggablesData) {
// embed the draggable canvas
const draggableElement = draggableData.element;
const response = await fetch(draggableElement.toDataURL());
const draggableImgBytes = await response.arrayBuffer();
const pdfImageObject = await pdfDocModified.embedPng(draggableImgBytes);
// calculate the position in the pdf document
const tansform = draggableElement.style.transform.replace(/[^.,-\d]/g, '');
const transformComponents = tansform.split(",");
const draggablePositionPixels = {
x: parseFloat(transformComponents[0]),
y: parseFloat(transformComponents[1]),
width: draggableData.offsetWidth,
height: draggableData.offsetHeight,
};
const draggablePositionRelative = {
x: draggablePositionPixels.x / offsetWidth,
y: draggablePositionPixels.y / offsetHeight,
width: draggablePositionPixels.width / offsetWidth,
height: draggablePositionPixels.height / offsetHeight,
}
const draggablePositionPdf = {
x: draggablePositionRelative.x * page.getWidth(),
y: draggablePositionRelative.y * page.getHeight(),
width: draggablePositionRelative.width * page.getWidth(),
height: draggablePositionRelative.height * page.getHeight(),
}
// draw the image
page.drawImage(pdfImageObject, {
x: draggablePositionPdf.x,
y: page.getHeight() - draggablePositionPdf.y - draggablePositionPdf.height,
width: draggablePositionPdf.width,
height: draggablePositionPdf.height,
});
}
}
this.loadPageContents();
return pdfDocModified;
},
}
this.loadPageContents();
return pdfDocModified;
},
};
document.addEventListener("DOMContentLoaded", () => {
DraggableUtils.init();
DraggableUtils.init();
});

View File

@@ -1,50 +1,50 @@
var traceVisible = false;
function toggletrace() {
var traceDiv = document.getElementById("trace");
if (!traceVisible) {
traceDiv.style.maxHeight = "500px";
traceVisible = true;
} else {
traceDiv.style.maxHeight = "0px";
traceVisible = false;
}
adjustContainerHeight();
var traceDiv = document.getElementById("trace");
if (!traceVisible) {
traceDiv.style.maxHeight = "500px";
traceVisible = true;
} else {
traceDiv.style.maxHeight = "0px";
traceVisible = false;
}
adjustContainerHeight();
}
function copytrace() {
var flip = false
if (!traceVisible) {
toggletrace()
flip = true
}
var traceContent = document.getElementById("traceContent");
var range = document.createRange();
range.selectNode(traceContent);
window.getSelection().removeAllRanges();
window.getSelection().addRange(range);
document.execCommand("copy");
window.getSelection().removeAllRanges();
if (flip) {
toggletrace()
}
var flip = false;
if (!traceVisible) {
toggletrace();
flip = true;
}
var traceContent = document.getElementById("traceContent");
var range = document.createRange();
range.selectNode(traceContent);
window.getSelection().removeAllRanges();
window.getSelection().addRange(range);
document.execCommand("copy");
window.getSelection().removeAllRanges();
if (flip) {
toggletrace();
}
}
function dismissError() {
var errorContainer = document.getElementById("errorContainer");
errorContainer.style.display = "none";
errorContainer.style.height = "0";
var errorContainer = document.getElementById("errorContainer");
errorContainer.style.display = "none";
errorContainer.style.height = "0";
}
function adjustContainerHeight() {
var errorContainer = document.getElementById("errorContainer");
var traceDiv = document.getElementById("trace");
if (traceVisible) {
errorContainer.style.height = errorContainer.scrollHeight - traceDiv.scrollHeight + traceDiv.offsetHeight + "px";
} else {
errorContainer.style.height = "auto";
}
var errorContainer = document.getElementById("errorContainer");
var traceDiv = document.getElementById("trace");
if (traceVisible) {
errorContainer.style.height = errorContainer.scrollHeight - traceDiv.scrollHeight + traceDiv.offsetHeight + "px";
} else {
errorContainer.style.height = "auto";
}
}
function showHelp() {
$('#helpModal').modal('show');
}
$("#helpModal").modal("show");
}

View File

@@ -1,45 +1,45 @@
function updateFavoritesDropdown() {
var dropdown = document.querySelector('#favoritesDropdown');
var dropdown = document.querySelector("#favoritesDropdown");
// Check if dropdown exists
if (!dropdown) {
console.error('Dropdown element with ID "favoritesDropdown" not found!');
return; // Exit the function
// Check if dropdown exists
if (!dropdown) {
console.error('Dropdown element with ID "favoritesDropdown" not found!');
return; // Exit the function
}
dropdown.innerHTML = ""; // Clear the current favorites
var hasFavorites = false;
for (var i = 0; i < localStorage.length; i++) {
var key = localStorage.key(i);
if (localStorage.getItem(key) === "favorite") {
// Find the corresponding navbar entry
var navbarEntry = document.querySelector(`a[href='${key}']`);
if (navbarEntry) {
// Create a new dropdown entry
var dropdownItem = document.createElement("a");
dropdownItem.className = "dropdown-item";
dropdownItem.href = navbarEntry.href;
dropdownItem.innerHTML = navbarEntry.innerHTML;
dropdown.appendChild(dropdownItem);
hasFavorites = true;
} else {
console.warn(`Navbar entry not found for key: ${key}`);
}
}
dropdown.innerHTML = ''; // Clear the current favorites
}
var hasFavorites = false;
for (var i = 0; i < localStorage.length; i++) {
var key = localStorage.key(i);
if (localStorage.getItem(key) === 'favorite') {
// Find the corresponding navbar entry
var navbarEntry = document.querySelector(`a[href='${key}']`);
if (navbarEntry) {
// Create a new dropdown entry
var dropdownItem = document.createElement('a');
dropdownItem.className = 'dropdown-item';
dropdownItem.href = navbarEntry.href;
dropdownItem.innerHTML = navbarEntry.innerHTML;
dropdown.appendChild(dropdownItem);
hasFavorites = true;
} else {
console.warn(`Navbar entry not found for key: ${key}`);
}
}
}
// Show or hide the default item based on whether there are any favorites
if (!hasFavorites) {
var defaultItem = document.createElement('a');
defaultItem.className = 'dropdown-item';
defaultItem.textContent = noFavourites;
dropdown.appendChild(defaultItem);
}
// Show or hide the default item based on whether there are any favorites
if (!hasFavorites) {
var defaultItem = document.createElement("a");
defaultItem.className = "dropdown-item";
defaultItem.textContent = noFavourites;
dropdown.appendChild(defaultItem);
}
}
// Ensure that the DOM content has been fully loaded before calling the function
document.addEventListener('DOMContentLoaded', function() {
console.log('DOMContentLoaded event fired');
updateFavoritesDropdown();
document.addEventListener("DOMContentLoaded", function () {
console.log("DOMContentLoaded event fired");
updateFavoritesDropdown();
});

View File

@@ -1,104 +1,107 @@
document.addEventListener('DOMContentLoaded', function() {
document.querySelectorAll('.custom-file-chooser').forEach(setupFileInput);
document.addEventListener("DOMContentLoaded", function () {
document.querySelectorAll(".custom-file-chooser").forEach(setupFileInput);
});
function setupFileInput(chooser) {
const elementId = chooser.getAttribute('data-bs-element-id');
const filesSelected = chooser.getAttribute('data-bs-files-selected');
const pdfPrompt = chooser.getAttribute('data-bs-pdf-prompt');
const elementId = chooser.getAttribute("data-bs-element-id");
const filesSelected = chooser.getAttribute("data-bs-files-selected");
const pdfPrompt = chooser.getAttribute("data-bs-pdf-prompt");
let allFiles = [];
let overlay;
let dragCounter = 0;
let allFiles = [];
let overlay;
let dragCounter = 0;
const dragenterListener = function() {
dragCounter++;
if (!overlay) {
overlay = document.createElement('div');
overlay.style.position = 'fixed';
overlay.style.top = 0;
overlay.style.left = 0;
overlay.style.width = '100%';
overlay.style.height = '100%';
overlay.style.background = 'rgba(0, 0, 0, 0.5)';
overlay.style.color = '#fff';
overlay.style.zIndex = '1000';
overlay.style.display = 'flex';
overlay.style.alignItems = 'center';
overlay.style.justifyContent = 'center';
overlay.style.pointerEvents = 'none';
overlay.innerHTML = '<p>Drop files anywhere to upload</p>';
document.getElementById('content-wrap').appendChild(overlay);
}
};
const dragenterListener = function () {
dragCounter++;
if (!overlay) {
overlay = document.createElement("div");
overlay.style.position = "fixed";
overlay.style.top = 0;
overlay.style.left = 0;
overlay.style.width = "100%";
overlay.style.height = "100%";
overlay.style.background = "rgba(0, 0, 0, 0.5)";
overlay.style.color = "#fff";
overlay.style.zIndex = "1000";
overlay.style.display = "flex";
overlay.style.alignItems = "center";
overlay.style.justifyContent = "center";
overlay.style.pointerEvents = "none";
overlay.innerHTML = "<p>Drop files anywhere to upload</p>";
document.getElementById("content-wrap").appendChild(overlay);
}
};
const dragleaveListener = function() {
dragCounter--;
if (dragCounter === 0) {
if (overlay) {
overlay.remove();
overlay = null;
}
}
};
const dragleaveListener = function () {
dragCounter--;
if (dragCounter === 0) {
if (overlay) {
overlay.remove();
overlay = null;
}
}
};
const dropListener = function(e) {
e.preventDefault();
const dt = e.dataTransfer;
const files = dt.files;
const dropListener = function (e) {
e.preventDefault();
const dt = e.dataTransfer;
const files = dt.files;
for (let i = 0; i < files.length; i++) {
allFiles.push(files[i]);
}
for (let i = 0; i < files.length; i++) {
allFiles.push(files[i]);
}
const dataTransfer = new DataTransfer();
allFiles.forEach(file => dataTransfer.items.add(file));
const dataTransfer = new DataTransfer();
allFiles.forEach((file) => dataTransfer.items.add(file));
const fileInput = document.getElementById(elementId);
fileInput.files = dataTransfer.files;
const fileInput = document.getElementById(elementId);
fileInput.files = dataTransfer.files;
if (overlay) {
overlay.remove();
overlay = null;
}
if (overlay) {
overlay.remove();
overlay = null;
}
dragCounter = 0;
dragCounter = 0;
fileInput.dispatchEvent(new Event('change', { bubbles: true }));
};
fileInput.dispatchEvent(new Event("change", { bubbles: true }));
};
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
document.body.addEventListener(eventName, preventDefaults, false);
["dragenter", "dragover", "dragleave", "drop"].forEach((eventName) => {
document.body.addEventListener(eventName, preventDefaults, false);
});
function preventDefaults(e) {
e.preventDefault();
e.stopPropagation();
}
document.body.addEventListener("dragenter", dragenterListener);
document.body.addEventListener("dragleave", dragleaveListener);
document.body.addEventListener("drop", dropListener);
$("#" + elementId).on("change", function (e) {
allFiles = Array.from(e.target.files);
handleFileInputChange(this);
});
function handleFileInputChange(inputElement) {
const files = allFiles;
const fileNames = files.map((f) => f.name);
const selectedFilesContainer = $(inputElement).siblings(".selected-files");
selectedFilesContainer.empty();
fileNames.forEach((fileName) => {
selectedFilesContainer.append("<div>" + fileName + "</div>");
});
function preventDefaults(e) {
e.preventDefault();
e.stopPropagation();
}
document.body.addEventListener('dragenter', dragenterListener);
document.body.addEventListener('dragleave', dragleaveListener);
document.body.addEventListener('drop', dropListener);
$("#" + elementId).on("change", function(e) {
allFiles = Array.from(e.target.files);
handleFileInputChange(this);
});
function handleFileInputChange(inputElement) {
const files = allFiles;
const fileNames = files.map(f => f.name);
const selectedFilesContainer = $(inputElement).siblings(".selected-files");
selectedFilesContainer.empty();
fileNames.forEach(fileName => {
selectedFilesContainer.append("<div>" + fileName + "</div>");
});
if (fileNames.length === 1) {
$(inputElement).siblings(".custom-file-label").addClass("selected").html(fileNames[0]);
} else if (fileNames.length > 1) {
$(inputElement).siblings(".custom-file-label").addClass("selected").html(fileNames.length + " " + filesSelected);
} else {
$(inputElement).siblings(".custom-file-label").addClass("selected").html(pdfPrompt);
}
if (fileNames.length === 1) {
$(inputElement).siblings(".custom-file-label").addClass("selected").html(fileNames[0]);
} else if (fileNames.length > 1) {
$(inputElement)
.siblings(".custom-file-label")
.addClass("selected")
.html(fileNames.length + " " + filesSelected);
} else {
$(inputElement).siblings(".custom-file-label").addClass("selected").html(pdfPrompt);
}
}
}

View File

@@ -1,292 +1,265 @@
function initializeGame() {
const gameContainer = document.getElementById('game-container');
const player = document.getElementById('player');
const gameContainer = document.getElementById("game-container");
const player = document.getElementById("player");
let playerSize = gameContainer.clientWidth * 0.0625; // 5% of container width
player.style.width = playerSize + 'px';
player.style.height = playerSize + 'px';
let playerSize = gameContainer.clientWidth * 0.0625; // 5% of container width
player.style.width = playerSize + "px";
player.style.height = playerSize + "px";
let playerX = gameContainer.clientWidth / 2 - playerSize / 2;
let playerY = gameContainer.clientHeight * 0.1;
const scoreElement = document.getElementById('score');
const levelElement = document.getElementById('level');
const livesElement = document.getElementById('lives');
const highScoreElement = document.getElementById('high-score');
let playerX = gameContainer.clientWidth / 2 - playerSize / 2;
let playerY = gameContainer.clientHeight * 0.1;
const scoreElement = document.getElementById("score");
const levelElement = document.getElementById("level");
const livesElement = document.getElementById("lives");
const highScoreElement = document.getElementById("high-score");
let pdfSize = gameContainer.clientWidth * 0.0625; // 5% of container width
let projectileWidth = gameContainer.clientWidth * 0.00625;// 0.00625; // 0.5% of container width
let projectileHeight = gameContainer.clientHeight * 0.01667; // 1% of container height
let pdfSize = gameContainer.clientWidth * 0.0625; // 5% of container width
let projectileWidth = gameContainer.clientWidth * 0.00625; // 0.00625; // 0.5% of container width
let projectileHeight = gameContainer.clientHeight * 0.01667; // 1% of container height
let paused = false;
let paused = false;
const fireRate = 200; // Time between shots in milliseconds
let lastProjectileTime = 0;
let lives = 3;
const fireRate = 200; // Time between shots in milliseconds
let lastProjectileTime = 0;
let lives = 3;
let highScore = localStorage.getItem("highScore") ? parseInt(localStorage.getItem("highScore")) : 0;
updateHighScore();
let highScore = localStorage.getItem('highScore') ? parseInt(localStorage.getItem('highScore')) : 0;
updateHighScore();
const keysPressed = {};
const pdfs = [];
const projectiles = [];
let score = 0;
let level = 1;
let pdfSpeed = 0.5;
let gameOver = false;
const keysPressed = {};
const pdfs = [];
const projectiles = [];
let score = 0;
let level = 1;
let pdfSpeed = 0.5;
let gameOver = false;
function handleKeys() {
if (keysPressed['ArrowLeft']) {
playerX -= 10;
}
if (keysPressed['ArrowRight']) {
playerX += 10;
}
if (keysPressed[' '] && !gameOver) {
const currentTime = new Date().getTime();
if (currentTime - lastProjectileTime >= fireRate) {
shootProjectile();
lastProjectileTime = currentTime;
}
}
updatePlayerPosition();
}
document.addEventListener('keydown', (event) => {
if (event.key === ' ') {
event.preventDefault();
}
keysPressed[event.key] = true;
handleKeys();
});
document.addEventListener('keyup', (event) => {
keysPressed[event.key] = false;
});
function updatePlayerPosition() {
player.style.left = playerX + 'px';
player.style.bottom = playerY + 'px';
function handleKeys() {
if (keysPressed["ArrowLeft"]) {
playerX -= 10;
}
function updateLives() {
livesElement.textContent = 'Lives: ' + lives;
if (keysPressed["ArrowRight"]) {
playerX += 10;
}
function updateHighScore() {
highScoreElement.textContent = 'High Score: ' + highScore;
if (keysPressed[" "] && !gameOver) {
const currentTime = new Date().getTime();
if (currentTime - lastProjectileTime >= fireRate) {
shootProjectile();
lastProjectileTime = currentTime;
}
}
function shootProjectile() {
const projectile = document.createElement('div');
projectile.classList.add('projectile');
projectile.style.backgroundColor = 'black';
projectile.style.width = projectileWidth + 'px';
projectile.style.height = projectileHeight + 'px';
projectile.style.left = (playerX + playerSize / 2 - projectileWidth / 2) + 'px';
projectile.style.top = (gameContainer.clientHeight - playerY - playerSize) + 'px';
gameContainer.appendChild(projectile);
projectiles.push(projectile);
}
function spawnPdf() {
const pdf = document.createElement('img');
pdf.src = 'images/file-earmark-pdf.svg';
pdf.classList.add('pdf');
pdf.style.width = pdfSize + 'px';
pdf.style.height = pdfSize + 'px';
pdf.style.left = Math.floor(Math.random() * (gameContainer.clientWidth - pdfSize)) + 'px';
pdf.style.top = '0px';
gameContainer.appendChild(pdf);
pdfs.push(pdf);
}
function resetEnemies() {
pdfs.forEach((pdf) => gameContainer.removeChild(pdf));
pdfs.length = 0;
}
function updateGame() {
if (gameOver || paused) return;
for (let pdfIndex = 0; pdfIndex < pdfs.length; pdfIndex++) {
const pdf = pdfs[pdfIndex];
const pdfY = parseFloat(pdf.style.top) + pdfSpeed;
if (pdfY + 50 > gameContainer.clientHeight) {
gameContainer.removeChild(pdf);
pdfs.splice(pdfIndex, 1);
// Deduct 2 points when a PDF gets past the player
score -= 0;
updateScore();
// Decrease lives and check if game over
lives--;
updateLives();
if (lives <= 0) {
endGame();
return;
}
} else {
pdf.style.top = pdfY + 'px';
// Check for collision with player
if (collisionDetected(player, pdf)) {
lives--;
updateLives();
resetEnemies();
if (lives <= 0) {
endGame();
return;
}
}
}
};
projectiles.forEach((projectile, projectileIndex) => {
const projectileY = parseInt(projectile.style.top) - 10;
if (projectileY < 0) {
gameContainer.removeChild(projectile);
projectiles.splice(projectileIndex, 1);
} else {
projectile.style.top = projectileY + 'px';
}
for (let pdfIndex = 0; pdfIndex < pdfs.length; pdfIndex++) {
const pdf = pdfs[pdfIndex];
if (collisionDetected(projectile, pdf)) {
gameContainer.removeChild(pdf);
gameContainer.removeChild(projectile);
pdfs.splice(pdfIndex, 1);
projectiles.splice(projectileIndex, 1);
score = score + 10;
updateScore();
break;
}
}
});
setTimeout(updateGame, 1000 / 60);
}
function resetGame() {
playerX = gameContainer.clientWidth / 2;
playerY = 50;
updatePlayerPosition();
pdfs.forEach((pdf) => gameContainer.removeChild(pdf));
projectiles.forEach((projectile) => gameContainer.removeChild(projectile));
pdfs.length = 0;
projectiles.length = 0;
score = 0;
level = 1;
lives = 3;
gameOver = false;
updateScore();
updateLives();
levelElement.textContent = 'Level: ' + level;
pdfSpeed = 1;
clearTimeout(spawnPdfTimeout); // Clear the existing spawnPdfTimeout
setTimeout(updateGame, 1000 / 60);
spawnPdfInterval();
}
function updateScore() {
scoreElement.textContent = 'Score: ' + score;
checkLevelUp();
}
function checkLevelUp() {
const newLevel = Math.floor(score / 100) + 1;
if (newLevel > level) {
level = newLevel;
levelElement.textContent = 'Level: ' + level;
pdfSpeed += 0.2;
}
}
function collisionDetected(a, b) {
const rectA = a.getBoundingClientRect();
const rectB = b.getBoundingClientRect();
return (
rectA.left < rectB.right &&
rectA.right > rectB.left &&
rectA.top < rectB.bottom &&
rectA.bottom > rectB.top
);
}
function endGame() {
gameOver = true;
if (score > highScore) {
highScore = score;
localStorage.setItem('highScore', highScore);
updateHighScore();
}
alert('Game Over! Your final score is: ' + score);
document.getElementById('game-container-wrapper').close();
}
let spawnPdfTimeout;
const BASE_SPAWN_INTERVAL_MS = 1250; // milliseconds before a new enemy spawns
const LEVEL_INCREASE_FACTOR_MS = 0; // milliseconds to decrease the spawn interval per level
const MAX_SPAWN_RATE_REDUCTION_MS = 800; // Max milliseconds from the base spawn interval
function spawnPdfInterval() {
console.log("spawnPdfInterval");
if (gameOver || paused) {
console.log("spawnPdfInterval 2");
clearTimeout(spawnPdfTimeout);
return;
}
console.log("spawnPdfInterval 3");
spawnPdf();
let spawnRateReduction = Math.min(level * LEVEL_INCREASE_FACTOR_MS, MAX_SPAWN_RATE_REDUCTION_MS);
let spawnRate = BASE_SPAWN_INTERVAL_MS - spawnRateReduction;
spawnPdfTimeout = setTimeout(spawnPdfInterval, spawnRate);
}
updatePlayerPosition();
updateGame();
spawnPdfInterval();
}
document.addEventListener("keydown", (event) => {
if (event.key === " ") {
event.preventDefault();
}
keysPressed[event.key] = true;
handleKeys();
});
document.addEventListener('visibilitychange', function() {
if (document.hidden) {
paused = true;
} else {
paused = false;
updateGame();
spawnPdfInterval();
document.addEventListener("keyup", (event) => {
keysPressed[event.key] = false;
});
function updatePlayerPosition() {
player.style.left = playerX + "px";
player.style.bottom = playerY + "px";
}
function updateLives() {
livesElement.textContent = "Lives: " + lives;
}
function updateHighScore() {
highScoreElement.textContent = "High Score: " + highScore;
}
function shootProjectile() {
const projectile = document.createElement("div");
projectile.classList.add("projectile");
projectile.style.backgroundColor = "black";
projectile.style.width = projectileWidth + "px";
projectile.style.height = projectileHeight + "px";
projectile.style.left = playerX + playerSize / 2 - projectileWidth / 2 + "px";
projectile.style.top = gameContainer.clientHeight - playerY - playerSize + "px";
gameContainer.appendChild(projectile);
projectiles.push(projectile);
}
function spawnPdf() {
const pdf = document.createElement("img");
pdf.src = "images/file-earmark-pdf.svg";
pdf.classList.add("pdf");
pdf.style.width = pdfSize + "px";
pdf.style.height = pdfSize + "px";
pdf.style.left = Math.floor(Math.random() * (gameContainer.clientWidth - pdfSize)) + "px";
pdf.style.top = "0px";
gameContainer.appendChild(pdf);
pdfs.push(pdf);
}
function resetEnemies() {
pdfs.forEach((pdf) => gameContainer.removeChild(pdf));
pdfs.length = 0;
}
function updateGame() {
if (gameOver || paused) return;
for (let pdfIndex = 0; pdfIndex < pdfs.length; pdfIndex++) {
const pdf = pdfs[pdfIndex];
const pdfY = parseFloat(pdf.style.top) + pdfSpeed;
if (pdfY + 50 > gameContainer.clientHeight) {
gameContainer.removeChild(pdf);
pdfs.splice(pdfIndex, 1);
// Deduct 2 points when a PDF gets past the player
score -= 0;
updateScore();
// Decrease lives and check if game over
lives--;
updateLives();
if (lives <= 0) {
endGame();
return;
}
} else {
pdf.style.top = pdfY + "px";
// Check for collision with player
if (collisionDetected(player, pdf)) {
lives--;
updateLives();
resetEnemies();
if (lives <= 0) {
endGame();
return;
}
}
}
}
projectiles.forEach((projectile, projectileIndex) => {
const projectileY = parseInt(projectile.style.top) - 10;
if (projectileY < 0) {
gameContainer.removeChild(projectile);
projectiles.splice(projectileIndex, 1);
} else {
projectile.style.top = projectileY + "px";
}
for (let pdfIndex = 0; pdfIndex < pdfs.length; pdfIndex++) {
const pdf = pdfs[pdfIndex];
if (collisionDetected(projectile, pdf)) {
gameContainer.removeChild(pdf);
gameContainer.removeChild(projectile);
pdfs.splice(pdfIndex, 1);
projectiles.splice(projectileIndex, 1);
score = score + 10;
updateScore();
break;
}
}
});
window.resetGame = resetGame;
setTimeout(updateGame, 1000 / 60);
}
function resetGame() {
playerX = gameContainer.clientWidth / 2;
playerY = 50;
updatePlayerPosition();
pdfs.forEach((pdf) => gameContainer.removeChild(pdf));
projectiles.forEach((projectile) => gameContainer.removeChild(projectile));
pdfs.length = 0;
projectiles.length = 0;
score = 0;
level = 1;
lives = 3;
gameOver = false;
updateScore();
updateLives();
levelElement.textContent = "Level: " + level;
pdfSpeed = 1;
clearTimeout(spawnPdfTimeout); // Clear the existing spawnPdfTimeout
setTimeout(updateGame, 1000 / 60);
spawnPdfInterval();
}
function updateScore() {
scoreElement.textContent = "Score: " + score;
checkLevelUp();
}
function checkLevelUp() {
const newLevel = Math.floor(score / 100) + 1;
if (newLevel > level) {
level = newLevel;
levelElement.textContent = "Level: " + level;
pdfSpeed += 0.2;
}
}
function collisionDetected(a, b) {
const rectA = a.getBoundingClientRect();
const rectB = b.getBoundingClientRect();
return rectA.left < rectB.right && rectA.right > rectB.left && rectA.top < rectB.bottom && rectA.bottom > rectB.top;
}
function endGame() {
gameOver = true;
if (score > highScore) {
highScore = score;
localStorage.setItem("highScore", highScore);
updateHighScore();
}
alert("Game Over! Your final score is: " + score);
document.getElementById("game-container-wrapper").close();
}
let spawnPdfTimeout;
const BASE_SPAWN_INTERVAL_MS = 1250; // milliseconds before a new enemy spawns
const LEVEL_INCREASE_FACTOR_MS = 0; // milliseconds to decrease the spawn interval per level
const MAX_SPAWN_RATE_REDUCTION_MS = 800; // Max milliseconds from the base spawn interval
function spawnPdfInterval() {
console.log("spawnPdfInterval");
if (gameOver || paused) {
console.log("spawnPdfInterval 2");
clearTimeout(spawnPdfTimeout);
return;
}
console.log("spawnPdfInterval 3");
spawnPdf();
let spawnRateReduction = Math.min(level * LEVEL_INCREASE_FACTOR_MS, MAX_SPAWN_RATE_REDUCTION_MS);
let spawnRate = BASE_SPAWN_INTERVAL_MS - spawnRateReduction;
spawnPdfTimeout = setTimeout(spawnPdfInterval, spawnRate);
}
updatePlayerPosition();
updateGame();
spawnPdfInterval();
document.addEventListener("visibilitychange", function () {
if (document.hidden) {
paused = true;
} else {
paused = false;
updateGame();
spawnPdfInterval();
}
});
window.resetGame = resetGame;
}
window.initializeGame = initializeGame;

View File

@@ -1,55 +1,52 @@
function compareVersions(version1, version2) {
const v1 = version1.split('.');
const v2 = version2.split('.');
const v1 = version1.split(".");
const v2 = version2.split(".");
for (let i = 0; i < v1.length || i < v2.length; i++) {
const n1 = parseInt(v1[i]) || 0;
const n2 = parseInt(v2[i]) || 0;
for (let i = 0; i < v1.length || i < v2.length; i++) {
const n1 = parseInt(v1[i]) || 0;
const n2 = parseInt(v2[i]) || 0;
if (n1 > n2) {
return 1;
} else if (n1 < n2) {
return -1;
}
}
if (n1 > n2) {
return 1;
} else if (n1 < n2) {
return -1;
}
}
return 0;
return 0;
}
async function getLatestReleaseVersion() {
const url = "https://api.github.com/repos/Stirling-Tools/Stirling-PDF/releases/latest";
try {
const response = await fetch(url);
const data = await response.json();
return data.tag_name ? data.tag_name.substring(1) : "";
} catch (error) {
console.error("Failed to fetch latest version:", error);
return ""; // Return an empty string if the fetch fails
}
const url = "https://api.github.com/repos/Stirling-Tools/Stirling-PDF/releases/latest";
try {
const response = await fetch(url);
const data = await response.json();
return data.tag_name ? data.tag_name.substring(1) : "";
} catch (error) {
console.error("Failed to fetch latest version:", error);
return ""; // Return an empty string if the fetch fails
}
}
async function checkForUpdate() {
// Initialize the update button as hidden
var updateBtn = document.getElementById("update-btn");
if (updateBtn !== null) {
updateBtn.style.display = "none";
}
// Initialize the update button as hidden
var updateBtn = document.getElementById("update-btn");
if (updateBtn !== null) {
updateBtn.style.display = "none";
}
const latestVersion = await getLatestReleaseVersion();
console.log("latestVersion=" + latestVersion)
console.log("currentVersion=" + currentVersion)
console.log("compareVersions(latestVersion, currentVersion) > 0)=" + compareVersions(latestVersion, currentVersion))
if (latestVersion && compareVersions(latestVersion, currentVersion) > 0) {
document.getElementById("update-btn").style.display = "block";
console.log("visible")
} else {
console.log("hidden")
}
const latestVersion = await getLatestReleaseVersion();
console.log("latestVersion=" + latestVersion);
console.log("currentVersion=" + currentVersion);
console.log("compareVersions(latestVersion, currentVersion) > 0)=" + compareVersions(latestVersion, currentVersion));
if (latestVersion && compareVersions(latestVersion, currentVersion) > 0) {
document.getElementById("update-btn").style.display = "block";
console.log("visible");
} else {
console.log("hidden");
}
}
document.addEventListener('DOMContentLoaded', (event) => {
checkForUpdate();
document.addEventListener("DOMContentLoaded", (event) => {
checkForUpdate();
});

View File

@@ -1,78 +1,76 @@
function filterCards() {
var input = document.getElementById('searchBar');
var filter = input.value.toUpperCase();
var cards = document.querySelectorAll('.feature-card');
var input = document.getElementById("searchBar");
var filter = input.value.toUpperCase();
var cards = document.querySelectorAll(".feature-card");
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;
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') : '';
// 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;
var content = title + " " + text + " " + navbarTags;
if (content.toUpperCase().indexOf(filter) > -1) {
card.style.display = "";
} else {
card.style.display = "none";
}
if (content.toUpperCase().indexOf(filter) > -1) {
card.style.display = "";
} else {
card.style.display = "none";
}
}
}
function toggleFavorite(element) {
var img = element.querySelector('img');
var card = element.closest('.feature-card');
var cardId = card.id;
if (img.src.endsWith('star.svg')) {
img.src = 'images/star-fill.svg';
card.classList.add('favorite');
localStorage.setItem(cardId, 'favorite');
} else {
img.src = 'images/star.svg';
card.classList.remove('favorite');
localStorage.removeItem(cardId);
}
reorderCards();
updateFavoritesDropdown();
filterCards();
var img = element.querySelector("img");
var card = element.closest(".feature-card");
var cardId = card.id;
if (img.src.endsWith("star.svg")) {
img.src = "images/star-fill.svg";
card.classList.add("favorite");
localStorage.setItem(cardId, "favorite");
} else {
img.src = "images/star.svg";
card.classList.remove("favorite");
localStorage.removeItem(cardId);
}
reorderCards();
updateFavoritesDropdown();
filterCards();
}
function reorderCards() {
var container = document.querySelector('.features-container');
var cards = Array.from(container.getElementsByClassName('feature-card'));
cards.sort(function(a, b) {
var aIsFavorite = localStorage.getItem(a.id) === 'favorite';
var bIsFavorite = localStorage.getItem(b.id) === 'favorite';
if (aIsFavorite && !bIsFavorite) {
return -1;
}
if (!aIsFavorite && bIsFavorite) {
return 1;
}
return 0;
});
cards.forEach(function(card) {
container.appendChild(card);
});
var container = document.querySelector(".features-container");
var cards = Array.from(container.getElementsByClassName("feature-card"));
cards.sort(function (a, b) {
var aIsFavorite = localStorage.getItem(a.id) === "favorite";
var bIsFavorite = localStorage.getItem(b.id) === "favorite";
if (aIsFavorite && !bIsFavorite) {
return -1;
}
if (!aIsFavorite && bIsFavorite) {
return 1;
}
return 0;
});
cards.forEach(function (card) {
container.appendChild(card);
});
}
function initializeCards() {
var cards = document.querySelectorAll('.feature-card');
cards.forEach(function(card) {
var cardId = card.id;
var img = card.querySelector('.favorite-icon img');
if (localStorage.getItem(cardId) === 'favorite') {
img.src = 'images/star-fill.svg';
card.classList.add('favorite');
}
});
reorderCards();
updateFavoritesDropdown();
filterCards();
var cards = document.querySelectorAll(".feature-card");
cards.forEach(function (card) {
var cardId = card.id;
var img = card.querySelector(".favorite-icon img");
if (localStorage.getItem(cardId) === "favorite") {
img.src = "images/star-fill.svg";
card.classList.add("favorite");
}
});
reorderCards();
updateFavoritesDropdown();
filterCards();
}
window.onload = initializeCards;
window.onload = initializeCards;

View File

@@ -1,80 +1,88 @@
document.addEventListener('DOMContentLoaded', function() {
setLanguageForDropdown('.lang_dropdown-item');
document.addEventListener("DOMContentLoaded", function () {
setLanguageForDropdown(".lang_dropdown-item");
// Detect the browser's preferred language
let browserLang = navigator.language || navigator.userLanguage;
// Convert to a format consistent with your language codes (e.g., en-GB, fr-FR)
browserLang = browserLang.replace('-', '_');
// Detect the browser's preferred language
let browserLang = navigator.language || navigator.userLanguage;
// Convert to a format consistent with your language codes (e.g., en-GB, fr-FR)
browserLang = browserLang.replace("-", "_");
// Check if the dropdown contains the browser's language
const dropdownLangExists = document.querySelector(`.lang_dropdown-item[data-language-code="${browserLang}"]`);
// Check if the dropdown contains the browser's language
const dropdownLangExists = document.querySelector(`.lang_dropdown-item[data-language-code="${browserLang}"]`);
// Set the default language to browser's language or 'en_GB' if not found in the dropdown
const defaultLocale = dropdownLangExists ? browserLang : 'en_GB';
const storedLocale = localStorage.getItem('languageCode') || defaultLocale;
// Set the default language to browser's language or 'en_GB' if not found in the dropdown
const defaultLocale = dropdownLangExists ? browserLang : "en_GB";
const storedLocale = localStorage.getItem("languageCode") || defaultLocale;
const dropdownItems = document.querySelectorAll(".lang_dropdown-item");
const dropdownItems = document.querySelectorAll('.lang_dropdown-item');
for (let i = 0; i < dropdownItems.length; i++) {
const item = dropdownItems[i];
item.classList.remove('active');
if (item.dataset.languageCode === storedLocale) {
item.classList.add('active');
}
item.addEventListener('click', handleDropdownItemClick);
}
for (let i = 0; i < dropdownItems.length; i++) {
const item = dropdownItems[i];
item.classList.remove("active");
if (item.dataset.languageCode === storedLocale) {
item.classList.add("active");
}
item.addEventListener("click", handleDropdownItemClick);
}
});
function setLanguageForDropdown(dropdownClass) {
const defaultLocale = document.documentElement.lang || 'en_GB';
const storedLocale = localStorage.getItem('languageCode') || defaultLocale;
const dropdownItems = document.querySelectorAll(dropdownClass);
const defaultLocale = document.documentElement.lang || "en_GB";
const storedLocale = localStorage.getItem("languageCode") || defaultLocale;
const dropdownItems = document.querySelectorAll(dropdownClass);
for (let i = 0; i < dropdownItems.length; i++) {
const item = dropdownItems[i];
item.classList.remove('active');
if (item.dataset.languageCode === storedLocale) {
item.classList.add('active');
}
item.addEventListener('click', handleDropdownItemClick);
for (let i = 0; i < dropdownItems.length; i++) {
const item = dropdownItems[i];
item.classList.remove("active");
if (item.dataset.languageCode === storedLocale) {
item.classList.add("active");
}
item.addEventListener("click", handleDropdownItemClick);
}
}
function handleDropdownItemClick(event) {
event.preventDefault();
const languageCode = event.currentTarget.dataset.bsLanguageCode; // change this to event.currentTarget
if (languageCode) {
localStorage.setItem('languageCode', languageCode);
event.preventDefault();
const languageCode = event.currentTarget.dataset.bsLanguageCode; // change this to event.currentTarget
if (languageCode) {
localStorage.setItem("languageCode", languageCode);
const currentUrl = window.location.href;
if (currentUrl.indexOf('?lang=') === -1) {
window.location.href = currentUrl + '?lang=' + languageCode;
} else {
window.location.href = currentUrl.replace(/\?lang=\w{2,}/, '?lang=' + languageCode);
}
const currentUrl = window.location.href;
if (currentUrl.indexOf("?lang=") === -1) {
window.location.href = currentUrl + "?lang=" + languageCode;
} else {
console.error("Language code is not set for this item."); // for debugging
window.location.href = currentUrl.replace(/\?lang=\w{2,}/, "?lang=" + languageCode);
}
} else {
console.error("Language code is not set for this item."); // for debugging
}
}
document.addEventListener("DOMContentLoaded", function () {
document.querySelectorAll(".nav-item.dropdown").forEach((element) => {
const dropdownMenu = element.querySelector(".dropdown-menu");
if (
dropdownMenu.id !== "favoritesDropdown" &&
dropdownMenu.children.length <= 2 &&
dropdownMenu.querySelectorAll("hr.dropdown-divider").length === dropdownMenu.children.length
) {
if (
element.previousElementSibling &&
element.previousElementSibling.classList.contains("nav-item") &&
element.previousElementSibling.classList.contains("nav-item-separator")
) {
element.previousElementSibling.remove();
}
element.remove();
}
});
document.addEventListener('DOMContentLoaded', function() {
document.querySelectorAll('.nav-item.dropdown').forEach((element) => {
const dropdownMenu = element.querySelector(".dropdown-menu");
if (dropdownMenu.id !== 'favoritesDropdown' && dropdownMenu.children.length <= 2 && dropdownMenu.querySelectorAll("hr.dropdown-divider").length === dropdownMenu.children.length) {
if (element.previousElementSibling && element.previousElementSibling.classList.contains('nav-item') && element.previousElementSibling.classList.contains('nav-item-separator')) {
element.previousElementSibling.remove();
}
element.remove();
}
});
//Sort languages by alphabet
const list = Array.from(document.querySelector('.dropdown-menu[aria-labelledby="languageDropdown"]').children).filter(child => child.matches('a'));
list.sort(function(a, b) {
return a.textContent.toUpperCase().localeCompare(b.textContent.toUpperCase());
}).forEach(node => document.querySelector('.dropdown-menu[aria-labelledby="languageDropdown"]').appendChild(node));
});
//Sort languages by alphabet
const list = Array.from(document.querySelector('.dropdown-menu[aria-labelledby="languageDropdown"]').children).filter(
(child) => child.matches("a"),
);
list
.sort(function (a, b) {
return a.textContent.toUpperCase().localeCompare(b.textContent.toUpperCase());
})
.forEach((node) => document.querySelector('.dropdown-menu[aria-labelledby="languageDropdown"]').appendChild(node));
});

View File

@@ -1,47 +1,47 @@
async function downloadFilesWithCallback(processFileCallback) {
const fileInput = document.querySelector('input[type="file"]');
const files = fileInput.files;
const fileInput = document.querySelector('input[type="file"]');
const files = fileInput.files;
const zipThreshold = 4;
const zipFiles = files.length > zipThreshold;
const zipThreshold = 4;
const zipFiles = files.length > zipThreshold;
let jszip = null;
if (zipFiles) {
jszip = new JSZip();
}
let jszip = null;
if (zipFiles) {
jszip = new JSZip();
}
const promises = Array.from(files).map(async file => {
const { processedData, fileName } = await processFileCallback(file);
if (zipFiles) {
jszip.file(fileName, processedData);
} else {
const url = URL.createObjectURL(processedData);
const downloadOption = localStorage.getItem('downloadOption');
if (downloadOption === 'sameWindow') {
window.location.href = url;
} else if (downloadOption === 'newWindow') {
window.open(url, '_blank');
} else {
const downloadLink = document.createElement('a');
downloadLink.href = url;
downloadLink.download = fileName;
downloadLink.click();
}
}
});
await Promise.all(promises);
const promises = Array.from(files).map(async (file) => {
const { processedData, fileName } = await processFileCallback(file);
if (zipFiles) {
const content = await jszip.generateAsync({ type: "blob" });
const url = URL.createObjectURL(content);
const a = document.createElement('a');
a.href = url;
a.download = "files.zip";
document.body.appendChild(a);
a.click();
a.remove();
jszip.file(fileName, processedData);
} else {
const url = URL.createObjectURL(processedData);
const downloadOption = localStorage.getItem("downloadOption");
if (downloadOption === "sameWindow") {
window.location.href = url;
} else if (downloadOption === "newWindow") {
window.open(url, "_blank");
} else {
const downloadLink = document.createElement("a");
downloadLink.href = url;
downloadLink.download = fileName;
downloadLink.click();
}
}
});
await Promise.all(promises);
if (zipFiles) {
const content = await jszip.generateAsync({ type: "blob" });
const url = URL.createObjectURL(content);
const a = document.createElement("a");
a.href = url;
a.download = "files.zip";
document.body.appendChild(a);
a.click();
a.remove();
}
}

View File

@@ -1,27 +1,27 @@
let currentSort = {
field: null,
descending: false
field: null,
descending: false,
};
document.getElementById("fileInput-input").addEventListener("change", function() {
var files = this.files;
displayFiles(files);
document.getElementById("fileInput-input").addEventListener("change", function () {
var files = this.files;
displayFiles(files);
});
/**
* @param {FileList} files
*/
function displayFiles(files) {
const list = document.getElementById("selectedFiles");
const list = document.getElementById("selectedFiles");
while (list.firstChild) {
list.removeChild(list.firstChild);
}
while (list.firstChild) {
list.removeChild(list.firstChild);
}
for (let i = 0; i < files.length; i++) {
const item = document.createElement("li");
item.className = "list-group-item";
item.innerHTML = `
for (let i = 0; i < files.length; i++) {
const item = document.createElement("li");
item.className = "list-group-item";
item.innerHTML = `
<div class="d-flex justify-content-between align-items-center w-100">
<div class="filename">${files[i].name}</div>
<div class="arrows d-flex">
@@ -31,100 +31,100 @@ function displayFiles(files) {
</div>
</div>
`;
list.appendChild(item);
}
list.appendChild(item);
}
attachMoveButtons();
attachMoveButtons();
}
function attachMoveButtons() {
var moveUpButtons = document.querySelectorAll(".move-up");
for (var i = 0; i < moveUpButtons.length; i++) {
moveUpButtons[i].addEventListener("click", function(event) {
event.preventDefault();
var parent = this.closest(".list-group-item");
var grandParent = parent.parentNode;
if (parent.previousElementSibling) {
grandParent.insertBefore(parent, parent.previousElementSibling);
updateFiles();
}
});
}
var moveUpButtons = document.querySelectorAll(".move-up");
for (var i = 0; i < moveUpButtons.length; i++) {
moveUpButtons[i].addEventListener("click", function (event) {
event.preventDefault();
var parent = this.closest(".list-group-item");
var grandParent = parent.parentNode;
if (parent.previousElementSibling) {
grandParent.insertBefore(parent, parent.previousElementSibling);
updateFiles();
}
});
}
var moveDownButtons = document.querySelectorAll(".move-down");
for (var i = 0; i < moveDownButtons.length; i++) {
moveDownButtons[i].addEventListener("click", function(event) {
event.preventDefault();
var parent = this.closest(".list-group-item");
var grandParent = parent.parentNode;
if (parent.nextElementSibling) {
grandParent.insertBefore(parent.nextElementSibling, parent);
updateFiles();
}
});
}
var moveDownButtons = document.querySelectorAll(".move-down");
for (var i = 0; i < moveDownButtons.length; i++) {
moveDownButtons[i].addEventListener("click", function (event) {
event.preventDefault();
var parent = this.closest(".list-group-item");
var grandParent = parent.parentNode;
if (parent.nextElementSibling) {
grandParent.insertBefore(parent.nextElementSibling, parent);
updateFiles();
}
});
}
var removeButtons = document.querySelectorAll(".remove-file");
for (var i = 0; i < removeButtons.length; i++) {
removeButtons[i].addEventListener("click", function (event) {
event.preventDefault();
var parent = this.closest(".list-group-item");
parent.remove();
updateFiles();
});
}
var removeButtons = document.querySelectorAll(".remove-file");
for (var i = 0; i < removeButtons.length; i++) {
removeButtons[i].addEventListener("click", function (event) {
event.preventDefault();
var parent = this.closest(".list-group-item");
parent.remove();
updateFiles();
});
}
}
document.getElementById("sortByNameBtn").addEventListener("click", function() {
if (currentSort.field === "name" && !currentSort.descending) {
currentSort.descending = true;
sortFiles((a, b) => b.name.localeCompare(a.name));
} else {
currentSort.field = "name";
currentSort.descending = false;
sortFiles((a, b) => a.name.localeCompare(b.name));
}
document.getElementById("sortByNameBtn").addEventListener("click", function () {
if (currentSort.field === "name" && !currentSort.descending) {
currentSort.descending = true;
sortFiles((a, b) => b.name.localeCompare(a.name));
} else {
currentSort.field = "name";
currentSort.descending = false;
sortFiles((a, b) => a.name.localeCompare(b.name));
}
});
document.getElementById("sortByDateBtn").addEventListener("click", function() {
if (currentSort.field === "lastModified" && !currentSort.descending) {
currentSort.descending = true;
sortFiles((a, b) => b.lastModified - a.lastModified);
} else {
currentSort.field = "lastModified";
currentSort.descending = false;
sortFiles((a, b) => a.lastModified - b.lastModified);
}
document.getElementById("sortByDateBtn").addEventListener("click", function () {
if (currentSort.field === "lastModified" && !currentSort.descending) {
currentSort.descending = true;
sortFiles((a, b) => b.lastModified - a.lastModified);
} else {
currentSort.field = "lastModified";
currentSort.descending = false;
sortFiles((a, b) => a.lastModified - b.lastModified);
}
});
function sortFiles(comparator) {
// Convert FileList to array and sort
const sortedFilesArray = Array.from(document.getElementById("fileInput-input").files).sort(comparator);
// Convert FileList to array and sort
const sortedFilesArray = Array.from(document.getElementById("fileInput-input").files).sort(comparator);
// Refresh displayed list
displayFiles(sortedFilesArray);
// Refresh displayed list
displayFiles(sortedFilesArray);
// Update the files property
const dataTransfer = new DataTransfer();
sortedFilesArray.forEach(file => dataTransfer.items.add(file));
document.getElementById("fileInput-input").files = dataTransfer.files;
// Update the files property
const dataTransfer = new DataTransfer();
sortedFilesArray.forEach((file) => dataTransfer.items.add(file));
document.getElementById("fileInput-input").files = dataTransfer.files;
}
function updateFiles() {
var dataTransfer = new DataTransfer();
var liElements = document.querySelectorAll("#selectedFiles li");
const files = document.getElementById("fileInput-input").files;
var dataTransfer = new DataTransfer();
var liElements = document.querySelectorAll("#selectedFiles li");
const files = document.getElementById("fileInput-input").files;
for (var i = 0; i < liElements.length; i++) {
var fileNameFromList = liElements[i].querySelector(".filename").innerText;
var fileFromFiles;
for (var j = 0; j < files.length; j++) {
var file = files[j];
if (file.name === fileNameFromList) {
dataTransfer.items.add(file);
break;
}
}
for (var i = 0; i < liElements.length; i++) {
var fileNameFromList = liElements[i].querySelector(".filename").innerText;
var fileFromFiles;
for (var j = 0; j < files.length; j++) {
var file = files[j];
if (file.name === fileNameFromList) {
dataTransfer.items.add(file);
break;
}
}
document.getElementById("fileInput-input").files = dataTransfer.files;
}
document.getElementById("fileInput-input").files = dataTransfer.files;
}

View File

@@ -1,125 +1,123 @@
class DragDropManager {
dragContainer;
wrapper;
pageDirection;
movePageTo;
pageDragging;
draggelEl;
draggedImageEl;
hoveredEl;
endInsertionElement;
dragContainer;
wrapper;
pageDirection;
movePageTo;
pageDragging;
draggelEl;
draggedImageEl;
hoveredEl;
endInsertionElement;
constructor(id, wrapperId) {
this.dragContainer = document.getElementById(id);
this.pageDirection = document.documentElement.getAttribute("lang-direction");
this.wrapper = document.getElementById(wrapperId);
this.pageDragging = false;
this.hoveredEl = undefined;
this.draggelEl = undefined
this.draggedImageEl = undefined;
constructor(id, wrapperId) {
this.dragContainer = document.getElementById(id);
this.pageDirection = document.documentElement.getAttribute("lang-direction");
this.wrapper = document.getElementById(wrapperId);
this.pageDragging = false;
this.hoveredEl = undefined;
this.draggelEl = undefined;
this.draggedImageEl = undefined;
var styleElement = document.createElement('link');
styleElement.rel = 'stylesheet';
styleElement.href = 'css/dragdrop.css'
var styleElement = document.createElement("link");
styleElement.rel = "stylesheet";
styleElement.href = "css/dragdrop.css";
document.head.appendChild(styleElement);
document.head.appendChild(styleElement);
const div = document.createElement('div');
div.classList.add('drag-manager_endpoint');
div.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-file-earmark-arrow-down" viewBox="0 0 16 16">
const div = document.createElement("div");
div.classList.add("drag-manager_endpoint");
div.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-file-earmark-arrow-down" viewBox="0 0 16 16">
<path d="M8.5 6.5a.5.5 0 0 0-1 0v3.793L6.354 9.146a.5.5 0 1 0-.708.708l2 2a.5.5 0 0 0 .708 0l2-2a.5.5 0 0 0-.708-.708L8.5 10.293V6.5z"/>
<path d="M14 14V4.5L9.5 0H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2zM9.5 3A1.5 1.5 0 0 0 11 4.5h2V14a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h5.5v2z"/>
</svg>`
this.endInsertionElement = div;
</svg>`;
this.endInsertionElement = div;
this.startDraggingPage = this.startDraggingPage.bind(this);
this.onDragEl = this.onDragEl.bind(this);
this.stopDraggingPage = this.stopDraggingPage.bind(this);
this.startDraggingPage = this.startDraggingPage.bind(this);
this.onDragEl = this.onDragEl.bind(this);
this.stopDraggingPage = this.stopDraggingPage.bind(this);
this.adapt(div);
this.adapt(div);
}
startDraggingPage(div) {
this.pageDragging = true;
this.draggedEl = div;
const img = div.querySelector("img");
div.classList.add("drag-manager_dragging");
const imageSrc = img.src;
const imgEl = document.createElement("img");
imgEl.classList.add("dragged-img");
imgEl.src = imageSrc;
this.draggedImageEl = imgEl;
imgEl.style.visibility = "hidden";
imgEl.style.transform = `rotate(${img.style.rotate === "" ? "0deg" : img.style.rotate}) translate(-50%, -50%)`;
this.dragContainer.appendChild(imgEl);
window.addEventListener("mouseup", this.stopDraggingPage);
window.addEventListener("mousemove", this.onDragEl);
this.wrapper.classList.add("drag-manager_dragging-container");
this.wrapper.appendChild(this.endInsertionElement);
}
onDragEl(mouseEvent) {
const { clientX, clientY } = mouseEvent;
if (this.draggedImageEl) {
this.draggedImageEl.style.visibility = "visible";
this.draggedImageEl.style.left = `${clientX}px`;
this.draggedImageEl.style.top = `${clientY}px`;
}
}
startDraggingPage(div,) {
this.pageDragging = true;
this.draggedEl = div;
const img = div.querySelector('img');
div.classList.add('drag-manager_dragging');
const imageSrc = img.src;
const imgEl = document.createElement('img');
imgEl.classList.add('dragged-img');
imgEl.src = imageSrc;
this.draggedImageEl = imgEl;
imgEl.style.visibility = 'hidden';
imgEl.style.transform = `rotate(${img.style.rotate === '' ? '0deg' : img.style.rotate}) translate(-50%, -50%)`;
this.dragContainer.appendChild(imgEl);
window.addEventListener('mouseup', this.stopDraggingPage)
window.addEventListener('mousemove', this.onDragEl)
this.wrapper.classList.add('drag-manager_dragging-container');
this.wrapper.appendChild(this.endInsertionElement);
stopDraggingPage() {
window.removeEventListener("mousemove", this.onDragEl);
this.wrapper.classList.remove("drag-manager_dragging-container");
this.wrapper.removeChild(this.endInsertionElement);
window.removeEventListener("mouseup", this.stopDraggingPage);
this.draggedImageEl = undefined;
this.pageDragging = false;
this.draggedEl.classList.remove("drag-manager_dragging");
this.hoveredEl?.classList.remove("drag-manager_draghover");
this.dragContainer.childNodes.forEach((dragChild) => {
this.dragContainer.removeChild(dragChild);
});
if (!this.hoveredEl) {
return;
}
onDragEl(mouseEvent) {
const { clientX, clientY } = mouseEvent;
if(this.draggedImageEl) {
this.draggedImageEl.style.visibility = 'visible';
this.draggedImageEl.style.left = `${clientX}px`;
this.draggedImageEl.style.top = `${clientY}px`;
}
if (this.hoveredEl === this.endInsertionElement) {
this.movePageTo(this.draggedEl);
return;
}
this.movePageTo(this.draggedEl, this.hoveredEl);
}
setActions({ movePageTo }) {
this.movePageTo = movePageTo;
}
stopDraggingPage() {
window.removeEventListener('mousemove', this.onDragEl);
this.wrapper.classList.remove('drag-manager_dragging-container');
this.wrapper.removeChild(this.endInsertionElement);
window.removeEventListener('mouseup', this.stopDraggingPage)
this.draggedImageEl = undefined;
this.pageDragging = false;
this.draggedEl.classList.remove('drag-manager_dragging');
this.hoveredEl?.classList.remove('drag-manager_draghover');
this.dragContainer.childNodes.forEach((dragChild) => {
this.dragContainer.removeChild(dragChild);
})
if(!this.hoveredEl) {
return;
}
if(this.hoveredEl === this.endInsertionElement) {
this.movePageTo(this.draggedEl);
return;
}
this.movePageTo(this.draggedEl, this.hoveredEl);
}
adapt(div) {
const onDragStart = () => {
this.startDraggingPage(div);
};
setActions({ movePageTo }) {
this.movePageTo = movePageTo;
}
const onMouseEnter = () => {
if (this.pageDragging) {
this.hoveredEl = div;
div.classList.add("drag-manager_draghover");
}
};
const onMouseLeave = () => {
this.hoveredEl = undefined;
div.classList.remove("drag-manager_draghover");
};
adapt(div) {
const onDragStart = () => {
this.startDraggingPage(div);
}
div.addEventListener("dragstart", onDragStart);
div.addEventListener("mouseenter", onMouseEnter);
div.addEventListener("mouseleave", onMouseLeave);
const onMouseEnter = () => {
if (this.pageDragging) {
this.hoveredEl = div;
div.classList.add('drag-manager_draghover');
}
}
const onMouseLeave = () => {
this.hoveredEl = undefined
div.classList.remove('drag-manager_draghover');
}
div.addEventListener('dragstart', onDragStart);
div.addEventListener('mouseenter', onMouseEnter);
div.addEventListener('mouseleave', onMouseLeave);
return div;
}
return div;
}
}
export default DragDropManager;

View File

@@ -1,46 +1,46 @@
class ImageHiglighter {
imageHighlighter;
constructor(id) {
this.imageHighlighter = document.getElementById(id);
this.imageHighlightCallback = this.imageHighlightCallback.bind(this);
imageHighlighter;
constructor(id) {
this.imageHighlighter = document.getElementById(id);
this.imageHighlightCallback = this.imageHighlightCallback.bind(this);
var styleElement = document.createElement('link');
styleElement.rel = 'stylesheet';
styleElement.href = 'css/imageHighlighter.css'
var styleElement = document.createElement("link");
styleElement.rel = "stylesheet";
styleElement.href = "css/imageHighlighter.css";
document.head.appendChild(styleElement);
document.head.appendChild(styleElement);
this.imageHighlighter.onclick = () => {
this.imageHighlighter.childNodes.forEach((child) => {
child.classList.add('remove');
setTimeout(() => {
this.imageHighlighter.removeChild(child);
}, 100)
})
}
}
imageHighlightCallback(highlightEvent) {
var bigImg = document.createElement('img');
bigImg.onclick = (imageClickEvent) => {
// This prevents the highlighter's onClick from closing the image when clicking
// on the image instead of next to it.
imageClickEvent.preventDefault();
imageClickEvent.stopPropagation();
};
bigImg.src = highlightEvent.target.src;
this.imageHighlighter.appendChild(bigImg);
this.imageHighlighter.onclick = () => {
this.imageHighlighter.childNodes.forEach((child) => {
child.classList.add("remove");
setTimeout(() => {
this.imageHighlighter.removeChild(child);
}, 100);
});
};
}
setActions() {
// not needed in this case
}
imageHighlightCallback(highlightEvent) {
var bigImg = document.createElement("img");
bigImg.onclick = (imageClickEvent) => {
// This prevents the highlighter's onClick from closing the image when clicking
// on the image instead of next to it.
imageClickEvent.preventDefault();
imageClickEvent.stopPropagation();
};
bigImg.src = highlightEvent.target.src;
this.imageHighlighter.appendChild(bigImg);
}
adapt(div) {
const img = div.querySelector('.page-image');
img.addEventListener('click', this.imageHighlightCallback)
return div;
}
setActions() {
// not needed in this case
}
adapt(div) {
const img = div.querySelector(".page-image");
img.addEventListener("click", this.imageHighlightCallback);
return div;
}
}
export default ImageHiglighter;
export default ImageHiglighter;

View File

@@ -1,198 +1,200 @@
class PdfActionsManager {
pageDirection;
pagesContainer;
pageDirection;
pagesContainer;
constructor(id) {
this.pagesContainer = document.getElementById(id);
this.pageDirection = document.documentElement.getAttribute("lang-direction");
constructor(id) {
this.pagesContainer = document.getElementById(id);
this.pageDirection = document.documentElement.getAttribute("lang-direction");
var styleElement = document.createElement('link');
styleElement.rel = 'stylesheet';
styleElement.href = 'css/pdfActions.css'
var styleElement = document.createElement("link");
styleElement.rel = "stylesheet";
styleElement.href = "css/pdfActions.css";
document.head.appendChild(styleElement);
document.head.appendChild(styleElement);
}
getPageContainer(element) {
var container = element;
while (!container.classList.contains("page-container")) {
container = container.parentNode;
}
return container;
}
getPageContainer(element) {
var container = element
while (!container.classList.contains('page-container')) {
container = container.parentNode;
}
return container;
moveUpButtonCallback(e) {
var imgContainer = this.getPageContainer(e.target);
const sibling = imgContainer.previousSibling;
if (sibling) {
this.movePageTo(imgContainer, sibling, true);
}
}
moveUpButtonCallback(e) {
var imgContainer = this.getPageContainer(e.target);
const sibling = imgContainer.previousSibling;
if (sibling) {
this.movePageTo(imgContainer, sibling, true);
}
moveDownButtonCallback(e) {
var imgContainer = this.getPageContainer(e.target);
const sibling = imgContainer.nextSibling;
if (sibling) {
this.movePageTo(imgContainer, sibling.nextSibling, true);
}
}
moveDownButtonCallback(e) {
var imgContainer = this.getPageContainer(e.target);
const sibling = imgContainer.nextSibling;
if (sibling) {
this.movePageTo(imgContainer, sibling.nextSibling, true);
}
};
rotateCCWButtonCallback(e) {
var imgContainer = this.getPageContainer(e.target);
const img = imgContainer.querySelector("img");
rotateCCWButtonCallback(e) {
var imgContainer = this.getPageContainer(e.target);
const img = imgContainer.querySelector("img");
this.rotateElement(img, -90);
}
this.rotateElement(img, -90)
};
rotateCWButtonCallback(e) {
var imgContainer = this.getPageContainer(e.target);
const img = imgContainer.querySelector("img");
rotateCWButtonCallback(e) {
var imgContainer = this.getPageContainer(e.target);
const img = imgContainer.querySelector("img");
this.rotateElement(img, 90);
}
this.rotateElement(img, 90)
};
deletePageButtonCallback(e) {
var imgContainer = this.getPageContainer(e.target);
this.pagesContainer.removeChild(imgContainer);
if (this.pagesContainer.childElementCount === 0) {
const filenameInput = document.getElementById("filename-input");
const filenameParagraph = document.getElementById("filename");
const downloadBtn = document.getElementById("export-button");
deletePageButtonCallback(e) {
var imgContainer = this.getPageContainer(e.target);
this.pagesContainer.removeChild(imgContainer);
if (this.pagesContainer.childElementCount === 0) {
const filenameInput = document.getElementById('filename-input');
const filenameParagraph = document.getElementById('filename');
const downloadBtn = document.getElementById('export-button');
filenameInput.disabled = true;
filenameInput.value = "";
filenameParagraph.innerText = "";
filenameInput.disabled = true;
filenameInput.value = "";
filenameParagraph.innerText = "";
downloadBtn.disabled = true;
}
};
insertFileButtonCallback(e) {
var imgContainer = this.getPageContainer(e.target);
this.addPdfs(imgContainer)
};
setActions({ movePageTo, addPdfs, rotateElement }) {
this.movePageTo = movePageTo;
this.addPdfs = addPdfs;
this.rotateElement = rotateElement;
this.moveUpButtonCallback = this.moveUpButtonCallback.bind(this);
this.moveDownButtonCallback = this.moveDownButtonCallback.bind(this);
this.rotateCCWButtonCallback = this.rotateCCWButtonCallback.bind(this);
this.rotateCWButtonCallback = this.rotateCWButtonCallback.bind(this);
this.deletePageButtonCallback = this.deletePageButtonCallback.bind(this);
this.insertFileButtonCallback = this.insertFileButtonCallback.bind(this);
downloadBtn.disabled = true;
}
}
adapt(div) {
div.classList.add('pdf-actions_container');
const leftDirection = this.pageDirection === 'rtl' ? 'right' : 'left'
const rightDirection = this.pageDirection === 'rtl' ? 'left' : 'right'
const buttonContainer = document.createElement('div');
insertFileButtonCallback(e) {
var imgContainer = this.getPageContainer(e.target);
this.addPdfs(imgContainer);
}
buttonContainer.classList.add("pdf-actions_button-container", "hide-on-drag");
setActions({ movePageTo, addPdfs, rotateElement }) {
this.movePageTo = movePageTo;
this.addPdfs = addPdfs;
this.rotateElement = rotateElement;
const moveUp = document.createElement('button');
moveUp.classList.add("pdf-actions_move-left-button","btn", "btn-secondary");
moveUp.innerHTML = `<i class="bi bi-arrow-${leftDirection}-short"></i>`;
moveUp.onclick = this.moveUpButtonCallback;
buttonContainer.appendChild(moveUp);
this.moveUpButtonCallback = this.moveUpButtonCallback.bind(this);
this.moveDownButtonCallback = this.moveDownButtonCallback.bind(this);
this.rotateCCWButtonCallback = this.rotateCCWButtonCallback.bind(this);
this.rotateCWButtonCallback = this.rotateCWButtonCallback.bind(this);
this.deletePageButtonCallback = this.deletePageButtonCallback.bind(this);
this.insertFileButtonCallback = this.insertFileButtonCallback.bind(this);
}
const moveDown = document.createElement('button');
moveDown.classList.add("pdf-actions_move-right-button","btn", "btn-secondary");
moveDown.innerHTML = `<i class="bi bi-arrow-${rightDirection}-short"></i>`;
moveDown.onclick = this.moveDownButtonCallback;
buttonContainer.appendChild(moveDown);
adapt(div) {
div.classList.add("pdf-actions_container");
const leftDirection = this.pageDirection === "rtl" ? "right" : "left";
const rightDirection = this.pageDirection === "rtl" ? "left" : "right";
const buttonContainer = document.createElement("div");
const rotateCCW = document.createElement('button');
rotateCCW.classList.add("btn", "btn-secondary");
rotateCCW.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-counterclockwise" viewBox="0 0 16 16">
buttonContainer.classList.add("pdf-actions_button-container", "hide-on-drag");
const moveUp = document.createElement("button");
moveUp.classList.add("pdf-actions_move-left-button", "btn", "btn-secondary");
moveUp.innerHTML = `<i class="bi bi-arrow-${leftDirection}-short"></i>`;
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 = `<i class="bi bi-arrow-${rightDirection}-short"></i>`;
moveDown.onclick = this.moveDownButtonCallback;
buttonContainer.appendChild(moveDown);
const rotateCCW = document.createElement("button");
rotateCCW.classList.add("btn", "btn-secondary");
rotateCCW.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-counterclockwise" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M8 3a5 5 0 1 1-4.546 2.914.5.5 0 0 0-.908-.417A6 6 0 1 0 8 2v1z" />
<path d="M8 4.466V.534a.25.25 0 0 0-.41-.192L5.23 2.308a.25.25 0 0 0 0 .384l2.36 1.966A.25.25 0 0 0 8 4.466z" />
</svg>`;
rotateCCW.onclick = this.rotateCCWButtonCallback;
buttonContainer.appendChild(rotateCCW);
rotateCCW.onclick = this.rotateCCWButtonCallback;
buttonContainer.appendChild(rotateCCW);
const rotateCW = document.createElement('button');
rotateCW.classList.add("btn", "btn-secondary");
rotateCW.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-clockwise" viewBox="0 0 16 16">
const rotateCW = document.createElement("button");
rotateCW.classList.add("btn", "btn-secondary");
rotateCW.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-clockwise" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M8 3a5 5 0 1 0 4.546 2.914.5.5 0 0 1 .908-.417A6 6 0 1 1 8 2v1z" />
<path d="M8 4.466V.534a.25.25 0 0 1 .41-.192l2.36 1.966c.12.1.12.284 0 .384L8.41 4.658A.25.25 0 0 1 8 4.466z" />
</svg>`;
rotateCW.onclick = this.rotateCWButtonCallback;
buttonContainer.appendChild(rotateCW);
rotateCW.onclick = this.rotateCWButtonCallback;
buttonContainer.appendChild(rotateCW);
const deletePage = document.createElement('button');
deletePage.classList.add("btn", "btn-danger");
deletePage.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-trash" viewBox="0 0 16 16">
const deletePage = document.createElement("button");
deletePage.classList.add("btn", "btn-danger");
deletePage.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-trash" viewBox="0 0 16 16">
<path d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5Zm2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5Zm3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0V6Z"/>
<path d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1v1ZM4.118 4 4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4H4.118ZM2.5 3h11V2h-11v1Z"/>
</svg>`;
deletePage.onclick = this.deletePageButtonCallback;
buttonContainer.appendChild(deletePage);
deletePage.onclick = this.deletePageButtonCallback;
buttonContainer.appendChild(deletePage);
div.appendChild(buttonContainer);
div.appendChild(buttonContainer);
const insertFileButtonContainer = document.createElement('div');
const insertFileButtonContainer = document.createElement("div");
insertFileButtonContainer.classList.add(
"pdf-actions_insert-file-button-container",
leftDirection,
`align-center-${leftDirection}`);
insertFileButtonContainer.classList.add(
"pdf-actions_insert-file-button-container",
leftDirection,
`align-center-${leftDirection}`,
);
const insertFileButton = document.createElement('button');
insertFileButton.classList.add("btn", "btn-primary", "pdf-actions_insert-file-button");
insertFileButton.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-file-earmark-plus" viewBox="0 0 16 16">
const insertFileButton = document.createElement("button");
insertFileButton.classList.add("btn", "btn-primary", "pdf-actions_insert-file-button");
insertFileButton.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-file-earmark-plus" viewBox="0 0 16 16">
<path d="M8 6.5a.5.5 0 0 1 .5.5v1.5H10a.5.5 0 0 1 0 1H8.5V11a.5.5 0 0 1-1 0V9.5H6a.5.5 0 0 1 0-1h1.5V7a.5.5 0 0 1 .5-.5z"/>
<path d="M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5L14 4.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5h-2z"/>
</svg>`;
insertFileButton.onclick = this.insertFileButtonCallback;
insertFileButtonContainer.appendChild(insertFileButton);
insertFileButton.onclick = this.insertFileButtonCallback;
insertFileButtonContainer.appendChild(insertFileButton);
div.appendChild(insertFileButtonContainer);
div.appendChild(insertFileButtonContainer);
// add this button to every element, but only show it on the last one :D
const insertFileButtonRightContainer = document.createElement('div');
insertFileButtonRightContainer.classList.add(
"pdf-actions_insert-file-button-container",
rightDirection,
`align-center-${rightDirection}`);
// add this button to every element, but only show it on the last one :D
const insertFileButtonRightContainer = document.createElement("div");
insertFileButtonRightContainer.classList.add(
"pdf-actions_insert-file-button-container",
rightDirection,
`align-center-${rightDirection}`,
);
const insertFileButtonRight = document.createElement('button');
insertFileButtonRight.classList.add("btn", "btn-primary", "pdf-actions_insert-file-button");
insertFileButtonRight.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-file-earmark-plus" viewBox="0 0 16 16">
const insertFileButtonRight = document.createElement("button");
insertFileButtonRight.classList.add("btn", "btn-primary", "pdf-actions_insert-file-button");
insertFileButtonRight.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-file-earmark-plus" viewBox="0 0 16 16">
<path d="M8 6.5a.5.5 0 0 1 .5.5v1.5H10a.5.5 0 0 1 0 1H8.5V11a.5.5 0 0 1-1 0V9.5H6a.5.5 0 0 1 0-1h1.5V7a.5.5 0 0 1 .5-.5z"/>
<path d="M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5L14 4.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5h-2z"/>
insertFileButtonRight</svg>`;
insertFileButtonRight.onclick = () => addPdfs();
insertFileButtonRightContainer.appendChild(insertFileButtonRight);
insertFileButtonRight.onclick = () => addPdfs();
insertFileButtonRightContainer.appendChild(insertFileButtonRight);
div.appendChild(insertFileButtonRightContainer);
div.appendChild(insertFileButtonRightContainer);
const adaptPageNumber = (pageNumber, div) => {
const pageNumberElement = document.createElement('span');
pageNumberElement.classList.add('page-number');
pageNumberElement.textContent = pageNumber;
const adaptPageNumber = (pageNumber, div) => {
const pageNumberElement = document.createElement("span");
pageNumberElement.classList.add("page-number");
pageNumberElement.textContent = pageNumber;
div.insertBefore(pageNumberElement, div.firstChild);
};
div.insertBefore(pageNumberElement, div.firstChild);
};
div.addEventListener('mouseenter', () => {
const pageNumber = Array.from(div.parentNode.children).indexOf(div) + 1;
adaptPageNumber(pageNumber, div);
});
div.addEventListener("mouseenter", () => {
const pageNumber = Array.from(div.parentNode.children).indexOf(div) + 1;
adaptPageNumber(pageNumber, div);
});
div.addEventListener('mouseleave', () => {
const pageNumberElement = div.querySelector('.page-number');
if (pageNumberElement) {
div.removeChild(pageNumberElement);
}
});
div.addEventListener("mouseleave", () => {
const pageNumberElement = div.querySelector(".page-number");
if (pageNumberElement) {
div.removeChild(pageNumberElement);
}
});
return div;
}
return div;
}
}
export default PdfActionsManager;
export default PdfActionsManager;

View File

@@ -1,285 +1,282 @@
class PdfContainer {
fileName;
pagesContainer;
pagesContainerWrapper;
pdfAdapters;
downloadLink;
fileName;
pagesContainer;
pagesContainerWrapper;
pdfAdapters;
downloadLink;
constructor(id, wrapperId, pdfAdapters) {
this.pagesContainer = document.getElementById(id)
this.pagesContainerWrapper = document.getElementById(wrapperId);
this.downloadLink = null;
this.movePageTo = this.movePageTo.bind(this);
this.addPdfs = this.addPdfs.bind(this);
this.addPdfsFromFiles = this.addPdfsFromFiles.bind(this);
this.rotateElement = this.rotateElement.bind(this);
this.rotateAll = this.rotateAll.bind(this);
this.exportPdf = this.exportPdf.bind(this);
this.updateFilename = this.updateFilename.bind(this);
this.setDownloadAttribute = this.setDownloadAttribute.bind(this);
this.preventIllegalChars = this.preventIllegalChars.bind(this);
constructor(id, wrapperId, pdfAdapters) {
this.pagesContainer = document.getElementById(id);
this.pagesContainerWrapper = document.getElementById(wrapperId);
this.downloadLink = null;
this.movePageTo = this.movePageTo.bind(this);
this.addPdfs = this.addPdfs.bind(this);
this.addPdfsFromFiles = this.addPdfsFromFiles.bind(this);
this.rotateElement = this.rotateElement.bind(this);
this.rotateAll = this.rotateAll.bind(this);
this.exportPdf = this.exportPdf.bind(this);
this.updateFilename = this.updateFilename.bind(this);
this.setDownloadAttribute = this.setDownloadAttribute.bind(this);
this.preventIllegalChars = this.preventIllegalChars.bind(this);
this.pdfAdapters = pdfAdapters;
this.pdfAdapters = pdfAdapters;
this.pdfAdapters.forEach(adapter => {
adapter.setActions({
movePageTo: this.movePageTo,
addPdfs: this.addPdfs,
rotateElement: this.rotateElement,
updateFilename: this.updateFilename
})
})
this.pdfAdapters.forEach((adapter) => {
adapter.setActions({
movePageTo: this.movePageTo,
addPdfs: this.addPdfs,
rotateElement: this.rotateElement,
updateFilename: this.updateFilename,
});
});
window.addPdfs = this.addPdfs;
window.exportPdf = this.exportPdf;
window.rotateAll = this.rotateAll;
window.addPdfs = this.addPdfs;
window.exportPdf = this.exportPdf;
window.rotateAll = this.rotateAll;
const filenameInput = document.getElementById('filename-input');
const downloadBtn = document.getElementById('export-button');
const filenameInput = document.getElementById("filename-input");
const downloadBtn = document.getElementById("export-button");
filenameInput.onkeyup = this.updateFilename;
filenameInput.onkeydown = this.preventIllegalChars;
filenameInput.disabled = false;
filenameInput.innerText = "";
downloadBtn.disabled = true;
filenameInput.onkeyup = this.updateFilename;
filenameInput.onkeydown = this.preventIllegalChars;
filenameInput.disabled = false;
filenameInput.innerText = "";
downloadBtn.disabled = true;
}
movePageTo(startElement, endElement, scrollTo = false) {
const childArray = Array.from(this.pagesContainer.childNodes);
const startIndex = childArray.indexOf(startElement);
const endIndex = childArray.indexOf(endElement);
this.pagesContainer.removeChild(startElement);
if (!endElement) {
this.pagesContainer.append(startElement);
} else {
this.pagesContainer.insertBefore(startElement, endElement);
}
movePageTo(startElement, endElement, scrollTo = false) {
const childArray = Array.from(this.pagesContainer.childNodes);
const startIndex = childArray.indexOf(startElement);
const endIndex = childArray.indexOf(endElement);
this.pagesContainer.removeChild(startElement);
if(!endElement) {
this.pagesContainer.append(startElement);
if (scrollTo) {
const { width } = startElement.getBoundingClientRect();
const vector = endIndex !== -1 && startIndex > endIndex ? 0 - width : width;
this.pagesContainerWrapper.scroll({
left: this.pagesContainerWrapper.scrollLeft + vector,
});
}
}
addPdfs(nextSiblingElement) {
var input = document.createElement("input");
input.type = "file";
input.multiple = true;
input.setAttribute("accept", "application/pdf");
input.onchange = async (e) => {
const files = e.target.files;
this.addPdfsFromFiles(files, nextSiblingElement);
this.updateFilename(files ? files[0].name : "");
};
input.click();
}
async addPdfsFromFiles(files, nextSiblingElement) {
this.fileName = files[0].name;
for (var i = 0; i < files.length; i++) {
await this.addPdfFile(files[i], nextSiblingElement);
}
document.querySelectorAll(".enable-on-file").forEach((element) => {
element.disabled = false;
});
}
rotateElement(element, deg) {
var lastTransform = element.style.rotate;
if (!lastTransform) {
lastTransform = "0";
}
const lastAngle = parseInt(lastTransform.replace(/[^\d-]/g, ""));
const newAngle = lastAngle + deg;
element.style.rotate = newAngle + "deg";
}
async addPdfFile(file, nextSiblingElement) {
const { renderer, pdfDocument } = await this.loadFile(file);
for (var i = 0; i < renderer.pageCount; i++) {
const div = document.createElement("div");
div.classList.add("page-container");
var img = document.createElement("img");
img.classList.add("page-image");
const imageSrc = await renderer.renderPage(i);
img.src = imageSrc;
img.pageIdx = i;
img.rend = renderer;
img.doc = pdfDocument;
div.appendChild(img);
this.pdfAdapters.forEach((adapter) => {
adapter.adapt?.(div);
});
if (nextSiblingElement) {
this.pagesContainer.insertBefore(div, nextSiblingElement);
} else {
this.pagesContainer.appendChild(div);
}
}
}
async loadFile(file) {
var objectUrl = URL.createObjectURL(file);
var pdfDocument = await this.toPdfLib(objectUrl);
var renderer = await this.toRenderer(objectUrl);
return { renderer, pdfDocument };
}
async toRenderer(objectUrl) {
pdfjsLib.GlobalWorkerOptions.workerSrc = "pdfjs/pdf.worker.js";
const pdf = await pdfjsLib.getDocument(objectUrl).promise;
return {
document: pdf,
pageCount: pdf.numPages,
renderPage: async function (pageIdx) {
const page = await this.document.getPage(pageIdx + 1);
const canvas = document.createElement("canvas");
// set the canvas size to the size of the page
if (page.rotate == 90 || page.rotate == 270) {
canvas.width = page.view[3];
canvas.height = page.view[2];
} else {
this.pagesContainer.insertBefore(startElement, endElement);
canvas.width = page.view[2];
canvas.height = page.view[3];
}
if(scrollTo) {
const { width } = startElement.getBoundingClientRect();
const vector = (endIndex !== -1 && startIndex > endIndex)
? 0-width
: width;
this.pagesContainerWrapper.scroll({
left: this.pagesContainerWrapper.scrollLeft + vector,
})
}
}
addPdfs(nextSiblingElement) {
var input = document.createElement('input');
input.type = 'file';
input.multiple = true;
input.setAttribute("accept", "application/pdf");
input.onchange = async(e) => {
const files = e.target.files;
this.addPdfsFromFiles(files, nextSiblingElement);
this.updateFilename(files ? files[0].name : "");
}
input.click();
}
async addPdfsFromFiles(files, nextSiblingElement) {
this.fileName = files[0].name;
for (var i=0; i < files.length; i++) {
await this.addPdfFile(files[i], nextSiblingElement);
}
document.querySelectorAll(".enable-on-file").forEach(element => {
element.disabled = false;
});
}
rotateElement(element, deg) {
var lastTransform = element.style.rotate;
if (!lastTransform) {
lastTransform = "0";
}
const lastAngle = parseInt(lastTransform.replace(/[^\d-]/g, ''));
const newAngle = lastAngle + deg;
element.style.rotate = newAngle + "deg";
}
async addPdfFile(file, nextSiblingElement) {
const { renderer, pdfDocument } = await this.loadFile(file);
for (var i=0; i < renderer.pageCount; i++) {
const div = document.createElement('div');
div.classList.add("page-container");
var img = document.createElement('img');
img.classList.add('page-image')
const imageSrc = await renderer.renderPage(i)
img.src = imageSrc;
img.pageIdx = i;
img.rend = renderer;
img.doc = pdfDocument;
div.appendChild(img);
this.pdfAdapters.forEach((adapter) => {
adapter.adapt?.(div)
})
if (nextSiblingElement) {
this.pagesContainer.insertBefore(div, nextSiblingElement);
} else {
this.pagesContainer.appendChild(div);
}
}
}
async loadFile(file) {
var objectUrl = URL.createObjectURL(file);
var pdfDocument = await this.toPdfLib(objectUrl);
var renderer = await this.toRenderer(objectUrl);
return { renderer, pdfDocument };
}
async toRenderer(objectUrl) {
pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdfjs/pdf.worker.js'
const pdf = await pdfjsLib.getDocument(objectUrl).promise;
return {
document: pdf,
pageCount: pdf.numPages,
renderPage: async function(pageIdx) {
const page = await this.document.getPage(pageIdx+1);
const canvas = document.createElement("canvas");
// set the canvas size to the size of the page
if (page.rotate == 90 || page.rotate == 270) {
canvas.width = page.view[3];
canvas.height = page.view[2];
} else {
canvas.width = page.view[2];
canvas.height = page.view[3];
}
// render the page onto the canvas
var renderContext = {
canvasContext: canvas.getContext("2d"),
viewport: page.getViewport({ scale: 1 })
};
await page.render(renderContext).promise;
return canvas.toDataURL();
}
// render the page onto the canvas
var renderContext = {
canvasContext: canvas.getContext("2d"),
viewport: page.getViewport({ scale: 1 }),
};
await page.render(renderContext).promise;
return canvas.toDataURL();
},
};
}
async toPdfLib(objectUrl) {
const existingPdfBytes = await fetch(objectUrl).then((res) => res.arrayBuffer());
const pdfDoc = await PDFLib.PDFDocument.load(existingPdfBytes, {
ignoreEncryption: true,
});
return pdfDoc;
}
rotateAll(deg) {
for (var i = 0; i < this.pagesContainer.childNodes.length; i++) {
const img = this.pagesContainer.childNodes[i].querySelector("img");
if (!img) continue;
this.rotateElement(img, deg);
}
}
async exportPdf() {
const pdfDoc = await PDFLib.PDFDocument.create();
const pageContainers = this.pagesContainer.querySelectorAll(".page-container"); // Select all .page-container elements
for (var i = 0; i < pageContainers.length; i++) {
const img = pageContainers[i].querySelector("img"); // Find the img element within each .page-container
if (!img) continue;
const pages = await pdfDoc.copyPages(img.doc, [img.pageIdx]);
const page = pages[0];
const rotation = img.style.rotate;
if (rotation) {
const rotationAngle = parseInt(rotation.replace(/[^\d-]/g, ""));
page.setRotation(PDFLib.degrees(page.getRotation().angle + rotationAngle));
}
pdfDoc.addPage(page);
}
const pdfBytes = await pdfDoc.save();
const pdfBlob = new Blob([pdfBytes], { type: "application/pdf" });
const url = URL.createObjectURL(pdfBlob);
const downloadOption = localStorage.getItem("downloadOption");
const filenameInput = document.getElementById("filename-input");
let inputArr = filenameInput.value.split(".");
if (inputArr !== null && inputArr !== undefined && inputArr.length > 0) {
inputArr = inputArr.filter((n) => n); // remove all empty strings, nulls or undefined
if (inputArr.length > 1) {
inputArr.pop(); // remove right part after last dot
}
filenameInput.value = inputArr.join("");
this.fileName = filenameInput.value;
}
async toPdfLib(objectUrl) {
const existingPdfBytes = await fetch(objectUrl).then(res => res.arrayBuffer());
const pdfDoc = await PDFLib.PDFDocument.load(existingPdfBytes, { ignoreEncryption: true });
return pdfDoc;
if (!filenameInput.value.includes(".pdf")) {
filenameInput.value = filenameInput.value + ".pdf";
this.fileName = filenameInput.value;
}
if (downloadOption === "sameWindow") {
// Open the file in the same window
window.location.href = url;
} else if (downloadOption === "newWindow") {
// Open the file in a new window
window.open(url, "_blank");
} else {
// Download the file
this.downloadLink = document.createElement("a");
this.downloadLink.id = "download-link";
this.downloadLink.href = url;
// downloadLink.download = this.fileName ? this.fileName : 'managed.pdf';
// downloadLink.download = this.fileName;
this.downloadLink.setAttribute("download", this.fileName ? this.fileName : "managed.pdf");
this.downloadLink.setAttribute("target", "_blank");
this.downloadLink.onclick = this.setDownloadAttribute;
this.downloadLink.click();
}
}
setDownloadAttribute() {
this.downloadLink.setAttribute("download", this.fileName ? this.fileName : "managed.pdf");
}
rotateAll(deg) {
for (var i=0; i<this.pagesContainer.childNodes.length; i++) {
const img = this.pagesContainer.childNodes[i].querySelector("img");
if (!img) continue;
this.rotateElement(img, deg)
}
updateFilename(fileName = "") {
const filenameInput = document.getElementById("filename-input");
const pagesContainer = document.getElementById("pages-container");
const downloadBtn = document.getElementById("export-button");
downloadBtn.disabled = pagesContainer.childElementCount === 0;
if (!this.fileName) {
this.fileName = fileName;
}
async exportPdf() {
const pdfDoc = await PDFLib.PDFDocument.create();
const pageContainers = this.pagesContainer.querySelectorAll('.page-container'); // Select all .page-container elements
for (var i = 0; i < pageContainers.length; i++) {
const img = pageContainers[i].querySelector("img"); // Find the img element within each .page-container
if (!img) continue;
const pages = await pdfDoc.copyPages(img.doc, [img.pageIdx])
const page = pages[0];
const rotation = img.style.rotate;
if (rotation) {
const rotationAngle = parseInt(rotation.replace(/[^\d-]/g, ''));
page.setRotation(PDFLib.degrees(page.getRotation().angle + rotationAngle))
}
pdfDoc.addPage(page);
}
const pdfBytes = await pdfDoc.save();
const pdfBlob = new Blob([pdfBytes], { type: 'application/pdf' });
const url = URL.createObjectURL(pdfBlob);
const downloadOption = localStorage.getItem('downloadOption');
const filenameInput = document.getElementById('filename-input');
let inputArr = filenameInput.value.split('.');
if (inputArr !== null && inputArr !== undefined && inputArr.length > 0) {
inputArr = inputArr.filter(n => n); // remove all empty strings, nulls or undefined
if (inputArr.length > 1) {
inputArr.pop(); // remove right part after last dot
}
filenameInput.value = inputArr.join('');
this.fileName = filenameInput.value;
}
if (!filenameInput.value.includes('.pdf')) {
filenameInput.value = filenameInput.value + '.pdf';
this.fileName = filenameInput.value;
}
if (downloadOption === 'sameWindow') {
// Open the file in the same window
window.location.href = url;
} else if (downloadOption === 'newWindow') {
// Open the file in a new window
window.open(url, '_blank');
} else {
// Download the file
this.downloadLink = document.createElement('a');
this.downloadLink.id = 'download-link';
this.downloadLink.href = url;
// downloadLink.download = this.fileName ? this.fileName : 'managed.pdf';
// downloadLink.download = this.fileName;
this.downloadLink.setAttribute('download', this.fileName ? this.fileName : 'managed.pdf');
this.downloadLink.setAttribute('target', '_blank');
this.downloadLink.onclick = this.setDownloadAttribute;
this.downloadLink.click();
}
if (!filenameInput.value) {
filenameInput.value = this.fileName;
}
}
setDownloadAttribute() {
this.downloadLink.setAttribute("download", this.fileName ? this.fileName : 'managed.pdf');
}
updateFilename(fileName = "") {
const filenameInput = document.getElementById('filename-input');
const pagesContainer = document.getElementById('pages-container');
const downloadBtn = document.getElementById('export-button');
downloadBtn.disabled = pagesContainer.childElementCount === 0
if (!this.fileName) {
this.fileName = fileName;
}
if (!filenameInput.value) {
filenameInput.value = this.fileName;
}
}
preventIllegalChars(e) {
// const filenameInput = document.getElementById('filename-input');
//
// filenameInput.value = filenameInput.value.replace('.pdf', '');
//
// // prevent .
// if (filenameInput.value.includes('.')) {
// filenameInput.value.replace('.','');
// }
}
preventIllegalChars(e) {
// const filenameInput = document.getElementById('filename-input');
//
// filenameInput.value = filenameInput.value.replace('.pdf', '');
//
// // prevent .
// if (filenameInput.value.includes('.')) {
// filenameInput.value.replace('.','');
// }
}
}
export default PdfContainer;

View File

@@ -1,94 +1,95 @@
class FileDragManager {
overlay;
dragCounter;
updateFilename;
overlay;
dragCounter;
updateFilename;
constructor(cb = null) {
this.dragCounter = 0;
this.setCallback(cb);
constructor(cb = null) {
this.dragCounter = 0;
this.setCallback(cb);
// Prevent default behavior for drag events
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
document.body.addEventListener(eventName, preventDefaults, false);
});
// Prevent default behavior for drag events
["dragenter", "dragover", "dragleave", "drop"].forEach((eventName) => {
document.body.addEventListener(eventName, preventDefaults, false);
});
function preventDefaults(e) {
e.preventDefault();
e.stopPropagation();
}
this.dragenterListener = this.dragenterListener.bind(this);
this.dragleaveListener = this.dragleaveListener.bind(this);
this.dropListener = this.dropListener.bind(this);
document.body.addEventListener('dragenter', this.dragenterListener);
document.body.addEventListener('dragleave', this.dragleaveListener);
// Add drop event listener
document.body.addEventListener('drop', this.dropListener);
function preventDefaults(e) {
e.preventDefault();
e.stopPropagation();
}
setActions({ updateFilename }) {
this.updateFilename = updateFilename;
this.dragenterListener = this.dragenterListener.bind(this);
this.dragleaveListener = this.dragleaveListener.bind(this);
this.dropListener = this.dropListener.bind(this);
document.body.addEventListener("dragenter", this.dragenterListener);
document.body.addEventListener("dragleave", this.dragleaveListener);
// Add drop event listener
document.body.addEventListener("drop", this.dropListener);
}
setActions({ updateFilename }) {
this.updateFilename = updateFilename;
}
setCallback(cb) {
if (cb) {
this.callback = cb;
} else {
this.callback = (files) => console.warn("FileDragManager not set");
}
}
setCallback(cb) {
if (cb) {
this.callback = cb;
} else {
this.callback = (files) => console.warn("FileDragManager not set");
}
dragenterListener() {
this.dragCounter++;
if (!this.overlay) {
// Create and show the overlay
this.overlay = document.createElement("div");
this.overlay.style.position = "fixed";
this.overlay.style.top = 0;
this.overlay.style.left = 0;
this.overlay.style.width = "100%";
this.overlay.style.height = "100%";
this.overlay.style.background = "rgba(0, 0, 0, 0.5)";
this.overlay.style.color = "#fff";
this.overlay.style.zIndex = "1000";
this.overlay.style.display = "flex";
this.overlay.style.alignItems = "center";
this.overlay.style.justifyContent = "center";
this.overlay.style.pointerEvents = "none";
this.overlay.innerHTML = "<p>Drop files anywhere to upload</p>";
document.getElementById("content-wrap").appendChild(this.overlay);
}
}
dragenterListener() {
this.dragCounter++;
if (!this.overlay) {
// Create and show the overlay
this.overlay = document.createElement('div');
this.overlay.style.position = 'fixed';
this.overlay.style.top = 0;
this.overlay.style.left = 0;
this.overlay.style.width = '100%';
this.overlay.style.height = '100%';
this.overlay.style.background = 'rgba(0, 0, 0, 0.5)';
this.overlay.style.color = '#fff';
this.overlay.style.zIndex = '1000';
this.overlay.style.display = 'flex';
this.overlay.style.alignItems = 'center';
this.overlay.style.justifyContent = 'center';
this.overlay.style.pointerEvents = 'none';
this.overlay.innerHTML = '<p>Drop files anywhere to upload</p>';
document.getElementById('content-wrap').appendChild(this.overlay);
dragleaveListener() {
this.dragCounter--;
if (this.dragCounter === 0) {
// Hide and remove the overlay
if (this.overlay) {
this.overlay.remove();
this.overlay = null;
}
}
}
dropListener(e) {
const dt = e.dataTransfer;
const files = dt.files;
this.callback(files)
.catch((err) => {
console.error(err);
//maybe
})
.finally(() => {
// Hide and remove the overlay
if (this.overlay) {
this.overlay.remove();
this.overlay = null;
}
};
dragleaveListener() {
this.dragCounter--;
if (this.dragCounter === 0) {
// Hide and remove the overlay
if (this.overlay) {
this.overlay.remove();
this.overlay = null;
}
}
};
dropListener(e) {
const dt = e.dataTransfer;
const files = dt.files;
this.callback(files).catch((err) => {
console.error(err);
//maybe
}).finally(() => {
// Hide and remove the overlay
if (this.overlay) {
this.overlay.remove();
this.overlay = null;
}
this.updateFilename(files ? files[0].name : "");
});
};
this.updateFilename(files ? files[0].name : "");
});
}
}
export default FileDragManager;

View File

@@ -1,35 +1,34 @@
const scrollDivHorizontally = (id) => {
var scrollDelta = 0; // variable to store the accumulated scroll delta
var isScrolling = false; // variable to track if scroll is already in progress
const divToScrollHorizontally = document.getElementById(id)
function scrollLoop() {
// Scroll the div horizontally by a fraction of the accumulated scroll delta
divToScrollHorizontally.scrollLeft += scrollDelta * 0.1;
var scrollDelta = 0; // variable to store the accumulated scroll delta
var isScrolling = false; // variable to track if scroll is already in progress
const divToScrollHorizontally = document.getElementById(id);
function scrollLoop() {
// Scroll the div horizontally by a fraction of the accumulated scroll delta
divToScrollHorizontally.scrollLeft += scrollDelta * 0.1;
// Reduce the accumulated scroll delta by a fraction
scrollDelta *= 0.9;
// Reduce the accumulated scroll delta by a fraction
scrollDelta *= 0.9;
// If scroll delta is still significant, continue the scroll loop
if (Math.abs(scrollDelta) > 0.1) {
requestAnimationFrame(scrollLoop);
} else {
isScrolling = false; // Reset scroll in progress flag
}
// If scroll delta is still significant, continue the scroll loop
if (Math.abs(scrollDelta) > 0.1) {
requestAnimationFrame(scrollLoop);
} else {
isScrolling = false; // Reset scroll in progress flag
}
}
divToScrollHorizontally.addEventListener("wheel", function (e) {
e.preventDefault(); // prevent default mousewheel behavior
divToScrollHorizontally.addEventListener("wheel", function(e) {
e.preventDefault(); // prevent default mousewheel behavior
// Accumulate the horizontal scroll delta
scrollDelta -= e.deltaX || e.wheelDeltaX || -e.deltaY || -e.wheelDeltaY;
// Accumulate the horizontal scroll delta
scrollDelta -= e.deltaX || e.wheelDeltaX || -e.deltaY || -e.wheelDeltaY;
// If scroll is not already in progress, start the scroll loop
if (!isScrolling) {
isScrolling = true;
requestAnimationFrame(scrollLoop);
}
});
}
// If scroll is not already in progress, start the scroll loop
if (!isScrolling) {
isScrolling = true;
requestAnimationFrame(scrollLoop);
}
});
};
export default scrollDivHorizontally;

File diff suppressed because it is too large Load Diff

View File

@@ -1,75 +1,76 @@
// Toggle search bar when the search icon is clicked
document.querySelector('#search-icon').addEventListener('click', function(e) {
e.preventDefault();
var searchBar = document.querySelector('#navbarSearch');
searchBar.classList.toggle('show');
document.querySelector("#search-icon").addEventListener("click", function (e) {
e.preventDefault();
var searchBar = document.querySelector("#navbarSearch");
searchBar.classList.toggle("show");
});
window.onload = function() {
var items = document.querySelectorAll('.dropdown-item, .nav-link');
var dummyContainer = document.createElement('div');
dummyContainer.style.position = 'absolute';
dummyContainer.style.visibility = 'hidden';
dummyContainer.style.whiteSpace = 'nowrap'; // Ensure we measure full width
document.body.appendChild(dummyContainer);
window.onload = function () {
var items = document.querySelectorAll(".dropdown-item, .nav-link");
var dummyContainer = document.createElement("div");
dummyContainer.style.position = "absolute";
dummyContainer.style.visibility = "hidden";
dummyContainer.style.whiteSpace = "nowrap"; // Ensure we measure full width
document.body.appendChild(dummyContainer);
var maxWidth = 0;
var maxWidth = 0;
items.forEach(function(item) {
var clone = item.cloneNode(true);
dummyContainer.appendChild(clone);
var width = clone.offsetWidth;
if (width > maxWidth) {
maxWidth = width;
}
dummyContainer.removeChild(clone);
});
items.forEach(function (item) {
var clone = item.cloneNode(true);
dummyContainer.appendChild(clone);
var width = clone.offsetWidth;
if (width > maxWidth) {
maxWidth = width;
}
dummyContainer.removeChild(clone);
});
document.body.removeChild(dummyContainer);
document.body.removeChild(dummyContainer);
// Store max width for later use
window.navItemMaxWidth = maxWidth;
// Store max width for later use
window.navItemMaxWidth = maxWidth;
};
// Show search results as user types in search box
document.querySelector('#navbarSearchInput').addEventListener('input', function(e) {
var searchText = e.target.value.toLowerCase();
var items = document.querySelectorAll('.dropdown-item, .nav-link');
var resultsBox = document.querySelector('#searchResults');
document.querySelector("#navbarSearchInput").addEventListener("input", function (e) {
var searchText = e.target.value.toLowerCase();
var items = document.querySelectorAll(".dropdown-item, .nav-link");
var resultsBox = document.querySelector("#searchResults");
// Clear any previous results
resultsBox.innerHTML = '';
// Clear any previous results
resultsBox.innerHTML = "";
items.forEach(function(item) {
var titleElement = item.querySelector('.icon-text');
var iconElement = item.querySelector('.icon');
var itemHref = item.getAttribute('href');
var tags = item.getAttribute('data-bs-tags') || ""; // If no tags, default to empty string
items.forEach(function (item) {
var titleElement = item.querySelector(".icon-text");
var iconElement = item.querySelector(".icon");
var itemHref = item.getAttribute("href");
var tags = item.getAttribute("data-bs-tags") || ""; // If no tags, default to empty string
if (titleElement && iconElement && itemHref !== '#') {
var title = titleElement.innerText;
if ((title.toLowerCase().indexOf(searchText) !== -1 || tags.toLowerCase().indexOf(searchText) !== -1) && !resultsBox.querySelector(`a[href="${item.getAttribute('href')}"]`)) {
var result = document.createElement('a');
result.href = itemHref;
result.classList.add('dropdown-item');
if (titleElement && iconElement && itemHref !== "#") {
var title = titleElement.innerText;
if (
(title.toLowerCase().indexOf(searchText) !== -1 || tags.toLowerCase().indexOf(searchText) !== -1) &&
!resultsBox.querySelector(`a[href="${item.getAttribute("href")}"]`)
) {
var result = document.createElement("a");
result.href = itemHref;
result.classList.add("dropdown-item");
var resultIcon = document.createElement('img');
resultIcon.src = iconElement.src;
resultIcon.alt = 'icon';
resultIcon.classList.add('icon');
result.appendChild(resultIcon);
var resultIcon = document.createElement("img");
resultIcon.src = iconElement.src;
resultIcon.alt = "icon";
resultIcon.classList.add("icon");
result.appendChild(resultIcon);
var resultText = document.createElement('span');
resultText.textContent = title;
resultText.classList.add('icon-text');
result.appendChild(resultText);
var resultText = document.createElement("span");
resultText.textContent = title;
resultText.classList.add("icon-text");
result.appendChild(resultText);
resultsBox.appendChild(result);
}
}
});
resultsBox.appendChild(result);
}
}
});
// Set the width of the search results box to the maximum width
resultsBox.style.width = window.navItemMaxWidth + 'px';
// Set the width of the search results box to the maximum width
resultsBox.style.width = window.navItemMaxWidth + "px";
});

View File

@@ -1,42 +1,33 @@
// Get the download option from local storage, or set it to 'sameWindow' if it doesn't exist
var downloadOption = localStorage.getItem('downloadOption')
|| 'sameWindow';
var downloadOption = localStorage.getItem("downloadOption") || "sameWindow";
// Set the selected option in the dropdown
document.getElementById('downloadOption').value = downloadOption;
document.getElementById("downloadOption").value = downloadOption;
// Save the selected option to local storage when the dropdown value changes
document.getElementById('downloadOption').addEventListener(
'change',
function() {
downloadOption = this.value;
localStorage.setItem('downloadOption',
downloadOption);
});
// Get the zipThreshold value from local storage, or set it to 0 if it doesn't exist
var zipThreshold = parseInt(localStorage.getItem('zipThreshold'), 10) || 4;
// Set the value of the slider and the display span
document.getElementById('zipThreshold').value = zipThreshold;
document.getElementById('zipThresholdValue').textContent = zipThreshold;
// Save the selected value to local storage when the slider value changes
document.getElementById('zipThreshold').addEventListener('input', function() {
zipThreshold = this.value;
document.getElementById('zipThresholdValue').textContent = zipThreshold;
localStorage.setItem('zipThreshold', zipThreshold);
document.getElementById("downloadOption").addEventListener("change", function () {
downloadOption = this.value;
localStorage.setItem("downloadOption", downloadOption);
});
// Get the zipThreshold value from local storage, or set it to 0 if it doesn't exist
var zipThreshold = parseInt(localStorage.getItem("zipThreshold"), 10) || 4;
var boredWaiting = localStorage.getItem('boredWaiting') || 'disabled';
document.getElementById('boredWaiting').checked = boredWaiting === 'enabled';
// Set the value of the slider and the display span
document.getElementById("zipThreshold").value = zipThreshold;
document.getElementById("zipThresholdValue").textContent = zipThreshold;
document.getElementById('boredWaiting').addEventListener('change', function() {
boredWaiting = this.checked ? 'enabled' : 'disabled';
localStorage.setItem('boredWaiting', boredWaiting);
});
// Save the selected value to local storage when the slider value changes
document.getElementById("zipThreshold").addEventListener("input", function () {
zipThreshold = this.value;
document.getElementById("zipThresholdValue").textContent = zipThreshold;
localStorage.setItem("zipThreshold", zipThreshold);
});
var boredWaiting = localStorage.getItem("boredWaiting") || "disabled";
document.getElementById("boredWaiting").checked = boredWaiting === "enabled";
document.getElementById("boredWaiting").addEventListener("change", function () {
boredWaiting = this.checked ? "enabled" : "disabled";
localStorage.setItem("boredWaiting", boredWaiting);
});

View File

@@ -1,39 +1,38 @@
TabContainer = {
initTabGroups() {
const groups = document.querySelectorAll(".tab-group");
const unloadedGroups = [...groups].filter(g => !g.initialised);
unloadedGroups.forEach(group => {
const containers = group.querySelectorAll(".tab-container");
const tabTitles = [...containers].map(c => c.getAttribute("title"));
initTabGroups() {
const groups = document.querySelectorAll(".tab-group");
const unloadedGroups = [...groups].filter((g) => !g.initialised);
unloadedGroups.forEach((group) => {
const containers = group.querySelectorAll(".tab-container");
const tabTitles = [...containers].map((c) => c.getAttribute("title"));
const tabList = document.createElement("div");
tabList.classList.add("tab-buttons");
tabTitles.forEach(title => {
const tabButton = document.createElement("button");
tabButton.innerHTML = title;
tabButton.onclick = e => {
this.setActiveTab(e.target);
}
tabList.appendChild(tabButton);
});
group.prepend(tabList);
const tabList = document.createElement("div");
tabList.classList.add("tab-buttons");
tabTitles.forEach((title) => {
const tabButton = document.createElement("button");
tabButton.innerHTML = title;
tabButton.onclick = (e) => {
this.setActiveTab(e.target);
};
tabList.appendChild(tabButton);
});
group.prepend(tabList);
this.setActiveTab(tabList.firstChild);
this.setActiveTab(tabList.firstChild);
group.initialised = true;
});
},
setActiveTab(tabButton) {
const group = tabButton.closest(".tab-group")
group.initialised = true;
});
},
setActiveTab(tabButton) {
const group = tabButton.closest(".tab-group");
group.querySelectorAll(".active").forEach(el => el.classList.remove("active"));
group.querySelectorAll(".active").forEach((el) => el.classList.remove("active"));
tabButton.classList.add("active");
group.querySelector(`[title="${tabButton.innerHTML}"]`).classList.add("active");
},
}
tabButton.classList.add("active");
group.querySelector(`[title="${tabButton.innerHTML}"]`).classList.add("active");
},
};
document.addEventListener("DOMContentLoaded", () => {
TabContainer.initTabGroups();
})
TabContainer.initTabGroups();
});

View File

@@ -116,7 +116,6 @@
top: 0;
}
:root {
--annotation-unfocused-field-background: url("data:image/svg+xml;charset=UTF-8,<svg width='1px' height='1px' xmlns='http://www.w3.org/2000/svg'><rect width='100%' height='100%' style='fill:rgba(0, 54, 255, 0.13);'/></svg>");
--input-focus-border-color: Highlight;
@@ -139,9 +138,7 @@
.annotationLayer .textWidgetAnnotation :is(input, textarea):required,
.annotationLayer .choiceWidgetAnnotation select:required,
.annotationLayer
.buttonWidgetAnnotation:is(.checkBox, .radioButton)
input:required {
.annotationLayer .buttonWidgetAnnotation:is(.checkBox, .radioButton) input:required {
outline: 1.5px solid selectedItem;
}
@@ -228,9 +225,7 @@
height: 100%;
}
.annotationLayer
:is(.linkAnnotation, .buttonWidgetAnnotation.pushButton):not(.hasBorder)
> a:hover {
.annotationLayer :is(.linkAnnotation, .buttonWidgetAnnotation.pushButton):not(.hasBorder) > a:hover {
opacity: 0.2;
background-color: rgba(255, 255, 0, 1);
box-shadow: 0 2px 10px rgba(255, 255, 0, 1);
@@ -268,9 +263,7 @@
.annotationLayer .textWidgetAnnotation :is(input, textarea):required,
.annotationLayer .choiceWidgetAnnotation select:required,
.annotationLayer
.buttonWidgetAnnotation:is(.checkBox, .radioButton)
input:required {
.annotationLayer .buttonWidgetAnnotation:is(.checkBox, .radioButton) input:required {
outline: 1.5px solid red;
}
@@ -288,9 +281,7 @@ input:required {
.annotationLayer .textWidgetAnnotation :is(input, textarea)[disabled],
.annotationLayer .choiceWidgetAnnotation select[disabled],
.annotationLayer
.buttonWidgetAnnotation:is(.checkBox, .radioButton)
input[disabled] {
.annotationLayer .buttonWidgetAnnotation:is(.checkBox, .radioButton) input[disabled] {
background: none;
border: 2px solid var(--input-disabled-border-color);
cursor: not-allowed;
@@ -298,9 +289,7 @@ input[disabled] {
.annotationLayer .textWidgetAnnotation :is(input, textarea):hover,
.annotationLayer .choiceWidgetAnnotation select:hover,
.annotationLayer
.buttonWidgetAnnotation:is(.checkBox, .radioButton)
input:hover {
.annotationLayer .buttonWidgetAnnotation:is(.checkBox, .radioButton) input:hover {
border: 2px solid var(--input-hover-border-color);
}
@@ -489,7 +478,6 @@ input:hover {
z-index: -1;
}
:root {
--xfa-unfocused-field-background: url("data:image/svg+xml;charset=UTF-8,<svg width='1px' height='1px' xmlns='http://www.w3.org/2000/svg'><rect width='100%' height='100%' style='fill:rgba(0, 54, 255, 0.13);'/></svg>");
--xfa-focus-outline: auto;
@@ -827,10 +815,7 @@ input:hover {
--freetext-padding: 2px;
--resizer-bg-color: var(--outline-color);
--resizer-size: 6px;
--resizer-shift: calc(
0px - (var(--outline-width) + var(--resizer-size)) / 2 -
var(--outline-around-width)
);
--resizer-shift: calc(0px - (var(--outline-width) + var(--resizer-size)) / 2 - var(--outline-around-width));
--editorFreeText-editing-cursor: text;
--editorInk-editing-cursor: url(../images/cursor-editorInk.svg) 0 16, pointer;
@@ -853,8 +838,7 @@ input:hover {
@media (-webkit-min-device-pixel-ratio: 1.1), (min-resolution: 1.1dppx) {
:root {
--editorFreeText-editing-cursor: url(../images/cursor-editorFreeText.svg) 0 16,
text;
--editorFreeText-editing-cursor: url(../images/cursor-editorFreeText.svg) 0 16, text;
}
}
@@ -1109,216 +1093,354 @@ input:hover {
}
.annotationEditorLayer[data-main-rotation="0"]
:is([data-editor-rotation="0"], [data-editor-rotation="180"]) > .resizers > .resizer.topLeft,
:is([data-editor-rotation="0"], [data-editor-rotation="180"])
> .resizers
> .resizer.topLeft,
.annotationEditorLayer[data-main-rotation="90"]
:is([data-editor-rotation="270"], [data-editor-rotation="90"]) > .resizers > .resizer.topLeft,
:is([data-editor-rotation="270"], [data-editor-rotation="90"])
> .resizers
> .resizer.topLeft,
.annotationEditorLayer[data-main-rotation="180"]
:is([data-editor-rotation="180"], [data-editor-rotation="0"]) > .resizers > .resizer.topLeft,
:is([data-editor-rotation="180"], [data-editor-rotation="0"])
> .resizers
> .resizer.topLeft,
.annotationEditorLayer[data-main-rotation="270"]
:is([data-editor-rotation="90"], [data-editor-rotation="270"]) > .resizers > .resizer.topLeft,
:is([data-editor-rotation="90"], [data-editor-rotation="270"])
> .resizers
> .resizer.topLeft,
.annotationEditorLayer[data-main-rotation="0"]
:is([data-editor-rotation="0"], [data-editor-rotation="180"]) > .resizers > .resizer.bottomRight,
:is([data-editor-rotation="0"], [data-editor-rotation="180"])
> .resizers
> .resizer.bottomRight,
.annotationEditorLayer[data-main-rotation="90"]
:is([data-editor-rotation="270"], [data-editor-rotation="90"]) > .resizers > .resizer.bottomRight,
:is([data-editor-rotation="270"], [data-editor-rotation="90"])
> .resizers
> .resizer.bottomRight,
.annotationEditorLayer[data-main-rotation="180"]
:is([data-editor-rotation="180"], [data-editor-rotation="0"]) > .resizers > .resizer.bottomRight,
:is([data-editor-rotation="180"], [data-editor-rotation="0"])
> .resizers
> .resizer.bottomRight,
.annotationEditorLayer[data-main-rotation="270"]
:is([data-editor-rotation="90"], [data-editor-rotation="270"]) > .resizers > .resizer.bottomRight {
:is([data-editor-rotation="90"], [data-editor-rotation="270"])
> .resizers
> .resizer.bottomRight {
cursor: nwse-resize;
}
.annotationEditorLayer[data-main-rotation="0"]
:is([data-editor-rotation="0"], [data-editor-rotation="180"]) > .resizers > .resizer.topMiddle,
:is([data-editor-rotation="0"], [data-editor-rotation="180"])
> .resizers
> .resizer.topMiddle,
.annotationEditorLayer[data-main-rotation="90"]
:is([data-editor-rotation="270"], [data-editor-rotation="90"]) > .resizers > .resizer.topMiddle,
:is([data-editor-rotation="270"], [data-editor-rotation="90"])
> .resizers
> .resizer.topMiddle,
.annotationEditorLayer[data-main-rotation="180"]
:is([data-editor-rotation="180"], [data-editor-rotation="0"]) > .resizers > .resizer.topMiddle,
:is([data-editor-rotation="180"], [data-editor-rotation="0"])
> .resizers
> .resizer.topMiddle,
.annotationEditorLayer[data-main-rotation="270"]
:is([data-editor-rotation="90"], [data-editor-rotation="270"]) > .resizers > .resizer.topMiddle,
:is([data-editor-rotation="90"], [data-editor-rotation="270"])
> .resizers
> .resizer.topMiddle,
.annotationEditorLayer[data-main-rotation="0"]
:is([data-editor-rotation="0"], [data-editor-rotation="180"]) > .resizers > .resizer.bottomMiddle,
:is([data-editor-rotation="0"], [data-editor-rotation="180"])
> .resizers
> .resizer.bottomMiddle,
.annotationEditorLayer[data-main-rotation="90"]
:is([data-editor-rotation="270"], [data-editor-rotation="90"]) > .resizers > .resizer.bottomMiddle,
:is([data-editor-rotation="270"], [data-editor-rotation="90"])
> .resizers
> .resizer.bottomMiddle,
.annotationEditorLayer[data-main-rotation="180"]
:is([data-editor-rotation="180"], [data-editor-rotation="0"]) > .resizers > .resizer.bottomMiddle,
:is([data-editor-rotation="180"], [data-editor-rotation="0"])
> .resizers
> .resizer.bottomMiddle,
.annotationEditorLayer[data-main-rotation="270"]
:is([data-editor-rotation="90"], [data-editor-rotation="270"]) > .resizers > .resizer.bottomMiddle {
:is([data-editor-rotation="90"], [data-editor-rotation="270"])
> .resizers
> .resizer.bottomMiddle {
cursor: ns-resize;
}
.annotationEditorLayer[data-main-rotation="0"]
:is([data-editor-rotation="0"], [data-editor-rotation="180"]) > .resizers > .resizer.topRight,
:is([data-editor-rotation="0"], [data-editor-rotation="180"])
> .resizers
> .resizer.topRight,
.annotationEditorLayer[data-main-rotation="90"]
:is([data-editor-rotation="270"], [data-editor-rotation="90"]) > .resizers > .resizer.topRight,
:is([data-editor-rotation="270"], [data-editor-rotation="90"])
> .resizers
> .resizer.topRight,
.annotationEditorLayer[data-main-rotation="180"]
:is([data-editor-rotation="180"], [data-editor-rotation="0"]) > .resizers > .resizer.topRight,
:is([data-editor-rotation="180"], [data-editor-rotation="0"])
> .resizers
> .resizer.topRight,
.annotationEditorLayer[data-main-rotation="270"]
:is([data-editor-rotation="90"], [data-editor-rotation="270"]) > .resizers > .resizer.topRight,
:is([data-editor-rotation="90"], [data-editor-rotation="270"])
> .resizers
> .resizer.topRight,
.annotationEditorLayer[data-main-rotation="0"]
:is([data-editor-rotation="0"], [data-editor-rotation="180"]) > .resizers > .resizer.bottomLeft,
:is([data-editor-rotation="0"], [data-editor-rotation="180"])
> .resizers
> .resizer.bottomLeft,
.annotationEditorLayer[data-main-rotation="90"]
:is([data-editor-rotation="270"], [data-editor-rotation="90"]) > .resizers > .resizer.bottomLeft,
:is([data-editor-rotation="270"], [data-editor-rotation="90"])
> .resizers
> .resizer.bottomLeft,
.annotationEditorLayer[data-main-rotation="180"]
:is([data-editor-rotation="180"], [data-editor-rotation="0"]) > .resizers > .resizer.bottomLeft,
:is([data-editor-rotation="180"], [data-editor-rotation="0"])
> .resizers
> .resizer.bottomLeft,
.annotationEditorLayer[data-main-rotation="270"]
:is([data-editor-rotation="90"], [data-editor-rotation="270"]) > .resizers > .resizer.bottomLeft {
:is([data-editor-rotation="90"], [data-editor-rotation="270"])
> .resizers
> .resizer.bottomLeft {
cursor: nesw-resize;
}
.annotationEditorLayer[data-main-rotation="0"]
:is([data-editor-rotation="0"], [data-editor-rotation="180"]) > .resizers > .resizer.middleRight,
:is([data-editor-rotation="0"], [data-editor-rotation="180"])
> .resizers
> .resizer.middleRight,
.annotationEditorLayer[data-main-rotation="90"]
:is([data-editor-rotation="270"], [data-editor-rotation="90"]) > .resizers > .resizer.middleRight,
:is([data-editor-rotation="270"], [data-editor-rotation="90"])
> .resizers
> .resizer.middleRight,
.annotationEditorLayer[data-main-rotation="180"]
:is([data-editor-rotation="180"], [data-editor-rotation="0"]) > .resizers > .resizer.middleRight,
:is([data-editor-rotation="180"], [data-editor-rotation="0"])
> .resizers
> .resizer.middleRight,
.annotationEditorLayer[data-main-rotation="270"]
:is([data-editor-rotation="90"], [data-editor-rotation="270"]) > .resizers > .resizer.middleRight,
:is([data-editor-rotation="90"], [data-editor-rotation="270"])
> .resizers
> .resizer.middleRight,
.annotationEditorLayer[data-main-rotation="0"]
:is([data-editor-rotation="0"], [data-editor-rotation="180"]) > .resizers > .resizer.middleLeft,
:is([data-editor-rotation="0"], [data-editor-rotation="180"])
> .resizers
> .resizer.middleLeft,
.annotationEditorLayer[data-main-rotation="90"]
:is([data-editor-rotation="270"], [data-editor-rotation="90"]) > .resizers > .resizer.middleLeft,
:is([data-editor-rotation="270"], [data-editor-rotation="90"])
> .resizers
> .resizer.middleLeft,
.annotationEditorLayer[data-main-rotation="180"]
:is([data-editor-rotation="180"], [data-editor-rotation="0"]) > .resizers > .resizer.middleLeft,
:is([data-editor-rotation="180"], [data-editor-rotation="0"])
> .resizers
> .resizer.middleLeft,
.annotationEditorLayer[data-main-rotation="270"]
:is([data-editor-rotation="90"], [data-editor-rotation="270"]) > .resizers > .resizer.middleLeft {
:is([data-editor-rotation="90"], [data-editor-rotation="270"])
> .resizers
> .resizer.middleLeft {
cursor: ew-resize;
}
.annotationEditorLayer[data-main-rotation="0"]
:is([data-editor-rotation="90"], [data-editor-rotation="270"]) > .resizers > .resizer.topLeft,
:is([data-editor-rotation="90"], [data-editor-rotation="270"])
> .resizers
> .resizer.topLeft,
.annotationEditorLayer[data-main-rotation="90"]
:is([data-editor-rotation="0"], [data-editor-rotation="180"]) > .resizers > .resizer.topLeft,
:is([data-editor-rotation="0"], [data-editor-rotation="180"])
> .resizers
> .resizer.topLeft,
.annotationEditorLayer[data-main-rotation="180"]
:is([data-editor-rotation="270"], [data-editor-rotation="90"]) > .resizers > .resizer.topLeft,
:is([data-editor-rotation="270"], [data-editor-rotation="90"])
> .resizers
> .resizer.topLeft,
.annotationEditorLayer[data-main-rotation="270"]
:is([data-editor-rotation="180"], [data-editor-rotation="0"]) > .resizers > .resizer.topLeft,
:is([data-editor-rotation="180"], [data-editor-rotation="0"])
> .resizers
> .resizer.topLeft,
.annotationEditorLayer[data-main-rotation="0"]
:is([data-editor-rotation="90"], [data-editor-rotation="270"]) > .resizers > .resizer.bottomRight,
:is([data-editor-rotation="90"], [data-editor-rotation="270"])
> .resizers
> .resizer.bottomRight,
.annotationEditorLayer[data-main-rotation="90"]
:is([data-editor-rotation="0"], [data-editor-rotation="180"]) > .resizers > .resizer.bottomRight,
:is([data-editor-rotation="0"], [data-editor-rotation="180"])
> .resizers
> .resizer.bottomRight,
.annotationEditorLayer[data-main-rotation="180"]
:is([data-editor-rotation="270"], [data-editor-rotation="90"]) > .resizers > .resizer.bottomRight,
:is([data-editor-rotation="270"], [data-editor-rotation="90"])
> .resizers
> .resizer.bottomRight,
.annotationEditorLayer[data-main-rotation="270"]
:is([data-editor-rotation="180"], [data-editor-rotation="0"]) > .resizers > .resizer.bottomRight {
:is([data-editor-rotation="180"], [data-editor-rotation="0"])
> .resizers
> .resizer.bottomRight {
cursor: nesw-resize;
}
.annotationEditorLayer[data-main-rotation="0"]
:is([data-editor-rotation="90"], [data-editor-rotation="270"]) > .resizers > .resizer.topMiddle,
:is([data-editor-rotation="90"], [data-editor-rotation="270"])
> .resizers
> .resizer.topMiddle,
.annotationEditorLayer[data-main-rotation="90"]
:is([data-editor-rotation="0"], [data-editor-rotation="180"]) > .resizers > .resizer.topMiddle,
:is([data-editor-rotation="0"], [data-editor-rotation="180"])
> .resizers
> .resizer.topMiddle,
.annotationEditorLayer[data-main-rotation="180"]
:is([data-editor-rotation="270"], [data-editor-rotation="90"]) > .resizers > .resizer.topMiddle,
:is([data-editor-rotation="270"], [data-editor-rotation="90"])
> .resizers
> .resizer.topMiddle,
.annotationEditorLayer[data-main-rotation="270"]
:is([data-editor-rotation="180"], [data-editor-rotation="0"]) > .resizers > .resizer.topMiddle,
:is([data-editor-rotation="180"], [data-editor-rotation="0"])
> .resizers
> .resizer.topMiddle,
.annotationEditorLayer[data-main-rotation="0"]
:is([data-editor-rotation="90"], [data-editor-rotation="270"]) > .resizers > .resizer.bottomMiddle,
:is([data-editor-rotation="90"], [data-editor-rotation="270"])
> .resizers
> .resizer.bottomMiddle,
.annotationEditorLayer[data-main-rotation="90"]
:is([data-editor-rotation="0"], [data-editor-rotation="180"]) > .resizers > .resizer.bottomMiddle,
:is([data-editor-rotation="0"], [data-editor-rotation="180"])
> .resizers
> .resizer.bottomMiddle,
.annotationEditorLayer[data-main-rotation="180"]
:is([data-editor-rotation="270"], [data-editor-rotation="90"]) > .resizers > .resizer.bottomMiddle,
:is([data-editor-rotation="270"], [data-editor-rotation="90"])
> .resizers
> .resizer.bottomMiddle,
.annotationEditorLayer[data-main-rotation="270"]
:is([data-editor-rotation="180"], [data-editor-rotation="0"]) > .resizers > .resizer.bottomMiddle {
:is([data-editor-rotation="180"], [data-editor-rotation="0"])
> .resizers
> .resizer.bottomMiddle {
cursor: ew-resize;
}
.annotationEditorLayer[data-main-rotation="0"]
:is([data-editor-rotation="90"], [data-editor-rotation="270"]) > .resizers > .resizer.topRight,
:is([data-editor-rotation="90"], [data-editor-rotation="270"])
> .resizers
> .resizer.topRight,
.annotationEditorLayer[data-main-rotation="90"]
:is([data-editor-rotation="0"], [data-editor-rotation="180"]) > .resizers > .resizer.topRight,
:is([data-editor-rotation="0"], [data-editor-rotation="180"])
> .resizers
> .resizer.topRight,
.annotationEditorLayer[data-main-rotation="180"]
:is([data-editor-rotation="270"], [data-editor-rotation="90"]) > .resizers > .resizer.topRight,
:is([data-editor-rotation="270"], [data-editor-rotation="90"])
> .resizers
> .resizer.topRight,
.annotationEditorLayer[data-main-rotation="270"]
:is([data-editor-rotation="180"], [data-editor-rotation="0"]) > .resizers > .resizer.topRight,
:is([data-editor-rotation="180"], [data-editor-rotation="0"])
> .resizers
> .resizer.topRight,
.annotationEditorLayer[data-main-rotation="0"]
:is([data-editor-rotation="90"], [data-editor-rotation="270"]) > .resizers > .resizer.bottomLeft,
:is([data-editor-rotation="90"], [data-editor-rotation="270"])
> .resizers
> .resizer.bottomLeft,
.annotationEditorLayer[data-main-rotation="90"]
:is([data-editor-rotation="0"], [data-editor-rotation="180"]) > .resizers > .resizer.bottomLeft,
:is([data-editor-rotation="0"], [data-editor-rotation="180"])
> .resizers
> .resizer.bottomLeft,
.annotationEditorLayer[data-main-rotation="180"]
:is([data-editor-rotation="270"], [data-editor-rotation="90"]) > .resizers > .resizer.bottomLeft,
:is([data-editor-rotation="270"], [data-editor-rotation="90"])
> .resizers
> .resizer.bottomLeft,
.annotationEditorLayer[data-main-rotation="270"]
:is([data-editor-rotation="180"], [data-editor-rotation="0"]) > .resizers > .resizer.bottomLeft {
:is([data-editor-rotation="180"], [data-editor-rotation="0"])
> .resizers
> .resizer.bottomLeft {
cursor: nwse-resize;
}
.annotationEditorLayer[data-main-rotation="0"]
:is([data-editor-rotation="90"], [data-editor-rotation="270"]) > .resizers > .resizer.middleRight,
:is([data-editor-rotation="90"], [data-editor-rotation="270"])
> .resizers
> .resizer.middleRight,
.annotationEditorLayer[data-main-rotation="90"]
:is([data-editor-rotation="0"], [data-editor-rotation="180"]) > .resizers > .resizer.middleRight,
:is([data-editor-rotation="0"], [data-editor-rotation="180"])
> .resizers
> .resizer.middleRight,
.annotationEditorLayer[data-main-rotation="180"]
:is([data-editor-rotation="270"], [data-editor-rotation="90"]) > .resizers > .resizer.middleRight,
:is([data-editor-rotation="270"], [data-editor-rotation="90"])
> .resizers
> .resizer.middleRight,
.annotationEditorLayer[data-main-rotation="270"]
:is([data-editor-rotation="180"], [data-editor-rotation="0"]) > .resizers > .resizer.middleRight,
:is([data-editor-rotation="180"], [data-editor-rotation="0"])
> .resizers
> .resizer.middleRight,
.annotationEditorLayer[data-main-rotation="0"]
:is([data-editor-rotation="90"], [data-editor-rotation="270"]) > .resizers > .resizer.middleLeft,
:is([data-editor-rotation="90"], [data-editor-rotation="270"])
> .resizers
> .resizer.middleLeft,
.annotationEditorLayer[data-main-rotation="90"]
:is([data-editor-rotation="0"], [data-editor-rotation="180"]) > .resizers > .resizer.middleLeft,
:is([data-editor-rotation="0"], [data-editor-rotation="180"])
> .resizers
> .resizer.middleLeft,
.annotationEditorLayer[data-main-rotation="180"]
:is([data-editor-rotation="270"], [data-editor-rotation="90"]) > .resizers > .resizer.middleLeft,
:is([data-editor-rotation="270"], [data-editor-rotation="90"])
> .resizers
> .resizer.middleLeft,
.annotationEditorLayer[data-main-rotation="270"]
:is([data-editor-rotation="180"], [data-editor-rotation="0"]) > .resizers > .resizer.middleLeft {
:is([data-editor-rotation="180"], [data-editor-rotation="0"])
> .resizers
> .resizer.middleLeft {
cursor: ns-resize;
}
.annotationEditorLayer
:is(
[data-main-rotation="0"] [data-editor-rotation="90"],
[data-main-rotation="90"] [data-editor-rotation="0"],
[data-main-rotation="180"] [data-editor-rotation="270"],
[data-main-rotation="270"] [data-editor-rotation="180"]
) .altText {
:is(
[data-main-rotation="0"] [data-editor-rotation="90"],
[data-main-rotation="90"] [data-editor-rotation="0"],
[data-main-rotation="180"] [data-editor-rotation="270"],
[data-main-rotation="270"] [data-editor-rotation="180"]
)
.altText {
rotate: 270deg;
}
[dir="ltr"] .annotationEditorLayer
:is(
[data-main-rotation="0"] [data-editor-rotation="90"],
[data-main-rotation="90"] [data-editor-rotation="0"],
[data-main-rotation="180"] [data-editor-rotation="270"],
[data-main-rotation="270"] [data-editor-rotation="180"]
) .altText {
[dir="ltr"]
.annotationEditorLayer
:is(
[data-main-rotation="0"] [data-editor-rotation="90"],
[data-main-rotation="90"] [data-editor-rotation="0"],
[data-main-rotation="180"] [data-editor-rotation="270"],
[data-main-rotation="270"] [data-editor-rotation="180"]
)
.altText {
inset-inline-start: calc(100% - 8px);
}
[dir="ltr"] .annotationEditorLayer
:is(
[data-main-rotation="0"] [data-editor-rotation="90"],
[data-main-rotation="90"] [data-editor-rotation="0"],
[data-main-rotation="180"] [data-editor-rotation="270"],
[data-main-rotation="270"] [data-editor-rotation="180"]
) .altText.small {
[dir="ltr"]
.annotationEditorLayer
:is(
[data-main-rotation="0"] [data-editor-rotation="90"],
[data-main-rotation="90"] [data-editor-rotation="0"],
[data-main-rotation="180"] [data-editor-rotation="270"],
[data-main-rotation="270"] [data-editor-rotation="180"]
)
.altText.small {
inset-inline-start: calc(100% + 8px);
inset-block-start: 100%;
}
[dir="rtl"] .annotationEditorLayer
:is(
[data-main-rotation="0"] [data-editor-rotation="90"],
[data-main-rotation="90"] [data-editor-rotation="0"],
[data-main-rotation="180"] [data-editor-rotation="270"],
[data-main-rotation="270"] [data-editor-rotation="180"]
) .altText {
[dir="rtl"]
.annotationEditorLayer
:is(
[data-main-rotation="0"] [data-editor-rotation="90"],
[data-main-rotation="90"] [data-editor-rotation="0"],
[data-main-rotation="180"] [data-editor-rotation="270"],
[data-main-rotation="270"] [data-editor-rotation="180"]
)
.altText {
inset-block-end: calc(100% - 8px);
}
[dir="rtl"] .annotationEditorLayer
:is(
[data-main-rotation="0"] [data-editor-rotation="90"],
[data-main-rotation="90"] [data-editor-rotation="0"],
[data-main-rotation="180"] [data-editor-rotation="270"],
[data-main-rotation="270"] [data-editor-rotation="180"]
) .altText.small {
[dir="rtl"]
.annotationEditorLayer
:is(
[data-main-rotation="0"] [data-editor-rotation="90"],
[data-main-rotation="90"] [data-editor-rotation="0"],
[data-main-rotation="180"] [data-editor-rotation="270"],
[data-main-rotation="270"] [data-editor-rotation="180"]
)
.altText.small {
inset-inline-start: -8px;
inset-block-start: 0;
}
.annotationEditorLayer
:is(
[data-main-rotation="0"] [data-editor-rotation="180"],
[data-main-rotation="90"] [data-editor-rotation="90"],
[data-main-rotation="180"] [data-editor-rotation="0"],
[data-main-rotation="270"] [data-editor-rotation="270"]
) .altText {
:is(
[data-main-rotation="0"] [data-editor-rotation="180"],
[data-main-rotation="90"] [data-editor-rotation="90"],
[data-main-rotation="180"] [data-editor-rotation="0"],
[data-main-rotation="270"] [data-editor-rotation="270"]
)
.altText {
rotate: 180deg;
inset-block-end: calc(100% - 8px);
@@ -1326,64 +1448,74 @@ input:hover {
}
.annotationEditorLayer
:is(
[data-main-rotation="0"] [data-editor-rotation="180"],
[data-main-rotation="90"] [data-editor-rotation="90"],
[data-main-rotation="180"] [data-editor-rotation="0"],
[data-main-rotation="270"] [data-editor-rotation="270"]
) .altText.small {
:is(
[data-main-rotation="0"] [data-editor-rotation="180"],
[data-main-rotation="90"] [data-editor-rotation="90"],
[data-main-rotation="180"] [data-editor-rotation="0"],
[data-main-rotation="270"] [data-editor-rotation="270"]
)
.altText.small {
inset-inline-start: 100%;
inset-block-start: -8px;
}
.annotationEditorLayer
:is(
[data-main-rotation="0"] [data-editor-rotation="270"],
[data-main-rotation="90"] [data-editor-rotation="180"],
[data-main-rotation="180"] [data-editor-rotation="90"],
[data-main-rotation="270"] [data-editor-rotation="0"]
) .altText {
:is(
[data-main-rotation="0"] [data-editor-rotation="270"],
[data-main-rotation="90"] [data-editor-rotation="180"],
[data-main-rotation="180"] [data-editor-rotation="90"],
[data-main-rotation="270"] [data-editor-rotation="0"]
)
.altText {
rotate: 90deg;
}
[dir="ltr"] .annotationEditorLayer
:is(
[data-main-rotation="0"] [data-editor-rotation="270"],
[data-main-rotation="90"] [data-editor-rotation="180"],
[data-main-rotation="180"] [data-editor-rotation="90"],
[data-main-rotation="270"] [data-editor-rotation="0"]
) .altText {
[dir="ltr"]
.annotationEditorLayer
:is(
[data-main-rotation="0"] [data-editor-rotation="270"],
[data-main-rotation="90"] [data-editor-rotation="180"],
[data-main-rotation="180"] [data-editor-rotation="90"],
[data-main-rotation="270"] [data-editor-rotation="0"]
)
.altText {
inset-block-end: calc(100% - 8px);
}
[dir="ltr"] .annotationEditorLayer
:is(
[data-main-rotation="0"] [data-editor-rotation="270"],
[data-main-rotation="90"] [data-editor-rotation="180"],
[data-main-rotation="180"] [data-editor-rotation="90"],
[data-main-rotation="270"] [data-editor-rotation="0"]
) .altText.small {
[dir="ltr"]
.annotationEditorLayer
:is(
[data-main-rotation="0"] [data-editor-rotation="270"],
[data-main-rotation="90"] [data-editor-rotation="180"],
[data-main-rotation="180"] [data-editor-rotation="90"],
[data-main-rotation="270"] [data-editor-rotation="0"]
)
.altText.small {
inset-inline-start: -8px;
inset-block-start: 0;
}
[dir="rtl"] .annotationEditorLayer
:is(
[data-main-rotation="0"] [data-editor-rotation="270"],
[data-main-rotation="90"] [data-editor-rotation="180"],
[data-main-rotation="180"] [data-editor-rotation="90"],
[data-main-rotation="270"] [data-editor-rotation="0"]
) .altText {
[dir="rtl"]
.annotationEditorLayer
:is(
[data-main-rotation="0"] [data-editor-rotation="270"],
[data-main-rotation="90"] [data-editor-rotation="180"],
[data-main-rotation="180"] [data-editor-rotation="90"],
[data-main-rotation="270"] [data-editor-rotation="0"]
)
.altText {
inset-inline-start: calc(100% - 8px);
}
[dir="rtl"] .annotationEditorLayer
:is(
[data-main-rotation="0"] [data-editor-rotation="270"],
[data-main-rotation="90"] [data-editor-rotation="180"],
[data-main-rotation="180"] [data-editor-rotation="90"],
[data-main-rotation="270"] [data-editor-rotation="0"]
) .altText.small {
[dir="rtl"]
.annotationEditorLayer
:is(
[data-main-rotation="0"] [data-editor-rotation="270"],
[data-main-rotation="90"] [data-editor-rotation="180"],
[data-main-rotation="180"] [data-editor-rotation="90"],
[data-main-rotation="270"] [data-editor-rotation="0"]
)
.altText.small {
inset-inline-start: calc(100% + 8px);
inset-block-start: 100%;
}
@@ -1421,7 +1553,6 @@ input:hover {
}
.altText.small {
inset-block-end: unset;
inset-inline-start: 0;
inset-block-start: calc(100% + 8px);
@@ -1515,7 +1646,6 @@ input:hover {
}
@media (prefers-color-scheme: dark) {
.altText .tooltip.show {
--alt-text-tooltip-bg: #1c1b22;
--alt-text-tooltip-fg: #fbfbfe;
@@ -1524,7 +1654,6 @@ input:hover {
}
@media screen and (forced-colors: active) {
.altText .tooltip.show {
--alt-text-tooltip-bg: Canvas;
--alt-text-tooltip-fg: CanvasText;
@@ -1581,7 +1710,6 @@ input:hover {
}
@media (prefers-color-scheme: dark) {
#altTextDialog {
--dialog-bg-color: #1c1b22;
--dialog-border-color: #1c1b22;
@@ -1604,7 +1732,6 @@ input:hover {
}
@media screen and (forced-colors: active) {
#altTextDialog {
--dialog-bg-color: Canvas;
--dialog-border-color: CanvasText;
@@ -2022,8 +2149,8 @@ input:hover {
--toolbar-border-color: rgba(184, 184, 184, 1);
--toolbar-box-shadow: 0 1px 0 var(--toolbar-border-color);
--toolbar-border-bottom: none;
--toolbarSidebar-box-shadow: inset calc(-1px * var(--dir-factor)) 0 0 rgba(0, 0, 0, 0.25),
0 1px 0 rgba(0, 0, 0, 0.15), 0 0 1px rgba(0, 0, 0, 0.1);
--toolbarSidebar-box-shadow: inset calc(-1px * var(--dir-factor)) 0 0 rgba(0, 0, 0, 0.25), 0 1px 0 rgba(0, 0, 0, 0.15),
0 0 1px rgba(0, 0, 0, 0.1);
--toolbarSidebar-border-bottom: none;
--button-hover-color: rgba(221, 222, 223, 1);
--toggled-btn-color: rgba(0, 0, 0, 1);
@@ -2319,8 +2446,7 @@ body {
font: message-box;
}
:is(.toolbar, .editorParamsToolbar, .findbar, #sidebarContainer)
:is(input, button, select),
:is(.toolbar, .editorParamsToolbar, .findbar, #sidebarContainer) :is(input, button, select),
.secondaryToolbar :is(input, button, a, select) {
outline: none;
font: message-box;
@@ -2417,19 +2543,18 @@ body {
height: 100%;
width: calc(100% + 150px);
background: repeating-linear-gradient(
135deg,
var(--progressBar-blend-color) 0,
var(--progressBar-bg-color) 5px,
var(--progressBar-bg-color) 45px,
var(--progressBar-color) 55px,
var(--progressBar-color) 95px,
var(--progressBar-blend-color) 100px
135deg,
var(--progressBar-blend-color) 0,
var(--progressBar-bg-color) 5px,
var(--progressBar-bg-color) 45px,
var(--progressBar-color) 55px,
var(--progressBar-color) 95px,
var(--progressBar-blend-color) 100px
);
animation: progressIndeterminate 1s linear infinite;
}
#outerContainer.sidebarResizing
:is(#sidebarContainer, #viewerContainer, #loadingBar) {
#outerContainer.sidebarResizing :is(#sidebarContainer, #viewerContainer, #loadingBar) {
/* Improve responsiveness and avoid visual glitches when the sidebar is resized. */
transition-duration: 0s;
}
@@ -2600,8 +2725,9 @@ body {
.doorHanger,
.doorHangerRight {
border-radius: 2px;
box-shadow: 0 1px 5px var(--doorhanger-border-color),
0 0 0 1px var(--doorhanger-border-color);
box-shadow:
0 1px 5px var(--doorhanger-border-color),
0 0 0 1px var(--doorhanger-border-color);
border: var(--doorhanger-border-color-whcm);
}
@@ -3455,8 +3581,7 @@ dialog :link {
cursor: grab !important;
}
.grab-to-pan-grab
*:not(input):not(textarea):not(button):not(select):not(:link) {
.grab-to-pan-grab *:not(input):not(textarea):not(button):not(select):not(:link) {
cursor: inherit !important;
}