change add numbers grid and remove files from pipelines
This commit is contained in:
parent
29aabdfba8
commit
d07e3e6522
2 changed files with 322 additions and 278 deletions
|
@ -75,12 +75,12 @@ document.getElementById('submitConfigBtn').addEventListener('click', function()
|
|||
"operation": selectedOperation,
|
||||
"parameters": parameters
|
||||
}],
|
||||
"_examples": {
|
||||
"outputDir" : "{outputFolder}/{folderName}",
|
||||
"outputFileName" : "{filename}-{pipelineName}-{date}-{time}"
|
||||
},
|
||||
"outputDir" : "httpWebRequest",
|
||||
"outputFileName" : "{filename}"
|
||||
"_examples": {
|
||||
"outputDir": "{outputFolder}/{folderName}",
|
||||
"outputFileName": "{filename}-{pipelineName}-{date}-{time}"
|
||||
},
|
||||
"outputDir": "httpWebRequest",
|
||||
"outputFileName": "{filename}"
|
||||
};
|
||||
|
||||
let pipelineConfigJson = JSON.stringify(pipelineConfig, null, 2);
|
||||
|
@ -126,11 +126,11 @@ let operationSettings = {};
|
|||
fetch('v3/api-docs')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
|
||||
|
||||
apiDocs = data.paths;
|
||||
let operationsDropdown = document.getElementById('operationsDropdown');
|
||||
const ignoreOperations = ["/handleData", "operationToIgnore"]; // Add the operations you want to ignore here
|
||||
|
||||
|
||||
operationsDropdown.innerHTML = '';
|
||||
|
||||
let operationsByTag = {};
|
||||
|
@ -148,25 +148,25 @@ fetch('v3/api-docs')
|
|||
});
|
||||
|
||||
// Specify the order of tags
|
||||
let tagOrder = ["General", "Security", "Convert", "Other", "Filter"];
|
||||
let tagOrder = ["General", "Security", "Convert", "Other", "Filter"];
|
||||
|
||||
// Create dropdown options
|
||||
tagOrder.forEach(tag => {
|
||||
if (operationsByTag[tag]) {
|
||||
let group = document.createElement('optgroup');
|
||||
group.label = tag;
|
||||
// Create dropdown options
|
||||
tagOrder.forEach(tag => {
|
||||
if (operationsByTag[tag]) {
|
||||
let group = document.createElement('optgroup');
|
||||
group.label = tag;
|
||||
|
||||
operationsByTag[tag].forEach(operationPath => {
|
||||
let option = document.createElement('option');
|
||||
let operationWithoutSlash = operationPath.replace(/\//g, ''); // Remove slashes
|
||||
option.textContent = operationWithoutSlash;
|
||||
option.value = operationPath; // Keep the value with slashes for querying
|
||||
group.appendChild(option);
|
||||
});
|
||||
operationsByTag[tag].forEach(operationPath => {
|
||||
let option = document.createElement('option');
|
||||
let operationWithoutSlash = operationPath.replace(/\//g, ''); // Remove slashes
|
||||
option.textContent = operationWithoutSlash;
|
||||
option.value = operationPath; // Keep the value with slashes for querying
|
||||
group.appendChild(option);
|
||||
});
|
||||
|
||||
operationsDropdown.appendChild(group);
|
||||
}
|
||||
});
|
||||
operationsDropdown.appendChild(group);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
@ -177,9 +177,9 @@ document.getElementById('addOperationBtn').addEventListener('click', function()
|
|||
let listItem = document.createElement('li');
|
||||
listItem.className = "list-group-item";
|
||||
let hasSettings = (apiDocs[selectedOperation] && apiDocs[selectedOperation].post &&
|
||||
((apiDocs[selectedOperation].post.parameters && apiDocs[selectedOperation].post.parameters.length > 0) ||
|
||||
(apiDocs[selectedOperation].post.requestBody &&
|
||||
apiDocs[selectedOperation].post.requestBody.content['multipart/form-data'].schema.properties)));
|
||||
((apiDocs[selectedOperation].post.parameters && apiDocs[selectedOperation].post.parameters.length > 0) ||
|
||||
(apiDocs[selectedOperation].post.requestBody &&
|
||||
apiDocs[selectedOperation].post.requestBody.content['multipart/form-data'].schema.properties)));
|
||||
|
||||
|
||||
|
||||
|
@ -226,77 +226,86 @@ document.getElementById('addOperationBtn').addEventListener('click', function()
|
|||
let pipelineSettingsModal = document.getElementById('pipelineSettingsModal');
|
||||
let pipelineSettingsContent = document.getElementById('pipelineSettingsContent');
|
||||
let operationData = apiDocs[operation].post.parameters || [];
|
||||
let requestBodyData = apiDocs[operation].post.requestBody.content['multipart/form-data'].schema.properties || {};
|
||||
|
||||
// Combine operationData and requestBodyData into a single array
|
||||
operationData = operationData.concat(Object.keys(requestBodyData).map(key => ({
|
||||
name: key,
|
||||
schema: requestBodyData[key]
|
||||
})));
|
||||
let requestBodyData = apiDocs[operation].post.requestBody.content['multipart/form-data'].schema.properties || {};
|
||||
|
||||
// Combine operationData and requestBodyData into a single array
|
||||
operationData = operationData.concat(Object.keys(requestBodyData).map(key => ({
|
||||
name: key,
|
||||
schema: requestBodyData[key]
|
||||
})));
|
||||
|
||||
pipelineSettingsContent.innerHTML = '';
|
||||
|
||||
operationData.forEach(parameter => {
|
||||
let parameterDiv = document.createElement('div');
|
||||
parameterDiv.className = "form-group";
|
||||
// If the parameter name is 'fileInput', return early to skip the rest of this iteration
|
||||
if (parameter.name === 'fileInput') return;
|
||||
|
||||
let parameterDiv = document.createElement('div');
|
||||
parameterDiv.className = "form-group";
|
||||
|
||||
let parameterLabel = document.createElement('label');
|
||||
parameterLabel.textContent = `${parameter.name} (${parameter.schema.type}): `;
|
||||
parameterLabel.title = parameter.description;
|
||||
parameterDiv.appendChild(parameterLabel);
|
||||
let parameterLabel = document.createElement('label');
|
||||
parameterLabel.textContent = `${parameter.name} (${parameter.schema.type}): `;
|
||||
parameterLabel.title = parameter.description;
|
||||
parameterDiv.appendChild(parameterLabel);
|
||||
|
||||
let parameterInput;
|
||||
let parameterInput;
|
||||
|
||||
// check if enum exists in schema
|
||||
if (parameter.schema.enum) {
|
||||
// if enum exists, create a select element
|
||||
parameterInput = document.createElement('select');
|
||||
parameterInput.className = "form-control";
|
||||
// check if enum exists in schema
|
||||
if (parameter.schema.enum) {
|
||||
// if enum exists, create a select element
|
||||
parameterInput = document.createElement('select');
|
||||
parameterInput.className = "form-control";
|
||||
|
||||
// iterate over each enum value and create an option for it
|
||||
parameter.schema.enum.forEach(value => {
|
||||
let option = document.createElement('option');
|
||||
option.value = value;
|
||||
option.text = value;
|
||||
parameterInput.appendChild(option);
|
||||
});
|
||||
} else {
|
||||
// switch-case statement for handling non-enum types
|
||||
switch (parameter.schema.type) {
|
||||
case 'string':
|
||||
if (parameter.schema.format === 'binary') {
|
||||
// This is a file input
|
||||
parameterInput = document.createElement('input');
|
||||
parameterInput.type = 'file';
|
||||
parameterInput.className = "form-control";
|
||||
} else {
|
||||
parameterInput = document.createElement('input');
|
||||
parameterInput.type = 'text';
|
||||
parameterInput.className = "form-control";
|
||||
}
|
||||
break;
|
||||
case 'number':
|
||||
case 'integer':
|
||||
parameterInput = document.createElement('input');
|
||||
parameterInput.type = 'number';
|
||||
parameterInput.className = "form-control";
|
||||
break;
|
||||
case 'boolean':
|
||||
parameterInput = document.createElement('input');
|
||||
parameterInput.type = 'checkbox';
|
||||
break;
|
||||
case 'array':
|
||||
case 'object':
|
||||
parameterInput = document.createElement('textarea');
|
||||
parameterInput.placeholder = `Enter a JSON formatted ${parameter.schema.type}`;
|
||||
parameterInput.className = "form-control";
|
||||
break;
|
||||
default:
|
||||
parameterInput = document.createElement('input');
|
||||
parameterInput.type = 'text';
|
||||
parameterInput.className = "form-control";
|
||||
}
|
||||
}
|
||||
// iterate over each enum value and create an option for it
|
||||
parameter.schema.enum.forEach(value => {
|
||||
let option = document.createElement('option');
|
||||
option.value = value;
|
||||
option.text = value;
|
||||
parameterInput.appendChild(option);
|
||||
});
|
||||
} else {
|
||||
// switch-case statement for handling non-enum types
|
||||
switch (parameter.schema.type) {
|
||||
case 'string':
|
||||
if (parameter.schema.format === 'binary') {
|
||||
// This is a file input
|
||||
|
||||
//parameterInput = document.createElement('input');
|
||||
//parameterInput.type = 'file';
|
||||
//parameterInput.className = "form-control";
|
||||
|
||||
parameterInput = document.createElement('input');
|
||||
parameterInput.type = 'text';
|
||||
parameterInput.className = "form-control";
|
||||
parameterInput.value = "automatedFileInput";
|
||||
} else {
|
||||
parameterInput = document.createElement('input');
|
||||
parameterInput.type = 'text';
|
||||
parameterInput.className = "form-control";
|
||||
}
|
||||
break;
|
||||
case 'number':
|
||||
case 'integer':
|
||||
parameterInput = document.createElement('input');
|
||||
parameterInput.type = 'number';
|
||||
parameterInput.className = "form-control";
|
||||
break;
|
||||
case 'boolean':
|
||||
parameterInput = document.createElement('input');
|
||||
parameterInput.type = 'checkbox';
|
||||
break;
|
||||
case 'array':
|
||||
case 'object':
|
||||
parameterInput = document.createElement('textarea');
|
||||
parameterInput.placeholder = `Enter a JSON formatted ${parameter.schema.type}`;
|
||||
parameterInput.className = "form-control";
|
||||
break;
|
||||
default:
|
||||
parameterInput = document.createElement('input');
|
||||
parameterInput.type = 'text';
|
||||
parameterInput.className = "form-control";
|
||||
}
|
||||
}
|
||||
parameterInput.id = parameter.name;
|
||||
|
||||
if (operationSettings[operation] && operationSettings[operation][parameter.name] !== undefined) {
|
||||
|
@ -380,12 +389,12 @@ document.getElementById('addOperationBtn').addEventListener('click', function()
|
|||
let pipelineConfig = {
|
||||
"name": pipelineName,
|
||||
"pipeline": [],
|
||||
"_examples": {
|
||||
"outputDir" : "{outputFolder}/{folderName}",
|
||||
"outputFileName" : "{filename}-{pipelineName}-{date}-{time}"
|
||||
},
|
||||
"outputDir" : "httpWebRequest",
|
||||
"outputFileName" : "{filename}"
|
||||
"_examples": {
|
||||
"outputDir": "{outputFolder}/{folderName}",
|
||||
"outputFileName": "{filename}-{pipelineName}-{date}-{time}"
|
||||
},
|
||||
"outputDir": "httpWebRequest",
|
||||
"outputFileName": "{filename}"
|
||||
};
|
||||
|
||||
for (let i = 0; i < pipelineList.length; i++) {
|
||||
|
@ -411,74 +420,74 @@ document.getElementById('addOperationBtn').addEventListener('click', function()
|
|||
});
|
||||
|
||||
async function processPipelineConfig(configString) {
|
||||
let pipelineConfig = JSON.parse(configString);
|
||||
let pipelineList = document.getElementById('pipelineList');
|
||||
|
||||
while (pipelineList.firstChild) {
|
||||
pipelineList.removeChild(pipelineList.firstChild);
|
||||
}
|
||||
document.getElementById('pipelineName').value = pipelineConfig.name
|
||||
for (const operationConfig of pipelineConfig.pipeline) {
|
||||
let operationsDropdown = document.getElementById('operationsDropdown');
|
||||
operationsDropdown.value = operationConfig.operation;
|
||||
operationSettings[operationConfig.operation] = operationConfig.parameters;
|
||||
let pipelineConfig = JSON.parse(configString);
|
||||
let pipelineList = document.getElementById('pipelineList');
|
||||
|
||||
// assuming addOperation is async
|
||||
await new Promise((resolve) => {
|
||||
document.getElementById('addOperationBtn').addEventListener('click', resolve, { once: true });
|
||||
document.getElementById('addOperationBtn').click();
|
||||
});
|
||||
while (pipelineList.firstChild) {
|
||||
pipelineList.removeChild(pipelineList.firstChild);
|
||||
}
|
||||
document.getElementById('pipelineName').value = pipelineConfig.name
|
||||
for (const operationConfig of pipelineConfig.pipeline) {
|
||||
let operationsDropdown = document.getElementById('operationsDropdown');
|
||||
operationsDropdown.value = operationConfig.operation;
|
||||
operationSettings[operationConfig.operation] = operationConfig.parameters;
|
||||
|
||||
let lastOperation = pipelineList.lastChild;
|
||||
|
||||
Object.keys(operationConfig.parameters).forEach(parameterName => {
|
||||
let input = document.getElementById(parameterName);
|
||||
if (input) {
|
||||
switch (input.type) {
|
||||
case 'checkbox':
|
||||
input.checked = operationConfig.parameters[parameterName];
|
||||
break;
|
||||
case 'number':
|
||||
input.value = operationConfig.parameters[parameterName].toString();
|
||||
break;
|
||||
case 'file':
|
||||
if (parameterName !== 'fileInput') {
|
||||
// Create a new file input element
|
||||
let newInput = document.createElement('input');
|
||||
newInput.type = 'file';
|
||||
newInput.id = parameterName;
|
||||
// assuming addOperation is async
|
||||
await new Promise((resolve) => {
|
||||
document.getElementById('addOperationBtn').addEventListener('click', resolve, { once: true });
|
||||
document.getElementById('addOperationBtn').click();
|
||||
});
|
||||
|
||||
// Add the new file input to the main page (change the selector according to your needs)
|
||||
document.querySelector('#main').appendChild(newInput);
|
||||
}
|
||||
break;
|
||||
case 'text':
|
||||
case 'textarea':
|
||||
default:
|
||||
input.value = JSON.stringify(operationConfig.parameters[parameterName]);
|
||||
}
|
||||
}
|
||||
});
|
||||
let lastOperation = pipelineList.lastChild;
|
||||
|
||||
Object.keys(operationConfig.parameters).forEach(parameterName => {
|
||||
let input = document.getElementById(parameterName);
|
||||
if (input) {
|
||||
switch (input.type) {
|
||||
case 'checkbox':
|
||||
input.checked = operationConfig.parameters[parameterName];
|
||||
break;
|
||||
case 'number':
|
||||
input.value = operationConfig.parameters[parameterName].toString();
|
||||
break;
|
||||
case 'file':
|
||||
if (parameterName !== 'fileInput') {
|
||||
// Create a new file input element
|
||||
let newInput = document.createElement('input');
|
||||
newInput.type = 'file';
|
||||
newInput.id = parameterName;
|
||||
|
||||
// Add the new file input to the main page (change the selector according to your needs)
|
||||
document.querySelector('#main').appendChild(newInput);
|
||||
}
|
||||
break;
|
||||
case 'text':
|
||||
case 'textarea':
|
||||
default:
|
||||
input.value = JSON.stringify(operationConfig.parameters[parameterName]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
document.getElementById('uploadPipelineBtn').addEventListener('click', function() {
|
||||
document.getElementById('uploadPipelineInput').click();
|
||||
document.getElementById('uploadPipelineInput').click();
|
||||
});
|
||||
|
||||
|
||||
document.getElementById('uploadPipelineInput').addEventListener('change', function(e) {
|
||||
let reader = new FileReader();
|
||||
reader.onload = function(event) {
|
||||
processPipelineConfig(event.target.result);
|
||||
};
|
||||
reader.readAsText(e.target.files[0]);
|
||||
let reader = new FileReader();
|
||||
reader.onload = function(event) {
|
||||
processPipelineConfig(event.target.result);
|
||||
};
|
||||
reader.readAsText(e.target.files[0]);
|
||||
});
|
||||
|
||||
|
||||
document.getElementById('pipelineSelect').addEventListener('change', function(e) {
|
||||
let selectedPipelineJson = e.target.value; // assuming the selected value is the JSON string of the pipeline config
|
||||
processPipelineConfig(selectedPipelineJson);
|
||||
let selectedPipelineJson = e.target.value; // assuming the selected value is the JSON string of the pipeline config
|
||||
processPipelineConfig(selectedPipelineJson);
|
||||
});
|
||||
|
||||
|
||||
|
|
|
@ -1,125 +1,160 @@
|
|||
<!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=#{autoCrop.title})}"></th:block>
|
||||
|
||||
|
||||
<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-6">
|
||||
<h2 th:text="#{addPageNumbers.header}"></h2>
|
||||
<form method="post" enctype="multipart/form-data" th:action="@{add-page-numbers}">
|
||||
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
|
||||
<br>
|
||||
<div class="form-group">
|
||||
<label for="customMargin">Margin Size</label>
|
||||
<select class="form-control" id="customMargin" name="customMargin" required>
|
||||
<option value="" disabled selected>Select a margin size</option>
|
||||
<option value="small">Small</option>
|
||||
<option value="medium">Medium</option>
|
||||
<option value="large">Large</option>
|
||||
<option value="x-large">X-Large</option>
|
||||
</select>
|
||||
</div>
|
||||
<style>
|
||||
.a4container {
|
||||
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
grid-template-rows: repeat(3, 1fr);
|
||||
gap: 0; /* No gap between the cells */
|
||||
width: 50%;
|
||||
aspect-ratio: 0.707; /* this sets the width-height ratio approximately same as A4 paper */
|
||||
justify-items: stretch; /* Stretch items to fill their cells */
|
||||
align-items: stretch; /* Stretch items to fill their cells */
|
||||
border: 1px solid #ddd;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.cell {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 1em;
|
||||
color: #333;
|
||||
cursor: pointer;
|
||||
background-color: #ccc;
|
||||
border: 1px solid #fff; /* Add a border to each cell */
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.cell:hover {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
#myForm {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<div class="form-group">
|
||||
<label for="position">Position</label>
|
||||
<div class="a4container">
|
||||
<div id="1" class="cell">1</div>
|
||||
<div id="2" class="cell">2</div>
|
||||
<div id="3" class="cell">3</div>
|
||||
<div id="4" class="cell">4</div>
|
||||
<div id="5" class="cell">5</div>
|
||||
<div id="6" class="cell">6</div>
|
||||
<div id="7" class="cell">7</div>
|
||||
<div id="8" class="cell">8</div>
|
||||
<div id="9" class="cell">9</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<form id="myForm">
|
||||
<input type="number" id="numberInput" name="number" min="1" max="9" required>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
let cells = document.querySelectorAll('.cell');
|
||||
let inputField = document.getElementById('numberInput');
|
||||
|
||||
cells.forEach(cell => {
|
||||
cell.addEventListener('click', function(e) {
|
||||
let selectedLocation = e.target.id;
|
||||
inputField.value = selectedLocation; // Set input field's value
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="startingNumber">Starting Number</label>
|
||||
<input type="number" class="form-control" id="startingNumber" name="startingNumber" min="1" required value="1"/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="pagesToNumber">Pages to Number</label>
|
||||
<input type="text" class="form-control" id="pagesToNumber" name="pagesToNumber" placeholder="Which pages to number, default 'all', also accepts 1-5 or 2,5,9 etc" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="customText">Custom Text</label>
|
||||
<input type="text" class="form-control" id="customText" name="customText" placeholder="Default just number, also accepts 'Page {n} of {total}', 'Tag-{n}' etc"/>
|
||||
</div>
|
||||
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{addPageNumbers.submit}"></button>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div th:insert="~{fragments/footer.html :: footer}"></div>
|
||||
</div>
|
||||
</body>
|
||||
<!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=#{autoCrop.title})}"></th:block>
|
||||
|
||||
|
||||
<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-6">
|
||||
<h2 th:text="#{addPageNumbers.header}"></h2>
|
||||
<form method="post" enctype="multipart/form-data"
|
||||
th:action="@{add-page-numbers}">
|
||||
<div
|
||||
th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
|
||||
<br>
|
||||
<div class="form-group">
|
||||
<label for="customMargin">Margin Size</label> <select
|
||||
class="form-control" id="customMargin" name="customMargin"
|
||||
required>
|
||||
<option value="" disabled selected>Select a margin
|
||||
size</option>
|
||||
<option value="small">Small</option>
|
||||
<option value="medium">Medium</option>
|
||||
<option value="large">Large</option>
|
||||
<option value="x-large">X-Large</option>
|
||||
</select>
|
||||
</div>
|
||||
<style>
|
||||
.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;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<div class="form-group">
|
||||
<label for="position">Position</label>
|
||||
<div class="a4container">
|
||||
<div class="pageNumber" id="1" style="top: 10%; left: 10%;">1</div>
|
||||
<div class="pageNumber" id="2" style="top: 10%; left: 50%;">2</div>
|
||||
<div class="pageNumber" id="3" style="top: 10%; left: 90%;">3</div>
|
||||
<div class="pageNumber" id="4" style="top: 50%; left: 10%;">4</div>
|
||||
<div class="pageNumber" id="5" style="top: 50%; left: 50%;">5</div>
|
||||
<div class="pageNumber" id="6" style="top: 50%; left: 90%;">6</div>
|
||||
<div class="pageNumber" id="7" style="top: 90%; left: 10%;">7</div>
|
||||
<div class="pageNumber" id="8" style="top: 90%; left: 50%;">8</div>
|
||||
<div class="pageNumber" id="9" style="top: 90%; left: 90%;">9</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<input type="hidden" id="numberInput" name="position" min="1"
|
||||
max="9" required>
|
||||
<div class="form-group">
|
||||
<label for="startingNumber">Starting Number</label> <input
|
||||
type="number" class="form-control" id="startingNumber"
|
||||
name="startingNumber" min="1" required value="1" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="pagesToNumber">Pages to Number</label> <input
|
||||
type="text" class="form-control" id="pagesToNumber"
|
||||
name="pagesToNumber"
|
||||
placeholder="Which pages to number, default 'all', also accepts 1-5 or 2,5,9 etc" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="customText">Custom Text</label> <input type="text"
|
||||
class="form-control" id="customText" name="customText"
|
||||
placeholder="Default just number, also accepts 'Page {n} of {total}', 'Tag-{n}' etc" />
|
||||
</div>
|
||||
<button type="submit" id="submitBtn" class="btn btn-primary"
|
||||
th:text="#{addPageNumbers.submit}"></button>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
let cells = document.querySelectorAll('.pageNumber');
|
||||
let inputField = document.getElementById('numberInput');
|
||||
|
||||
cells.forEach(cell => {
|
||||
cell.addEventListener('click', function(e) {
|
||||
cells.forEach(cell => {
|
||||
cell.classList.remove('selectedPosition'); // Remove selected class from all cells
|
||||
cell.classList.remove('selectedHovered'); // Also remove selectedHovered class
|
||||
});
|
||||
let selectedLocation = e.target.id;
|
||||
inputField.value = selectedLocation;
|
||||
e.target.classList.add('selectedPosition'); // Add selected class to clicked cell
|
||||
e.target.classList.add('selectedHovered'); // Add selectedHovered class
|
||||
});
|
||||
|
||||
cell.addEventListener('mouseenter', function(e) {
|
||||
if(e.target.classList.contains('selectedPosition')) {
|
||||
e.target.classList.add('selectedHovered');
|
||||
}
|
||||
});
|
||||
|
||||
cell.addEventListener('mouseleave', function(e) {
|
||||
if(e.target.classList.contains('selectedPosition')) {
|
||||
e.target.classList.remove('selectedHovered');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
</div>
|
||||
<div th:insert="~{fragments/footer.html :: footer}"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in a new issue