Compare commits
35 Commits
normalize_
...
v0.21.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
625275124a | ||
|
|
c96ebccae4 | ||
|
|
20cb460a7e | ||
|
|
3a62d19979 | ||
|
|
51ad741744 | ||
|
|
673f005fe6 | ||
|
|
8d9f0361d0 | ||
|
|
56e3ec1219 | ||
|
|
a0acafcefc | ||
|
|
918f5954b7 | ||
|
|
148dcdaee7 | ||
|
|
a5f0777892 | ||
|
|
010426d488 | ||
|
|
6fc9c7be90 | ||
|
|
094fde9801 | ||
|
|
e4a76e96af | ||
|
|
68f582bcb9 | ||
|
|
639aed7120 | ||
|
|
994bb4d1d2 | ||
|
|
80b11a55fa | ||
|
|
3cfb554623 | ||
|
|
e84f9c5946 | ||
|
|
17cc31d6e7 | ||
|
|
0c6e10a6dd | ||
|
|
297c57631f | ||
|
|
bd4e252bb6 | ||
|
|
0ce34c70bc | ||
|
|
4df75cfba1 | ||
|
|
2aa435bcfb | ||
|
|
0a4a9e6947 | ||
|
|
d5860d0b55 | ||
|
|
6a487ce514 | ||
|
|
4f3b85e66b | ||
|
|
370cd97e05 | ||
|
|
55d4fda01b |
@@ -1,2 +1,5 @@
|
||||
# Formatting
|
||||
5f771b785130154ed47952635b7acef371ffe0ec
|
||||
|
||||
# Normalize files
|
||||
55d4fda01b2f39f5b7d7b4fda5214bd7ff0fd5dd
|
||||
|
||||
@@ -12,7 +12,7 @@ https://github.com/Stirling-Tools/Stirling-PDF/blob/main/src/main/resources/temp
|
||||
and add a flag svg file to
|
||||
https://github.com/Stirling-Tools/Stirling-PDF/tree/main/src/main/resources/static/images/flags
|
||||
Any SVG flags are fine, i got most of mine from [here](https://flagicons.lipis.dev/)
|
||||
If your language isnt represented by a flag just find whichever closely matches it, such as for Arabic i chose Saudi Arabia
|
||||
If your language isn't represented by a flag just find whichever closely matches it, such as for Arabic i chose Saudi Arabia
|
||||
|
||||
|
||||
For example to add Polish you would add
|
||||
@@ -32,7 +32,7 @@ Copy and rename it to messages_{your data-language-code here}.properties, in the
|
||||
|
||||
Then simply translate all property entries within that file and make a PR into main for others to use!
|
||||
|
||||
If you do not have a java IDE i am happy to verify the changes worked once you raise PR (but wont be able to verify the translations themselves)
|
||||
If you do not have a java IDE i am happy to verify the changes worked once you raise PR (but won't be able to verify the translations themselves)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
This document provides instructions on how to add additional language packs for the OCR tab in Stirling-PDF, both inside and outside of Docker.
|
||||
|
||||
## My OCR used to work and now doesnt!
|
||||
Please update your tesseract docker volume path version from 4.00 to 5
|
||||
## My OCR used to work and now doesn't!
|
||||
The paths have changed for the tessadata locations on new docker images, please use ``/usr/share/tessdata`` (Others should still work for backwards compatability but might not)
|
||||
|
||||
## How does the OCR Work
|
||||
Stirling-PDF uses [OCRmyPDF](https://github.com/ocrmypdf/OCRmyPDF) which in turn uses tesseract for its text recognition.
|
||||
|
||||
@@ -65,7 +65,7 @@ sudo make install
|
||||
```
|
||||
|
||||
### Step 3: Install Additional Software
|
||||
Next we need to install LibreOffice for conversions, ocrmypdf for OCR, and opencv for patern recognition functionality.
|
||||
Next we need to install LibreOffice for conversions, ocrmypdf for OCR, and opencv for pattern recognition functionality.
|
||||
|
||||
Install the following software:
|
||||
|
||||
@@ -264,7 +264,7 @@ sudo systemctl restart stirlingpdf.service
|
||||
|
||||
Remember to set the necessary environment variables before running the project if you want to customize the application the list can be seen in the main readme.
|
||||
|
||||
You can do this in the terminal by using the `export` command or -D arguements to java -jar command:
|
||||
You can do this in the terminal by using the `export` command or -D argument to java -jar command:
|
||||
|
||||
```bash
|
||||
export APP_HOME_NAME="Stirling PDF"
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
[](https://github.com/Stirling-Tools/Stirling-PDF/)
|
||||
[](https://github.com/Stirling-Tools/stirling-pdf)
|
||||
[](https://www.paypal.com/paypalme/froodleplex)
|
||||
[](https://github.com/sponsors/Frooodle)
|
||||
[](https://github.com/sponsors/Frooodle)
|
||||
|
||||
[](https://cloud.digitalocean.com/apps/new?repo=https://github.com/Stirling-Tools/Stirling-PDF/tree/digitalOcean&refcode=c3210994b1af)
|
||||
|
||||
@@ -172,7 +172,7 @@ Stirling PDF currently supports 26!
|
||||
- Hindi (हिंदी) (hi_IN)
|
||||
- Hungarian (Magyar) (hu_HU)
|
||||
- Bulgarian (Български) (bg_BG)
|
||||
- Sebian Latin alphabet (Srpski) (sr-Latn-RS)
|
||||
- Sebian Latin alphabet (Srpski) (sr_LATN_RS)
|
||||
|
||||
## Contributing (creating issues, translations, fixing bugs, etc.)
|
||||
|
||||
@@ -262,7 +262,7 @@ For API usage you must provide a header with 'X-API-Key' and the associated API
|
||||
- Redact text (Via UI not just automated way)
|
||||
- Add Forms
|
||||
- Multi page layout (Stich PDF pages together) support x rows y columns and custom page sizing
|
||||
- Fill forms mannual and automatic
|
||||
- Fill forms manually or automatically
|
||||
|
||||
### Q2: Why is my application downloading .htm files?
|
||||
This is an issue caused commonly by your NGINX configuration. The default file upload size for NGINX is 1MB, you need to add the following in your Nginx sites-available file. ``client_max_body_size SIZE;`` Where "SIZE" is 50M for example for 50MB files.
|
||||
|
||||
@@ -89,7 +89,7 @@ dependencies {
|
||||
//security updates
|
||||
implementation 'ch.qos.logback:logback-classic:1.4.14'
|
||||
implementation 'ch.qos.logback:logback-core:1.4.14'
|
||||
implementation 'org.springframework:spring-webmvc:6.1.2'
|
||||
implementation 'org.springframework:spring-webmvc:6.1.3'
|
||||
|
||||
implementation("io.github.pixee:java-security-toolkit:1.1.2")
|
||||
|
||||
@@ -150,7 +150,7 @@ dependencies {
|
||||
implementation 'org.bouncycastle:bcprov-jdk18on:1.77'
|
||||
implementation 'org.bouncycastle:bcpkix-jdk18on:1.77'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-actuator:3.2.2'
|
||||
implementation 'io.micrometer:micrometer-core:1.12.2'
|
||||
implementation 'io.micrometer:micrometer-core:1.12.3'
|
||||
implementation group: 'com.google.zxing', name: 'core', version: '3.5.2'
|
||||
// https://mvnrepository.com/artifact/org.commonmark/commonmark
|
||||
implementation 'org.commonmark:commonmark:0.21.0'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
apiVersion: v2
|
||||
appVersion: 0.14.2
|
||||
appVersion: 0.20.2
|
||||
description: locally hosted web application that allows you to perform various operations on PDF files
|
||||
home: https://github.com/Stirling-Tools/Stirling-PDF
|
||||
keywords:
|
||||
|
||||
@@ -16,11 +16,11 @@ commonLabels: {}
|
||||
# team_name: dev
|
||||
|
||||
envs: []
|
||||
# - name: PP_HOME_NAME
|
||||
# - name: UI_APP_NAME
|
||||
# value: "Stirling PDF"
|
||||
# - name: APP_HOME_DESCRIPTION
|
||||
# - name: UI_HOME_DESCRIPTION
|
||||
# value: "Your locally hosted one-stop-shop for all your PDF needs."
|
||||
# - name: APP_NAVBAR_NAME
|
||||
# - name: UI_APP_NAVBAR_NAME
|
||||
# value: "Stirling PDF"
|
||||
# - name: ALLOW_GOOGLE_VISIBILITY
|
||||
# value: "true"
|
||||
|
||||
@@ -15,7 +15,7 @@ services:
|
||||
ports:
|
||||
- 8080:8080
|
||||
volumes:
|
||||
- /stirling/latest/data:/usr/share/tesseract-ocr/5/tessdata:rw
|
||||
- /stirling/latest/data:/usr/share/tessdata:rw
|
||||
- /stirling/latest/config:/configs:rw
|
||||
- /stirling/latest/logs:/logs:rw
|
||||
environment:
|
||||
|
||||
@@ -15,7 +15,7 @@ services:
|
||||
ports:
|
||||
- 8080:8080
|
||||
volumes:
|
||||
- /stirling/latest/data:/usr/share/tesseract-ocr/5/tessdata:rw
|
||||
- /stirling/latest/data:/usr/share/tessdata:rw
|
||||
- /stirling/latest/config:/configs:rw
|
||||
- /stirling/latest/logs:/logs:rw
|
||||
environment:
|
||||
|
||||
@@ -15,7 +15,7 @@ services:
|
||||
ports:
|
||||
- 8080:8080
|
||||
volumes:
|
||||
- /stirling/latest/data:/usr/share/tesseract-ocr/5/tessdata:rw
|
||||
- /stirling/latest/data:/usr/share/tessdata:rw
|
||||
- /stirling/latest/config:/configs:rw
|
||||
- /stirling/latest/logs:/logs:rw
|
||||
environment:
|
||||
|
||||
@@ -15,7 +15,7 @@ services:
|
||||
ports:
|
||||
- 8080:8080
|
||||
volumes:
|
||||
- /stirling/latest/data:/usr/share/tesseract-ocr/5/tessdata:rw
|
||||
- /stirling/latest/data:/usr/share/tessdata:rw
|
||||
- /stirling/latest/config:/configs:rw
|
||||
- /stirling/latest/logs:/logs:rw
|
||||
environment:
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
import cv2
|
||||
import sys
|
||||
import argparse
|
||||
import numpy as np
|
||||
|
||||
def is_blank_image(image_path, threshold=10, white_percent=99, white_value=255, blur_size=5):
|
||||
image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
|
||||
|
||||
if image is None:
|
||||
print(f"Error: Unable to read the image file: {image_path}")
|
||||
return False
|
||||
|
||||
# Apply Gaussian blur to reduce noise
|
||||
blurred_image = cv2.GaussianBlur(image, (blur_size, blur_size), 0)
|
||||
|
||||
_, thresholded_image = cv2.threshold(blurred_image, white_value - threshold, white_value, cv2.THRESH_BINARY)
|
||||
|
||||
# Calculate the percentage of white pixels in the thresholded image
|
||||
white_pixels = np.sum(thresholded_image == white_value)
|
||||
white_pixel_percentage = (white_pixels / thresholded_image.size) * 100
|
||||
|
||||
print(f"Page has white pixel percent of {white_pixel_percentage}")
|
||||
return white_pixel_percentage >= white_percent
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description='Detect if an image is considered blank or not.')
|
||||
parser.add_argument('image_path', help='The path to the image file.')
|
||||
parser.add_argument('-t', '--threshold', type=int, default=10, help='Threshold for determining white pixels. The default value is 10.')
|
||||
parser.add_argument('-w', '--white_percent', type=float, default=99, help='The percentage of white pixels for an image to be considered blank. The default value is 99.')
|
||||
args = parser.parse_args()
|
||||
|
||||
blank = is_blank_image(args.image_path, args.threshold, args.white_percent)
|
||||
|
||||
# Return code 1: The image is considered blank.
|
||||
# Return code 0: The image is not considered blank.
|
||||
sys.exit(int(blank))
|
||||
@@ -79,6 +79,16 @@ public class ConfigInitializer
|
||||
return parts.length > 0 ? parts[0].trim().replace("#", "").trim() : "";
|
||||
};
|
||||
|
||||
Function<String, Integer> getIndentationLevel =
|
||||
line -> {
|
||||
int count = 0;
|
||||
for (char ch : line.toCharArray()) {
|
||||
if (ch == ' ') count++;
|
||||
else break;
|
||||
}
|
||||
return count;
|
||||
};
|
||||
|
||||
Set<String> userKeys = userLines.stream().map(extractKey).collect(Collectors.toSet());
|
||||
|
||||
for (String line : templateLines) {
|
||||
@@ -134,10 +144,77 @@ public class ConfigInitializer
|
||||
.map(extractKey)
|
||||
.anyMatch(templateKey -> templateKey.equalsIgnoreCase(userKey));
|
||||
if (!isPresentInTemplate && !isCommented.apply(userLine)) {
|
||||
mergedLines.add(userLine);
|
||||
if (!childOfTemplateEntry(
|
||||
isCommented,
|
||||
extractKey,
|
||||
getIndentationLevel,
|
||||
userLines,
|
||||
userLine,
|
||||
templateLines)) {
|
||||
// check if userLine is a child of a entry within templateLines or not, if child
|
||||
// of parent in templateLines then dont add to mergedLines, if anything else
|
||||
// then add
|
||||
mergedLines.add(userLine);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Files.write(outputPath, mergedLines, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
// New method to check if a userLine is a child of an entry in templateLines
|
||||
boolean childOfTemplateEntry(
|
||||
Function<String, Boolean> isCommented,
|
||||
Function<String, String> extractKey,
|
||||
Function<String, Integer> getIndentationLevel,
|
||||
List<String> userLines,
|
||||
String userLine,
|
||||
List<String> templateLines) {
|
||||
String userKey = extractKey.apply(userLine).trim();
|
||||
int userIndentation = getIndentationLevel.apply(userLine);
|
||||
|
||||
// Start by assuming the line is not a child of an entry in templateLines
|
||||
boolean isChild = false;
|
||||
|
||||
// Iterate backwards through userLines from the current line to find any parent
|
||||
for (int i = userLines.indexOf(userLine) - 1; i >= 0; i--) {
|
||||
String potentialParentLine = userLines.get(i);
|
||||
int parentIndentation = getIndentationLevel.apply(potentialParentLine);
|
||||
|
||||
// Check if we've reached a potential parent based on indentation
|
||||
if (parentIndentation < userIndentation) {
|
||||
String parentKey = extractKey.apply(potentialParentLine).trim();
|
||||
|
||||
// Now, check if this potential parent or any of its parents exist in templateLines
|
||||
boolean parentExistsInTemplate =
|
||||
templateLines.stream()
|
||||
.filter(line -> !isCommented.apply(line)) // Skip commented lines
|
||||
.anyMatch(
|
||||
templateLine -> {
|
||||
String templateKey =
|
||||
extractKey.apply(templateLine).trim();
|
||||
return parentKey.equalsIgnoreCase(templateKey);
|
||||
});
|
||||
|
||||
if (!parentExistsInTemplate) {
|
||||
// If the parent does not exist in template, check the next level parent
|
||||
userIndentation =
|
||||
parentIndentation; // Update userIndentation to the parent's indentation
|
||||
// for next iteration
|
||||
if (parentIndentation == 0) {
|
||||
// If we've reached the top-level parent and it's not in template, the
|
||||
// original line is considered not a child
|
||||
isChild = false;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// If any parent exists in template, the original line is considered a child
|
||||
isChild = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return isChild; // Return true if the line is not a child of any entry in templateLines
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,7 +140,6 @@ public class EndpointConfiguration {
|
||||
// CLI
|
||||
addEndpointToGroup("CLI", "compress-pdf");
|
||||
addEndpointToGroup("CLI", "extract-image-scans");
|
||||
addEndpointToGroup("CLI", "remove-blanks");
|
||||
addEndpointToGroup("CLI", "repair");
|
||||
addEndpointToGroup("CLI", "pdf-to-pdfa");
|
||||
addEndpointToGroup("CLI", "file-to-pdf");
|
||||
@@ -218,6 +217,7 @@ public class EndpointConfiguration {
|
||||
addEndpointToGroup("Java", "split-by-size-or-count");
|
||||
addEndpointToGroup("Java", "overlay-pdf");
|
||||
addEndpointToGroup("Java", "split-pdf-by-sections");
|
||||
addEndpointToGroup("Java", "remove-blanks");
|
||||
|
||||
// Javascript
|
||||
addEndpointToGroup("Javascript", "pdf-organizer");
|
||||
|
||||
@@ -9,6 +9,9 @@ import org.springframework.security.authentication.dao.DaoAuthenticationProvider
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.core.session.SessionRegistry;
|
||||
import org.springframework.security.core.session.SessionRegistryImpl;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
@@ -44,6 +47,11 @@ public class SecurityConfiguration {
|
||||
|
||||
@Autowired private FirstLoginFilter firstLoginFilter;
|
||||
|
||||
@Bean
|
||||
public SessionRegistry sessionRegistry() {
|
||||
return new SessionRegistryImpl();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
http.addFilterBefore(userAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
|
||||
@@ -53,6 +61,14 @@ public class SecurityConfiguration {
|
||||
http.csrf(csrf -> csrf.disable());
|
||||
http.addFilterBefore(rateLimitingFilter(), UsernamePasswordAuthenticationFilter.class);
|
||||
http.addFilterAfter(firstLoginFilter, UsernamePasswordAuthenticationFilter.class);
|
||||
http.sessionManagement(
|
||||
sessionManagement ->
|
||||
sessionManagement
|
||||
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
|
||||
.maximumSessions(3)
|
||||
.maxSessionsPreventsLogin(true)
|
||||
.sessionRegistry(sessionRegistry())
|
||||
.expiredUrl("/login?logout=true"));
|
||||
http.formLogin(
|
||||
formLogin ->
|
||||
formLogin
|
||||
|
||||
@@ -10,6 +10,9 @@ import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.session.SessionInformation;
|
||||
import org.springframework.security.core.session.SessionRegistry;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
@@ -228,11 +231,27 @@ public class UserController {
|
||||
if (currentUsername.equals(username)) {
|
||||
throw new IllegalArgumentException("Cannot delete currently logined in user.");
|
||||
}
|
||||
|
||||
invalidateUserSessions(username);
|
||||
userService.deleteUser(username);
|
||||
return "redirect:/addUsers";
|
||||
}
|
||||
|
||||
@Autowired private SessionRegistry sessionRegistry;
|
||||
|
||||
private void invalidateUserSessions(String username) {
|
||||
for (Object principal : sessionRegistry.getAllPrincipals()) {
|
||||
if (principal instanceof UserDetails) {
|
||||
UserDetails userDetails = (UserDetails) principal;
|
||||
if (userDetails.getUsername().equals(username)) {
|
||||
for (SessionInformation session :
|
||||
sessionRegistry.getAllSessions(principal, false)) {
|
||||
session.expireNow();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PreAuthorize("!hasAuthority('ROLE_DEMO_USER')")
|
||||
@PostMapping("/get-api-key")
|
||||
public ResponseEntity<String> getApiKey(Principal principal) {
|
||||
|
||||
@@ -41,7 +41,7 @@ public class OCRController {
|
||||
private static final Logger logger = LoggerFactory.getLogger(OCRController.class);
|
||||
|
||||
public List<String> getAvailableTesseractLanguages() {
|
||||
String tessdataDir = "/usr/share/tesseract-ocr/5/tessdata";
|
||||
String tessdataDir = "/usr/share/tessdata";
|
||||
File[] files = new File(tessdataDir).listFiles();
|
||||
if (files == null) {
|
||||
return Collections.emptyList();
|
||||
|
||||
@@ -33,6 +33,8 @@ public class AccountWebController {
|
||||
return "redirect:/";
|
||||
}
|
||||
|
||||
model.addAttribute("currentPage", "login");
|
||||
|
||||
if (request.getParameter("error") != null) {
|
||||
|
||||
model.addAttribute("error", request.getParameter("error"));
|
||||
@@ -112,6 +114,7 @@ public class AccountWebController {
|
||||
model.addAttribute("role", user.get().getRolesAsString());
|
||||
model.addAttribute("settings", settingsJson);
|
||||
model.addAttribute("changeCredsFlag", user.get().isFirstLogin());
|
||||
model.addAttribute("currentPage", "account");
|
||||
}
|
||||
} else {
|
||||
return "redirect:/";
|
||||
|
||||
@@ -82,7 +82,7 @@ public class OtherWebController {
|
||||
}
|
||||
|
||||
public List<String> getAvailableTesseractLanguages() {
|
||||
String tessdataDir = "/usr/share/tesseract-ocr/5/tessdata";
|
||||
String tessdataDir = "/usr/share/tessdata";
|
||||
File[] files = new File(tessdataDir).listFiles();
|
||||
if (files == null) {
|
||||
return Collections.emptyList();
|
||||
|
||||
@@ -12,6 +12,6 @@ public class PdfToTextOrRTFRequest extends PDFFile {
|
||||
|
||||
@Schema(
|
||||
description = "The output Text or RTF format",
|
||||
allowableValues = {"rtf", "txt:Text"})
|
||||
allowableValues = {"rtf", "txt"})
|
||||
private String outputFormat;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -11,6 +11,7 @@ imgPrompt=اختر صورة
|
||||
genericSubmit=إرسال
|
||||
processTimeWarning=تحذير: يمكن أن تستغرق هذه العملية ما يصل إلى دقيقة حسب حجم الملف
|
||||
pageOrderPrompt=ترتيب الصفحات (أدخل قائمة بأرقام الصفحات مفصولة بفواصل):
|
||||
pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :
|
||||
goToPage=اذهب
|
||||
true=\u0635\u062D\u064A\u062D
|
||||
false=\u062E\u0637\u0623
|
||||
@@ -19,6 +20,7 @@ save=\u062D\u0641\u0638
|
||||
close=\u0625\u063A\u0644\u0627\u0642
|
||||
filesSelected=الملفات المحددة
|
||||
noFavourites=لم تتم إضافة أي مفضلات
|
||||
downloadComplete=Download Complete
|
||||
bored=الانتظار بالملل؟
|
||||
alphabet=\u0627\u0644\u0623\u0628\u062C\u062F\u064A\u0629
|
||||
downloadPdf=تنزيل PDF
|
||||
@@ -42,7 +44,7 @@ red=Red
|
||||
green=Green
|
||||
blue=Blue
|
||||
custom=Custom...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any problems!
|
||||
poweredBy=Powered by
|
||||
yes=Yes
|
||||
no=No
|
||||
@@ -120,7 +122,7 @@ account.accountSettings=Account Settings
|
||||
account.adminSettings=Admin Settings - View and Add Users
|
||||
account.userControlSettings=User Control Settings
|
||||
account.changeUsername=Change Username
|
||||
account.changeUsername=Change Username
|
||||
account.newUsername=New Username
|
||||
account.password=Confirmation Password
|
||||
account.oldPassword=Old password
|
||||
account.newPassword=New Password
|
||||
@@ -366,7 +368,7 @@ showJS.tags=JS
|
||||
|
||||
home.autoRedact.title=Auto Redact
|
||||
home.autoRedact.desc=Auto Redacts(Blacks out) text in a PDF based on input text
|
||||
showJS.tags=JS
|
||||
autoRedact.tags=Redact,Hide,black out,black,marker,hidden
|
||||
|
||||
home.tableExtraxt.title=PDF to CSV
|
||||
home.tableExtraxt.desc=Extracts Tables from a PDF converting it to CSV
|
||||
@@ -410,7 +412,7 @@ autoRedact.title=Auto Redact
|
||||
autoRedact.header=Auto Redact
|
||||
autoRedact.colorLabel=Colour
|
||||
autoRedact.textsToRedactLabel=Text to Redact (line-separated)
|
||||
autoRedact.textsToRedactPlaceholder=e.g. \nConfidential \nTop-Secret
|
||||
autoRedact.textsToRedactPlaceholder=e.g. \nConfidential \nTop-Secret
|
||||
autoRedact.useRegexLabel=Use Regex
|
||||
autoRedact.wholeWordSearchLabel=Whole Word Search
|
||||
autoRedact.customPaddingLabel=Custom Extra Padding
|
||||
@@ -498,6 +500,7 @@ AddStampRequest.customMargin=Custom Margin
|
||||
AddStampRequest.customColor=Custom Text Color
|
||||
AddStampRequest.submit=Submit
|
||||
|
||||
|
||||
#sanitizePDF
|
||||
sanitizePDF.title=Sanitize PDF
|
||||
sanitizePDF.header=Sanitize a PDF file
|
||||
@@ -866,7 +869,6 @@ changeMetadata.keywords=\u0627\u0644\u0643\u0644\u0645\u0627\u062A \u0627\u0644\
|
||||
changeMetadata.modDate=\u062A\u0627\u0631\u064A\u062E \u0627\u0644\u062A\u0639\u062F\u064A\u0644 (yyyy / MM / dd HH: mm: ss):
|
||||
changeMetadata.producer=\u0627\u0644\u0645\u0646\u062A\u062C:
|
||||
changeMetadata.subject=\u0627\u0644\u0645\u0648\u0636\u0648\u0639:
|
||||
changeMetadata.title=\u0627\u0644\u0639\u0646\u0648\u0627\u0646:
|
||||
changeMetadata.trapped=\u0645\u062D\u0627\u0635\u0631:
|
||||
changeMetadata.selectText.4=\u0628\u064A\u0627\u0646\u0627\u062A \u0648\u0635\u0641\u064A\u0629 \u0623\u062E\u0631\u0649:
|
||||
changeMetadata.selectText.5=\u0625\u0636\u0627\u0641\u0629 \u0625\u062F\u062E\u0627\u0644 \u0628\u064A\u0627\u0646\u0627\u062A \u0623\u0648\u0644\u064A\u0629 \u0645\u062E\u0635\u0635
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -11,6 +11,7 @@ imgPrompt=Изберете изображение(я)
|
||||
genericSubmit=Подайте
|
||||
processTimeWarning=Предупреждение: Този процес може да отнеме до минута в зависимост от размера на файла
|
||||
pageOrderPrompt=Персонализиран ред на страниците (Въведете разделен със запетаи списък с номера на страници или функции като 2n+1):
|
||||
pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :
|
||||
goToPage=Давай
|
||||
true=Вярно
|
||||
false=Невярно
|
||||
@@ -19,6 +20,7 @@ save=Съхранете
|
||||
close=Затворете
|
||||
filesSelected=избрани файлове
|
||||
noFavourites=Няма добавени любими
|
||||
downloadComplete=Download Complete
|
||||
bored=Отекчени сте да чакате?
|
||||
alphabet=Азбука
|
||||
downloadPdf=Изтеглете PDF
|
||||
@@ -42,7 +44,7 @@ red=Червено
|
||||
green=Зелено
|
||||
blue=Синьо
|
||||
custom=Персонализиране...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any problems!
|
||||
poweredBy=Powered by
|
||||
yes=Yes
|
||||
no=No
|
||||
@@ -120,7 +122,7 @@ account.accountSettings=Настройки на акаунта
|
||||
account.adminSettings=Настройки на администратора - Преглед и добавяне на потребители
|
||||
account.userControlSettings=Настройки за потребителски контрол
|
||||
account.changeUsername=Промени потребител
|
||||
account.changeUsername=Промени потребител
|
||||
account.newUsername=Ново потребителско име
|
||||
account.password=Парола за потвърждение
|
||||
account.oldPassword=Стара парола
|
||||
account.newPassword=Нова парола
|
||||
@@ -362,11 +364,11 @@ PdfToSinglePage.tags=единична страница
|
||||
|
||||
home.showJS.title=Показване на Javascript
|
||||
home.showJS.desc=Търси и показва всеки JS, инжектиран в PDF
|
||||
showJS.tags=Редактиране,Скриване,затъмняване,черен,маркер,скрит
|
||||
showJS.tags=JS
|
||||
|
||||
home.autoRedact.title=Автоматично редактиране
|
||||
home.autoRedact.desc=Автоматично редактира (зачернява) текст в PDF въз основа на въведен текст
|
||||
showJS.tags=Редактиране,Скриване,затъмняване,черен,маркер,скрит
|
||||
autoRedact.tags=Редактиране,Скриване,затъмняване,черен,маркер,скрит
|
||||
|
||||
home.tableExtraxt.title=PDF to CSV
|
||||
home.tableExtraxt.desc=Extracts Tables from a PDF converting it to CSV
|
||||
@@ -410,7 +412,7 @@ autoRedact.title=Автоматично редактиране
|
||||
autoRedact.header=Автоматично редактиране
|
||||
autoRedact.colorLabel=Цвят
|
||||
autoRedact.textsToRedactLabel=Текст за редактиране (разделен с редове)
|
||||
autoRedact.textsToRedactPlaceholder=например: \nПоверително \nСтрого секретно
|
||||
autoRedact.textsToRedactPlaceholder=например: \nПоверително \nСтрого секретно
|
||||
autoRedact.useRegexLabel=Използване на Regex
|
||||
autoRedact.wholeWordSearchLabel=Търсене на цялата дума
|
||||
autoRedact.customPaddingLabel=Персонализирана допълнителна подложка
|
||||
@@ -498,6 +500,7 @@ AddStampRequest.customMargin=Custom Margin
|
||||
AddStampRequest.customColor=Custom Text Color
|
||||
AddStampRequest.submit=Submit
|
||||
|
||||
|
||||
#sanitizePDF
|
||||
sanitizePDF.title=Дезинфектирай PDF
|
||||
sanitizePDF.header=Дезинфектира PDF файл
|
||||
@@ -866,7 +869,6 @@ changeMetadata.keywords=Ключови думи:
|
||||
changeMetadata.modDate=Дата на промяна (гггг/ММ/дд ЧЧ:мм:сс):
|
||||
changeMetadata.producer=Продуцент:
|
||||
changeMetadata.subject=Тема:
|
||||
changeMetadata.title=Заглавие:
|
||||
changeMetadata.trapped=В капан:
|
||||
changeMetadata.selectText.4=Други метаданни:
|
||||
changeMetadata.selectText.5=Добавяне на персонализиране метаданни
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -11,6 +11,7 @@ imgPrompt=Selecciona Imatge(s)
|
||||
genericSubmit=Envia
|
||||
processTimeWarning=Alerta: Aquest procés pot tardar 1 minut depenent de la mida de l'arxiu
|
||||
pageOrderPrompt=Ordre de Pàgines (Llista separada per comes) :
|
||||
pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :
|
||||
goToPage=Anar
|
||||
true=Verdader
|
||||
false=Fals
|
||||
@@ -19,6 +20,7 @@ save=Desa
|
||||
close=Tanca
|
||||
filesSelected=fitxers seleccionats
|
||||
noFavourites=No s'ha afegit cap favorit
|
||||
downloadComplete=Download Complete
|
||||
bored=Avorrit esperant?
|
||||
alphabet=Alfabet
|
||||
downloadPdf=Descarregueu PDF
|
||||
@@ -42,7 +44,7 @@ red=Vermell
|
||||
green=Verd
|
||||
blue=Blau
|
||||
custom=Personalitzat...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any problems!
|
||||
poweredBy=Powered by
|
||||
yes=Yes
|
||||
no=No
|
||||
@@ -120,7 +122,7 @@ account.accountSettings=Opcions del compte
|
||||
account.adminSettings=Opcions d'Admin - Veure i afegir usuaris
|
||||
account.userControlSettings=Opcions de Control d'Usuari
|
||||
account.changeUsername=Canvia nom usuari
|
||||
account.changeUsername=Canvia nom usuari
|
||||
account.newUsername=Nom d'usuari nou
|
||||
account.password=Confirma contrasenya
|
||||
account.oldPassword=Password Antic
|
||||
account.newPassword=Password Nou
|
||||
@@ -366,7 +368,7 @@ showJS.tags=JS
|
||||
|
||||
home.autoRedact.title=Auto Redact
|
||||
home.autoRedact.desc=Auto Redacts(Blacks out) text in a PDF based on input text
|
||||
showJS.tags=JS
|
||||
autoRedact.tags=Redact,Hide,black out,black,marker,hidden
|
||||
|
||||
home.tableExtraxt.title=PDF to CSV
|
||||
home.tableExtraxt.desc=Extracts Tables from a PDF converting it to CSV
|
||||
@@ -410,7 +412,7 @@ autoRedact.title=Auto Redact
|
||||
autoRedact.header=Auto Redact
|
||||
autoRedact.colorLabel=Colour
|
||||
autoRedact.textsToRedactLabel=Text to Redact (line-separated)
|
||||
autoRedact.textsToRedactPlaceholder=e.g. \nConfidential \nTop-Secret
|
||||
autoRedact.textsToRedactPlaceholder=e.g. \nConfidential \nTop-Secret
|
||||
autoRedact.useRegexLabel=Use Regex
|
||||
autoRedact.wholeWordSearchLabel=Whole Word Search
|
||||
autoRedact.customPaddingLabel=Custom Extra Padding
|
||||
@@ -498,6 +500,7 @@ AddStampRequest.customMargin=Custom Margin
|
||||
AddStampRequest.customColor=Custom Text Color
|
||||
AddStampRequest.submit=Submit
|
||||
|
||||
|
||||
#sanitizePDF
|
||||
sanitizePDF.title=Sanitize PDF
|
||||
sanitizePDF.header=Sanitize a PDF file
|
||||
@@ -866,7 +869,6 @@ changeMetadata.keywords=Keywords:
|
||||
changeMetadata.modDate=Data Modificació (yyyy/MM/dd HH:mm:ss):
|
||||
changeMetadata.producer=Productor:
|
||||
changeMetadata.subject=Assumpte:
|
||||
changeMetadata.title=Títol:
|
||||
changeMetadata.trapped=Atrapat:
|
||||
changeMetadata.selectText.4=Altres Metadades:
|
||||
changeMetadata.selectText.5=Afegir entrada personalizada
|
||||
|
||||
@@ -11,6 +11,7 @@ imgPrompt=Wählen Sie ein Bild
|
||||
genericSubmit=Einreichen
|
||||
processTimeWarning=Achtung: Abhängig von der Dateigröße kann dieser Prozess bis zu einer Minute dauern
|
||||
pageOrderPrompt=Seitenreihenfolge (Geben Sie eine durch Komma getrennte Liste von Seitenzahlen ein):
|
||||
pageSelectionPrompt=Benutzerdefinierte Seitenauswahl (Geben Sie eine durch Kommas getrennte Liste von Seitenzahlen 1,5,6 oder Funktionen wie 2n+1 ein):
|
||||
goToPage=Los
|
||||
true=Wahr
|
||||
false=Falsch
|
||||
@@ -19,6 +20,7 @@ save=Speichern
|
||||
close=Schließen
|
||||
filesSelected=Dateien ausgewählt
|
||||
noFavourites=Keine Favoriten hinzugefügt
|
||||
downloadComplete=Download Complete
|
||||
bored=Langeweile beim Warten?
|
||||
alphabet=Alphabet
|
||||
downloadPdf=PDF herunterladen
|
||||
@@ -42,10 +44,10 @@ red=Rot
|
||||
green=Grün
|
||||
blue=Blau
|
||||
custom=benutzerdefiniert...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
WorkInProgess=In Arbeit, funktioniert möglicherweise nicht oder ist fehlerhaft. Bitte melden Sie alle Probleme!
|
||||
poweredBy=Powered by
|
||||
yes=Yes
|
||||
no=No
|
||||
yes=Ja
|
||||
no=Nein
|
||||
changedCredsMessage=Anmeldedaten geändert!
|
||||
notAuthenticatedMessage=Benutzer nicht authentifiziert.
|
||||
userNotFoundMessage=Benutzer nicht gefunden.
|
||||
@@ -56,24 +58,24 @@ usernameExistsMessage=Neuer Benutzername existiert bereits.
|
||||
###############
|
||||
# Pipeline #
|
||||
###############
|
||||
pipeline.header=Pipeline Menu (Alpha)
|
||||
pipeline.uploadButton=Upload Custom
|
||||
pipeline.configureButton=Configure
|
||||
pipeline.defaultOption=Custom
|
||||
pipeline.submitButton=Submit
|
||||
pipeline.header=Pipeline-Menü (Alpha)
|
||||
pipeline.uploadButton=Benutzerdefinierter Upload
|
||||
pipeline.configureButton=Konfigurieren
|
||||
pipeline.defaultOption=Benutzerdefiniert
|
||||
pipeline.submitButton=Speichern
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
######################
|
||||
pipelineOptions.header=Pipeline Configuration
|
||||
pipelineOptions.pipelineNameLabel=Pipeline Name
|
||||
pipelineOptions.header=Pipeline-Konfiguration
|
||||
pipelineOptions.pipelineNameLabel=Pipeline-Name
|
||||
pipelineOptions.saveSettings=Save Operation Settings
|
||||
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
|
||||
pipelineOptions.selectOperation=Select Operation
|
||||
pipelineOptions.addOperationButton=Add operation
|
||||
pipelineOptions.pipelineNamePrompt=Geben Sie hier den Namen der Pipeline ein
|
||||
pipelineOptions.selectOperation=Vorgang auswählen
|
||||
pipelineOptions.addOperationButton=Vorgang hinzufügen
|
||||
pipelineOptions.pipelineHeader=Pipeline:
|
||||
pipelineOptions.saveButton=Download
|
||||
pipelineOptions.validateButton=Validate
|
||||
pipelineOptions.saveButton=Downloaden
|
||||
pipelineOptions.validateButton=Validieren
|
||||
|
||||
|
||||
|
||||
@@ -120,11 +122,11 @@ account.accountSettings=Kontoeinstellungen
|
||||
account.adminSettings=Admin Einstellungen - Benutzer anzeigen und hinzufügen
|
||||
account.userControlSettings=Benutzerkontrolle
|
||||
account.changeUsername=Benutzername ändern
|
||||
account.changeUsername=Benutzername ändern
|
||||
account.newUsername=Neuer Benutzername
|
||||
account.password=Bestätigungspasswort
|
||||
account.oldPassword=Altes Passwort
|
||||
account.newPassword=Neues Passwort
|
||||
account.changePassword=Password ändern
|
||||
account.changePassword=Passwort ändern
|
||||
account.confirmNewPassword=Neues Passwort bestätigen
|
||||
account.signOut=Abmelden
|
||||
account.yourApiKey=Dein API Schlüssel
|
||||
@@ -146,7 +148,7 @@ adminUserSettings.role=Rolle
|
||||
adminUserSettings.actions=Aktion
|
||||
adminUserSettings.apiUser=Eingeschränkter API-Benutzer
|
||||
adminUserSettings.webOnlyUser=Nur Web-Benutzer
|
||||
adminUserSettings.demoUser=Demo User (No custom settings)
|
||||
adminUserSettings.demoUser=Demo-Benutzer (Keine benutzerdefinierten Einstellungen)
|
||||
adminUserSettings.forceChange=Benutzer dazu zwingen, Benutzernamen/Passwort bei der Anmeldung zu ändern
|
||||
adminUserSettings.submit=Benutzer speichern
|
||||
|
||||
@@ -283,8 +285,8 @@ home.removeBlanks.title=Leere Seiten entfernen
|
||||
home.removeBlanks.desc=Erkennt und entfernt leere Seiten aus einem Dokument
|
||||
removeBlanks.tags=cleanup,streamline,non-content,organize
|
||||
|
||||
home.removeAnnotations.title=Remove Annotations
|
||||
home.removeAnnotations.desc=Removes all comments/annotations from a PDF
|
||||
home.removeAnnotations.title=Anmerkungen entfernen
|
||||
home.removeAnnotations.desc=Entfernt alle Kommentare/Anmerkungen aus einem PDF
|
||||
removeAnnotations.tags=comments,highlight,notes,markup,remove
|
||||
|
||||
home.compare.title=Vergleichen
|
||||
@@ -304,7 +306,7 @@ home.scalePages.desc=Größe/Skalierung der Seite und/oder des Inhalts ändern
|
||||
scalePages.tags=resize,modify,dimension,adapt
|
||||
|
||||
home.pipeline.title=Pipeline (Fortgeschritten)
|
||||
home.pipeline.desc=Mehrere Aktionen auf ein PDF anwenden, definiert durch einen Pipeline Skript
|
||||
home.pipeline.desc=Mehrere Aktionen auf ein PDF anwenden, definiert durch ein Pipeline Skript
|
||||
pipeline.tags=automate,sequence,scripted,batch-process
|
||||
|
||||
home.add-page-numbers.title=Seitenzahlen hinzufügen
|
||||
@@ -366,7 +368,7 @@ showJS.tags=JS
|
||||
|
||||
home.autoRedact.title=Automatisch zensieren/schwärzen
|
||||
home.autoRedact.desc=Automatisches Zensieren (Schwärzen) von Text in einer PDF-Datei basierend auf dem eingegebenen Text
|
||||
showJS.tags=zensieren,schwärzen
|
||||
autoRedact.tags=zensieren,schwärzen
|
||||
|
||||
home.tableExtraxt.title=Tabelle extrahieren
|
||||
home.tableExtraxt.desc=Tabelle aus PDF in CSV extrahieren
|
||||
@@ -386,8 +388,8 @@ home.split-by-sections.title=PDF in Abschnitte teilen
|
||||
home.split-by-sections.desc=Teilen Sie jede Seite einer PDF-Datei in kleinere horizontale und vertikale Abschnitte auf
|
||||
split-by-sections.tags=abschnitte,teilen,bearbeiten
|
||||
|
||||
home.AddStampRequest.title=Add Stamp to PDF
|
||||
home.AddStampRequest.desc=Add text or add image stamps at set locations
|
||||
home.AddStampRequest.title=Stempel zu PDF hinzufügen
|
||||
home.AddStampRequest.desc=Fügen Sie an festgelegten Stellen Text oder Bildstempel hinzu
|
||||
AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize
|
||||
|
||||
|
||||
@@ -466,37 +468,38 @@ HTMLToPDF.header=HTML zu PDF
|
||||
HTMLToPDF.help=Akzeptiert HTML-Dateien und ZIPs mit html/css/images etc.
|
||||
HTMLToPDF.submit=Konvertieren
|
||||
HTMLToPDF.credit=Verwendet WeasyPrint
|
||||
HTMLToPDF.zoom=Zoom level for displaying the website.
|
||||
HTMLToPDF.pageWidth=Width of the page in centimeters. (Blank to default)
|
||||
HTMLToPDF.pageHeight=Height of the page in centimeters. (Blank to default)
|
||||
HTMLToPDF.marginTop=Top margin of the page in millimeters. (Blank to default)
|
||||
HTMLToPDF.marginBottom=Bottom margin of the page in millimeters. (Blank to default)
|
||||
HTMLToPDF.marginLeft=Left margin of the page in millimeters. (Blank to default)
|
||||
HTMLToPDF.marginRight=Right margin of the page in millimeters. (Blank to default)
|
||||
HTMLToPDF.printBackground=Render the background of websites.
|
||||
HTMLToPDF.defaultHeader=Enable Default Header (Name and page number)
|
||||
HTMLToPDF.cssMediaType=Change the CSS media type of the page.
|
||||
HTMLToPDF.none=None
|
||||
HTMLToPDF.print=Print
|
||||
HTMLToPDF.screen=Screen
|
||||
HTMLToPDF.zoom=Zoomstufe zur Darstellung der Website.
|
||||
HTMLToPDF.pageWidth=Breite der Seite in Zentimetern. (Leer auf Standard)
|
||||
HTMLToPDF.pageHeight=Höhe der Seite in Zentimetern. (Leer auf Standard)
|
||||
HTMLToPDF.marginTop=Oberer Rand der Seite in Millimetern. (Leer auf Standard)
|
||||
HTMLToPDF.marginBottom=Unterer Rand der Seite in Millimetern. (Leer auf Standard)
|
||||
HTMLToPDF.marginLeft=Linker Rand der Seite in Millimetern. (Leer auf Standard)
|
||||
HTMLToPDF.marginRight=Linker Rand der Seite in Millimetern. (Leer auf Standard)
|
||||
HTMLToPDF.printBackground=Den Hintergrund der Website rendern.
|
||||
HTMLToPDF.defaultHeader=Standardkopfzeile aktivieren (Name und Seitenzahl)
|
||||
HTMLToPDF.cssMediaType=CSS-Medientyp der Seite ändern.
|
||||
HTMLToPDF.none=Keine
|
||||
HTMLToPDF.print=Drucken
|
||||
HTMLToPDF.screen=Bildschirm
|
||||
|
||||
|
||||
#AddStampRequest
|
||||
AddStampRequest.header=Stamp PDF
|
||||
AddStampRequest.title=Stamp PDF
|
||||
AddStampRequest.stampType=Stamp Type
|
||||
AddStampRequest.stampText=Stamp Text
|
||||
AddStampRequest.stampImage=Stamp Image
|
||||
AddStampRequest.header=PDF Stempel
|
||||
AddStampRequest.title=PDF Stempel
|
||||
AddStampRequest.stampType=Stempeltyp
|
||||
AddStampRequest.stampText=Stempeltext
|
||||
AddStampRequest.stampImage=Stampelbild
|
||||
AddStampRequest.alphabet=Alphabet
|
||||
AddStampRequest.fontSize=Font/Image Size
|
||||
AddStampRequest.fontSize=Schriftart/Bildgröße
|
||||
AddStampRequest.rotation=Rotation
|
||||
AddStampRequest.opacity=Opacity
|
||||
AddStampRequest.opacity=Deckkraft
|
||||
AddStampRequest.position=Position
|
||||
AddStampRequest.overrideX=Override X Coordinate
|
||||
AddStampRequest.overrideY=Override Y Coordinate
|
||||
AddStampRequest.customMargin=Custom Margin
|
||||
AddStampRequest.customColor=Custom Text Color
|
||||
AddStampRequest.submit=Submit
|
||||
AddStampRequest.overrideX=X-Koordinate überschreiben
|
||||
AddStampRequest.overrideY=Y-Koordinate überschreiben
|
||||
AddStampRequest.customMargin=Benutzerdefinierter Rand
|
||||
AddStampRequest.customColor=Benutzerdefinierte Textfarbe
|
||||
AddStampRequest.submit=Abschicken
|
||||
|
||||
|
||||
#sanitizePDF
|
||||
sanitizePDF.title=PDF Bereinigen
|
||||
@@ -548,7 +551,7 @@ crop.submit=Abschicken
|
||||
#autoSplitPDF
|
||||
autoSplitPDF.title=PDF automatisch teilen
|
||||
autoSplitPDF.header=PDF automatisch teilen
|
||||
autoSplitPDF.description=Drucken Sie, fügen Sie ein, scannen Sie, laden Sie hoch, und lassen Sie uns Ihre Dokumente automatisch trennen. Kein manuelles Sortieren erforderlich.
|
||||
autoSplitPDF.description=Drucken Sie, fügen Sie ein, scannen Sie, laden Sie hoch und lassen Sie uns Ihre Dokumente automatisch trennen. Kein manuelles Sortieren erforderlich.
|
||||
autoSplitPDF.selectText.1=Drucken Sie einige Trennblätter aus (schwarz/weiß ist ausreichend).
|
||||
autoSplitPDF.selectText.2=Scannen Sie alle Dokumente auf einmal, indem Sie das Trennblatt zwischen die Dokumente einlegen.
|
||||
autoSplitPDF.selectText.3=Laden Sie die einzelne große gescannte PDF-Datei hoch und überlassen Sie Stirling PDF den Rest.
|
||||
@@ -568,7 +571,7 @@ pipeline.title=Pipeline
|
||||
pageLayout.title=Mehrseitiges Layout
|
||||
pageLayout.header=Mehrseitiges Layout
|
||||
pageLayout.pagesPerSheet=Seiten pro Blatt:
|
||||
pageLayout.addBorder=Add Borders
|
||||
pageLayout.addBorder=Ränder hinzufügen
|
||||
pageLayout.submit=Abschicken
|
||||
|
||||
|
||||
@@ -584,11 +587,11 @@ scalePages.submit=Abschicken
|
||||
certSign.title=Zertifikatsignierung
|
||||
certSign.header=Signieren Sie ein PDF mit Ihrem Zertifikat (in Arbeit)
|
||||
certSign.selectPDF=Wählen Sie eine PDF-Datei zum Signieren aus:
|
||||
certSign.jksNote=Note: If your certificate type is not listed below, please convert it to a Java Keystore (.jks) file using the keytool command line tool. Then, choose the .jks file option below.
|
||||
certSign.jksNote=Hinweis: Wenn Ihr Zertifikatstyp unten nicht aufgeführt ist, konvertieren Sie ihn bitte mit dem Befehlszeilentool keytool in eine Java Keystore-Datei (.jks). Wählen Sie dann unten die Option „.jks-Datei“ aus.
|
||||
certSign.selectKey=Wählen Sie Ihre private Schlüsseldatei aus (PKCS#8-Format, könnte .pem oder .der sein):
|
||||
certSign.selectCert=Wählen Sie Ihre Zertifikatsdatei aus (X.509-Format, könnte .pem oder .der sein):
|
||||
certSign.selectP12=Wählen Sie Ihre PKCS#12-Keystore-Datei (.p12 oder .pfx) aus (optional, falls angegeben, sollte sie Ihren privaten Schlüssel und Ihr Zertifikat enthalten):
|
||||
certSign.selectJKS=Select Your Java Keystore File (.jks or .keystore):
|
||||
certSign.selectJKS=Wählen Sie Ihre Java Keystore-Datei (.jks oder .keystore):
|
||||
certSign.certType=Zertifikattyp
|
||||
certSign.password=Geben Sie Ihr Keystore- oder Private-Key-Passwort ein (falls vorhanden):
|
||||
certSign.showSig=Signatur anzeigen
|
||||
@@ -700,7 +703,7 @@ compress.selectText.1=Manueller Modus – Von 1 bis 4
|
||||
compress.selectText.2=Optimierungsstufe:
|
||||
compress.selectText.3=4 (Schrecklich für Textbilder)
|
||||
compress.selectText.4=Automatischer Modus – Passt die Qualität automatisch an, um das PDF auf die exakte Größe zu bringen
|
||||
compress.selectText.5=Erwartete PDF-Größe (z. B. 25 MB, 10,8 MB, 25 KB)
|
||||
compress.selectText.5=Erwartete PDF-Größe (z.B. 25 MB, 10,8 MB, 25 KB)
|
||||
compress.submit=Komprimieren
|
||||
|
||||
|
||||
@@ -731,8 +734,8 @@ multiTool.title=PDF-Multitool
|
||||
multiTool.header=PDF-Multitool
|
||||
|
||||
#view pdf
|
||||
viewPdf.title=View PDF
|
||||
viewPdf.header=View PDF
|
||||
viewPdf.title=PDF anzeigen
|
||||
viewPdf.header=PDF anzeigen
|
||||
|
||||
#pageRemover
|
||||
pageRemover.title=Seiten entfernen
|
||||
@@ -767,10 +770,10 @@ split.submit=Aufteilen
|
||||
imageToPDF.title=Bild zu PDF
|
||||
imageToPDF.header=Bild zu PDF
|
||||
imageToPDF.submit=Umwandeln
|
||||
imageToPDF.selectLabel=Image Fit Options
|
||||
imageToPDF.fillPage=Fill Page
|
||||
imageToPDF.fitDocumentToImage=Fit Page to Image
|
||||
imageToPDF.maintainAspectRatio=Maintain Aspect Ratios
|
||||
imageToPDF.selectLabel=Bild anpassen
|
||||
imageToPDF.fillPage=Seite füllen
|
||||
imageToPDF.fitDocumentToImage=Seite an Bild anpassen
|
||||
imageToPDF.maintainAspectRatio=Seitenverhältnisse beibehalten
|
||||
imageToPDF.selectText.2=PDF automatisch drehen
|
||||
imageToPDF.selectText.3=Mehrere Dateien verarbeiten (nur aktiv, wenn Sie mit mehreren Bildern arbeiten)
|
||||
imageToPDF.selectText.4=In ein einziges PDF zusammenführen
|
||||
@@ -860,13 +863,12 @@ changeMetadata.selectText.1=Bitte bearbeiten Sie die Variablen, die Sie ändern
|
||||
changeMetadata.selectText.2=Alle Metadaten löschen
|
||||
changeMetadata.selectText.3=Benutzerdefinierte Metadaten anzeigen:
|
||||
changeMetadata.author=Autor:
|
||||
changeMetadata.creationDate=Erstellungsdatum (jjjj/MM/tt HH:mm:ss):
|
||||
changeMetadata.creationDate=Erstellungsdatum (JJJJ/MM/TT HH:mm:ss):
|
||||
changeMetadata.creator=Ersteller:
|
||||
changeMetadata.keywords=Schlüsselwörter:
|
||||
changeMetadata.modDate=Änderungsdatum (JJJJ/MM/TT HH:mm:ss):
|
||||
changeMetadata.producer=Produzent:
|
||||
changeMetadata.subject=Betreff:
|
||||
changeMetadata.title=Titel:
|
||||
changeMetadata.trapped=Gefangen:
|
||||
changeMetadata.selectText.4=Andere Metadaten:
|
||||
changeMetadata.selectText.5=Benutzerdefinierten Metadateneintrag hinzufügen
|
||||
@@ -930,7 +932,7 @@ split-by-size-or-count.type.size=Nach Größe
|
||||
split-by-size-or-count.type.pageCount=Nach Anzahl Seiten
|
||||
split-by-size-or-count.type.docCount=Nach Anzahl Dokumenten
|
||||
split-by-size-or-count.value.label=Wert eingeben
|
||||
split-by-size-or-count.value.placeholder=Größe eingeben (z. B.: 2MB oder 3KB) oder Anzahl (z. B.: 5)
|
||||
split-by-size-or-count.value.placeholder=Größe eingeben (z.B.: 2MB oder 3KB) oder Anzahl (z.B.: 5)
|
||||
split-by-size-or-count.submit=Erstellen
|
||||
|
||||
|
||||
@@ -943,7 +945,7 @@ overlay-pdfs.mode.sequential=Sequentielles Overlay
|
||||
overlay-pdfs.mode.interleaved=Verschachteltes Overlay
|
||||
overlay-pdfs.mode.fixedRepeat=Feste-Wiederholung Overlay
|
||||
overlay-pdfs.counts.label=Overlay Anzahl (für Feste-Wiederholung)
|
||||
overlay-pdfs.counts.placeholder=Komma-separierte Anzahl eingeben (z. B.: 2,3,1)
|
||||
overlay-pdfs.counts.placeholder=Komma-separierte Anzahl eingeben (z.B.: 2,3,1)
|
||||
overlay-pdfs.position.label=Overlay Position auswählen
|
||||
overlay-pdfs.position.foreground=Vordergrund
|
||||
overlay-pdfs.position.background=Hintergrund
|
||||
@@ -961,10 +963,11 @@ split-by-sections.submit=PDF teilen
|
||||
|
||||
|
||||
#licenses
|
||||
licenses.nav=Licenses
|
||||
licenses.title=3rd Party Licenses
|
||||
licenses.header=3rd Party Licenses
|
||||
licenses.module=Module
|
||||
licenses.nav=Lizenzen
|
||||
licenses.title=Lizenzen von Drittanbietern
|
||||
licenses.header=Lizenzen von Drittanbietern
|
||||
licenses.module=Modul
|
||||
licenses.version=Version
|
||||
licenses.license=License
|
||||
licenses.license=Lizenz
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -11,6 +11,7 @@ imgPrompt=\u0395\u03C0\u03B9\u03BB\u03BF\u03B3\u03AE \u0395\u03B9\u03BA\u03CC\u0
|
||||
genericSubmit=\u03A5\u03C0\u03BF\u03B2\u03BF\u03BB\u03AE
|
||||
processTimeWarning=\u03A0\u03C1\u03BF\u03C3\u03BF\u03C7\u03AE: \u0391\u03C5\u03C4\u03AE \u03B7 \u03B4\u03B9\u03B1\u03B4\u03B9\u03BA\u03B1\u03C3\u03AF\u03B1 \u03BC\u03C0\u03BF\u03C1\u03B5\u03AF \u03BD\u03B1 \u03B4\u03B9\u03B1\u03C1\u03BA\u03AD\u03C3\u03B5\u03B9 \u03AD\u03C9\u03C2 \u03BA\u03B1\u03B9 \u03AD\u03BD\u03B1 \u03BB\u03B5\u03C0\u03C4\u03CC \u03B1\u03BD\u03AC\u03BB\u03BF\u03B3\u03B1 \u03BC\u03B5 \u03C4\u03BF \u03BC\u03AD\u03B3\u03B5\u03B8\u03BF\u03C2 \u03C4\u03BF\u03C5 \u03B1\u03C1\u03C7\u03B5\u03AF\u03BF\u03C5
|
||||
pageOrderPrompt=\u03A0\u03C1\u03BF\u03C3\u03B1\u03C1\u03BC\u03BF\u03C3\u03BC\u03AD\u03BD\u03B7 \u03A3\u03B5\u03B9\u03C1\u03AC \u03A3\u03B5\u03BB\u03AF\u03B4\u03B1\u03C2 (\u03A0\u03C1\u03BF\u03C3\u03B8\u03AD\u03C3\u03C4\u03B5 \u03BC\u03AF\u03B1 \u03BB\u03AF\u03C3\u03C4\u03B5 \u03B1\u03C0\u03BF \u03B1\u03C1\u03B9\u03B8\u03BC\u03BF\u03CD\u03C2 \u03C3\u03B5\u03BB\u03B9\u03B4\u03CE\u03BD, \u03C7\u03C9\u03C1\u03B9\u03C3\u03BC\u03AD\u03BD\u03B5\u03C2 \u03BC\u03B5 \u03BA\u03CC\u03BC\u03BC\u03B1 \u03AE \u03C3\u03C5\u03BD\u03B1\u03C1\u03C4\u03AE\u03C3\u03B5\u03B9\u03C2 \u03CC\u03C0\u03C9\u03C2 2n+1) :
|
||||
pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :
|
||||
goToPage=Go
|
||||
true=\u0391\u03BB\u03B7\u03B8\u03AD\u03C2
|
||||
false=\u039B\u03B1\u03BD\u03B8\u03B1\u03C3\u03BC\u03AD\u03BD\u03BF
|
||||
@@ -19,6 +20,7 @@ save=\u0391\u03C0\u03BF\u03B8\u03AE\u03BA\u03B5\u03C5\u03C3\u03B7
|
||||
close=\u039A\u03BB\u03B5\u03AF\u03C3\u03B9\u03BC\u03BF
|
||||
filesSelected=\u03B1\u03C1\u03C7\u03B5\u03AF\u03B1 \u03C0\u03BF\u03C5 \u03B5\u03C0\u03B9\u03BB\u03AD\u03C7\u03B8\u03B7\u03BA\u03B1\u03BD
|
||||
noFavourites=\u039A\u03B1\u03BD\u03AD\u03BD\u03B1 \u03B1\u03B3\u03B1\u03C0\u03AE\u03BC\u03B5\u03BD\u03BF \u03B4\u03B5\u03BD \u03AD\u03C7\u03B5\u03B9 \u03C0\u03C1\u03BF\u03C3\u03C4\u03B5\u03B8\u03B5\u03AF
|
||||
downloadComplete=Download Complete
|
||||
bored=\u0392\u03B1\u03C1\u03B9\u03AD\u03C3\u03C4\u03B5 \u03BD\u03B1 \u03C0\u03B5\u03C1\u03B9\u03BC\u03AD\u03BD\u03B5\u03C4\u03B5;
|
||||
alphabet=\u0391\u03BB\u03C6\u03AC\u03B2\u03B7\u03C4\u03BF
|
||||
downloadPdf=\u039A\u03B1\u03C4\u03AD\u03B2\u03B1\u03C3\u03BC\u03B1 \u03C4\u03BF\u03C5 PDF
|
||||
@@ -42,7 +44,7 @@ red=\u039A\u03CC\u03BA\u03BA\u03B9\u03BD\u03BF
|
||||
green=\u03A0\u03C1\u03AC\u03C3\u03B9\u03BD\u03BF
|
||||
blue=\u039C\u03C0\u03BB\u03AD
|
||||
custom=\u03A0\u03C1\u03BF\u03C3\u03B1\u03C1\u03BC\u03BF\u03B3\u03AE...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any problems!
|
||||
poweredBy=Powered by
|
||||
yes=Yes
|
||||
no=No
|
||||
@@ -120,7 +122,7 @@ account.accountSettings=\u03A1\u03C5\u03B8\u03BC\u03AF\u03C3\u03B5\u03B9\u03C2 \
|
||||
account.adminSettings=\u03A1\u03C5\u03B8\u03BC\u03AF\u03C3\u03B5\u03B9\u03C2 \u0394\u03B9\u03B1\u03C7\u03B5\u03B9\u03C1\u03B9\u03C3\u03C4\u03AE - \u03A0\u03C1\u03BF\u03B2\u03BF\u03BB\u03AE \u03BA\u03B1\u03B9 \u03C0\u03C1\u03BF\u03C3\u03B8\u03AE\u03BA\u03B7 \u03C7\u03C1\u03B7\u03C3\u03C4\u03CE\u03BD
|
||||
account.userControlSettings=\u03A1\u03C5\u03B8\u03BC\u03AF\u03C3\u03B5\u03B9\u03C2 \u03A7\u03B5\u03B9\u03C1\u03B9\u03C3\u03BC\u03BF\u03CD \u03A7\u03C1\u03B7\u03C3\u03C4\u03CE\u03BD
|
||||
account.changeUsername=\u0391\u03BB\u03BB\u03B1\u03B3\u03AE \u039F\u03BD\u03CC\u03BC\u03B1\u03C4\u03BF\u03C2 \u03A7\u03C1\u03AE\u03C3\u03C4\u03B7
|
||||
account.changeUsername=\u0391\u03BB\u03BB\u03B1\u03B3\u03AE \u039F\u03BD\u03CC\u03BC\u03B1\u03C4\u03BF\u03C2 \u03A7\u03C1\u03AE\u03C3\u03C4\u03B7
|
||||
account.newUsername=\u039d\u03ad\u03bf \u038c\u03bd\u03bf\u03bc\u03b1 \u03a7\u03c1\u03ae\u03c3\u03c4\u03b7
|
||||
account.password=\u0395\u03C0\u03B9\u03B2\u03B5\u03B2\u03B1\u03AF\u03C9\u03C3\u03B7 \u039A\u03C9\u03B4\u03B9\u03BA\u03BF\u03CD \u03A0\u03C1\u03CC\u03C3\u03B2\u03B1\u03C3\u03B7\u03C2
|
||||
account.oldPassword=\u03A0\u03B1\u03BB\u03B9\u03CC\u03C2 \u039A\u03C9\u03B4\u03B9\u03BA\u03CC\u03C2 \u03A0\u03C1\u03CC\u03C3\u03B2\u03B1\u03C3\u03B7\u03C2
|
||||
account.newPassword=\u039D\u03AD\u03BF\u03C2 \u039A\u03C9\u03B4\u03B9\u03BA\u03CC\u03C2 \u03A0\u03C1\u03CC\u03C3\u03B2\u03B1\u03C3\u03B7\u03C2
|
||||
@@ -362,11 +364,11 @@ PdfToSinglePage.tags=single page
|
||||
|
||||
home.showJS.title=\u0395\u03BC\u03C6\u03AC\u03BD\u03B9\u03C3\u03B7 Javascript
|
||||
home.showJS.desc=\u0391\u03BD\u03B6\u03AE\u03C4\u03B7\u03C3\u03B7 \u03BA\u03B1\u03B9 \u03B5\u03BC\u03C6\u03AC\u03BD\u03B9\u03C3\u03B7 \u03BA\u03CE\u03B4\u03B9\u03BA\u03B1 Javascript \u03C0\u03BF\u03C5 \u03B5\u03AF\u03BD\u03B1\u03B9 \u03B5\u03BD\u03C3\u03C9\u03BC\u03B1\u03C4\u03C9\u03BC\u03AD\u03BD\u03BF \u03BC\u03AD\u03C3\u03B1 \u03C3\u03B5 \u03AD\u03BD\u03B1 PDF
|
||||
showJS.tags=Redact,Hide,black out,black,marker,hidden
|
||||
showJS.tags=JS
|
||||
|
||||
home.autoRedact.title=\u0391\u03C5\u03C4\u03CC\u03BC\u03B1\u03C4\u03BF \u039C\u03B1\u03CD\u03C1\u03B9\u03C3\u03BC\u03B1 \u039A\u03B5\u03B9\u03BC\u03AD\u03BD\u03BF\u03C5
|
||||
home.autoRedact.desc=\u0391\u03C5\u03C4\u03CC\u03BC\u03B1\u03C4\u03B7 \u03B5\u03C0\u03B5\u03BE\u03B5\u03C1\u03B3\u03B1\u03C3\u03AF\u03B1 (\u039C\u03B1\u03CD\u03C1\u03B9\u03C3\u03BC\u03B1) \u03BA\u03B5\u03AF\u03BC\u03B5\u03BD\u03BF\u03C5 \u03C3\u03B5 PDF \u03BC\u03B5 \u03B2\u03AC\u03C3\u03B7 \u03C4\u03BF \u03BA\u03B5\u03AF\u03BC\u03B5\u03BD\u03BF \u03B5\u03B9\u03C3\u03B1\u03B3\u03C9\u03B3\u03AE\u03C2
|
||||
showJS.tags=Redact,Hide,black out,black,marker,hidden
|
||||
autoRedact.tags=Redact,Hide,black out,black,marker,hidden
|
||||
|
||||
home.tableExtraxt.title=PDF to CSV
|
||||
home.tableExtraxt.desc=Extracts Tables from a PDF converting it to CSV
|
||||
@@ -410,7 +412,7 @@ autoRedact.title=\u0391\u03C5\u03C4\u03CC\u03BC\u03B1\u03C4\u03BF \u039C\u03B1\u
|
||||
autoRedact.header=\u0391\u03C5\u03C4\u03CC\u03BC\u03B1\u03C4\u03BF \u039C\u03B1\u03CD\u03C1\u03B9\u03C3\u03BC\u03B1 \u039A\u03B5\u03B9\u03BC\u03AD\u03BD\u03BF\u03C5
|
||||
autoRedact.colorLabel=\u03A7\u03C1\u03CE\u03BC\u03B1
|
||||
autoRedact.textsToRedactLabel=\u039A\u03B5\u03AF\u03BC\u03B5\u03BD\u03BF \u03B3\u03B9\u03B1 \u03BC\u03B1\u03CD\u03C1\u03B9\u03C3\u03BC\u03B1 (\u03B4\u03B9\u03B1\u03C7\u03C9\u03C1\u03B9\u03C3\u03BC\u03AD\u03BD\u03BF \u03C3\u03B5 \u03B3\u03C1\u03B1\u03BC\u03BC\u03AD\u03C2)
|
||||
autoRedact.textsToRedactPlaceholder=\u03C0.\u03C7. \n\u0395\u03BC\u03C0\u03B9\u03C3\u03C4\u03B5\u03C5\u03C4\u03B9\u03BA\u03CC \n\u0391\u03BA\u03C1\u03CE\u03C2 \u03B1\u03C0\u03CC\u03C1\u03C1\u03B7\u03C4\u03BF
|
||||
autoRedact.textsToRedactPlaceholder=\u03C0.\u03C7. \n\u0395\u03BC\u03C0\u03B9\u03C3\u03C4\u03B5\u03C5\u03C4\u03B9\u03BA\u03CC \n\u0391\u03BA\u03C1\u03CE\u03C2 \u03B1\u03C0\u03CC\u03C1\u03C1\u03B7\u03C4\u03BF
|
||||
autoRedact.useRegexLabel=\u03A7\u03C1\u03AE\u03C3\u03B7 Regex
|
||||
autoRedact.wholeWordSearchLabel=\u0391\u03BD\u03B1\u03B6\u03AE\u03C4\u03B7\u03C3\u03B7 \u03BF\u03BB\u03CC\u03BA\u03BB\u03B7\u03C1\u03B7\u03C2 \u03C4\u03B7\u03C2 \u03BB\u03AD\u03BE\u03B7\u03C2
|
||||
autoRedact.customPaddingLabel=Custom Extra Padding
|
||||
@@ -498,6 +500,7 @@ AddStampRequest.customMargin=Custom Margin
|
||||
AddStampRequest.customColor=Custom Text Color
|
||||
AddStampRequest.submit=Submit
|
||||
|
||||
|
||||
#sanitizePDF
|
||||
sanitizePDF.title=\u0391\u03C0\u03BF\u03BB\u03CD\u03BC\u03B1\u03BD\u03C3\u03B7 PDF
|
||||
sanitizePDF.header=\u0391\u03C0\u03BF\u03BB\u03CD\u03BC\u03B1\u03BD\u03C3\u03B7 \u03B5\u03BD\u03CC\u03C2 PDF \u03B1\u03C1\u03C7\u03B5\u03AF\u03BF\u03C5
|
||||
@@ -866,7 +869,6 @@ changeMetadata.keywords=\u039B\u03AD\u03BE\u03B5\u03B9\u03C2-\u03BA\u03BB\u03B5\
|
||||
changeMetadata.modDate=\u0397\u03BC\u03B5\u03C1\u03BF\u03BC\u03B7\u03BD\u03AF\u03B1 \u03A4\u03C1\u03BF\u03C0\u03BF\u03C0\u03BF\u03AF\u03B7\u03C3\u03B7\u03C2 (yyyy/MM/dd HH:mm:ss):
|
||||
changeMetadata.producer=\u03A0\u03B1\u03C1\u03B1\u03B3\u03C9\u03B3\u03CC\u03C2:
|
||||
changeMetadata.subject=\u0398\u03AD\u03BC\u03B1:
|
||||
changeMetadata.title=\u03A4\u03AF\u03C4\u03BB\u03BF\u03C2:
|
||||
changeMetadata.trapped=Trapped:
|
||||
changeMetadata.selectText.4=\u0386\u03BB\u03BB\u03B1 \u03BC\u03B5\u03C4\u03B1\u03B4\u03B5\u03B4\u03BF\u03BC\u03AD\u03BD\u03B1:
|
||||
changeMetadata.selectText.5=\u03A0\u03C1\u03BF\u03C3\u03B8\u03AE\u03BA\u03B7 \u03B5\u03B3\u03B3\u03C1\u03B1\u03C6\u03AE\u03C2 \u03C0\u03C1\u03BF\u03C3\u03B1\u03C1\u03BC\u03BF\u03C3\u03BC\u03AD\u03BD\u03C9\u03BD \u03BC\u03B5\u03C4\u03B1\u03B4\u03B5\u03B4\u03BF\u03BC\u03AD\u03BD\u03C9\u03BD
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr = left to right, rtl = right to left)
|
||||
@@ -20,6 +20,7 @@ save=Save
|
||||
close=Close
|
||||
filesSelected=files selected
|
||||
noFavourites=No favourites added
|
||||
downloadComplete=Download Complete
|
||||
bored=Bored Waiting?
|
||||
alphabet=Alphabet
|
||||
downloadPdf=Download PDF
|
||||
@@ -43,7 +44,7 @@ red=Red
|
||||
green=Green
|
||||
blue=Blue
|
||||
custom=Custom...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any problems!
|
||||
poweredBy=Powered by
|
||||
yes=Yes
|
||||
no=No
|
||||
@@ -120,8 +121,8 @@ account.title=Account Settings
|
||||
account.accountSettings=Account Settings
|
||||
account.adminSettings=Admin Settings - View and Add Users
|
||||
account.userControlSettings=User Control Settings
|
||||
account.changeUsername=New Username
|
||||
account.changeUsername=Change Username
|
||||
account.newUsername=New Username
|
||||
account.password=Confirmation Password
|
||||
account.oldPassword=Old password
|
||||
account.newPassword=New Password
|
||||
@@ -367,7 +368,7 @@ showJS.tags=JS
|
||||
|
||||
home.autoRedact.title=Auto Redact
|
||||
home.autoRedact.desc=Auto Redacts(Blacks out) text in a PDF based on input text
|
||||
showJS.tags=Redact,Hide,black out,black,marker,hidden
|
||||
autoRedact.tags=Redact,Hide,black out,black,marker,hidden
|
||||
|
||||
home.tableExtraxt.title=PDF to CSV
|
||||
home.tableExtraxt.desc=Extracts Tables from a PDF converting it to CSV
|
||||
@@ -411,7 +412,7 @@ autoRedact.title=Auto Redact
|
||||
autoRedact.header=Auto Redact
|
||||
autoRedact.colorLabel=Colour
|
||||
autoRedact.textsToRedactLabel=Text to Redact (line-separated)
|
||||
autoRedact.textsToRedactPlaceholder=e.g. \nConfidential \nTop-Secret
|
||||
autoRedact.textsToRedactPlaceholder=e.g. \nConfidential \nTop-Secret
|
||||
autoRedact.useRegexLabel=Use Regex
|
||||
autoRedact.wholeWordSearchLabel=Whole Word Search
|
||||
autoRedact.customPaddingLabel=Custom Extra Padding
|
||||
@@ -499,6 +500,7 @@ AddStampRequest.customMargin=Custom Margin
|
||||
AddStampRequest.customColor=Custom Text Color
|
||||
AddStampRequest.submit=Submit
|
||||
|
||||
|
||||
#sanitizePDF
|
||||
sanitizePDF.title=Sanitize PDF
|
||||
sanitizePDF.header=Sanitize a PDF file
|
||||
@@ -867,7 +869,6 @@ changeMetadata.keywords=Keywords:
|
||||
changeMetadata.modDate=Modification Date (yyyy/MM/dd HH:mm:ss):
|
||||
changeMetadata.producer=Producer:
|
||||
changeMetadata.subject=Subject:
|
||||
changeMetadata.title=Title:
|
||||
changeMetadata.trapped=Trapped:
|
||||
changeMetadata.selectText.4=Other Metadata:
|
||||
changeMetadata.selectText.5=Add Custom Metadata Entry
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -11,6 +11,7 @@ imgPrompt=Select Image(s)
|
||||
genericSubmit=Submit
|
||||
processTimeWarning=Warning: This process can take up to a minute depending on file-size
|
||||
pageOrderPrompt=Custom Page Order (Enter a comma-separated list of page numbers or Functions like 2n+1) :
|
||||
pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :
|
||||
goToPage=Go
|
||||
true=True
|
||||
false=False
|
||||
@@ -19,6 +20,7 @@ save=Save
|
||||
close=Close
|
||||
filesSelected=files selected
|
||||
noFavourites=No favorites added
|
||||
downloadComplete=Download Complete
|
||||
bored=Bored Waiting?
|
||||
alphabet=Alphabet
|
||||
downloadPdf=Download PDF
|
||||
@@ -42,7 +44,7 @@ red=Red
|
||||
green=Green
|
||||
blue=Blue
|
||||
custom=Custom...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any problems!
|
||||
poweredBy=Powered by
|
||||
yes=Yes
|
||||
no=No
|
||||
@@ -120,7 +122,7 @@ account.accountSettings=Account Settings
|
||||
account.adminSettings=Admin Settings - View and Add Users
|
||||
account.userControlSettings=User Control Settings
|
||||
account.changeUsername=Change Username
|
||||
account.changeUsername=Change Username
|
||||
account.newUsername=New Username
|
||||
account.password=Confirmation Password
|
||||
account.oldPassword=Old password
|
||||
account.newPassword=New Password
|
||||
@@ -366,7 +368,7 @@ showJS.tags=JS
|
||||
|
||||
home.autoRedact.title=Auto Redact
|
||||
home.autoRedact.desc=Auto Redacts(Blacks out) text in a PDF based on input text
|
||||
showJS.tags=JS
|
||||
autoRedact.tags=Redact,Hide,black out,black,marker,hidden
|
||||
|
||||
home.tableExtraxt.title=PDF to CSV
|
||||
home.tableExtraxt.desc=Extracts Tables from a PDF converting it to CSV
|
||||
@@ -410,7 +412,7 @@ autoRedact.title=Auto Redact
|
||||
autoRedact.header=Auto Redact
|
||||
autoRedact.colorLabel=Color
|
||||
autoRedact.textsToRedactLabel=Text to Redact (line-separated)
|
||||
autoRedact.textsToRedactPlaceholder=e.g. \nConfidential \nTop-Secret
|
||||
autoRedact.textsToRedactPlaceholder=e.g. \nConfidential \nTop-Secret
|
||||
autoRedact.useRegexLabel=Use Regex
|
||||
autoRedact.wholeWordSearchLabel=Whole Word Search
|
||||
autoRedact.customPaddingLabel=Custom Extra Padding
|
||||
@@ -498,6 +500,7 @@ AddStampRequest.customMargin=Custom Margin
|
||||
AddStampRequest.customColor=Custom Text Color
|
||||
AddStampRequest.submit=Submit
|
||||
|
||||
|
||||
#sanitizePDF
|
||||
sanitizePDF.title=Sanitize PDF
|
||||
sanitizePDF.header=Sanitize a PDF file
|
||||
@@ -866,7 +869,6 @@ changeMetadata.keywords=Keywords:
|
||||
changeMetadata.modDate=Modification Date (yyyy/MM/dd HH:mm:ss):
|
||||
changeMetadata.producer=Producer:
|
||||
changeMetadata.subject=Subject:
|
||||
changeMetadata.title=Title:
|
||||
changeMetadata.trapped=Trapped:
|
||||
changeMetadata.selectText.4=Other Metadata:
|
||||
changeMetadata.selectText.5=Add Custom Metadata Entry
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -11,6 +11,7 @@ imgPrompt=Seleccionar Imagen(es)
|
||||
genericSubmit=Enviar
|
||||
processTimeWarning=Advertencia: este proceso puede tardar hasta un minuto dependiendo del tamaño del archivo
|
||||
pageOrderPrompt=Orden de páginas (Introduzca una lista de números de página separados por coma):
|
||||
pageSelectionPrompt=Selección de página personalizada (Intruduzca una lista de números de página separados por comas 1,5,6 o funciones como 2n+1) :
|
||||
goToPage=Ir a
|
||||
true=Verdadero
|
||||
false=Falso
|
||||
@@ -19,6 +20,7 @@ save=Guardar
|
||||
close=Cerrar
|
||||
filesSelected=archivos seleccionados
|
||||
noFavourites=No se agregaron favoritos
|
||||
downloadComplete=Download Complete
|
||||
bored=¿Cansado de esperar?
|
||||
alphabet=Alfabeto
|
||||
downloadPdf=Descargar PDF
|
||||
@@ -56,7 +58,7 @@ usernameExistsMessage=El nuevo nombre de usuario está en uso.
|
||||
###############
|
||||
# Pipeline #
|
||||
###############
|
||||
pipeline.header=Menu Pipeline (Alfa)
|
||||
pipeline.header=Menú de canalización (Alfa)
|
||||
pipeline.uploadButton=Cargar personalización
|
||||
pipeline.configureButton=Configurar
|
||||
pipeline.defaultOption=Personalizar
|
||||
@@ -65,13 +67,13 @@ pipeline.submitButton=Enviar
|
||||
######################
|
||||
# Pipeline Options #
|
||||
######################
|
||||
pipelineOptions.header=Configuración Pipeline
|
||||
pipelineOptions.pipelineNameLabel=Nombre del Pipeline
|
||||
pipelineOptions.saveSettings=Guardar configuración de la oiperación
|
||||
pipelineOptions.pipelineNamePrompt=Introduzca aquí el nombre del pipeline
|
||||
pipelineOptions.header=Configuración de la canalización
|
||||
pipelineOptions.pipelineNameLabel=Nombre de la canalización
|
||||
pipelineOptions.saveSettings=Guardar configuración de la canalización
|
||||
pipelineOptions.pipelineNamePrompt=Introduzca aquí el nombre de la canalización
|
||||
pipelineOptions.selectOperation=Seleccione la operación
|
||||
pipelineOptions.addOperationButton=Añadir operación
|
||||
pipelineOptions.pipelineHeader=Pipeline:
|
||||
pipelineOptions.pipelineHeader=Canalización:
|
||||
pipelineOptions.saveButton=Descargar
|
||||
pipelineOptions.validateButton=Validar
|
||||
|
||||
@@ -120,7 +122,7 @@ account.accountSettings=Configuración de la cuenta
|
||||
account.adminSettings=Configuración de Administrador - Ver y Añadir Usuarios
|
||||
account.userControlSettings=Configuración de control de usuario
|
||||
account.changeUsername=Cambiar nombre de usuario
|
||||
account.changeUsername=Cambiar nombre de usuario
|
||||
account.newUsername=nuevo nombre de usuario
|
||||
account.password=Confirmar contraseña
|
||||
account.oldPassword=Contraseña anterior
|
||||
account.newPassword=Nueva Contraseña
|
||||
@@ -366,7 +368,7 @@ showJS.tags=JS
|
||||
|
||||
home.autoRedact.title=Auto Redactar
|
||||
home.autoRedact.desc=Redactar automáticamente (ocultar) texto en un PDF según el texto introducido
|
||||
showJS.tags=JS
|
||||
autoRedact.tags=Redact,Hide,black out,black,marker,hidden
|
||||
|
||||
home.tableExtraxt.title=PDF a CSV
|
||||
home.tableExtraxt.desc=Extraer Tablas de un PDF convirtiéndolas a CSV
|
||||
@@ -410,7 +412,7 @@ autoRedact.title=Auto Redactar
|
||||
autoRedact.header=Auto Redactar
|
||||
autoRedact.colorLabel=Color
|
||||
autoRedact.textsToRedactLabel=Texto para Redactar (separado por líneas)
|
||||
autoRedact.textsToRedactPlaceholder=por ej. \nConfidencial \nAlto-Secreto
|
||||
autoRedact.textsToRedactPlaceholder=por ej. \nConfidencial \nAlto-Secreto
|
||||
autoRedact.useRegexLabel=Usar Regex
|
||||
autoRedact.wholeWordSearchLabel=Búsqueda por palabra completa
|
||||
autoRedact.customPaddingLabel=Extra Padding personalizado
|
||||
@@ -498,6 +500,7 @@ AddStampRequest.customMargin=Personalizar margen
|
||||
AddStampRequest.customColor=Personalizar color de texto
|
||||
AddStampRequest.submit=Enviar
|
||||
|
||||
|
||||
#sanitizePDF
|
||||
sanitizePDF.title=Desinfectar archivo PDF
|
||||
sanitizePDF.header=Desinfectar un archivo PDF
|
||||
@@ -561,7 +564,7 @@ autoSplitPDF.submit=Entregar
|
||||
|
||||
|
||||
#pipeline
|
||||
pipeline.title=Pipeline
|
||||
pipeline.title=Canalización
|
||||
|
||||
|
||||
#pageLayout
|
||||
@@ -866,7 +869,6 @@ changeMetadata.keywords=Palabras clave:
|
||||
changeMetadata.modDate=Fecha de modificación (aaaa/MM/dd HH:mm:ss):
|
||||
changeMetadata.producer=Productor:
|
||||
changeMetadata.subject=Asunto:
|
||||
changeMetadata.title=Título:
|
||||
changeMetadata.trapped=Capturado:
|
||||
changeMetadata.selectText.4=Otros Metadatos:
|
||||
changeMetadata.selectText.5=Agregar entrada de metadatos personalizados
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -11,6 +11,7 @@ imgPrompt=Hautatu Irudia(k)
|
||||
genericSubmit=Bidali
|
||||
processTimeWarning=Oharra: prozesu honetarako minutu bat ere beharko da fitxategiaren tamaiaren arabera
|
||||
pageOrderPrompt=Orrialdeen ordena (sartu komaz bereizitako orrialde-zenbakien zerrenda)
|
||||
pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :
|
||||
goToPage=Joan
|
||||
true=Egiazkoa
|
||||
false=Faltsua
|
||||
@@ -19,6 +20,7 @@ save=Gorde
|
||||
close=Itxi
|
||||
filesSelected=Hautatutako fitxategiak
|
||||
noFavourites=Ez dira gogokoak gehitu
|
||||
downloadComplete=Download Complete
|
||||
bored=Itxaroten aspertuta?
|
||||
alphabet=Alfabetoa
|
||||
downloadPdf=PDFa deskargatu
|
||||
@@ -42,7 +44,7 @@ red=Gorria
|
||||
green=Berdea
|
||||
blue=Urdina
|
||||
custom=Pertsonalizatu...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any problems!
|
||||
poweredBy=Powered by
|
||||
yes=Yes
|
||||
no=No
|
||||
@@ -120,7 +122,7 @@ account.accountSettings=Kontuaren ezarpenak
|
||||
account.adminSettings=Admin ezarpenak - Ikusi eta gehitu Erabiltzaileak
|
||||
account.userControlSettings=Erabiltzaile ezarpen kontrolak
|
||||
account.changeUsername=Aldatu erabiltzaile izena
|
||||
account.changeUsername=Aldatu erabiltzaile izena
|
||||
account.newUsername=Erabiltzaile izen berria
|
||||
account.password=Konfirmatu pasahitza
|
||||
account.oldPassword=Pasahitz zaharra
|
||||
account.newPassword=Pasahitz berria
|
||||
@@ -366,7 +368,7 @@ showJS.tags=JS
|
||||
|
||||
home.autoRedact.title=Auto Idatzi
|
||||
home.autoRedact.desc=Auto Idatzi testua pdf fitxategian sarrerako testuan oinarritua
|
||||
showJS.tags=JS
|
||||
autoRedact.tags=Redact,Hide,black out,black,marker,hidden
|
||||
|
||||
home.tableExtraxt.title=PDF to CSV
|
||||
home.tableExtraxt.desc=Extracts Tables from a PDF converting it to CSV
|
||||
@@ -410,7 +412,7 @@ autoRedact.title=Auto Idatzi
|
||||
autoRedact.header=Auto Idatzi
|
||||
autoRedact.colorLabel=Kolorea
|
||||
autoRedact.textsToRedactLabel=Idazteko testua (lerro bidez bereizia)
|
||||
autoRedact.textsToRedactPlaceholder=adib. \nKonfidentziala \nTop-Secret
|
||||
autoRedact.textsToRedactPlaceholder=adib. \nKonfidentziala \nTop-Secret
|
||||
autoRedact.useRegexLabel=Regex erabili
|
||||
autoRedact.wholeWordSearchLabel=Hitz osoen bilaketa
|
||||
autoRedact.customPaddingLabel=Custom Extra Padding
|
||||
@@ -498,6 +500,7 @@ AddStampRequest.customMargin=Custom Margin
|
||||
AddStampRequest.customColor=Custom Text Color
|
||||
AddStampRequest.submit=Submit
|
||||
|
||||
|
||||
#sanitizePDF
|
||||
sanitizePDF.title=PDF-a desinfektatu
|
||||
sanitizePDF.header=PDF fitxategi bat desinfektatu
|
||||
@@ -866,7 +869,6 @@ changeMetadata.keywords=Gako-hitzak:
|
||||
changeMetadata.modDate=Aldatze-data (aaaa/MM/dd HH:mm:ss):
|
||||
changeMetadata.producer=Ekoizlea:
|
||||
changeMetadata.subject=Gaia:
|
||||
changeMetadata.title=Izenburua:
|
||||
changeMetadata.trapped=Trapped:
|
||||
changeMetadata.selectText.4=Beste metadatu batzuk:
|
||||
changeMetadata.selectText.5=Gehitu metadatu pertsonalizatuen sarrera
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -11,6 +11,7 @@ imgPrompt=Choisir une image
|
||||
genericSubmit=Envoyer
|
||||
processTimeWarning=Attention, ce processus peut prendre jusqu\u2019à une minute en fonction de la taille du fichier.
|
||||
pageOrderPrompt=Ordre des pages (entrez une liste de numéros de page séparés par des virgules ou des fonctions telles que 2n+1)\u00a0:
|
||||
pageSelectionPrompt=Sélection des pages (entrez une liste de numéros de page séparés par des virgules ou des fonctions telles que 2n+1)\u00a0:
|
||||
goToPage=Aller
|
||||
true=Vrai
|
||||
false=Faux
|
||||
@@ -19,6 +20,7 @@ save=Enregistrer
|
||||
close=Fermer
|
||||
filesSelected=fichiers sélectionnés
|
||||
noFavourites=Aucun favori ajouté
|
||||
downloadComplete=Téléchargement terminé
|
||||
bored=Ennuyé d\u2019attendre\u00a0?
|
||||
alphabet=Alphabet
|
||||
downloadPdf=Télécharger le PDF
|
||||
@@ -42,10 +44,10 @@ red=Rouge
|
||||
green=Vert
|
||||
blue=Bleu
|
||||
custom=Personnalisé\u2026
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
poweredBy=Powered by
|
||||
yes=Yes
|
||||
no=No
|
||||
WorkInProgess=En cours de développement, merci de nous remonter les problèmes que vous pourriez constater!
|
||||
poweredBy=Propulsé par
|
||||
yes=Oui
|
||||
no=Non
|
||||
changedCredsMessage=Les identifiants ont été mis à jour\u00a0!
|
||||
notAuthenticatedMessage=Utilisateur non authentifié.
|
||||
userNotFoundMessage=Utilisateur non trouvé.
|
||||
@@ -56,24 +58,24 @@ usernameExistsMessage=Le nouveau nom d\u2019utilisateur existe déjà.
|
||||
###############
|
||||
# Pipeline #
|
||||
###############
|
||||
pipeline.header=Pipeline Menu (Alpha)
|
||||
pipeline.uploadButton=Upload Custom
|
||||
pipeline.configureButton=Configure
|
||||
pipeline.defaultOption=Custom
|
||||
pipeline.submitButton=Submit
|
||||
pipeline.header=Menu Pipeline (Alpha)
|
||||
pipeline.uploadButton=Télécharger une personnalisation
|
||||
pipeline.configureButton=Configurer
|
||||
pipeline.defaultOption=Personnaliser
|
||||
pipeline.submitButton=Soumettre
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
######################
|
||||
pipelineOptions.header=Pipeline Configuration
|
||||
pipelineOptions.pipelineNameLabel=Pipeline Name
|
||||
pipelineOptions.saveSettings=Save Operation Settings
|
||||
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
|
||||
pipelineOptions.selectOperation=Select Operation
|
||||
pipelineOptions.addOperationButton=Add operation
|
||||
pipelineOptions.header=Configuration du pipeline
|
||||
pipelineOptions.pipelineNameLabel=Nom du pipeline
|
||||
pipelineOptions.saveSettings=Sauvegarder la configuration
|
||||
pipelineOptions.pipelineNamePrompt=Entrez ici le nom du pipeline
|
||||
pipelineOptions.selectOperation=Sélectionner une opération
|
||||
pipelineOptions.addOperationButton=Ajouter une opération
|
||||
pipelineOptions.pipelineHeader=Pipeline:
|
||||
pipelineOptions.saveButton=Download
|
||||
pipelineOptions.validateButton=Validate
|
||||
pipelineOptions.saveButton=Télécharger
|
||||
pipelineOptions.validateButton=Valider
|
||||
|
||||
|
||||
|
||||
@@ -120,7 +122,7 @@ account.accountSettings=Paramètres du compte
|
||||
account.adminSettings=Paramètres d\u2019administration \u2013 Voir et ajouter des utilisateurs
|
||||
account.userControlSettings=Contrôle des paramètres des utilisateurs
|
||||
account.changeUsername=Modifier le nom d\u2019utilisateur
|
||||
account.changeUsername=Modifier le nom d\u2019utilisateur
|
||||
account.newUsername=Nouveau nom d\u2019utilisateur
|
||||
account.password=Mot de passe de confirmation
|
||||
account.oldPassword=Ancien mot de passe
|
||||
account.newPassword=Nouveau mot de passe
|
||||
@@ -146,7 +148,7 @@ adminUserSettings.role=Rôle
|
||||
adminUserSettings.actions=Actions
|
||||
adminUserSettings.apiUser=Utilisateur API limité
|
||||
adminUserSettings.webOnlyUser=Utilisateur Web uniquement
|
||||
adminUserSettings.demoUser=Demo User (No custom settings)
|
||||
adminUserSettings.demoUser=Demo User (Paramètres par défaut)
|
||||
adminUserSettings.forceChange=Forcer l\u2019utilisateur à changer son nom d\u2019utilisateur/mot de passe lors de la connexion
|
||||
adminUserSettings.submit=Ajouter
|
||||
|
||||
@@ -158,7 +160,7 @@ home.searchBar=Rechercher des fonctionnalités...
|
||||
|
||||
|
||||
home.viewPdf.title=Visionner le PDF
|
||||
home.viewPdf.desc=Visionner, annoter, ajouter du texte ou des images
|
||||
home.viewPdf.desc=Visionner, annoter, ajouter du texte ou des images.
|
||||
viewPdf.tags=visualiser,lire,annoter,texte,image
|
||||
|
||||
home.multiTool.title=Outil multifonction PDF
|
||||
@@ -167,7 +169,7 @@ multiTool.tags=outil multifonction,opération multifonction,interface utilisateu
|
||||
|
||||
home.merge.title=Fusionner
|
||||
home.merge.desc=Fusionnez facilement plusieurs PDF en un seul.
|
||||
merge.tags=fusionner,opérations sur les pages,backeend,server side,merge
|
||||
merge.tags=fusionner,opérations sur les pages,backend,server side,merge
|
||||
|
||||
home.split.title=Diviser
|
||||
home.split.desc=Divisez un PDF en plusieurs documents.
|
||||
@@ -283,9 +285,9 @@ home.removeBlanks.title=Supprimer les pages vierges
|
||||
home.removeBlanks.desc=Détectez et supprimez les pages vierges d\u2019un PDF.
|
||||
removeBlanks.tags=pages vierges,supprimer,nettoyer,cleanup,streamline,non-content,organize
|
||||
|
||||
home.removeAnnotations.title=Remove Annotations
|
||||
home.removeAnnotations.desc=Removes all comments/annotations from a PDF
|
||||
removeAnnotations.tags=comments,highlight,notes,markup,remove
|
||||
home.removeAnnotations.title=Supprimer les annotations
|
||||
home.removeAnnotations.desc=Supprimer tous les commentaires/annotations d\u2019un PDF.
|
||||
removeAnnotations.tags=commentaires,supprimer,annotations,highlight,notes,markup,remove
|
||||
|
||||
home.compare.title=Comparer
|
||||
home.compare.desc=Comparez et visualisez les différences entre deux PDF.
|
||||
@@ -362,14 +364,14 @@ PdfToSinglePage.tags=fusionner,merge,une seule page,single page
|
||||
|
||||
home.showJS.title=Afficher le JavaScript
|
||||
home.showJS.desc=Recherche et affiche tout JavaScript injecté dans un PDF.
|
||||
showJS.tags=caviarder,redact,auto
|
||||
showJS.tags=JS
|
||||
|
||||
home.autoRedact.title=Caviarder automatiquement
|
||||
home.autoRedact.desc=Caviardez automatiquement les informations sensibles d\u2019un PDF.
|
||||
showJS.tags=caviarder,redact,auto
|
||||
autoRedact.tags=caviarder,redact,auto
|
||||
|
||||
home.tableExtraxt.title=PDF en CSV
|
||||
home.tableExtraxt.desc=Extrait les tableaux d\u2019un PDF et les transforme en CSV
|
||||
home.tableExtraxt.desc=Extrait les tableaux d\u2019un PDF et les transforme en CSV.
|
||||
tableExtraxt.tags=CSV,Table Extraction,extract,convert
|
||||
|
||||
|
||||
@@ -379,16 +381,16 @@ autoSizeSplitPDF.tags=pdf,split,document,organization
|
||||
|
||||
|
||||
home.overlay-pdfs.title=Incrustation de PDF
|
||||
home.overlay-pdfs.desc=Incrustation d\u2019un PDF sur un autre PDF
|
||||
overlay-pdfs.tags=Overlay
|
||||
home.overlay-pdfs.desc=Incrustation d\u2019un PDF sur un autre PDF.
|
||||
overlay-pdfs.tags=Overlay,incrustation
|
||||
|
||||
home.split-by-sections.title=Split PDF by Sections
|
||||
home.split-by-sections.desc=Divide each page of a PDF into smaller horizontal and vertical sections
|
||||
split-by-sections.tags=Section Split, Divide, Customize
|
||||
home.split-by-sections.title=Séparer un PDF en sections
|
||||
home.split-by-sections.desc=Diviser chaque page d\u2019un PDF en sections horizontales/verticales plus petites.
|
||||
split-by-sections.tags=Sections,Diviser,Section Split, Divide, Customize
|
||||
|
||||
home.AddStampRequest.title=Add Stamp to PDF
|
||||
home.AddStampRequest.desc=Add text or add image stamps at set locations
|
||||
AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize
|
||||
home.AddStampRequest.title=Ajouter un tampon sur un PDF
|
||||
home.AddStampRequest.desc=Ajouter un texte ou l\u2019image d\u2019un tampon à un emplacement défini.
|
||||
AddStampRequest.tags=Tampon,Ajouter,Stamp,Add image,center image,Watermark,PDF,Embed,Customize
|
||||
|
||||
|
||||
###########################
|
||||
@@ -410,7 +412,7 @@ autoRedact.title=Caviarder automatiquement
|
||||
autoRedact.header=Caviarder automatiquement
|
||||
autoRedact.colorLabel=Couleur
|
||||
autoRedact.textsToRedactLabel=Texte à caviarder (séparé par des lignes)
|
||||
autoRedact.textsToRedactPlaceholder=ex. \nConfidentiel \nTop secret
|
||||
autoRedact.textsToRedactPlaceholder=ex. \nConfidentiel \nTop secret
|
||||
autoRedact.useRegexLabel=Utiliser une Regex
|
||||
autoRedact.wholeWordSearchLabel=Recherche de mots entiers
|
||||
autoRedact.customPaddingLabel=Marge intérieure supplémentaire
|
||||
@@ -466,37 +468,38 @@ HTMLToPDF.header=HTML en PDF
|
||||
HTMLToPDF.help=Accepte les fichiers HTML et les ZIP contenant du HTML, du CSS, des images, etc. (requis).
|
||||
HTMLToPDF.submit=Convertir
|
||||
HTMLToPDF.credit=Utilise WeasyPrint.
|
||||
HTMLToPDF.zoom=Zoom level for displaying the website.
|
||||
HTMLToPDF.pageWidth=Width of the page in centimeters. (Blank to default)
|
||||
HTMLToPDF.pageHeight=Height of the page in centimeters. (Blank to default)
|
||||
HTMLToPDF.marginTop=Top margin of the page in millimeters. (Blank to default)
|
||||
HTMLToPDF.marginBottom=Bottom margin of the page in millimeters. (Blank to default)
|
||||
HTMLToPDF.marginLeft=Left margin of the page in millimeters. (Blank to default)
|
||||
HTMLToPDF.marginRight=Right margin of the page in millimeters. (Blank to default)
|
||||
HTMLToPDF.printBackground=Render the background of websites.
|
||||
HTMLToPDF.defaultHeader=Enable Default Header (Name and page number)
|
||||
HTMLToPDF.cssMediaType=Change the CSS media type of the page.
|
||||
HTMLToPDF.none=None
|
||||
HTMLToPDF.print=Print
|
||||
HTMLToPDF.screen=Screen
|
||||
HTMLToPDF.zoom=Niveau de zoom pour l\u2019affichage du site web.
|
||||
HTMLToPDF.pageWidth=Largeur de la page en centimètres. (Vide par défaut)
|
||||
HTMLToPDF.pageHeight=Hauteur de la page en centimètres. (Vide par défaut)
|
||||
HTMLToPDF.marginTop=Marge supérieure de la page en millimètres. (Vide par défaut)
|
||||
HTMLToPDF.marginBottom=Marge inférieure de la page en millimètres. (Vide par défaut)
|
||||
HTMLToPDF.marginLeft=Marge gauche de la page en millimètres. (Vide par défaut)
|
||||
HTMLToPDF.marginRight=Marge droite de la page en millimètres. (Vide par défaut)
|
||||
HTMLToPDF.printBackground=Restituer l\u2019image de fond des sites web.
|
||||
HTMLToPDF.defaultHeader=Activer l\u2019entête par défaut (Nom et numéro de page)
|
||||
HTMLToPDF.cssMediaType=Modifier le type de média CSS de la page.
|
||||
HTMLToPDF.none=Aucun
|
||||
HTMLToPDF.print=Imprimer
|
||||
HTMLToPDF.screen=Écran
|
||||
|
||||
|
||||
#AddStampRequest
|
||||
AddStampRequest.header=Stamp PDF
|
||||
AddStampRequest.title=Stamp PDF
|
||||
AddStampRequest.stampType=Stamp Type
|
||||
AddStampRequest.stampText=Stamp Text
|
||||
AddStampRequest.stampImage=Stamp Image
|
||||
AddStampRequest.header=Tampon PDF
|
||||
AddStampRequest.title=Tampon PDF
|
||||
AddStampRequest.stampType=Type de tampon
|
||||
AddStampRequest.stampText=Tampon texte
|
||||
AddStampRequest.stampImage=Tampon image
|
||||
AddStampRequest.alphabet=Alphabet
|
||||
AddStampRequest.fontSize=Font/Image Size
|
||||
AddStampRequest.fontSize=Taille de fonte/image
|
||||
AddStampRequest.rotation=Rotation
|
||||
AddStampRequest.opacity=Opacity
|
||||
AddStampRequest.opacity=Opacité
|
||||
AddStampRequest.position=Position
|
||||
AddStampRequest.overrideX=Override X Coordinate
|
||||
AddStampRequest.overrideY=Override Y Coordinate
|
||||
AddStampRequest.customMargin=Custom Margin
|
||||
AddStampRequest.customColor=Custom Text Color
|
||||
AddStampRequest.submit=Submit
|
||||
AddStampRequest.overrideX=Définir coordonnées X
|
||||
AddStampRequest.overrideY=Définir coordonnées Y
|
||||
AddStampRequest.customMargin=Marge personnalisée
|
||||
AddStampRequest.customColor=Couleur de texte personnalisée
|
||||
AddStampRequest.submit=Soumettre
|
||||
|
||||
|
||||
#sanitizePDF
|
||||
sanitizePDF.title=Assainir
|
||||
@@ -584,11 +587,11 @@ scalePages.submit=Ajuster
|
||||
certSign.title=Signer avec un certificat
|
||||
certSign.header=Signer avec un certificat (Travail en cours)
|
||||
certSign.selectPDF=PDF à signer
|
||||
certSign.jksNote=Note: If your certificate type is not listed below, please convert it to a Java Keystore (.jks) file using the keytool command line tool. Then, choose the .jks file option below.
|
||||
certSign.jksNote=Note: Si votre type de certificat n\u2019est pas listé ci\u002Ddessous, merci de le convertir en fichier Java Keystore (.jks) en utilisant l\u2019outil en ligne de commande keytool. Puis choisissez l\u2019option Fichier .jks ci\u002Ddessous.
|
||||
certSign.selectKey=Fichier de clé privée (format PKCS#8, peut être .pem ou .der)
|
||||
certSign.selectCert=Fichier de certificat (format X.509, peut être .pem ou .der)
|
||||
certSign.selectP12=Fichier keystore de clés PKCS#12 (.p12 ou .pfx) (facultatif, s\u2019il n\u2019est fourni, il doit contenir votre clé privée et votre certificat)
|
||||
certSign.selectJKS=Select Your Java Keystore File (.jks or .keystore):
|
||||
certSign.selectJKS=Sélectionner votre fichier Java Keystore File (.jks or .keystore):
|
||||
certSign.certType=Type de certificat
|
||||
certSign.password=Mot de passe keystore ou clé privée le cas échéant
|
||||
certSign.showSig=Afficher la signature
|
||||
@@ -609,9 +612,9 @@ removeBlanks.submit=Supprimer les pages vierges
|
||||
|
||||
|
||||
#removeAnnotations
|
||||
removeAnnotations.title=Remove Annotations
|
||||
removeAnnotations.header=Remove Annotations
|
||||
removeAnnotations.submit=Remove
|
||||
removeAnnotations.title=Supprimer les annotations
|
||||
removeAnnotations.header=Supprimer les annotations
|
||||
removeAnnotations.submit=Supprimer
|
||||
|
||||
|
||||
#compare
|
||||
@@ -693,14 +696,14 @@ fileToPDF.submit=Convertir
|
||||
|
||||
|
||||
#compress
|
||||
compress.title=Compresser
|
||||
compress.header=Compresser
|
||||
compress.title=Compresser un PDF
|
||||
compress.header=Compresser un PDF (lorsque c\u2019est possible!)
|
||||
compress.credit=Ce service utilise Ghostscript pour la compression et l\u2019optimisation des PDF.
|
||||
compress.selectText.1=Mode manuel \u2013 de 1 à 4
|
||||
compress.selectText.2=Niveau d\u2019optimisation
|
||||
compress.selectText.3=4 (terrible pour les images textuelles)
|
||||
compress.selectText.4=Mode automatique \u2013 ajuste automatiquement la qualité pour obtenir le PDF à la taille exacte
|
||||
compress.selectText.5=Taille PDF attendue (par exemple, 25\u202fMo, 10,8\u202fMo, 25\u202fKo)
|
||||
compress.selectText.5=Taille PDF attendue (par exemple, 25\u202fMB, 10,8\u202fMB, 25\u202fKB)
|
||||
compress.submit=Compresser
|
||||
|
||||
|
||||
@@ -731,8 +734,8 @@ multiTool.title=Outil multifonction PDF
|
||||
multiTool.header=Outil multifonction PDF
|
||||
|
||||
#view pdf
|
||||
viewPdf.title=View PDF
|
||||
viewPdf.header=View PDF
|
||||
viewPdf.title=Visualiser un PDF
|
||||
viewPdf.header=Visualiser un PDF
|
||||
|
||||
#pageRemover
|
||||
pageRemover.title=Supprimer des pages
|
||||
@@ -787,7 +790,7 @@ pdfToImage.multi=Plusieurs images
|
||||
pdfToImage.colorType=Type d\u2019impression
|
||||
pdfToImage.color=Couleur
|
||||
pdfToImage.grey=Niveaux de gris
|
||||
pdfToImage.blackwhite=Noir et blanc (peut engendre une perde de données\u00a0!)
|
||||
pdfToImage.blackwhite=Noir et blanc (peut engendrer une perte de données\u00a0!)
|
||||
pdfToImage.submit=Convertir
|
||||
|
||||
|
||||
@@ -866,8 +869,7 @@ changeMetadata.keywords=Mots clés
|
||||
changeMetadata.modDate=Date de modification (yyyy/MM/dd HH:mm:ss)
|
||||
changeMetadata.producer=Producteur
|
||||
changeMetadata.subject=Sujet
|
||||
changeMetadata.title=Titre
|
||||
changeMetadata.trapped=Défoncé (technique d’impression)
|
||||
changeMetadata.trapped=Recouvrement (technique d’impression)
|
||||
changeMetadata.selectText.4=Autres métadonnées
|
||||
changeMetadata.selectText.5=Ajouter une entrée de métadonnées personnalisée
|
||||
changeMetadata.submit=Modifier
|
||||
@@ -935,19 +937,19 @@ split-by-size-or-count.submit=Séparer
|
||||
|
||||
|
||||
#overlay-pdfs
|
||||
overlay-pdfs.header=Overlay PDF Files
|
||||
overlay-pdfs.header=Incrustation de PDF
|
||||
overlay-pdfs.baseFile.label=Sélectionner le fichier PDF de base
|
||||
overlay-pdfs.overlayFiles.label=Sélectionner les fichiers PDF à superposer
|
||||
overlay-pdfs.mode.label=Select Overlay Mode
|
||||
overlay-pdfs.mode.sequential=Sequential Overlay
|
||||
overlay-pdfs.mode.interleaved=Interleaved Overlay
|
||||
overlay-pdfs.mode.label=Sélectionner le mode d\u2019incrustation
|
||||
overlay-pdfs.mode.sequential=Superposition séquentielle
|
||||
overlay-pdfs.mode.interleaved=Superposition entrelacée
|
||||
overlay-pdfs.mode.fixedRepeat=Superposition à répétition fixe
|
||||
overlay-pdfs.counts.label=Nombre de superpositions (pour le mode de répétition fixe)
|
||||
overlay-pdfs.counts.placeholder=Enter comma-separated counts (e.g., 2,3,1)
|
||||
overlay-pdfs.position.label=Select Overlay Position
|
||||
overlay-pdfs.counts.placeholder=Compteurs (séparés par des virgules, exemple : 2,3,1)
|
||||
overlay-pdfs.position.label=Définir la position de l\u2019incrustation
|
||||
overlay-pdfs.position.foreground=Premier plan
|
||||
overlay-pdfs.position.background=Arrière-plan
|
||||
overlay-pdfs.submit=Submit
|
||||
overlay-pdfs.submit=Soumettre
|
||||
|
||||
|
||||
#split-by-sections
|
||||
@@ -961,11 +963,11 @@ split-by-sections.submit=Diviser le PDF
|
||||
|
||||
|
||||
#licenses
|
||||
licenses.nav=Licenses
|
||||
licenses.title=3rd Party Licenses
|
||||
licenses.header=3rd Party Licenses
|
||||
licenses.nav=Licences
|
||||
licenses.title=Licences tierces
|
||||
licenses.header=Licences tierces
|
||||
licenses.module=Module
|
||||
licenses.version=Version
|
||||
licenses.license=License
|
||||
licenses.license=Licence
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -11,6 +11,7 @@ imgPrompt=छवियों का चयन करें
|
||||
genericSubmit=प्रस्तुत करें
|
||||
processTimeWarning=चेतावनी: यह प्रक्रिया फ़ाइल के आकार पर निर्भर करती है और यह से एक मिनट तक लग सकती है
|
||||
pageOrderPrompt=कस्टम पेज क्रम (पेज नंबरों या 2n+1 जैसे कार्यों की एक कॉमा से अलग-अलग सूची दर्ज करें):
|
||||
pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :
|
||||
goToPage=जाएँ
|
||||
true=सही
|
||||
false=गलत
|
||||
@@ -19,6 +20,7 @@ save=सहेजें
|
||||
close=बंद करें
|
||||
filesSelected=फ़ाइलें चयनित हैं
|
||||
noFavourites=कोई पसंदीदा जोड़ा नहीं गया है
|
||||
downloadComplete=Download Complete
|
||||
bored=बोर हो रहे हैं?
|
||||
alphabet=वर्णमाला
|
||||
downloadPdf=पीडीएफ़ डाउनलोड करें
|
||||
@@ -42,7 +44,7 @@ red=लाल
|
||||
green=हरा
|
||||
blue=नीला
|
||||
custom=कस्टम...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any problems!
|
||||
poweredBy=Powered by
|
||||
yes=Yes
|
||||
no=No
|
||||
@@ -120,7 +122,7 @@ account.accountSettings=खाता सेटिंग्स
|
||||
account.adminSettings=व्यवस्थापक सेटिंग्स - उपयोगकर्ताओं को देखें और जोड़ें
|
||||
account.userControlSettings=उपयोगकर्ता नियंत्रण सेटिंग्स
|
||||
account.changeUsername=उपयोगकर्ता नाम परिवर्तन करें
|
||||
account.changeUsername=उपयोगकर्ता नाम परिवर्तन करें
|
||||
account.newUsername=नया उपयोगकर्ता नाम
|
||||
account.password=पासवर्ड पुष्टि
|
||||
account.oldPassword=पुराना पासवर्ड
|
||||
account.newPassword=नया पासवर्ड
|
||||
@@ -362,11 +364,11 @@ PdfToSinglePage.tags=एकल पृष्ठ
|
||||
|
||||
home.showJS.title=जावास्क्रिप्ट दिखाएं
|
||||
home.showJS.desc=पीडीएफ़ में डाला गया कोई भी जावास्क्रिप्ट खोजता है और प्रदर्शित करता है
|
||||
showJS.tags=गोपनीयकरण, छिपाना, काला करना, काला, मार्कर, छिपा हुआ
|
||||
showJS.tags=जे एस
|
||||
|
||||
home.autoRedact.title=स्वतः गोपनीयकरण
|
||||
home.autoRedact.desc=प्रविष्ट पाठ के आधार पर पीडीएफ़ में पाठ को स्वतः गोपनीयकरित(काला करें)
|
||||
showJS.tags=गोपनीयकरण, छिपाना, काला करना, काला, मार्कर, छिपा हुआ
|
||||
autoRedact.tags=गोपनीयकरण, छिपाना, काला करना, काला, मार्कर, छिपा हुआ
|
||||
|
||||
home.tableExtraxt.title=PDF से CSV में
|
||||
home.tableExtraxt.desc=CSV में बदलते हुए पीडीएफ़ से तालिकाएँ निकालता है
|
||||
@@ -498,6 +500,7 @@ AddStampRequest.customMargin=Custom Margin
|
||||
AddStampRequest.customColor=Custom Text Color
|
||||
AddStampRequest.submit=Submit
|
||||
|
||||
|
||||
#sanitizePDF
|
||||
sanitizePDF.title=पीडीएफ़ को सफाई करें
|
||||
sanitizePDF.header=एक पीडीएफ़ फ़ाइल को सफाई करें
|
||||
@@ -866,7 +869,6 @@ changeMetadata.keywords=कीवर्ड्स:
|
||||
changeMetadata.modDate=संशोधन तिथि (yyyy/MM/dd HH:mm:ss):
|
||||
changeMetadata.producer=निर्माता:
|
||||
changeMetadata.subject=विषय:
|
||||
changeMetadata.title=शीर्षक:
|
||||
changeMetadata.trapped=फंसा हुआ:
|
||||
changeMetadata.selectText.4=अन्य मेटाडेटा:
|
||||
changeMetadata.selectText.5=कस्टम मेटाडेटा एंट्री जोड़ें
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -11,6 +11,7 @@ imgPrompt=Válasszon képeket
|
||||
genericSubmit=Beküldés
|
||||
processTimeWarning=Figyelmeztetés: Ez a folyamat akár egy percig is eltarthat a fájlmérettől függően
|
||||
pageOrderPrompt=Egyedi oldalsorrend (Adjon meg vesszővel elválasztott oldalszámokat vagy függvényeket, például 2n+1):
|
||||
pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :
|
||||
goToPage=Ugrás
|
||||
true=Igaz
|
||||
false=Hamis
|
||||
@@ -19,6 +20,7 @@ save=Mentés
|
||||
close=Bezárás
|
||||
filesSelected=kiválasztott fájlok
|
||||
noFavourites=Nincs hozzáadva kedvenc
|
||||
downloadComplete=Download Complete
|
||||
bored=Unatkozol?
|
||||
alphabet=Ábécé
|
||||
downloadPdf=PDF letöltése
|
||||
@@ -42,7 +44,7 @@ red=Piros
|
||||
green=Zöld
|
||||
blue=Kék
|
||||
custom=Egyedi...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any problems!
|
||||
poweredBy=Powered by
|
||||
yes=Yes
|
||||
no=No
|
||||
@@ -119,8 +121,8 @@ account.title=Fiókbeállítások
|
||||
account.accountSettings=Fiókbeállítások
|
||||
account.adminSettings=Admin Beállítások - Felhasználók megtekintése és hozzáadása
|
||||
account.userControlSettings=Felhasználói vezérlési beállítások
|
||||
account.changeUsername=Új felhasználónév
|
||||
account.changeUsername=Új felhasználónév
|
||||
account.changeUsername=Felhasználónév módosítása
|
||||
account.newUsername=Új felhasználónév
|
||||
account.password=Megerősítő jelszó
|
||||
account.oldPassword=Régi jelszó
|
||||
account.newPassword=Új jelszó
|
||||
@@ -362,11 +364,11 @@ PdfToSinglePage.tags=egyetlen lap
|
||||
|
||||
home.showJS.title=JavaScript megjelenítése
|
||||
home.showJS.desc=Keres és megjelenít bármilyen JS-t, amit beinjektáltak a PDF-be
|
||||
showJS.tags=Elrejt,Elrejtés,kitakarás,fekete,fekete,marker,elrejtett
|
||||
showJS.tags=JS
|
||||
|
||||
home.autoRedact.title=Automatikus Elrejtés
|
||||
home.autoRedact.desc=Automatikusan kitakar (elrejt) szöveget egy PDF-ben az input szöveg alapján
|
||||
showJS.tags=Elrejt,Elrejtés,kitakarás,fekete,fekete,marker,elrejtett
|
||||
autoRedact.tags=Elrejt,Elrejtés,kitakarás,fekete,fekete,marker,elrejtett
|
||||
|
||||
home.tableExtraxt.title=PDF to CSV
|
||||
home.tableExtraxt.desc=Táblázatok kinyerése a PDF-ből CSV formátumra konvertálva
|
||||
@@ -410,7 +412,7 @@ autoRedact.title=Érzékeny tartalom eltávolítása
|
||||
autoRedact.header=Érzékeny tartalom eltávolítása
|
||||
autoRedact.colorLabel=Szín
|
||||
autoRedact.textsToRedactLabel=Kivonand szövegek (sorokra bontva)
|
||||
autoRedact.textsToRedactPlaceholder=például \nBizalmas \nLegfelsőbb Titok
|
||||
autoRedact.textsToRedactPlaceholder=például \nBizalmas \nLegfelsőbb Titok
|
||||
autoRedact.useRegexLabel=Reguláris kifejezés használata
|
||||
autoRedact.wholeWordSearchLabel=Teljes szó keresése
|
||||
autoRedact.customPaddingLabel=Egyedi extra kitöltés
|
||||
@@ -498,6 +500,7 @@ AddStampRequest.customMargin=Custom Margin
|
||||
AddStampRequest.customColor=Custom Text Color
|
||||
AddStampRequest.submit=Submit
|
||||
|
||||
|
||||
#sanitizePDF
|
||||
sanitizePDF.title=PDF tisztítása
|
||||
sanitizePDF.header=PDF fájl megtisztítása
|
||||
@@ -866,7 +869,6 @@ changeMetadata.keywords=Kulcsszavak:
|
||||
changeMetadata.modDate=Módosítás dátuma (éééé/hh/nn ÓÓ:PP:MM):
|
||||
changeMetadata.producer=Készítő:
|
||||
changeMetadata.subject=Tárgy:
|
||||
changeMetadata.title=Cím:
|
||||
changeMetadata.trapped=Trapped:
|
||||
changeMetadata.selectText.4=Egyéb metaadatok:
|
||||
changeMetadata.selectText.5=Egyedi metaadatbejegyzés hozzáadása
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl=right to left)
|
||||
@@ -11,6 +11,7 @@ imgPrompt=Pilih Gambar
|
||||
genericSubmit=Kirim
|
||||
processTimeWarning=Peringatan: Proses ini dapat memakan waktu hingga satu menit, tergantung pada ukuran berkas
|
||||
pageOrderPrompt=Urutan Halaman Khusus (Masukkan daftar nomor halaman yang dipisahkan dengan koma atau Fungsi seperti 2n + 1) :
|
||||
pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :
|
||||
goToPage=Ke
|
||||
true=Benar
|
||||
false=Salah
|
||||
@@ -19,6 +20,7 @@ save=Simpan
|
||||
close=Tutup
|
||||
filesSelected=berkas dipilih
|
||||
noFavourites=Tidak ada favorit yang ditambahkan
|
||||
downloadComplete=Download Complete
|
||||
bored=Bosan Menunggu?
|
||||
alphabet=Abjad
|
||||
downloadPdf=Unduh PDF
|
||||
@@ -42,7 +44,7 @@ red=Merah
|
||||
green=Hijau
|
||||
blue=Biru
|
||||
custom=Kustom...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any problems!
|
||||
poweredBy=Powered by
|
||||
yes=Yes
|
||||
no=No
|
||||
@@ -120,7 +122,7 @@ account.accountSettings=Pengaturan Akun
|
||||
account.adminSettings=Pengaturan Admin - Melihat dan Menambahkan Pengguna
|
||||
account.userControlSettings=Pengaturan Kontrol Pengguna
|
||||
account.changeUsername=Ubah Nama Pengguna
|
||||
account.changeUsername=Ubah Nama Pengguna
|
||||
account.newUsername=Nama pengguna baru
|
||||
account.password=Konfirmasi Kata sandi
|
||||
account.oldPassword=Kata sandi lama
|
||||
account.newPassword=Kata Sandi Baru
|
||||
@@ -362,11 +364,11 @@ PdfToSinglePage.tags=halaman tunggal
|
||||
|
||||
home.showJS.title=Tampilkan Javascript
|
||||
home.showJS.desc=Mencari dan menampilkan JS apa pun yang disuntikkan ke dalam PDF
|
||||
showJS.tags=Hapus, Sembunyikan, padamkan, hitam, hitam, penanda, tersembunyi
|
||||
showJS.tags=JS
|
||||
|
||||
home.autoRedact.title=Redaksional Otomatis
|
||||
home.autoRedact.desc=Menyunting Otomatis (Menghitamkan) teks dalam PDF berdasarkan teks masukan
|
||||
showJS.tags=Hapus, Sembunyikan, padamkan, hitam, hitam, penanda, tersembunyi
|
||||
autoRedact.tags=Hapus, Sembunyikan, padamkan, hitam, hitam, penanda, tersembunyi
|
||||
|
||||
home.tableExtraxt.title=PDF ke CSV
|
||||
home.tableExtraxt.desc=Mengekstrak Tabel dari PDF yang mengonversinya menjadi CSV
|
||||
@@ -498,6 +500,7 @@ AddStampRequest.customMargin=Custom Margin
|
||||
AddStampRequest.customColor=Custom Text Color
|
||||
AddStampRequest.submit=Submit
|
||||
|
||||
|
||||
#sanitizePDF
|
||||
sanitizePDF.title=Bersihkan PDF
|
||||
sanitizePDF.header=Membersihkan berkas PDF
|
||||
@@ -866,7 +869,6 @@ changeMetadata.keywords=Kata kunci:
|
||||
changeMetadata.modDate=Tangal Diupdate (yyyy/MM/dd HH:mm:ss):
|
||||
changeMetadata.producer=Produser:
|
||||
changeMetadata.subject=Subjek:
|
||||
changeMetadata.title=Judul:
|
||||
changeMetadata.trapped=Terperangkap:
|
||||
changeMetadata.selectText.4=Metadata Lain-lain:
|
||||
changeMetadata.selectText.5=Tambahkan Metadata Khusus
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -11,6 +11,7 @@ imgPrompt=Scegli immagine/i
|
||||
genericSubmit=Invia
|
||||
processTimeWarning=Nota: Questo processo potrebbe richiedere fino a un minuto in base alla dimensione dei file
|
||||
pageOrderPrompt=Ordine delle pagine (inserisci una lista di numeri separati da virgola):
|
||||
pageSelectionPrompt=Selezione pagina personalizzata (inserisci un elenco separato da virgole di numeri di pagina 1,5,6 o funzioni come 2n+1) :
|
||||
goToPage=Vai
|
||||
true=Vero
|
||||
false=Falso
|
||||
@@ -19,6 +20,7 @@ save=Salva
|
||||
close=Chiudi
|
||||
filesSelected=file selezionati
|
||||
noFavourites=Nessun preferito
|
||||
downloadComplete=Download Complete
|
||||
bored=Stanco di aspettare?
|
||||
alphabet=Alfabeto
|
||||
downloadPdf=Scarica PDF
|
||||
@@ -119,8 +121,8 @@ account.title=Impostazioni Account
|
||||
account.accountSettings=Impostazioni Account
|
||||
account.adminSettings=Impostazioni Admin - Aggiungi e Vedi Utenti
|
||||
account.userControlSettings=Impostazioni Utente
|
||||
account.changeUsername=Cambia Username
|
||||
account.changeUsername=Cambia Username
|
||||
account.changeUsername=Cambia nome utente
|
||||
account.newUsername=Nuovo nome utente
|
||||
account.password=Conferma Password
|
||||
account.oldPassword=Vecchia Password
|
||||
account.newPassword=Nuova Password
|
||||
@@ -366,7 +368,7 @@ showJS.tags=JS
|
||||
|
||||
home.autoRedact.title=Redazione automatica
|
||||
home.autoRedact.desc=Redige automaticamente (oscura) il testo in un PDF in base al testo immesso
|
||||
showJS.tags=JS
|
||||
autoRedact.tags=Redact,Hide,black out,black,marker,hidden
|
||||
|
||||
home.tableExtraxt.title=Da PDF a CSV
|
||||
home.tableExtraxt.desc=Estrae tabelle da un PDF convertendolo in CSV
|
||||
@@ -498,6 +500,7 @@ AddStampRequest.customMargin=Margine personalizzato
|
||||
AddStampRequest.customColor=Colore testo personalizzato
|
||||
AddStampRequest.submit=Invia
|
||||
|
||||
|
||||
#sanitizePDF
|
||||
sanitizePDF.title=Pulire PDF
|
||||
sanitizePDF.header=Pulisci un file PDF
|
||||
@@ -866,7 +869,6 @@ changeMetadata.keywords=Parole chiave:
|
||||
changeMetadata.modDate=Data di modifica (yyyy/MM/dd HH:mm:ss):
|
||||
changeMetadata.producer=Produttore:
|
||||
changeMetadata.subject=Oggetto:
|
||||
changeMetadata.title=Titolo:
|
||||
changeMetadata.trapped=Trapped:
|
||||
changeMetadata.selectText.4=Altre proprietà:
|
||||
changeMetadata.selectText.5=Aggiungi proprietà personalizzata:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -11,6 +11,7 @@ imgPrompt=画像を選択
|
||||
genericSubmit=送信
|
||||
processTimeWarning=警告:この処理はファイルサイズによって1分程度かかることがあります
|
||||
pageOrderPrompt=ページ順序 (ページ番号をカンマ区切り又は2n+1のような関数で入力):
|
||||
pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :
|
||||
goToPage=移動
|
||||
true=True
|
||||
false=False
|
||||
@@ -19,6 +20,7 @@ save=保存
|
||||
close=閉じる
|
||||
filesSelected=選択されたファイル
|
||||
noFavourites=お気に入りはありません
|
||||
downloadComplete=Download Complete
|
||||
bored=待ち時間が退屈
|
||||
alphabet=\u30A2\u30EB\u30D5\u30A1\u30D9\u30C3\u30C8
|
||||
downloadPdf=PDFをダウンロード
|
||||
@@ -42,7 +44,7 @@ red=赤
|
||||
green=緑
|
||||
blue=青
|
||||
custom=カスタム...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any problems!
|
||||
poweredBy=Powered by
|
||||
yes=Yes
|
||||
no=No
|
||||
@@ -120,7 +122,7 @@ account.accountSettings=アカウント設定
|
||||
account.adminSettings=管理者設定 - ユーザーの表示と追加
|
||||
account.userControlSettings=ユーザー制御設定
|
||||
account.changeUsername=ユーザー名を変更
|
||||
account.changeUsername=ユーザー名を変更
|
||||
account.newUsername=新しいユーザーネーム
|
||||
account.password=確認用パスワード
|
||||
account.oldPassword=旧パスワード
|
||||
account.newPassword=新パスワード
|
||||
@@ -366,7 +368,7 @@ showJS.tags=JS
|
||||
|
||||
home.autoRedact.title=自動塗りつぶし
|
||||
home.autoRedact.desc=入力したテキストに基づいてPDF内のテキストを自動で塗りつぶし(黒塗り)します。
|
||||
showJS.tags=JS
|
||||
autoRedact.tags=Redact,Hide,black out,black,marker,hidden
|
||||
|
||||
home.tableExtraxt.title=PDFをCSVに変換
|
||||
home.tableExtraxt.desc=PDFから表を抽出しCSVに変換します。
|
||||
@@ -410,7 +412,7 @@ autoRedact.title=自動塗りつぶし
|
||||
autoRedact.header=自動塗りつぶし
|
||||
autoRedact.colorLabel=カラー
|
||||
autoRedact.textsToRedactLabel=編集するテキスト (line-separated)
|
||||
autoRedact.textsToRedactPlaceholder=例 \n機密 \n極秘
|
||||
autoRedact.textsToRedactPlaceholder=例 \n機密 \n極秘
|
||||
autoRedact.useRegexLabel=正規表現を使用する
|
||||
autoRedact.wholeWordSearchLabel=単語単位の検索
|
||||
autoRedact.customPaddingLabel=追加の余白
|
||||
@@ -498,6 +500,7 @@ AddStampRequest.customMargin=Custom Margin
|
||||
AddStampRequest.customColor=Custom Text Color
|
||||
AddStampRequest.submit=Submit
|
||||
|
||||
|
||||
#sanitizePDF
|
||||
sanitizePDF.title=PDFをサニタイズ
|
||||
sanitizePDF.header=PDFファイルをサニタイズ
|
||||
@@ -866,7 +869,6 @@ changeMetadata.keywords=キーワード:
|
||||
changeMetadata.modDate=変更日 (yyyy/MM/dd HH:mm:ss):
|
||||
changeMetadata.producer=プロデューサー:
|
||||
changeMetadata.subject=主題:
|
||||
changeMetadata.title=タイトル:
|
||||
changeMetadata.trapped=トラッピング:
|
||||
changeMetadata.selectText.4=その他のメタデータ:
|
||||
changeMetadata.selectText.5=カスタムメタデータの追加
|
||||
@@ -968,3 +970,4 @@ licenses.module=モジュール
|
||||
licenses.version=バージョン
|
||||
licenses.license=ライセンス
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -11,6 +11,7 @@ imgPrompt=이미지 선택
|
||||
genericSubmit=확인
|
||||
processTimeWarning=경고: 파일 크기에 따라 1분 정도 소요될 수 있습니다
|
||||
pageOrderPrompt=페이지 순서(쉼표로 구분된 페이지 번호 목록 입력):
|
||||
pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :
|
||||
goToPage=이동
|
||||
true=참
|
||||
false=거짓
|
||||
@@ -19,6 +20,7 @@ save=저장
|
||||
close=닫기
|
||||
filesSelected=개 파일 선택됨
|
||||
noFavourites=즐겨찾기 없음
|
||||
downloadComplete=Download Complete
|
||||
bored=기다리는 게 지루하신가요?
|
||||
alphabet=\uC54C\uD30C\uBCB3
|
||||
downloadPdf=PDF 다운로드
|
||||
@@ -42,7 +44,7 @@ red=Red
|
||||
green=Green
|
||||
blue=Blue
|
||||
custom=Custom...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any problems!
|
||||
poweredBy=Powered by
|
||||
yes=Yes
|
||||
no=No
|
||||
@@ -120,7 +122,7 @@ account.accountSettings=계정 설정
|
||||
account.adminSettings=관리자 설정 - 사용자 추가 및 확인
|
||||
account.userControlSettings=User Control Settings
|
||||
account.changeUsername=사용자명 변경
|
||||
account.changeUsername=사용자명 변경
|
||||
account.newUsername=새 사용자 이름
|
||||
account.password=Confirmation Password
|
||||
account.oldPassword=이전 비밀번호
|
||||
account.newPassword=새 비밀번호
|
||||
@@ -366,7 +368,7 @@ showJS.tags=JS
|
||||
|
||||
home.autoRedact.title=자동 검열
|
||||
home.autoRedact.desc=PDF 문서에서 입력된 텍스트들을 자동으로 검열(모자이크)합니다.
|
||||
showJS.tags=JS
|
||||
autoRedact.tags=Redact,Hide,black out,black,marker,hidden
|
||||
|
||||
home.tableExtraxt.title=PDF to CSV
|
||||
home.tableExtraxt.desc=Extracts Tables from a PDF converting it to CSV
|
||||
@@ -410,7 +412,7 @@ autoRedact.title=자동 검열
|
||||
autoRedact.header=자동 검열
|
||||
autoRedact.colorLabel=색상
|
||||
autoRedact.textsToRedactLabel=검열할 텍스트 (줄바꿈으로 구분)
|
||||
autoRedact.textsToRedactPlaceholder=예: \n비밀 \n일급 기밀
|
||||
autoRedact.textsToRedactPlaceholder=예: \n비밀 \n일급 기밀
|
||||
autoRedact.useRegexLabel=정규표현식 사용
|
||||
autoRedact.wholeWordSearchLabel=전체 단어 일치
|
||||
autoRedact.customPaddingLabel=추가 윤곽(패딩)
|
||||
@@ -498,6 +500,7 @@ AddStampRequest.customMargin=Custom Margin
|
||||
AddStampRequest.customColor=Custom Text Color
|
||||
AddStampRequest.submit=Submit
|
||||
|
||||
|
||||
#sanitizePDF
|
||||
sanitizePDF.title=PDF 정제
|
||||
sanitizePDF.header=PDF 문서 정제
|
||||
@@ -866,7 +869,6 @@ changeMetadata.keywords=키워드:
|
||||
changeMetadata.modDate=수정일 (yyyy/MM/dd HH:mm:ss):
|
||||
changeMetadata.producer=생성자:
|
||||
changeMetadata.subject=주제:
|
||||
changeMetadata.title=제목:
|
||||
changeMetadata.trapped=잠긴 상태:
|
||||
changeMetadata.selectText.4=기타 메타데이터:
|
||||
changeMetadata.selectText.5=사용자 정의 메타데이터 항목 추가
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -11,6 +11,7 @@ imgPrompt=Selecteer afbeelding(en)
|
||||
genericSubmit=Indienen
|
||||
processTimeWarning=Waarschuwing: Dit proces kan tot een minuut duren afhankelijk van de bestandsgrootte
|
||||
pageOrderPrompt=Aangepaste pagina volgorde (Voer een komma-gescheiden lijst van paginanummers of functies in, zoals 2n+1) :
|
||||
pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :
|
||||
goToPage=Ga
|
||||
true=Waar
|
||||
false=Onwaar
|
||||
@@ -19,6 +20,7 @@ save=Opslaan
|
||||
close=Sluiten
|
||||
filesSelected=Bestanden geselecteerd
|
||||
noFavourites=Geen favorieten toegevoegd
|
||||
downloadComplete=Download Complete
|
||||
bored=Verveeld met wachten?
|
||||
alphabet=Alfabet
|
||||
downloadPdf=Download PDF
|
||||
@@ -120,7 +122,7 @@ account.accountSettings=Account instellingen
|
||||
account.adminSettings=Beheerdersinstellingen - Gebruikers bekijken en toevoegen
|
||||
account.userControlSettings=Gebruikerscontrole instellingen
|
||||
account.changeUsername=Wijzig gebruikersnaam
|
||||
account.changeUsername=Wijzig gebruikersnaam
|
||||
account.newUsername=Nieuwe gebruikersnaam
|
||||
account.password=Bevestigingswachtwoord
|
||||
account.oldPassword=Oud wachtwoord
|
||||
account.newPassword=Nieuw wachtwoord
|
||||
@@ -366,7 +368,7 @@ showJS.tags=JS
|
||||
|
||||
home.autoRedact.title=Automatisch censureren
|
||||
home.autoRedact.desc=Automatisch censureren (onherkenbaar maken) van tekst in een PDF op basis van ingevoerde tekst
|
||||
showJS.tags=JS
|
||||
autoRedact.tags=Redact,Hide,black out,black,marker,hidden
|
||||
|
||||
home.tableExtraxt.title=PDF naar CSV
|
||||
home.tableExtraxt.desc=Haalt tabellen uit een PDF en converteert ze naar CSV
|
||||
@@ -410,7 +412,7 @@ autoRedact.title=Automatisch censureren
|
||||
autoRedact.header=Automatisch censureren
|
||||
autoRedact.colorLabel=Kleur
|
||||
autoRedact.textsToRedactLabel=Tekst om te censureren (gescheiden door regels)
|
||||
autoRedact.textsToRedactPlaceholder=bijv.\Vertrouwelijk \nTopgeheim
|
||||
autoRedact.textsToRedactPlaceholder=bijv.\Vertrouwelijk \nTopgeheim
|
||||
autoRedact.useRegexLabel=Gebruik regex
|
||||
autoRedact.wholeWordSearchLabel=Zoeken op hele woorden
|
||||
autoRedact.customPaddingLabel=Aangepaste extra ruimtevulling
|
||||
@@ -498,6 +500,7 @@ AddStampRequest.customMargin=Aangepaste marge
|
||||
AddStampRequest.customColor=Aangepaste tekstkleur
|
||||
AddStampRequest.submit=Indienen
|
||||
|
||||
|
||||
#sanitizePDF
|
||||
sanitizePDF.title=PDF opschonen
|
||||
sanitizePDF.header=Een PDF-bestand opschonen
|
||||
@@ -866,7 +869,6 @@ changeMetadata.keywords=Trefwoorden:
|
||||
changeMetadata.modDate=Wijzigingsdatum (yyyy/MM/dd HH:mm:ss):
|
||||
changeMetadata.producer=Producent:
|
||||
changeMetadata.subject=Onderwerp:
|
||||
changeMetadata.title=Titel:
|
||||
changeMetadata.trapped=Vastgezet:
|
||||
changeMetadata.selectText.4=Overige metadata:
|
||||
changeMetadata.selectText.5=Voeg aangepaste metadata-invoer toe
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -11,6 +11,7 @@ imgPrompt=Wybierz obraz(y)
|
||||
genericSubmit=Wyślij
|
||||
processTimeWarning=Ostrzeżenie: Ten proces może potrwać do minuty, w zależności od rozmiaru pliku
|
||||
pageOrderPrompt=Kolejność stron (wprowadź listę numerów stron oddzielonych przecinkami) :
|
||||
pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :
|
||||
goToPage=Idź
|
||||
true=Tak
|
||||
false=Nie
|
||||
@@ -19,6 +20,7 @@ save=Zapisz
|
||||
close=Zamknij
|
||||
filesSelected=wybrane pliki
|
||||
noFavourites=Nie dodano ulubionych
|
||||
downloadComplete=Download Complete
|
||||
bored=Znudzony czekaniem?
|
||||
alphabet=Alfabet
|
||||
downloadPdf=Pobierz PDF
|
||||
@@ -42,7 +44,7 @@ red=Red
|
||||
green=Green
|
||||
blue=Blue
|
||||
custom=Custom...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any problems!
|
||||
poweredBy=Powered by
|
||||
yes=Yes
|
||||
no=No
|
||||
@@ -120,7 +122,7 @@ account.accountSettings=Account Settings
|
||||
account.adminSettings=Admin Settings - View and Add Users
|
||||
account.userControlSettings=User Control Settings
|
||||
account.changeUsername=Change Username
|
||||
account.changeUsername=Change Username
|
||||
account.newUsername=New Username
|
||||
account.password=Confirmation Password
|
||||
account.oldPassword=Old password
|
||||
account.newPassword=New Password
|
||||
@@ -366,7 +368,7 @@ showJS.tags=JS
|
||||
|
||||
home.autoRedact.title=Auto Redact
|
||||
home.autoRedact.desc=Auto Redacts(Blacks out) text in a PDF based on input text
|
||||
showJS.tags=JS
|
||||
autoRedact.tags=Redact,Hide,black out,black,marker,hidden
|
||||
|
||||
home.tableExtraxt.title=PDF to CSV
|
||||
home.tableExtraxt.desc=Extracts Tables from a PDF converting it to CSV
|
||||
@@ -410,7 +412,7 @@ autoRedact.title=Auto Redact
|
||||
autoRedact.header=Auto Redact
|
||||
autoRedact.colorLabel=Colour
|
||||
autoRedact.textsToRedactLabel=Text to Redact (line-separated)
|
||||
autoRedact.textsToRedactPlaceholder=e.g. \nConfidential \nTop-Secret
|
||||
autoRedact.textsToRedactPlaceholder=e.g. \nConfidential \nTop-Secret
|
||||
autoRedact.useRegexLabel=Use Regex
|
||||
autoRedact.wholeWordSearchLabel=Whole Word Search
|
||||
autoRedact.customPaddingLabel=Custom Extra Padding
|
||||
@@ -498,6 +500,7 @@ AddStampRequest.customMargin=Custom Margin
|
||||
AddStampRequest.customColor=Custom Text Color
|
||||
AddStampRequest.submit=Submit
|
||||
|
||||
|
||||
#sanitizePDF
|
||||
sanitizePDF.title=Sanitize PDF
|
||||
sanitizePDF.header=Sanitize a PDF file
|
||||
@@ -866,7 +869,6 @@ changeMetadata.keywords=Słowa kluczowe:
|
||||
changeMetadata.modDate=Data modyfikacji (yyyy/MM/dd HH:mm:ss):
|
||||
changeMetadata.producer=Producent:
|
||||
changeMetadata.subject=Temat:
|
||||
changeMetadata.title=Tytuł:
|
||||
changeMetadata.trapped=Zablokowany:
|
||||
changeMetadata.selectText.4=Inne metadane:
|
||||
changeMetadata.selectText.5=Dodaj niestandardowy wpis w metadanych
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -11,6 +11,7 @@ imgPrompt=Selecione a(s) imagem(ns)
|
||||
genericSubmit=Enviar
|
||||
processTimeWarning=Aviso: esse processo pode levar até um minuto, dependendo do tamanho do arquivo
|
||||
pageOrderPrompt=Ordem das páginas (digite uma lista separada por vírgulas de números de página):
|
||||
pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :
|
||||
goToPage=Ir
|
||||
true=Verdadeiro
|
||||
false=Falso
|
||||
@@ -19,6 +20,7 @@ save=Salvar
|
||||
close=Fechar
|
||||
filesSelected=arquivos selecionados
|
||||
noFavourites=Nenhum favorito adicionado
|
||||
downloadComplete=Download Complete
|
||||
bored=Entediado esperando?
|
||||
alphabet=Alfabeto
|
||||
downloadPdf=baixar PDF
|
||||
@@ -42,7 +44,7 @@ red=Red
|
||||
green=Green
|
||||
blue=Blue
|
||||
custom=Custom...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any problems!
|
||||
poweredBy=Powered by
|
||||
yes=Yes
|
||||
no=No
|
||||
@@ -120,7 +122,7 @@ account.accountSettings=Account Settings
|
||||
account.adminSettings=Admin Settings - View and Add Users
|
||||
account.userControlSettings=User Control Settings
|
||||
account.changeUsername=Change Username
|
||||
account.changeUsername=Change Username
|
||||
account.newUsername=New Username
|
||||
account.password=Confirmation Password
|
||||
account.oldPassword=Old password
|
||||
account.newPassword=New Password
|
||||
@@ -366,7 +368,7 @@ showJS.tags=JavaScript
|
||||
|
||||
home.autoRedact.title=Auto Redact
|
||||
home.autoRedact.desc=Auto Redacts(Blacks out) text in a PDF based on input text
|
||||
showJS.tags=JavaScript
|
||||
autoRedact.tags=Redact,Hide,black out,black,marker,hidden
|
||||
|
||||
home.tableExtraxt.title=PDF to CSV
|
||||
home.tableExtraxt.desc=Extracts Tables from a PDF converting it to CSV
|
||||
@@ -410,7 +412,7 @@ autoRedact.title=Auto Redact
|
||||
autoRedact.header=Auto Redact
|
||||
autoRedact.colorLabel=Colour
|
||||
autoRedact.textsToRedactLabel=Text to Redact (line-separated)
|
||||
autoRedact.textsToRedactPlaceholder=e.g. \nConfidential \nTop-Secret
|
||||
autoRedact.textsToRedactPlaceholder=e.g. \nConfidential \nTop-Secret
|
||||
autoRedact.useRegexLabel=Use Regex
|
||||
autoRedact.wholeWordSearchLabel=Whole Word Search
|
||||
autoRedact.customPaddingLabel=Custom Extra Padding
|
||||
@@ -498,6 +500,7 @@ AddStampRequest.customMargin=Custom Margin
|
||||
AddStampRequest.customColor=Custom Text Color
|
||||
AddStampRequest.submit=Submit
|
||||
|
||||
|
||||
#sanitizePDF
|
||||
sanitizePDF.title=Sanitizar PDF
|
||||
sanitizePDF.header=Sanitizar um arquivo PDF
|
||||
@@ -866,7 +869,6 @@ changeMetadata.keywords=Palavras-chave:
|
||||
changeMetadata.modDate=Data de Modificação (aaaa/MM/dd HH:mm:ss):
|
||||
changeMetadata.producer=Produtor:
|
||||
changeMetadata.subject=Assunto:
|
||||
changeMetadata.title=Título:
|
||||
changeMetadata.trapped=Trapped:
|
||||
changeMetadata.selectText.4=Outros Metadados
|
||||
changeMetadata.selectText.5=Adicionar Entrada de Metadados Personalizados
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -11,6 +11,7 @@ imgPrompt=Selectează imagini
|
||||
genericSubmit=Trimite
|
||||
processTimeWarning=Avertisment: Acest proces poate dura până la un minut în funcție de dimensiunea fișierului
|
||||
pageOrderPrompt=Ordinea paginilor (Introdu o listă separată prin virgulă de numere de pagină):
|
||||
pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :
|
||||
goToPage=Mergi la pagină
|
||||
true=Adevărat
|
||||
false=Fals
|
||||
@@ -19,6 +20,7 @@ save=Salvează
|
||||
close=Închide
|
||||
filesSelected=fișiere selectate
|
||||
noFavourites=Niciun favorit adăugat
|
||||
downloadComplete=Download Complete
|
||||
bored=Plictisit așteptând?
|
||||
alphabet=Alfabet
|
||||
downloadPdf=Descarcă PDF
|
||||
@@ -42,7 +44,7 @@ red=Red
|
||||
green=Green
|
||||
blue=Blue
|
||||
custom=Custom...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any problems!
|
||||
poweredBy=Powered by
|
||||
yes=Yes
|
||||
no=No
|
||||
@@ -120,7 +122,7 @@ account.accountSettings=Account Settings
|
||||
account.adminSettings=Admin Settings - View and Add Users
|
||||
account.userControlSettings=User Control Settings
|
||||
account.changeUsername=Change Username
|
||||
account.changeUsername=Change Username
|
||||
account.newUsername=New Username
|
||||
account.password=Confirmation Password
|
||||
account.oldPassword=Old password
|
||||
account.newPassword=New Password
|
||||
@@ -366,7 +368,7 @@ showJS.tags=JS
|
||||
|
||||
home.autoRedact.title=Auto Redact
|
||||
home.autoRedact.desc=Auto Redacts(Blacks out) text in a PDF based on input text
|
||||
showJS.tags=JS
|
||||
autoRedact.tags=Redact,Hide,black out,black,marker,hidden
|
||||
|
||||
home.tableExtraxt.title=PDF to CSV
|
||||
home.tableExtraxt.desc=Extracts Tables from a PDF converting it to CSV
|
||||
@@ -410,7 +412,7 @@ autoRedact.title=Auto Redact
|
||||
autoRedact.header=Auto Redact
|
||||
autoRedact.colorLabel=Colour
|
||||
autoRedact.textsToRedactLabel=Text to Redact (line-separated)
|
||||
autoRedact.textsToRedactPlaceholder=e.g. \nConfidential \nTop-Secret
|
||||
autoRedact.textsToRedactPlaceholder=e.g. \nConfidential \nTop-Secret
|
||||
autoRedact.useRegexLabel=Use Regex
|
||||
autoRedact.wholeWordSearchLabel=Whole Word Search
|
||||
autoRedact.customPaddingLabel=Custom Extra Padding
|
||||
@@ -498,6 +500,7 @@ AddStampRequest.customMargin=Custom Margin
|
||||
AddStampRequest.customColor=Custom Text Color
|
||||
AddStampRequest.submit=Submit
|
||||
|
||||
|
||||
#sanitizePDF
|
||||
sanitizePDF.title=Sanitize PDF
|
||||
sanitizePDF.header=Sanitize a PDF file
|
||||
@@ -866,7 +869,6 @@ changeMetadata.keywords=Cuvinte cheie:
|
||||
changeMetadata.modDate=Data modificării (yyyy/MM/dd HH:mm:ss):
|
||||
changeMetadata.producer=Producător:
|
||||
changeMetadata.subject=Subiect:
|
||||
changeMetadata.title=Titlu:
|
||||
changeMetadata.trapped=Blocat:
|
||||
changeMetadata.selectText.4=Alte Metadate:
|
||||
changeMetadata.selectText.5=Adăugați Intrare Metadate Personalizate
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -11,6 +11,7 @@ imgPrompt=Выберите картинку(и)
|
||||
genericSubmit=Отправить
|
||||
processTimeWarning=Внимание: Этот процесс может занять до минуты в зависимости от размера файла.
|
||||
pageOrderPrompt=Порядок страниц (введите список номеров страниц через запятую):
|
||||
pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :
|
||||
goToPage=Вперед
|
||||
true=Истина
|
||||
false=Ложь
|
||||
@@ -19,6 +20,7 @@ save=Сохранить
|
||||
close=Закрыть
|
||||
filesSelected=файлов выбрано
|
||||
noFavourites=Нет избранного
|
||||
downloadComplete=Download Complete
|
||||
bored=Скучно ждать?
|
||||
alphabet=Алфавит
|
||||
downloadPdf=Скачать PDF
|
||||
@@ -42,7 +44,7 @@ red=Red
|
||||
green=Green
|
||||
blue=Blue
|
||||
custom=Custom...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any problems!
|
||||
poweredBy=Powered by
|
||||
yes=Yes
|
||||
no=No
|
||||
@@ -120,7 +122,7 @@ account.accountSettings=Account Settings
|
||||
account.adminSettings=Admin Settings - View and Add Users
|
||||
account.userControlSettings=User Control Settings
|
||||
account.changeUsername=Change Username
|
||||
account.changeUsername=Change Username
|
||||
account.newUsername=New Username
|
||||
account.password=Confirmation Password
|
||||
account.oldPassword=Old password
|
||||
account.newPassword=New Password
|
||||
@@ -366,7 +368,7 @@ showJS.tags=JS
|
||||
|
||||
home.autoRedact.title=Auto Redact
|
||||
home.autoRedact.desc=Auto Redacts(Blacks out) text in a PDF based on input text
|
||||
showJS.tags=JS
|
||||
autoRedact.tags=Redact,Hide,black out,black,marker,hidden
|
||||
|
||||
home.tableExtraxt.title=PDF to CSV
|
||||
home.tableExtraxt.desc=Extracts Tables from a PDF converting it to CSV
|
||||
@@ -410,7 +412,7 @@ autoRedact.title=Auto Redact
|
||||
autoRedact.header=Auto Redact
|
||||
autoRedact.colorLabel=Colour
|
||||
autoRedact.textsToRedactLabel=Text to Redact (line-separated)
|
||||
autoRedact.textsToRedactPlaceholder=e.g. \nConfidential \nTop-Secret
|
||||
autoRedact.textsToRedactPlaceholder=e.g. \nConfidential \nTop-Secret
|
||||
autoRedact.useRegexLabel=Use Regex
|
||||
autoRedact.wholeWordSearchLabel=Whole Word Search
|
||||
autoRedact.customPaddingLabel=Custom Extra Padding
|
||||
@@ -498,6 +500,7 @@ AddStampRequest.customMargin=Custom Margin
|
||||
AddStampRequest.customColor=Custom Text Color
|
||||
AddStampRequest.submit=Submit
|
||||
|
||||
|
||||
#sanitizePDF
|
||||
sanitizePDF.title=Дезинфицировать PDF
|
||||
sanitizePDF.header=Дезинфицировать PDF файл
|
||||
@@ -866,7 +869,6 @@ changeMetadata.keywords=Ключевые слова:
|
||||
changeMetadata.modDate=Дата изменения (yyyy/MM/dd HH:mm:ss):
|
||||
changeMetadata.producer=Изготовитель:
|
||||
changeMetadata.subject=Тема:
|
||||
changeMetadata.title=Заголовок:
|
||||
changeMetadata.trapped=Trapped:
|
||||
changeMetadata.selectText.4=Другие метаданные:
|
||||
changeMetadata.selectText.5=Добавить пользовательскую запись метаданных
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -11,6 +11,7 @@ imgPrompt=Odaberi sliku (slike)
|
||||
genericSubmit=Prihvatiti
|
||||
processTimeWarning=Warning:Upozorenje: Ovaj proces može trajati i do minut, u zavisnosti od veličine dokumenta
|
||||
pageOrderPrompt=Prilagođeni redosled stranica (unesi listu brojeva stranica ili funkcija, kao što su 2n+1, razdvojene zarezima) :
|
||||
pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :
|
||||
goToPage=Idi
|
||||
true=Tačno
|
||||
false=Netačno
|
||||
@@ -19,6 +20,7 @@ save=Sačuvaj
|
||||
close=Zatvori
|
||||
filesSelected=odabrani fajlovi
|
||||
noFavourites=Nema dodatih favorita
|
||||
downloadComplete=Download Complete
|
||||
bored=Da li ti je dosadno dok čekaš?
|
||||
alphabet=Alfabet
|
||||
downloadPdf=Skini PDF
|
||||
@@ -120,7 +122,7 @@ account.accountSettings=Podešavanja naloga
|
||||
account.adminSettings=Admin podešavanja - Pregled i dodavanje korisnika
|
||||
account.userControlSettings=Podešavanja kontrole korisnika
|
||||
account.changeUsername=Pormeni korisničko ime
|
||||
account.changeUsername=Pormeni korisničko ime
|
||||
account.newUsername=Novo korisničko ime
|
||||
account.password=Potvrda lozinke
|
||||
account.oldPassword=Stara lozinka
|
||||
account.newPassword=Nova lozinka
|
||||
@@ -362,11 +364,11 @@ PdfToSinglePage.tags=jedna-stranica
|
||||
|
||||
home.showJS.title=Prikaži JavaScript
|
||||
home.showJS.desc=Pretražuje i prikazuje bilo koji JavaScript ubačen u PDF
|
||||
showJS.tags=Cenzura,Sakrij,prekrivanje,crna,marker,skriveno
|
||||
showJS.tags=JS
|
||||
|
||||
home.autoRedact.title=Automatsko Cenzurisanje
|
||||
home.autoRedact.desc=Automatsko cenzurisanje teksta u PDF-u na osnovu unetog teksta
|
||||
showJS.tags=Cenzura,Sakrij,prekrivanje,crna,marker,skriveno
|
||||
autoRedact.tags=Cenzura,Sakrij,prekrivanje,crna,marker,skriveno
|
||||
|
||||
home.tableExtraxt.title=PDF u CSV
|
||||
home.tableExtraxt.desc=Izdvaja tabele iz PDF-a pretvarajući ih u CSV
|
||||
@@ -498,6 +500,7 @@ AddStampRequest.customMargin=Custom Margin
|
||||
AddStampRequest.customColor=Custom Text Color
|
||||
AddStampRequest.submit=Submit
|
||||
|
||||
|
||||
#sanitizePDF
|
||||
sanitizePDF.title=Sanitizacija PDF-a
|
||||
sanitizePDF.header=Sanitizacija PDF fajla
|
||||
@@ -866,7 +869,6 @@ changeMetadata.keywords=Ključne reči:
|
||||
changeMetadata.modDate=Datum izmene (gggg/MM/dd HH:mm:ss):
|
||||
changeMetadata.producer=Proizvođač:
|
||||
changeMetadata.subject=Tema:
|
||||
changeMetadata.title=Naslov:
|
||||
changeMetadata.trapped=Zaglavljeno:
|
||||
changeMetadata.selectText.4=Drugi metapodaci:
|
||||
changeMetadata.selectText.5=Dodaj prilagođeni unos metapodataka
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -11,6 +11,7 @@ imgPrompt=Välj bild(er)
|
||||
genericSubmit=Skicka
|
||||
processTimeWarning=Varning: Denna process kan ta upp till en minut beroende på filstorlek
|
||||
pageOrderPrompt=Sidordning (Ange en kommaseparerad lista med sidnummer) :
|
||||
pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :
|
||||
goToPage=Gå till
|
||||
true=True
|
||||
false=Falskt
|
||||
@@ -19,6 +20,7 @@ save=Spara
|
||||
close=Stäng
|
||||
filesSelected=filer valda
|
||||
noFavourites=Inga favoriter har lagts till
|
||||
downloadComplete=Download Complete
|
||||
bored=Utråkad att vänta?
|
||||
alphabet=Alfabet
|
||||
downloadPdf=Ladda ner PDF
|
||||
@@ -42,7 +44,7 @@ red=Red
|
||||
green=Green
|
||||
blue=Blue
|
||||
custom=Custom...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any problems!
|
||||
poweredBy=Powered by
|
||||
yes=Yes
|
||||
no=No
|
||||
@@ -120,7 +122,7 @@ account.accountSettings=Account Settings
|
||||
account.adminSettings=Admin Settings - View and Add Users
|
||||
account.userControlSettings=User Control Settings
|
||||
account.changeUsername=Change Username
|
||||
account.changeUsername=Change Username
|
||||
account.newUsername=New Username
|
||||
account.password=Confirmation Password
|
||||
account.oldPassword=Old password
|
||||
account.newPassword=New Password
|
||||
@@ -366,7 +368,7 @@ showJS.tags=JS
|
||||
|
||||
home.autoRedact.title=Auto Redact
|
||||
home.autoRedact.desc=Auto Redacts(Blacks out) text in a PDF based on input text
|
||||
showJS.tags=JS
|
||||
autoRedact.tags=Redact,Hide,black out,black,marker,hidden
|
||||
|
||||
home.tableExtraxt.title=PDF to CSV
|
||||
home.tableExtraxt.desc=Extracts Tables from a PDF converting it to CSV
|
||||
@@ -410,7 +412,7 @@ autoRedact.title=Auto Redact
|
||||
autoRedact.header=Auto Redact
|
||||
autoRedact.colorLabel=Colour
|
||||
autoRedact.textsToRedactLabel=Text to Redact (line-separated)
|
||||
autoRedact.textsToRedactPlaceholder=e.g. \nConfidential \nTop-Secret
|
||||
autoRedact.textsToRedactPlaceholder=e.g. \nConfidential \nTop-Secret
|
||||
autoRedact.useRegexLabel=Use Regex
|
||||
autoRedact.wholeWordSearchLabel=Whole Word Search
|
||||
autoRedact.customPaddingLabel=Custom Extra Padding
|
||||
@@ -498,6 +500,7 @@ AddStampRequest.customMargin=Custom Margin
|
||||
AddStampRequest.customColor=Custom Text Color
|
||||
AddStampRequest.submit=Submit
|
||||
|
||||
|
||||
#sanitizePDF
|
||||
sanitizePDF.title=Sanitize PDF
|
||||
sanitizePDF.header=Sanitize a PDF file
|
||||
@@ -866,7 +869,6 @@ changeMetadata.keywords=Sökord:
|
||||
changeMetadata.modDate=Ändringsdatum (åååå/MM/dd HH:mm:ss):
|
||||
changeMetadata.producer=Producent:
|
||||
changeMetadata.subject=Ämne:
|
||||
changeMetadata.title=Titel:
|
||||
changeMetadata.trapped=Fångad:
|
||||
changeMetadata.selectText.4=Andra metadata:
|
||||
changeMetadata.selectText.5=Lägg till anpassad metadatapost
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -11,6 +11,7 @@ imgPrompt=Resim(leri) seçin
|
||||
genericSubmit=Gönder
|
||||
processTimeWarning=Uyarı: Bu işlem, dosya boyutuna bağlı olarak bir dakikaya kadar sürebilir.
|
||||
pageOrderPrompt=Özel Sayfa Sırası (Virgülle ayrılmış sayfa numaraları veya 2n+1 gibi bir fonksiyon girin) :
|
||||
pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :
|
||||
goToPage=Git
|
||||
true=Doğru
|
||||
false=Yanlış
|
||||
@@ -19,6 +20,7 @@ save=Kaydet
|
||||
close=Kapat
|
||||
filesSelected=dosya seçildi
|
||||
noFavourites=Favori eklenmedi
|
||||
downloadComplete=Download Complete
|
||||
bored=Sıkıldınız mı?
|
||||
alphabet=Alfabe
|
||||
downloadPdf=PDF İndir
|
||||
@@ -42,7 +44,7 @@ red=Kırmızı
|
||||
green=Yeşil
|
||||
blue=Mavi
|
||||
custom=Özel
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any problems!
|
||||
poweredBy=Powered by
|
||||
yes=Yes
|
||||
no=No
|
||||
@@ -120,7 +122,7 @@ account.accountSettings=Hesap Ayarları
|
||||
account.adminSettings=Yönetici Ayarları - Kullanıcıları Görüntüle ve Ekle
|
||||
account.userControlSettings=Kullanıcı Kontrol Ayarları
|
||||
account.changeUsername=Kullanıcı Adını Değiştir
|
||||
account.changeUsername=Kullanıcı Adını Değiştir
|
||||
account.newUsername=Yeni kullanıcı adı
|
||||
account.password=Onay Şifresi
|
||||
account.oldPassword=Eski Şifre
|
||||
account.newPassword=Yeni Şifre
|
||||
@@ -362,11 +364,11 @@ PdfToSinglePage.tags=tek sayfa
|
||||
|
||||
home.showJS.title=Javascript'i Göster
|
||||
home.showJS.desc=Bir PDF'e enjekte edilen herhangi bir JS'i araştırır ve gösterir
|
||||
showJS.tags=Karart,Gizle,karartma,siyah,markör,gizli
|
||||
showJS.tags=JS
|
||||
|
||||
home.autoRedact.title=Otomatik Karartma
|
||||
home.autoRedact.desc=Giriş metnine dayanarak bir PDF'teki metni Otomatik Karartır (Redakte)
|
||||
showJS.tags=Karart,Gizle,karartma,siyah,markör,gizli
|
||||
autoRedact.tags=Karart,Gizle,karartma,siyah,markör,gizli
|
||||
|
||||
home.tableExtraxt.title=PDF to CSV
|
||||
home.tableExtraxt.desc=Extracts Tables from a PDF converting it to CSV
|
||||
@@ -410,7 +412,7 @@ autoRedact.title=Otomatik Karartma
|
||||
autoRedact.header=Otomatik Karartma
|
||||
autoRedact.colorLabel=Renk
|
||||
autoRedact.textsToRedactLabel=Karartılacak Metin (satır ayrılmış)
|
||||
autoRedact.textsToRedactPlaceholder=Örn. \nGizli \nÇok Gizli
|
||||
autoRedact.textsToRedactPlaceholder=Örn. \nGizli \nÇok Gizli
|
||||
autoRedact.useRegexLabel=Regex Kullan
|
||||
autoRedact.wholeWordSearchLabel=Tam Kelime Arama
|
||||
autoRedact.customPaddingLabel=Özel Ekstra Dolgu
|
||||
@@ -498,6 +500,7 @@ AddStampRequest.customMargin=Custom Margin
|
||||
AddStampRequest.customColor=Custom Text Color
|
||||
AddStampRequest.submit=Submit
|
||||
|
||||
|
||||
#sanitizePDF
|
||||
sanitizePDF.title=PDF'i Temizle
|
||||
sanitizePDF.header=PDF dosyasını temizle
|
||||
@@ -866,7 +869,6 @@ changeMetadata.keywords=Anahtar Kelimeler:
|
||||
changeMetadata.modDate=Değişiklik Tarihi (yyyy/MM/dd HH:mm:ss):
|
||||
changeMetadata.producer=Üretici:
|
||||
changeMetadata.subject=Konu:
|
||||
changeMetadata.title=Başlık:
|
||||
changeMetadata.trapped=Tuzak:
|
||||
changeMetadata.selectText.4=Diğer Metaveri:
|
||||
changeMetadata.selectText.5=Özel Metaveri Girişi Ekle
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -11,6 +11,7 @@ imgPrompt=选择图像
|
||||
genericSubmit=提交
|
||||
processTimeWarning=警告:此过程可能需要多达一分钟,具体时间取决于文件大小
|
||||
pageOrderPrompt=页面顺序(输入逗号分隔的页码列表):
|
||||
pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :
|
||||
goToPage=到
|
||||
true=对
|
||||
false=错
|
||||
@@ -19,6 +20,7 @@ save=保存
|
||||
close=关闭
|
||||
filesSelected=选中的文件
|
||||
noFavourites=没有添加收藏夹
|
||||
downloadComplete=Download Complete
|
||||
bored=无聊等待吗?
|
||||
alphabet=字母表
|
||||
downloadPdf=下载PDF
|
||||
@@ -42,7 +44,7 @@ red=Red
|
||||
green=Green
|
||||
blue=Blue
|
||||
custom=Custom...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any problems!
|
||||
poweredBy=Powered by
|
||||
yes=Yes
|
||||
no=No
|
||||
@@ -120,7 +122,7 @@ account.accountSettings=帐号设定
|
||||
account.adminSettings=管理员设置 - 查看和添加用户
|
||||
account.userControlSettings=用户控制设置
|
||||
account.changeUsername=更改用户名
|
||||
account.changeUsername=更改用户名
|
||||
account.newUsername=新用户名
|
||||
account.password=确认密码
|
||||
account.oldPassword=旧密码
|
||||
account.newPassword=新密码
|
||||
@@ -366,7 +368,7 @@ showJS.tags=JavaScript
|
||||
|
||||
home.autoRedact.title=自动删除
|
||||
home.autoRedact.desc=根据输入文本自动删除(覆盖)PDF中的文本
|
||||
showJS.tags=JavaScript
|
||||
autoRedact.tags=Redact,Hide,black out,black,marker,hidden
|
||||
|
||||
home.tableExtraxt.title=PDF to CSV
|
||||
home.tableExtraxt.desc=从PDF中提取表格并将其转换为CSV
|
||||
@@ -498,6 +500,7 @@ AddStampRequest.customMargin=Custom Margin
|
||||
AddStampRequest.customColor=Custom Text Color
|
||||
AddStampRequest.submit=Submit
|
||||
|
||||
|
||||
#sanitizePDF
|
||||
sanitizePDF.title=清理PDF
|
||||
sanitizePDF.header=清理PDF文件
|
||||
@@ -866,7 +869,6 @@ changeMetadata.keywords=关键词:
|
||||
changeMetadata.modDate=修改日期(yyyy/MM/dd HH:mm:ss):
|
||||
changeMetadata.producer=生产者:
|
||||
changeMetadata.subject=主题:
|
||||
changeMetadata.title=标题:
|
||||
changeMetadata.trapped=被困:
|
||||
changeMetadata.selectText.4=其他元数据:
|
||||
changeMetadata.selectText.5=添加自定义元数据条目
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -11,6 +11,7 @@ imgPrompt=選擇圖片
|
||||
genericSubmit=送出
|
||||
processTimeWarning=警告:此過程可能需要長達一分鐘,具體取決於檔案大小
|
||||
pageOrderPrompt=自訂頁面順序(輸入以逗號分隔的頁碼或函式,如 2n+1):
|
||||
pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :
|
||||
goToPage=前往
|
||||
true=是
|
||||
false=否
|
||||
@@ -19,6 +20,7 @@ save=儲存
|
||||
close=關閉
|
||||
filesSelected=已選擇的檔案
|
||||
noFavourites=未新增收藏
|
||||
downloadComplete=Download Complete
|
||||
bored=等待時覺得無聊?
|
||||
alphabet=字母表
|
||||
downloadPdf=下載 PDF
|
||||
@@ -42,7 +44,7 @@ red=紅色
|
||||
green=綠色
|
||||
blue=藍色
|
||||
custom=自訂...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any problems!
|
||||
poweredBy=Powered by
|
||||
yes=Yes
|
||||
no=No
|
||||
@@ -120,7 +122,7 @@ account.accountSettings=帳戶設定
|
||||
account.adminSettings=管理設定 - 檢視和新增使用者
|
||||
account.userControlSettings=使用者控制設定
|
||||
account.changeUsername=修改使用者名稱
|
||||
account.changeUsername=修改使用者名稱
|
||||
account.newUsername=新使用者名稱
|
||||
account.password=確認密碼
|
||||
account.oldPassword=舊密碼
|
||||
account.newPassword=新密碼
|
||||
@@ -362,11 +364,11 @@ PdfToSinglePage.tags=單一頁面
|
||||
|
||||
home.showJS.title=顯示 JavaScript
|
||||
home.showJS.desc=搜尋並顯示嵌入 PDF 中的任何 JS(JavaScript)
|
||||
showJS.tags=塗黑,隱藏,塗黑,黑色,標記,隱藏
|
||||
showJS.tags=JS
|
||||
|
||||
home.autoRedact.title=自動塗黑
|
||||
home.autoRedact.desc=根據輸入的文字自動塗黑 PDF 中的文字
|
||||
showJS.tags=塗黑,隱藏,塗黑,黑色,標記,隱藏
|
||||
autoRedact.tags=塗黑,隱藏,塗黑,黑色,標記,隱藏
|
||||
|
||||
home.tableExtraxt.title=PDF 轉 CSV
|
||||
home.tableExtraxt.desc=從 PDF 中提取表格並將其轉換為 CSV
|
||||
@@ -410,7 +412,7 @@ autoRedact.title=自動塗黑
|
||||
autoRedact.header=自動塗黑
|
||||
autoRedact.colorLabel=顏色
|
||||
autoRedact.textsToRedactLabel=要塗黑的文字(以行分隔)
|
||||
autoRedact.textsToRedactPlaceholder=例如 \n機密 \n最高機密
|
||||
autoRedact.textsToRedactPlaceholder=例如 \n機密 \n最高機密
|
||||
autoRedact.useRegexLabel=使用正則表達式
|
||||
autoRedact.wholeWordSearchLabel=整個單詞搜尋
|
||||
autoRedact.customPaddingLabel=自訂額外填充
|
||||
@@ -498,6 +500,7 @@ AddStampRequest.customMargin=Custom Margin
|
||||
AddStampRequest.customColor=Custom Text Color
|
||||
AddStampRequest.submit=Submit
|
||||
|
||||
|
||||
#sanitizePDF
|
||||
sanitizePDF.title=清理 PDF
|
||||
sanitizePDF.header=清理 PDF 檔案
|
||||
@@ -866,7 +869,6 @@ changeMetadata.keywords=關鍵字:
|
||||
changeMetadata.modDate=修改日期(yyyy/MM/dd HH:mm:ss):
|
||||
changeMetadata.producer=製作人:
|
||||
changeMetadata.subject=主題:
|
||||
changeMetadata.title=標題:
|
||||
changeMetadata.trapped=陷阱:
|
||||
changeMetadata.selectText.4=其他中繼資料:
|
||||
changeMetadata.selectText.5=新增自訂中繼資料項目
|
||||
|
||||
4
src/main/resources/static/css/account.css
Normal file
4
src/main/resources/static/css/account.css
Normal file
@@ -0,0 +1,4 @@
|
||||
.buttons-container {
|
||||
margin-top: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
28
src/main/resources/static/css/add-image.css
Normal file
28
src/main/resources/static/css/add-image.css
Normal 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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
88
src/main/resources/static/css/error.css
Normal file
88
src/main/resources/static/css/error.css
Normal 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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
20
src/main/resources/static/css/footer.css
Normal file
20
src/main/resources/static/css/footer.css
Normal 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 */
|
||||
}
|
||||
@@ -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(9vw); /* 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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
9
src/main/resources/static/css/licenses.css
Normal file
9
src/main/resources/static/css/licenses.css
Normal 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 */
|
||||
}
|
||||
@@ -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;*/
|
||||
|
||||
111
src/main/resources/static/css/login.css
Normal file
111
src/main/resources/static/css/login.css
Normal 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;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
119
src/main/resources/static/css/multi-tool.css
Normal file
119
src/main/resources/static/css/multi-tool.css
Normal 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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
21
src/main/resources/static/css/pipeline.css
Normal file
21
src/main/resources/static/css/pipeline.css
Normal 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 */
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
29
src/main/resources/static/css/rotate-pdf.css
Normal file
29
src/main/resources/static/css/rotate-pdf.css
Normal 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;
|
||||
}
|
||||
39
src/main/resources/static/css/sign.css
Normal file
39
src/main/resources/static/css/sign.css
Normal 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;
|
||||
}
|
||||
10
src/main/resources/static/css/split-pdf-by-sections.css
Normal file
10
src/main/resources/static/css/split-pdf-by-sections.css
Normal 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 */
|
||||
}
|
||||
41
src/main/resources/static/css/stamp.css
Normal file
41
src/main/resources/static/css/stamp.css
Normal 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;
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,242 +1,265 @@
|
||||
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);
|
||||
|
||||
// Set a timeout to show the game button if operation takes more than 5 seconds
|
||||
const timeoutId = setTimeout(() => {
|
||||
var boredWaiting = localStorage.getItem("boredWaiting") || "disabled";
|
||||
const showGameBtn = document.getElementById("show-game-btn");
|
||||
if (boredWaiting === "enabled" && showGameBtn) {
|
||||
showGameBtn.style.display = "block";
|
||||
}
|
||||
}, 5000);
|
||||
|
||||
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);
|
||||
}
|
||||
clearTimeout(timeoutId);
|
||||
$("#submitBtn").text(originalButtonText);
|
||||
|
||||
// After process finishes, check for boredWaiting and gameDialog open status
|
||||
const boredWaiting = localStorage.getItem("boredWaiting") || "disabled";
|
||||
const gameDialog = document.getElementById('game-container-wrapper');
|
||||
if (boredWaiting === "enabled" && gameDialog && gameDialog.open) {
|
||||
// Display a green banner at the bottom of the screen saying "Download complete"
|
||||
let downloadCompleteText = "Download Complete";
|
||||
if(window.downloadCompleteText){
|
||||
downloadCompleteText = window.downloadCompleteText;
|
||||
}
|
||||
});
|
||||
$("body").append('<div id="download-complete-banner" style="position:fixed;bottom:0;left:0;width:100%;background-color:green;color:white;text-align:center;padding:10px;font-size:16px;z-index:1000;">'+ downloadCompleteText + '</div>');
|
||||
setTimeout(function() {
|
||||
$("#download-complete-banner").fadeOut("slow", function() {
|
||||
$(this).remove(); // Remove the banner after fading out
|
||||
});
|
||||
}, 5000); // Banner will fade out after 5 seconds
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
clearTimeout(timeoutId);
|
||||
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);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,292 +1,276 @@
|
||||
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();
|
||||
|
||||
const PLAYER_MOVE_SPEED = 5;
|
||||
const BASE_PDF_SPEED = 1;
|
||||
const LEVEL_INCREASE_PDF_SPEED = 0.2;
|
||||
const BASE_SPAWN_INTERVAL_MS = 1250; // milliseconds before a new enemy spawns
|
||||
const LEVEL_INCREASE_FACTOR_MS = 25; // milliseconds to decrease the spawn interval per level
|
||||
const MAX_SPAWN_RATE_REDUCTION_MS = 800; // Max milliseconds from the base spawn interval
|
||||
|
||||
|
||||
let highScore = localStorage.getItem('highScore') ? parseInt(localStorage.getItem('highScore')) : 0;
|
||||
updateHighScore();
|
||||
let keysPressed = {};
|
||||
const pdfs = [];
|
||||
const projectiles = [];
|
||||
let score = 0;
|
||||
let level = 1;
|
||||
let pdfSpeed = BASE_PDF_SPEED;
|
||||
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 -= PLAYER_MOVE_SPEED;
|
||||
playerX = Math.max(0, playerX)
|
||||
}
|
||||
|
||||
function updateLives() {
|
||||
livesElement.textContent = 'Lives: ' + lives;
|
||||
if (keysPressed["ArrowRight"]) {
|
||||
playerX += PLAYER_MOVE_SPEED;
|
||||
playerX = Math.min(gameContainer.clientWidth - playerSize, playerX);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
function onKeydown(event) {
|
||||
if (event.key === " ") {
|
||||
event.preventDefault();
|
||||
}
|
||||
keysPressed[event.key] = true;
|
||||
handleKeys();
|
||||
}
|
||||
function onKeyUp(event) {
|
||||
keysPressed[event.key] = false;
|
||||
}
|
||||
|
||||
document.addEventListener('visibilitychange', function() {
|
||||
if (document.hidden) {
|
||||
paused = true;
|
||||
} else {
|
||||
paused = false;
|
||||
updateGame();
|
||||
spawnPdfInterval();
|
||||
document.removeEventListener("keydown", onKeydown);
|
||||
document.removeEventListener("keyup", onKeyUp);
|
||||
document.addEventListener("keydown", onKeydown);
|
||||
document.addEventListener("keyup", onKeyUp);
|
||||
|
||||
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 - (2*pdfSize))) + 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;
|
||||
|
||||
handleKeys();
|
||||
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 = BASE_PDF_SPEED;
|
||||
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 += LEVEL_INCREASE_PDF_SPEED;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
||||
|
||||
function spawnPdfInterval() {
|
||||
if (gameOver || paused) {
|
||||
clearTimeout(spawnPdfTimeout);
|
||||
return;
|
||||
}
|
||||
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;
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
@@ -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.language || "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));
|
||||
});
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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";
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
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 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;
|
||||
|
||||
|
||||
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("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";
|
||||
|
||||
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);
|
||||
document.getElementById("boredWaiting").addEventListener("change", function () {
|
||||
boredWaiting = this.checked ? "enabled" : "disabled";
|
||||
localStorage.setItem("boredWaiting", boredWaiting);
|
||||
});
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
503
src/main/resources/static/pdfjs/css/viewer.css
vendored
503
src/main/resources/static/pdfjs/css/viewer.css
vendored
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
4
src/main/resources/static/pdfjs/js/viewer.js
vendored
4
src/main/resources/static/pdfjs/js/viewer.js
vendored
@@ -3323,13 +3323,13 @@
|
||||
kind: OptionKind.WORKER
|
||||
},
|
||||
workerSrc: {
|
||||
value: "/pdfjs/pdf.worker.js",
|
||||
value: "./pdfjs/pdf.worker.js",
|
||||
kind: OptionKind.WORKER
|
||||
}
|
||||
};
|
||||
{
|
||||
defaultOptions.defaultUrl = {
|
||||
value: "/pdfjs/example/Welcome.pdf",
|
||||
value: "./pdfjs/example/Welcome.pdf",
|
||||
kind: OptionKind.VIEWER
|
||||
};
|
||||
defaultOptions.disablePreferences = {
|
||||
|
||||
@@ -244,3 +244,19 @@ editor_stamp_add_image.title=Grafik hinzufügen
|
||||
editor_free_text2_aria_label=Texteditor
|
||||
editor_ink2_aria_label=Zeichnungseditor
|
||||
editor_ink_canvas_aria_label=Vom Benutzer erstelltes Bild
|
||||
# Alt-text dialog
|
||||
# LOCALIZATION NOTE (editor_alt_text_button_label): Alternative text (alt text) helps
|
||||
# when people can't see the image.
|
||||
editor_alt_text_button_label=Alternativer Text
|
||||
editor_alt_text_edit_button_label=Alternativer Text bearbeiten
|
||||
editor_alt_text_dialog_label=Wählen Sie eine Option
|
||||
editor_alt_text_dialog_description=Alternativer Text hilft, wenn die Leute das Bild nicht sehen können oder es nicht lädt.
|
||||
editor_alt_text_add_description_label=Eine Beschreibung hinzufügen
|
||||
editor_alt_text_add_description_description=Setzen Sie auf 1–2 Sätze, die das Thema, die Einstellung oder die Aktionen beschreiben.
|
||||
editor_alt_text_mark_decorative_label=Als dekorativ markieren
|
||||
editor_alt_text_mark_decorative_description=Dies wird für dekorative Bilder wie Ränder oder Wasserzeichen verwendet.
|
||||
editor_alt_text_cancel_button=Abbrechen
|
||||
editor_alt_text_save_button=Speichern
|
||||
editor_alt_text_decorative_tooltip=Als dekorativ markiert
|
||||
# This is a placeholder for the alt text input area
|
||||
editor_alt_text_textarea.placeholder=Zum Beispiel: „Ein junger Mann setzt sich an einen Tisch, um eine Mahlzeit einzunehmen.“
|
||||
|
||||
@@ -1,22 +1,21 @@
|
||||
<!DOCTYPE html>
|
||||
<html th:lang="${#locale.toString()}" th:lang-direction="#{language.direction}" xmlns:th="http://www.thymeleaf.org">
|
||||
|
||||
<th:block th:insert="~{fragments/common :: head(title='<3')}"></th:block>
|
||||
|
||||
<body>
|
||||
<div id="page-container">
|
||||
<div id="content-wrap">
|
||||
<div th:insert="~{fragments/navbar.html :: navbar}"></div>
|
||||
<br> <br>
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6">
|
||||
<html th:lang="${#locale.language}" th:lang-direction="#{language.direction}" th:language="${#locale.toString()}" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<th:block th:insert="~{fragments/common :: head(title='<3')}"></th:block>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="page-container">
|
||||
<div id="content-wrap">
|
||||
<th:block th:insert="~{fragments/navbar.html :: navbar}"></th:block>
|
||||
<br /><br />
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<th:block th:insert="~{fragments/footer.html :: footer}"></th:block>
|
||||
</div>
|
||||
<div th:insert="~{fragments/footer.html :: footer}"></div>
|
||||
</div>
|
||||
</body>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -1,326 +1,286 @@
|
||||
<!doctype html>
|
||||
<html th:lang="${#locale.toString()}" th:lang-direction="#{language.direction}" xmlns:th="http://www.thymeleaf.org">
|
||||
<!DOCTYPE html>
|
||||
<html th:lang="${#locale.language}" th:lang-direction="#{language.direction}" th:language="${#locale.toString()}" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<th:block th:insert="~{fragments/common :: head(title=#{account.title})}"></th:block>
|
||||
</head>
|
||||
|
||||
<th:block th:insert="~{fragments/common :: head(title=#{account.title}, header=#{account.header})}"></th:block>
|
||||
|
||||
<body>
|
||||
<body>
|
||||
<th:block th:insert="~{fragments/common :: game}"></th:block>
|
||||
<div id="page-container">
|
||||
<div id="content-wrap">
|
||||
<div th:insert="~{fragments/navbar.html :: navbar}"></div>
|
||||
<br> <br>
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-9">
|
||||
<div id="content-wrap">
|
||||
<th:block th:insert="~{fragments/navbar.html :: navbar}"></th:block>
|
||||
<br /><br />
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-9">
|
||||
|
||||
<!-- User Settings Title -->
|
||||
<h2 class="text-center" th:text="#{account.accountSettings}">User Settings</h2>
|
||||
<hr>
|
||||
<div th:if="${param.messageType != null and param.messageType.size() > 0 and param.messageType[0] == 'notAuthenticated'}" class="alert alert-danger">
|
||||
<span th:text="#{notAuthenticatedMessage}">Default message if not found</span>
|
||||
</div>
|
||||
<div th:if="${param.messageType != null and param.messageType.size() > 0 and param.messageType[0] == 'userNotFound'}" class="alert alert-danger">
|
||||
<span th:text="#{userNotFoundMessage}">Default message if not found</span>
|
||||
</div>
|
||||
<div th:if="${param.messageType != null and param.messageType.size() > 0 and param.messageType[0] == 'incorrectPassword'}" class="alert alert-danger">
|
||||
<span th:text="#{incorrectPasswordMessage}">Default message if not found</span>
|
||||
</div>
|
||||
<div th:if="${param.messageType != null and param.messageType.size() > 0 and param.messageType[0] == 'usernameExists'}" class="alert alert-danger">
|
||||
<span th:text="#{usernameExistsMessage}">Default message if not found</span>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- At the top of the user settings -->
|
||||
<h3 class="text-center"><span th:text="#{welcome} + ' ' + ${username}">User</span>!</h3>
|
||||
|
||||
<div th:if="${error}" class="alert alert-danger" role="alert">
|
||||
<span th:text="${error}">Error Message</span>
|
||||
</div>
|
||||
<!-- Change Username Form -->
|
||||
<h4></h4>
|
||||
<form action="api/v1/user/change-username" method="post">
|
||||
<div class="mb-3">
|
||||
<label for="newUsername" th:text="#{account.changeUsername}">Change Username</label>
|
||||
<input type="text" class="form-control" name="newUsername" id="newUsername" placeholder="New Username">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="currentPassword" th:text="#{password}">Password</label>
|
||||
<input type="password" class="form-control" name="currentPassword" id="currentPasswordUsername" placeholder="Password">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<button type="submit" class="btn btn-primary" th:text="#{account.changeUsername}">Change Username</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<hr> <!-- Separator Line -->
|
||||
|
||||
<!-- Change Password Form -->
|
||||
<h4 th:text="#{account.changePassword}">Change Password?</h4>
|
||||
<form action="api/v1/user/change-password" method="post">
|
||||
<div class="mb-3">
|
||||
<label for="currentPassword" th:text="#{account.oldPassword}">Old Password</label>
|
||||
<input type="password" class="form-control" name="currentPassword" id="currentPasswordPassword" th:placeholder="#{account.oldPassword}">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="newPassword" th:text="#{account.newPassword}">New Password</label>
|
||||
<input type="password" class="form-control" name="newPassword" id="newPassword" th:placeholder="#{account.newPassword}">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="confirmNewPassword" th:text="#{account.confirmNewPassword}">Confirm New Password</label>
|
||||
<input type="password" class="form-control" name="confirmNewPassword" id="confirmNewPassword" th:placeholder="#{account.confirmNewPassword}">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<button type="submit" class="btn btn-primary" th:text="#{account.changePassword}">Change Password</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header" th:text="#{account.yourApiKey}">
|
||||
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="input-group mb-3">
|
||||
<input type="password" class="form-control" id="apiKey" th:placeholder="#{account.yourApiKey}" readonly>
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-outline-secondary" id="copyBtn" type="button" onclick="copyToClipboard()">
|
||||
<img class="blackwhite-icon" src="images/clipboard.svg" alt="Copy" style="height:20px;">
|
||||
</button>
|
||||
<button class="btn btn-outline-secondary" id="showBtn" type="button" onclick="showApiKey()">
|
||||
<img class="blackwhite-icon" id="eyeIcon" src="images/eye.svg" alt="Toggle API Key Visibility" style="height:20px;">
|
||||
</button>
|
||||
<button class="btn btn-outline-secondary" id="refreshBtn" type="button" onclick="refreshApiKey()">
|
||||
<img class="blackwhite-icon" id="eyeIcon" src="images/arrow-clockwise.svg" alt="Refresh API-Key" style="height:20px;">
|
||||
</button>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function copyToClipboard() {
|
||||
const apiKeyElement = document.getElementById("apiKey");
|
||||
apiKeyElement.select();
|
||||
document.execCommand("copy");
|
||||
}
|
||||
|
||||
|
||||
function showApiKey() {
|
||||
const apiKeyElement = document.getElementById("apiKey");
|
||||
const copyBtn = document.getElementById("copyBtn");
|
||||
const eyeIcon = document.getElementById("eyeIcon");
|
||||
if (apiKeyElement.type === "password") {
|
||||
apiKeyElement.type = "text";
|
||||
eyeIcon.src = "images/eye-slash.svg";
|
||||
copyBtn.disabled = false; // Enable copy button when API key is visible
|
||||
} else {
|
||||
apiKeyElement.type = "password";
|
||||
eyeIcon.src = "images/eye.svg";
|
||||
copyBtn.disabled = true; // Disable copy button when API key is hidden
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", async function() {
|
||||
try {
|
||||
let response = await fetch('/api/v1/user/get-api-key', { method: 'POST' });
|
||||
if (response.status === 200) {
|
||||
let apiKey = await response.text();
|
||||
manageUIState(apiKey);
|
||||
} else {
|
||||
manageUIState(null);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('There was an error:', error);
|
||||
}
|
||||
});
|
||||
|
||||
async function refreshApiKey() {
|
||||
try {
|
||||
let response = await fetch('/api/v1/user/update-api-key', { method: 'POST' });
|
||||
if (response.status === 200) {
|
||||
let apiKey = await response.text();
|
||||
manageUIState(apiKey);
|
||||
document.getElementById("apiKey").type = 'text';
|
||||
document.getElementById("copyBtn").disabled = false;
|
||||
} else {
|
||||
alert('Error refreshing API key.');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('There was an error:', error);
|
||||
}
|
||||
}
|
||||
|
||||
function manageUIState(apiKey) {
|
||||
const apiKeyElement = document.getElementById("apiKey");
|
||||
const showBtn = document.getElementById("showBtn");
|
||||
const copyBtn = document.getElementById("copyBtn");
|
||||
|
||||
if (apiKey && apiKey.trim().length > 0) {
|
||||
apiKeyElement.value = apiKey;
|
||||
showBtn.disabled = false;
|
||||
copyBtn.disabled = true;
|
||||
} else {
|
||||
apiKeyElement.value = "";
|
||||
showBtn.disabled = true;
|
||||
copyBtn.disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const form = document.querySelector('form[action="api/v1/user/change-password"]');
|
||||
|
||||
form.addEventListener('submit', function(event) {
|
||||
const newPassword = document.getElementById('newPassword').value;
|
||||
const confirmNewPassword = document.getElementById('confirmNewPassword').value;
|
||||
|
||||
if (newPassword !== confirmNewPassword) {
|
||||
alert('New Password and Confirm New Password must match.');
|
||||
event.preventDefault(); // Prevent form submission
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<hr> <!-- Separator Line -->
|
||||
|
||||
<h4 th:text="#{account.syncTitle}">Sync browser settings with Account</h4>
|
||||
<div class="container mt-4">
|
||||
<h3 th:text="#{account.settingsCompare}">Settings Comparison:</h3>
|
||||
<table id="settingsTable" class="table table-bordered table-sm table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th th:text="#{account.property}">Property</th>
|
||||
<th th:text="#{account.accountSettings}">Account Setting</th>
|
||||
<th th:text="#{account.webBrowserSettings}">Web Browser Setting</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- This will be dynamically populated by JavaScript -->
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="buttons-container mt-3 text-center">
|
||||
<button id="syncToBrowser" class="btn btn-primary btn-sm" th:text="#{account.syncToBrowser}">Sync Account -> Browser</button>
|
||||
<button id="syncToAccount" class="btn btn-secondary btn-sm" th:text="#{account.syncToAccount}">Sync Account <- Browser</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<style>
|
||||
.container {
|
||||
width: 100%;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.buttons-container {
|
||||
margin-top: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<script th:inline="javascript">
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const settingsTableBody = document.querySelector("#settingsTable tbody");
|
||||
|
||||
/*<![CDATA[*/
|
||||
var accountSettingsString = /*[[${settings}]]*/ {};
|
||||
/*]]>*/
|
||||
var accountSettings = JSON.parse(accountSettingsString);
|
||||
|
||||
let allKeys = new Set([...Object.keys(accountSettings), ...Object.keys(localStorage)]);
|
||||
|
||||
allKeys.forEach(key => {
|
||||
if(key === 'debug' || key === '0' || key === '1') return; // Ignoring specific keys
|
||||
|
||||
const accountValue = accountSettings[key] || '-';
|
||||
const browserValue = localStorage.getItem(key) || '-';
|
||||
|
||||
const row = settingsTableBody.insertRow();
|
||||
const propertyCell = row.insertCell(0);
|
||||
const accountCell = row.insertCell(1);
|
||||
const browserCell = row.insertCell(2);
|
||||
|
||||
propertyCell.textContent = key;
|
||||
accountCell.textContent = accountValue;
|
||||
browserCell.textContent = browserValue;
|
||||
});
|
||||
|
||||
document.getElementById('syncToBrowser').addEventListener('click', function() {
|
||||
// First, clear the local storage
|
||||
localStorage.clear();
|
||||
|
||||
// Then, set the account settings to local storage
|
||||
for (let key in accountSettings) {
|
||||
if(key !== 'debug' && key !== '0' && key !== '1') { // Only sync non-ignored keys
|
||||
localStorage.setItem(key, accountSettings[key]);
|
||||
}
|
||||
}
|
||||
location.reload(); // Refresh the page after sync
|
||||
});
|
||||
|
||||
|
||||
document.getElementById('syncToAccount').addEventListener('click', function() {
|
||||
let form = document.createElement("form");
|
||||
form.method = "POST";
|
||||
form.action = "api/v1/user/updateUserSettings"; // Your endpoint URL
|
||||
|
||||
for (let i = 0; i < localStorage.length; i++) {
|
||||
const key = localStorage.key(i);
|
||||
if(key !== 'debug' && key !== '0' && key !== '1') { // Only send non-ignored keys
|
||||
let hiddenField = document.createElement("input");
|
||||
hiddenField.type = "hidden";
|
||||
hiddenField.name = key;
|
||||
hiddenField.value = localStorage.getItem(key);
|
||||
form.appendChild(hiddenField);
|
||||
}
|
||||
}
|
||||
|
||||
document.body.appendChild(form);
|
||||
form.submit();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="mb-3 mt-4">
|
||||
<a href="logout">
|
||||
<button type="button" class="btn btn-danger" th:text="#{account.signOut}">Sign Out</button>
|
||||
</a>
|
||||
<a th:if="${role == 'ROLE_ADMIN'}" href="addUsers" target="_blank">
|
||||
<button type="button" class="btn btn-info" th:text="#{account.adminSettings}">Admin Settings</button>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!-- User Settings Title -->
|
||||
<h2 class="text-center" th:text="#{account.accountSettings}">User Settings</h2>
|
||||
<hr />
|
||||
<th:block th:if="${param.messageType != null and param.messageType.size() > 0}">
|
||||
<div th:if="${param.messageType[0] == 'notAuthenticated'}" class="alert alert-danger">
|
||||
<span th:text="#{notAuthenticatedMessage}">Default message if not found</span>
|
||||
</div>
|
||||
<div th:if="${param.messageType[0] == 'userNotFound'}" class="alert alert-danger">
|
||||
<span th:text="#{userNotFoundMessage}">Default message if not found</span>
|
||||
</div>
|
||||
<div th:if="${param.messageType[0] == 'incorrectPassword'}" class="alert alert-danger">
|
||||
<span th:text="#{incorrectPasswordMessage}">Default message if not found</span>
|
||||
</div>
|
||||
<div th:if="${param.messageType[0] == 'usernameExists'}" class="alert alert-danger">
|
||||
<span th:text="#{usernameExistsMessage}">Default message if not found</span>
|
||||
</div>
|
||||
</th:block>
|
||||
<!-- At the top of the user settings -->
|
||||
<h3 class="text-center"><span th:text="#{welcome} + ' ' + ${username}">User</span>!</h3>
|
||||
<th:block th:if="${error}">
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<span th:text="${error}">Error Message</span>
|
||||
</div>
|
||||
</th:block>
|
||||
<!-- Change Username Form -->
|
||||
<h4></h4>
|
||||
<form action="api/v1/user/change-username" method="post">
|
||||
<div class="mb-3">
|
||||
<label for="newUsername" th:text="#{account.changeUsername}">Change Username</label>
|
||||
<input type="text" class="form-control" name="newUsername" id="newUsername" th:placeholder="#{account.newUsername}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="currentPassword" th:text="#{password}">Password</label>
|
||||
<input type="password" class="form-control" name="currentPassword" id="currentPasswordUsername" th:placeholder="#{password}">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<button type="submit" class="btn btn-primary" th:text="#{account.changeUsername}">Change Username</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<hr /> <!-- Separator Line -->
|
||||
|
||||
<!-- Change Password Form -->
|
||||
<h4 th:text="#{account.changePassword}">Change Password?</h4>
|
||||
<form action="api/v1/user/change-password" method="post">
|
||||
<div class="mb-3">
|
||||
<label for="currentPassword" th:text="#{account.oldPassword}">Old Password</label>
|
||||
<input type="password" class="form-control" name="currentPassword" id="currentPasswordPassword" th:placeholder="#{account.oldPassword}">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="newPassword" th:text="#{account.newPassword}">New Password</label>
|
||||
<input type="password" class="form-control" name="newPassword" id="newPassword" th:placeholder="#{account.newPassword}">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="confirmNewPassword" th:text="#{account.confirmNewPassword}">Confirm New Password</label>
|
||||
<input type="password" class="form-control" name="confirmNewPassword" id="confirmNewPassword" th:placeholder="#{account.confirmNewPassword}">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<button type="submit" class="btn btn-primary" th:text="#{account.changePassword}">Change Password</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header" th:text="#{account.yourApiKey}"></div>
|
||||
<div class="card-body">
|
||||
<div class="input-group mb-3">
|
||||
<input type="password" class="form-control" id="apiKey" th:placeholder="#{account.yourApiKey}" readonly>
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-outline-secondary" id="copyBtn" type="button" onclick="copyToClipboard()">
|
||||
<img class="blackwhite-icon" src="images/clipboard.svg" alt="Copy" style="height:20px;">
|
||||
</button>
|
||||
<button class="btn btn-outline-secondary" id="showBtn" type="button" onclick="showApiKey()">
|
||||
<img class="blackwhite-icon" id="eyeIcon" src="images/eye.svg" alt="Toggle API Key Visibility" style="height:20px;">
|
||||
</button>
|
||||
<button class="btn btn-outline-secondary" id="refreshBtn" type="button" onclick="refreshApiKey()">
|
||||
<img class="blackwhite-icon" id="eyeIcon" src="images/arrow-clockwise.svg" alt="Refresh API-Key" style="height:20px;">
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function copyToClipboard() {
|
||||
const apiKeyElement = document.getElementById("apiKey");
|
||||
apiKeyElement.select();
|
||||
document.execCommand("copy");
|
||||
}
|
||||
|
||||
function showApiKey() {
|
||||
const apiKeyElement = document.getElementById("apiKey");
|
||||
const copyBtn = document.getElementById("copyBtn");
|
||||
const eyeIcon = document.getElementById("eyeIcon");
|
||||
if (apiKeyElement.type === "password") {
|
||||
apiKeyElement.type = "text";
|
||||
eyeIcon.src = "images/eye-slash.svg";
|
||||
copyBtn.disabled = false; // Enable copy button when API key is visible
|
||||
} else {
|
||||
apiKeyElement.type = "password";
|
||||
eyeIcon.src = "images/eye.svg";
|
||||
copyBtn.disabled = true; // Disable copy button when API key is hidden
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", async function() {
|
||||
try {
|
||||
let response = await fetch('/api/v1/user/get-api-key', { method: 'POST' });
|
||||
if (response.status === 200) {
|
||||
let apiKey = await response.text();
|
||||
manageUIState(apiKey);
|
||||
} else {
|
||||
manageUIState(null);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('There was an error:', error);
|
||||
}
|
||||
});
|
||||
|
||||
async function refreshApiKey() {
|
||||
try {
|
||||
let response = await fetch('/api/v1/user/update-api-key', { method: 'POST' });
|
||||
if (response.status === 200) {
|
||||
let apiKey = await response.text();
|
||||
manageUIState(apiKey);
|
||||
document.getElementById("apiKey").type = 'text';
|
||||
document.getElementById("copyBtn").disabled = false;
|
||||
} else {
|
||||
alert('Error refreshing API key.');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('There was an error:', error);
|
||||
}
|
||||
}
|
||||
|
||||
function manageUIState(apiKey) {
|
||||
const apiKeyElement = document.getElementById("apiKey");
|
||||
const showBtn = document.getElementById("showBtn");
|
||||
const copyBtn = document.getElementById("copyBtn");
|
||||
|
||||
if (apiKey && apiKey.trim().length > 0) {
|
||||
apiKeyElement.value = apiKey;
|
||||
showBtn.disabled = false;
|
||||
copyBtn.disabled = true;
|
||||
} else {
|
||||
apiKeyElement.value = "";
|
||||
showBtn.disabled = true;
|
||||
copyBtn.disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const form = document.querySelector('form[action="api/v1/user/change-password"]');
|
||||
|
||||
form.addEventListener('submit', function(event) {
|
||||
const newPassword = document.getElementById('newPassword').value;
|
||||
const confirmNewPassword = document.getElementById('confirmNewPassword').value;
|
||||
|
||||
if (newPassword !== confirmNewPassword) {
|
||||
alert('New Password and Confirm New Password must match.');
|
||||
event.preventDefault(); // Prevent form submission
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<hr /> <!-- Separator Line -->
|
||||
|
||||
<h4 th:text="#{account.syncTitle}">Sync browser settings with Account</h4>
|
||||
<div class="container mt-4">
|
||||
<h3 th:text="#{account.settingsCompare}">Settings Comparison:</h3>
|
||||
<table id="settingsTable" class="table table-bordered table-sm table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th th:text="#{account.property}">Property</th>
|
||||
<th th:text="#{account.accountSettings}">Account Setting</th>
|
||||
<th th:text="#{account.webBrowserSettings}">Web Browser Setting</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- This will be dynamically populated by JavaScript -->
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="buttons-container mt-3 text-center">
|
||||
<button id="syncToBrowser" class="btn btn-primary btn-sm" th:text="#{account.syncToBrowser}">Sync Account -> Browser</button>
|
||||
<button id="syncToAccount" class="btn btn-secondary btn-sm" th:text="#{account.syncToAccount}">Sync Account <- Browser</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script th:inline="javascript">
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const settingsTableBody = document.querySelector("#settingsTable tbody");
|
||||
|
||||
/*<![CDATA[*/
|
||||
var accountSettingsString = /*[[${settings}]]*/ {};
|
||||
/*]]>*/
|
||||
var accountSettings = JSON.parse(accountSettingsString);
|
||||
|
||||
let allKeys = new Set([...Object.keys(accountSettings), ...Object.keys(localStorage)]);
|
||||
|
||||
allKeys.forEach(key => {
|
||||
if(key === 'debug' || key === '0' || key === '1') return; // Ignoring specific keys
|
||||
|
||||
const accountValue = accountSettings[key] || '-';
|
||||
const browserValue = localStorage.getItem(key) || '-';
|
||||
|
||||
const row = settingsTableBody.insertRow();
|
||||
const propertyCell = row.insertCell(0);
|
||||
const accountCell = row.insertCell(1);
|
||||
const browserCell = row.insertCell(2);
|
||||
|
||||
propertyCell.textContent = key;
|
||||
accountCell.textContent = accountValue;
|
||||
browserCell.textContent = browserValue;
|
||||
});
|
||||
|
||||
document.getElementById('syncToBrowser').addEventListener('click', function() {
|
||||
// First, clear the local storage
|
||||
localStorage.clear();
|
||||
|
||||
// Then, set the account settings to local storage
|
||||
for (let key in accountSettings) {
|
||||
if(key !== 'debug' && key !== '0' && key !== '1') { // Only sync non-ignored keys
|
||||
localStorage.setItem(key, accountSettings[key]);
|
||||
}
|
||||
}
|
||||
location.reload(); // Refresh the page after sync
|
||||
});
|
||||
|
||||
document.getElementById('syncToAccount').addEventListener('click', function() {
|
||||
let form = document.createElement("form");
|
||||
form.method = "POST";
|
||||
form.action = "api/v1/user/updateUserSettings"; // Your endpoint URL
|
||||
|
||||
for (let i = 0; i < localStorage.length; i++) {
|
||||
const key = localStorage.key(i);
|
||||
if(key !== 'debug' && key !== '0' && key !== '1') { // Only send non-ignored keys
|
||||
let hiddenField = document.createElement("input");
|
||||
hiddenField.type = "hidden";
|
||||
hiddenField.name = key;
|
||||
hiddenField.value = localStorage.getItem(key);
|
||||
form.appendChild(hiddenField);
|
||||
}
|
||||
}
|
||||
|
||||
document.body.appendChild(form);
|
||||
form.submit();
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
<div class="mb-3 mt-4">
|
||||
<a href="logout">
|
||||
<button type="button" class="btn btn-danger" th:text="#{account.signOut}">Sign Out</button>
|
||||
</a>
|
||||
<a th:if="${role == 'ROLE_ADMIN'}" href="addUsers" target="_blank">
|
||||
<button type="button" class="btn btn-info" th:text="#{account.adminSettings}">Admin Settings</button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div th:insert="~{fragments/footer.html :: footer}"></div>
|
||||
</div>
|
||||
<th:block th:insert="~{fragments/footer.html :: footer}"></th:block>
|
||||
</div>
|
||||
</body>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user