Commit 08e2c531 by Jorem Magcawas

commit all files

parent 9422f066
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Web-GDE</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.wst.validation.validationbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.wst.jsdt.core.jsNature</nature>
</natures>
</projectDescription>
# Web-GDE
A prototype Web General Data Entry Tool.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Ending session...</title>
</head>
<body>
<div class="dv_body">
<div class="content">
<div class="panel-widget" style="display: flex;justify-content: center;padding: 100px 0;">
<div class="panel-body">
<div class="logout-icon">
<img src="https://static.vecteezy.com/system/resources/thumbnails/000/593/212/small/40_350.jpg" width="200px" height="200px" alt="logout icon" style="display: block;margin-left: auto;margin-right: auto;width: 50%;">
</div>
<h1 style="text-align: center;font-family: sans-serif; font-size: 36px;color: rgb(54,54,54); max-width: 500px; min-width: 100px;">Session has been successfully ended</h1>
<h3 style="text-align: center;font-family: sans-serif;color: rgb(54,54,54); max-width: 500px; min-width: 100px;">Thank you for using GDE Tool</h3>
<h5 style="text-align: center;font-family: sans-serif;color: rgb(54,54,54); max-width: 500px; min-width: 100px;">Please click <a href="./index.html">here</a> to return to the GDE Tool</h5>
</div>
</div>
</div>
</div>
</body>
</html>
\ No newline at end of file
/**
* for testing purposes, below are different files to be used showing
* some possible configurations of the file
*/
// schema with no "SECTION" key
// const SCHEMA_FILE = "./src/sample_schema/no_section.json"
// schema with missing fields (fieldLabel, validation)
// const SCHEMA_FILE = "./src/sample_schema/missing_fields.json"
// schema with 20 fields
// const SCHEMA_FILE = "./src/sample_schema/20_field_schema.json"
// schema with 15 fields
// const SCHEMA_FILE = "./src/sample_schema/15_field_schema.json"
// schema with 10 fields
const SCHEMA_FILE = "./src/sample_schema/10_field_schema.json"
// schema with 5 fields and all possible collections
// const SCHEMA_FILE = "./src/sample_schema/5_field_schema.json"
// const SCHEMA_FILE = "./src/sample_schema/Sample_Schema.json"
const INPUT_FILES = ["./input/Ong, Mae Janica - Application Form.TIFF","./input/Magalona, Rowell James - Application Form.TIFF","./input/Felizardo, Brylle Theodure - Application Form.TIFF","./input/Laxamana, Conrad John - Application Form.TIFF"] // list of URLs
const OUTPUT_FILES = "../../output/"
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- <link rel="stylesheet" type="text/css" href="gde.css"> -->
<!-- CSS for the fields -->
<link rel="stylesheet" href="style.css">
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
<script src="https://code.jquery.com/jquery-3.6.0.min.js"
integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<script src="https://cdn.rawgit.com/seikichi/tiff.js/master/tiff.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js" type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.8.0/jszip.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.8.0/xlsx.js"></script>
<script src="https://requirejs.org/docs/release/2.3.5/minified/require.js"></script>
<script src="./src/accessFile/accessFile.js"></script>
<script src="./src/XMLWriter/Global.js" language="javascript"></script>
<script src="./src/XMLWriter/XMLWriter.js" language="javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js%22%3E"></script>
<script src="./src/XMLWriter/XML_Saver.js" language="javascript"></script>
<script src="./src/submit/submit.js" language="javascript"></script>
</head>
<script src="./src/fetchConfig/fetchConfig.js"></script>
<script>
fetchConfig();
</script>
<body>
<div id="no-config" style="display:none"> There is no config file found</div>
<div id="with-config" style="display:grid">
<!-- Creates the right pane of the window -->
<aside class="sidebar" id="sidebar">
<!-- Holds the login credentials -->
<!-- <div class="sidebar" id="username">
<button class="sidebar" id="user-settings">...</button>
<span class="sidebar" id="username-text">username@svi ()</span>
</div> -->
<!-- Holds the project description -->
<!-- <aside class="sidebar" id="project-description">
<p class="sidebar" id="column"><br />
</p>
<p class="sidebar" id="column">
</p>
</aside> -->
<!-- Space for the fields -->
<!-- <div class="sidebar" id="fields"> </div> -->
<form id='fields' style="display: flex; flex-direction:column;" onsubmit="return submitForm(event);"></form>
</aside>
<!-- Embed viewer -->
<main id="viewer">
<!-- CHANGED: commented out button that triggers the modal -->
<!-- <div> -->
<!-- CHANGED: keep img since id is used for displaying image on modal -->
<img id="TestTIFFDisplay">
<!-- <br><br> -->
<!-- Trigger/Open The Modal -->
<!-- <button id="TestBtn">Open TIFF Image</button>
</div> -->
<div id="TiffViewerModal">
<!-- Modal content -->
<div class="TiffModalContent">
<div class="bar">
<progress id="progressBar" value="0" max="100" style="width:300px;"></progress>
<div id="status">&nbsp;</div>
<h3 id="progress">&nbsp;</h3>
</div>
<div id="TiffModalHeader">
<!-- CHANGED: commented out close button, to avoid closing the modal -->
<!-- <span class="TiffModalClose">&times;</span> -->
</div>
<div id="TiffModalBody">
</div>
<div id="TiffModalFooter">
</div>
</div>
</div>
<img src="" id="tableBanner" />
<img id="myImage" crossorigin="anonymous" src="">
<img id="ImgPrev" crossorigin="anonymous" src="">
<img id="my-img" />
<img id="img" />
</main>
</div>
</body>
<script src="./config.js"></script>
<script src="./src/captureMetrics/captureMetrics.js"></script>
<script src="./src/fetchSchema/fetchSchema.js"></script><!-- fetch the schema -->
<script src="./src/validateSchema/validateSchema.js"></script> <!-- validate the schema -->
<script src="./src/validateInput/validateInput.js"></script> <!-- functions for validating inputs -->
<script src="./src/getFields/getFields.js"></script> <!-- display the input fields -->
<!-- <script src="./src/accessFile/accessFile.js"></script> -->
<script>
if (!found) { //if config file is not found, change the screen
let withConfig = document.getElementById("with-config");
let noConfig = document.getElementById("no-config");
if (withConfig.style.display === "grid") {
withConfig.style.display = "none";
noConfig.style.display = "block";
}
} else {
startMetricCapture();
displayFields("fields");
accessFile();
}
</script>
<script src="./src/endSession/endSession.js"></script>
<script src="./src/tiffViewer/tiffViewer.js"></script>
<script src="./src/highlight/highlight.js"></script>
</html>
\ No newline at end of file
function JSettings()
{
this.IE=document.all?true:false;
this.MouseX=_JSettings_MouseX;
this.MouseY=_JSettings_MouseY;
this.SrcElement=_JSettings_SrcElement;
this.Parent=_JSettings_Parent;
this.RunOnLoad=_JSettings_RunOnLoad;
this.FindParent=_JSettings_FindParent;
this.FindChild=_JSettings_FindChild;
this.FindSibling=_JSettings_FindSibling;
this.FindParentTag=_JSettings_FindParentTag;
}
function _JSettings_MouseX(e)
{return this.IE?event.clientX:e.clientX;}
function _JSettings_MouseY(e)
{return this.IE?event.clientY:e.clientY;}
function _JSettings_SrcElement(e)
{return this.IE?event.srcElement:e.target;}
function _JSettings_Parent(Node)
{return this.IE?Node.parentNode:Node.parentElement;}
function _JSettings_RunOnLoad(Meth){var Prev=(window.onload)?window.onload:function(){};window.onload=function(){Prev();Meth();};}
function _JSettings_FindParent(Node, Attrib, Value)
{var Root = document.getElementsByTagName("BODY")[0];
Node = Node.parentNode; while (Node != Root && Node.getAttribute(Attrib) != Value){Node=Node.parentNode;}
if (Node.getAttribute(Attrib) == Value) {return Node;} else {return null;}}
function _JSettings_FindParentTag(Node, TagName)
{var Root = document.getElementsByTagName("BODY")[0];
TagName=TagName.toLowerCase();
Node = Node.parentNode; while (Node != Root && Node.tagName.toLowerCase() != TagName){Node=Node.parentNode;}
if (Node.tagName.toLowerCase() == TagName) {return Node;} else {return null;}}
function _JSettings_FindChild(Node, Attrib, Value)
{
if (Node.getAttribute)
if (Node.getAttribute(Attrib) == Value) return Node;
var I=0;
var Ret = null;
for (I=0;I<Node.childNodes.length;I++)
{
Ret = FindChildByAttrib(Node.childNodes[I]);
if (Ret) return Ret;
}
return null;
}
function _JSettings_FindSibling(Node, Attrib, Value)
{
var Nodes=Node.parentNode.childNodes;
var I=0;
for (I=0;I<Nodes.length;I++)
{
if (Nodes[I].getAttribute)
{
if (Nodes[I].getAttribute(Attrib) == Value)
{return Nodes[I];}
}
}
return null;
}
var Settings = new JSettings();
\ No newline at end of file
function XMLWriter()
{
this.XML=[];
this.Nodes=[];
this.State="";
this.FormatXML = function(Str)
{
if (Str)
return Str.replace(/&/g, "&amp;").replace(/\"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
return ""
}
this.BeginNode = function(Name)
{
if (!Name) return;
if (this.State=="beg") this.XML.push(">");
this.State="beg";
this.Nodes.push(Name);
this.XML.push("<"+Name);
}
this.EndNode = function()
{
if (this.State=="beg")
{
this.XML.push("/>");
this.Nodes.pop();
}
else if (this.Nodes.length>0)
this.XML.push("</"+this.Nodes.pop()+">");
this.State="";
}
this.Attrib = function(Name, Value)
{
if (this.State!="beg" || !Name) return;
this.XML.push(" "+Name+"=\""+this.FormatXML(Value)+"\"");
}
this.WriteString = function(Value)
{
if (this.State=="beg") this.XML.push(">");
this.XML.push(this.FormatXML(Value));
this.State="";
}
this.Node = function(Name, Value)
{
if (!Name) return;
if (this.State=="beg") this.XML.push(">");
this.XML.push((Value=="" || !Value)?"<"+Name+"/>":"<"+Name+">"+this.FormatXML(Value)+"</"+Name+">");
this.State="";
}
this.Close = function()
{
while (this.Nodes.length>0)
this.EndNode();
this.State="closed";
}
this.ToString = function(){return this.XML.join("");}
}
\ No newline at end of file
function WriteForm(e,metrics)
{
try
{
const myArray = Object.values(metrics);
localStorage.setItem("submit", "1");
var Frm=Settings.SrcElement(e);
var XML=new XMLWriter();
XML.WriteString('<?xml version="1.0" encoding="UTF-8" standalone="no"?>');
XML.BeginNode(Frm.name);
var Nodes=Frm.elements;
XML.Node("Image_Source_Path",File_Path);
XML.Node("No_of_Keystrokes",JSON.stringify(myArray[0]));
XML.Node("Processing_Time_Seconds",JSON.stringify(myArray[1]));
for (var i=0;i<Nodes.length;i++){
XML.Node(Nodes[i].id, Nodes[i].value);
console.log(Nodes[i]);
}
XML.EndNode();
XML.Close();
var final_xml=XML.ToString().replace(/</g,"\n<").replace(/&lt;/g,"\<").replace(/&quot;/g,'"').replace(/&gt;/g,">").replace(/\n<\//g,"</").replace(/<\/xml>/g,"\n</xml>");
var myFile = new File([final_xml], File_Name + ".xml", {type: "text/plain;charset=utf-8"});
// saveAs(myFile);
let formData = new FormData();
formData.append("file", myFile);
fetch('./src/XMLWriter/upload.php', {
method: "POST",
body: formData
});
}
catch(Err)
{
alert("Error: " + Err.description);
}
return false;
}
<?php
/* Get the name of the uploaded file */
$filename = $_FILES['file']['name'];
/* Choose where to save the uploaded file */
$location = "../../output/".$filename;
/* Save the uploaded file to the local filesystem */
if ( move_uploaded_file($_FILES['file']['tmp_name'], $location) ) {
echo 'Success';
} else {
echo 'Failure';
}
?>
\ No newline at end of file
var File_Name;
var File_Path;
function accessFile() {
var button = 0;
var size = 0;
const elStatus = document.getElementById('status');
function status(text) {
elStatus.innerHTML = text;
}
const progressBar = document.getElementById('progressBar');
const elProgress = document.getElementById('progress');
function progress({ loaded, total }) {
// elProgress.innerHTML = Math.round(loaded * .000001) + " mb of " + Math.round(total * .000001);
progressBar.value = Math.round(loaded / total * 100);
}
const indexedDB =
window.indexedDB ||
window.mozIndexedDB ||
window.webkitIndexedDB ||
window.msIndexedDB ||
window.shimIndexedDB;
if (!indexedDB) {
console.log("IndexedDB could not be found in this browser.");
}
const request = indexedDB.open("ImageDatabase", 1);
request.onerror = function (event) {
console.error("An error occurred with IndexedDB");
console.error(event);
};
request.onupgradeneeded = function () {
const db = request.result;
const store = db.createObjectStore("image", { keyPath: "id" });
store.createIndex("image_address", ["address"], { unique: false });
};
async function main(img) { status('downloading ...');
var image_info=[];
const response = await fetch(img);
const contentLength = response.headers.get('content-length');
// console.log(contentLength);
const total = (parseInt(contentLength, 10));
let loaded = 0;
const res = new Response(new ReadableStream({
async start(controller) {
const reader = response.body.getReader();
for (;;) {
const {done, value} = await reader.read();
if (done) break;
loaded += (value.byteLength);
// console.log("1");
progress({loaded, total});
controller.enqueue(value);
}
controller.close();
},
}));
const blob = await res.blob();
status('download completed');
const request = indexedDB.open("ImageDatabase", 1);
request.onsuccess = async function () {
// console.log("Database opened successfully " + val );
const db = request.result;
const transaction = db.transaction("image", "readwrite");
const store = transaction.objectStore("image");
const imageIndex = store.index("image_address");
if(img!=null){
var filename = get_file_name(img);
}
var count = store.count();
count.onsuccess = function() {
if (count.result == 0 && (localStorage.length) == 0) {
url = URL.createObjectURL(blob);
window.addEventListener("load", loadDoc(url, TIFFViewer,filename), false);
localStorage.setItem("display_counter", 1);
size = size + total;
File_Name = filename;
File_Path = img;
var file = new File([blob], filename + ".TIFF", {type: "img"}); //uplaod to uploadimgfolder //scanned images
uploadFile(file);
} else if (count.result == 0 && (localStorage.length) == 1) {
store.put({ id: count.result + 1, address: blob , name:filename, path:img});
localStorage.setItem("submit", "0");
localStorage.setItem("display_counter", 2);
size = size + total;
var file = new File([blob], filename + ".TIFF", {type: "img"}); //uplaod to uploadimgfolder //scanned images
uploadFile(file);
} else if(img == null && count.result == 1 && (localStorage.length) == 2 && localStorage.getItem("submit") == 1){ //if only one file left
const idQuery = store.get(1);
idQuery.onsuccess = function () {
url = URL.createObjectURL(idQuery.result.address);
window.addEventListener("load", loadDoc(url, TIFFViewer,idQuery.result.name), false);
File_Name = idQuery.result.name;
File_Path = idQuery.result.path;
store.clear();
localStorage.setItem("submit", "0");
};
} else if(img == null && count.result == 0 && (localStorage.length) == 2 && localStorage.getItem("submit") == 1){//no files left
alert("No Files Left");
}else if (count.result == 1 && (localStorage.length) == 2 && localStorage.getItem("submit") == 1) {
const idQuery = store.get(1);
idQuery.onsuccess = function () {
url = URL.createObjectURL(idQuery.result.address);
window.addEventListener("load", loadDoc(url, TIFFViewer,idQuery.result.name), false);
File_Name = idQuery.result.name;
File_Path = idQuery.result.path;
store.clear();
store.put({ id: count.result, address: blob , name:filename, path:img});
localStorage.setItem("submit", "0");
localStorage.setItem("display_counter", parseInt(localStorage.getItem("display_counter")) + 1); //update how many have been fetched
var file = new File([blob], filename + ".TIFF", {type: "img"}); //uplaod to uploadimgfolder //scanned images
uploadFile(file);
};
size = size + total;
} else {
// console.log(count.result);
// console.log(localStorage.length);
}
}
transaction.oncomplete = function () {
db.close();
status('downloaded '+Math.trunc(size/1000)+" kb");
};
};
}
var updated_input_files = Input_files();
if((localStorage.length)==0){
if(updated_input_files.length==0){
alert("No Inputs");
}else{
main(updated_input_files[0]);
main(updated_input_files[1]);
}
}else{
main(updated_input_files[0]);
}
function get_file_name(filepath){
var filename = filepath.substring(8);
var flag=0;
for (var i = 0; i < filename.length; i++) {
if(filename.charAt(filename.length-i) != "."){
flag++;
}else{
break;
}
}
filename = filename.substring(0,filename.length-flag);
return filename;
}
function Input_files() {
var urls = INPUT_FILES; //from config
var count;
if((localStorage.length) == 0){
count = 0;
}else{
count = parseInt(localStorage.getItem("display_counter"));
}
for (var i = 0; i < count; i++) {
urls.shift();
}
// console.log(urls);
return urls;
}
function uploadFile(file) {
let formData = new FormData();
formData.append("file", file);
fetch('http://localhost:8000/src/accessFile/uploadimg.php',{
method: "POST",
body: formData
});
}
}
\ No newline at end of file
<?php
/* Get the name of the uploaded file */
$filename = $_FILES['file']['name'];
/* Choose where to save the uploaded file */
$location = "../../uploadimg/".$filename;
/* Save the uploaded file to the local filesystem */
if ( move_uploaded_file($_FILES['file']['tmp_name'], $location) ) {
echo 'Success';
} else {
echo 'Failure';
}
?>
\ No newline at end of file
let key_strokes = 0
let time_spent = 0
let time_start = 0
const conflicts = ['F', 'f', 'alphabet', 'alphanumeric']
const shift_shortcuts = ['+', '_', 'ArrowLeft', 'ArrowRight', 'f', 'F']
const ctrl_shortcuts = ['.', ',', 'ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown']
const ctrl_shift_shortcuts = ['v', 'h', 'V', 'H']
const shortcut_triggers = ['Shift', 'Control']
let shortcut_flag = false
const startMetricCapture = () => {
// reset key strokes
key_strokes = 0
time_start = Date.now()
console.log(`Metric Capture Started
Key strokes: ${key_strokes}
Start of encoding time: ${time_start}
Total time spent encoding: ${time_spent}`) // for demonstration purposes
window.onkeyup = (key) => {
const onfocus = document.activeElement
if(shortcut_flag && shortcut_triggers.includes(key.key)) {
if (!key.ctrlKey && !key.shiftKey) { // will disregard key up event on shift or ctrl right after a short cut key combination
console.log('Shortcut trigger lifted') // for demonstration purposes
shortcut_flag = false
}
return
}
if((key.shiftKey && shift_shortcuts.includes(key.key)) || // shift shortcut
(key.ctrlKey && ctrl_shortcuts.includes(key.key))) { // ctrl shortcut
if(onfocus.nodeName !== 'INPUT' ||
!conflicts.includes(key.key)) { // ignore shortcuts with conflict if triggered inside input field
console.log('Shortcut Triggered') // for demonstration purposes
shortcut_flag = true
return
}
}
if(key.shiftKey && key.ctrlKey && ctrl_shift_shortcuts.includes(key.key)) {
console.log('Shortcut Triggered') // for demonstration purposes
shortcut_flag = true
return
}
key_strokes++
console.log(`key: ${key.key}; key_strokes: ${key_strokes}; time_spent: ${(Date.now()-time_start)/1000}`) // for demonstration purposes
}
}
const stopMetricCapture = () => {
const time_end = Date.now()
time_spent = (time_end-time_start)/1000 // time spend in seconds
const rate = (key_strokes/time_spent)*3600 // key strokes made per hour
return {
key_strokes,
time_spent,
rate
}
}
\ No newline at end of file
var submitted = false;
const form = document.getElementById("fields");
const sidebar = document.getElementById("sidebar");
let closerWindow;
form.addEventListener('submit', (e)=>{
submitted = true;
})
endButton = document.createElement("button");
endButton.id = "endBtn";
endButton.style = "display: flex; flex-direction:column;";
endButton.innerHTML = "End Session";
sidebar.append(endButton);
//checks if form is empty
function checkForm(form){
var inputs = form.getElementsByTagName("input");
var selects = form.getElementsByTagName("select");
inputsBlankCount = inputs.length;
selectsBlankCount = selects.length;
for(var i=0; i<inputs.length; i++){
if(inputs[i].value == "") inputsBlankCount--;
}
for(var i=0; i<selects.length; i++){
if(selects[i].options[selects[i].selectedIndex].value === "null") selectsBlankCount--;
}
if(inputsBlankCount==0 && selectsBlankCount==0) return true;
}
//deletes the indexedDB if form is submitted or form is empty
endButton.addEventListener("click", function(){
//clear localStorage
localStorage.clear();
//if form is submitted or fields are blank, delete database
if(submitted || checkForm(form)){
var DBdeleteRequest = window.indexedDB.deleteDatabase("ImageDatabase");
DBdeleteRequest.addEventListener('blocked', function(e){
console.log("Database cleared.");
closerWindow = window.open("closer.html", '_self');
});
DBdeleteRequest.addEventListener('upgradeneeded', function(e){
console.log("Upgrade needed in deleting database");
});
DBdeleteRequest.addEventListener('error', function(e){
console.log("Error in deleting database");
});
DBdeleteRequest.addEventListener('success', function(e){
console.log("Database cleared.");
closerWindow = window.open("closer.html", '_self');
});
//resets the the boolean checker if data is submitted
submitted = false;
}
//if form is not empty but "End Session" button is pressed without submitting the form
else{
alert("Fields are not empty. Submit or clear fields first.");
}
});
\ No newline at end of file
var found = true; //variable to return
var embed = 0; //checker if which file is using the function
const fetchConfig = () => {
$.ajax({ //locates the config file
url: './config.js',
async: false,
success: function(data){},
error: function(data){
handleError();
},
})
}
const handleError = () => {
if (embed == 0) {//to ensure the prompt appears only once
if (confirm("config.js not found, application will not commence")) {}
}
found = false;
}
/**
* will fetch the json file containing the schema.
* update the value of the variable file to the path/url of the json file
*/
// const file = "./fetchSchema/5_field_schema.json"
let schema = {}
const fetchSchema = async () => {
await fetch(SCHEMA_FILE)
.then(res => res.json())
.then(data => {
schema = data;
})
.catch(schema = {})
}
\ No newline at end of file
/**
* AUTHOR: btsfelizardo
* DATE: 20 July 2022
* DESCRIPTION: User: Encode specific document based on fixed schema. The main function
* will loop through all the keys in schema then create a div containing a label
* and an input field, which will depend on the type of collection specified in
* the validation. Text input field for alphanumeric, alphabet, and numeric. Date
* input field for date and datepicker type. Additional validation are also included
* if found in the schema like maximum length of input and required fields.
*/
/**
*
* @param {*} parentID
* ID of the element that will contain the input fields
* @returns
*/
let getSection;
const displayFields = async (parentID) => {
try {
const div = document.getElementById(parentID)
if(!div) return { valid: false, error: `Element with ID '${parentID}' not found` }
clearFields(parentID) // make sure input fields are clear
await fetchSchema()
const { SECTION } = schema
getSection = SECTION ;
const { valid, error } = validateSchema()
if(!valid){
div.textContent = error
div.style.color = '#ff3333'
}
for(const key in SECTION) {
const { fieldLabel } = SECTION[key]
const validation = getValidation(key)
const newField = document.createElement('div') // will contain input field and label
newField.setAttribute('class', 'fieldContainer')
div.appendChild(newField)
const labelContainer = document.createElement('div') // name beside input field
labelContainer.setAttribute('class', 'labelContainer')
newField.appendChild(labelContainer)
const label = document.createElement('label')
label.textContent = fieldLabel ? fieldLabel : `Missing label`
label.style.color = fieldLabel ? '#000000' : '#ff3333'
labelContainer.appendChild(label)
const inputContainer = document.createElement('div') // input field
inputContainer.setAttribute('class', 'inputContainer')
newField.appendChild(inputContainer)
let input
switch(fieldLabel && validation && validation.collection) {
case 'alphanumeric':
case 'alphabet':
input = inputString(key, validation)
break
case 'specific':
case 'dropdown':
input = inputDropdown(key, validation)
break
case 'numeric':
input = inputNumeric(key, validation)
break
case 'date':
case 'datepicker':
input = inputDate(key, validation)
break
default:
input = noValidation()
break
}
input.classList.add('inputField')
inputContainer.appendChild(input)
}
const submit = document.createElement('input')
submit.type = 'submit'
div.appendChild(submit)
// add handler event handler for dropdown
// separate handler is used to fit with the library used 'select2'
$(document).ready(function() {
const dropdowns = $('.dropdown-input').select2();
dropdowns.on('select2:close', handleDropdown)
})
} catch(err) {
console.log(err)
return { valid: false, error: err }
}
}
/**
*
* @param {*} key
* will serve as id of input field
* @returns
* created input field element
*/
const noValidation = (key) => {
try {
const input = document.createElement('input')
input.setAttribute('id', `${key}`)
input.setAttribute('placeholder', 'Invalid field!')
input.setAttribute('disabled', 'true')
return input
} catch(err) {
throw err
}
}
/**
*
* @param {*} key
* will serve as id of input field
* @param {*} validation
* validation of field from schema
* @returns
* created input field element
*/
const inputString = (key, validation) => {
try {
const { mandatory, fieldLength } = validation
const input = document.createElement('input')
input.setAttribute('id', `${key}`)
input.setAttribute('type', 'text')
input.setAttribute('autocomplete', 'on')
input.addEventListener('focusout', handleInput)
fieldLength ? input.setAttribute('maxLength', `${fieldLength}`) : null
mandatory ? input.setAttribute('required', 'true') : null
return input
} catch(err) {
throw err
}
}
/**
*
* @param {*} key
* will serve as id of input field
* @param {*} validation
* validation of field from schema
* @returns
* created input field element
*/
const inputNumeric = (key, validation) => {
try {
const { mandatory, fieldLength } = validation
const input = document.createElement('input')
input.setAttribute('id', `${key}`)
input.setAttribute('type', 'text')
input.setAttribute('autocomplete', 'on')
input.setAttribute('pattern', '[0-9/-]+')
input.addEventListener('focusout', handleInput)
fieldLength ? input.setAttribute('maxLength', `${fieldLength}`) : null
mandatory ? input.setAttribute('required', 'true') : null
return input
} catch(err) {
throw err
}
}
/**
*
* @param {*} key
* will serve as id of input field
* @param {*} validation
* validation of field from schema
* @returns
* created input field element
*/
const inputDate = (key, validation) => {
try {
const { mandatory, fieldLength } = validation
const input = document.createElement('input')
input.setAttribute('id', `${key}`)
input.setAttribute('type', 'date')
input.addEventListener('focusout', handleInput)
mandatory ? input.setAttribute('required', 'true') : null
return input
} catch(err) {
throw err
}
}
/**
*
* @param {*} key
* will serve as id of input field
* @param {*} validation
* validation of field from schema
* @returns
* created input field element
*/
const inputDropdown = (key, validation) => {
try {
const { mandatory, options } = validation
const input = document.createElement('select')
input.setAttribute('id', `${key}`)
input.classList.add('dropdown-input')
input.addEventListener('focusout', handleInput)
if(options && options.length>0) {
newOption = document.createElement("option")
newOption.text = 'Choose an option'
newOption.value = null
input.add(newOption)
for(const option of options) {
newOption = document.createElement("option")
newOption.text = option
newOption.value = option
input.add(newOption)
}
}
else {
newOption = document.createElement("option")
newOption.text = 'No option available'
newOption.value = null
input.add(newOption)
input.setAttribute('disabled', 'false')
}
return input
} catch(err) {
throw err
}
}
/**
*
* @param {*} event
*/
const handleInput = (event) => {
const { id, value, style} = event.target
try {
const validation = validateInput(id, value)
if(!validation.valid) {
event.target.classList.remove('input-valid')
event.target.classList.add('input-invalid')
} else {
event.target.classList.remove('input-ivalid')
event.target.classList.add('input-valid')
}
} catch(err) {
throw err
}
}
const handleDropdown = (event) => {
const [id, value, style] = [
event.currentTarget.id,
$(event.currentTarget).val(),
event.currentTarget.style
]
try {
const validation = validateInput(id, value)
if(!validation.valid) {
$(`#${id}`).select2({
selectionCssClass: 'input-invalid'
})
} else {
$(`#${id}`).select2({
selectionCssClass: 'input-valid'
})
}
} catch(err) {
throw err
}
}
/**
*
* @param {*} elementID
* id of element containing the input fields
*/
const clearFields = (elementID) => {
try{
const element = document.getElementById(elementID)
element.innerHTML = ''
} catch(err) {
throw err
}
}
\ No newline at end of file
var coordinatesData;
var highlightCanvas;
var ctx;
var isCanvasNotCreated = true;
var isInitialPositioning = true;
var resizeWidthVal;
var resizeHeightVal;
var currIdVal;
var rect;
//creates the canvas for highlight rectangles
function createHighlight(width, height){
highlightCanvas = document.createElement('canvas');
highlightCanvas.id = "highlightCanvas";
ctx = highlightCanvas.getContext("2d");
highlightCanvas.classList.add("TiffViewer_imgclass");
// document.getElementById('TiffViewer_ImageContainer').append(highlightCanvas);
//inserts canvas before the TIFF image to fix its position at the top/first page
var imgContainer = document.getElementById('TiffViewer_ImageContainer');
imgContainer.insertBefore(highlightCanvas, imgContainer.firstChild);
//set style for highlight canvas
//z-index is increased to put it above the TIFF image
highlightCanvas.style.position = "absolute";
highlightCanvas.style.width = width;
highlightCanvas.style.height = height;
highlightCanvas.style.zIndex = "20";
}
//function for drawing translucent rectangle
function highlight(nameVal){
for(var i=0; i<coordinatesData.length; i++){
if(nameVal.toUpperCase().localeCompare(coordinatesData[i].FieldName.toUpperCase())==0){
//clears the canvas
ctx.clearRect(0, 0, highlightCanvas.width, highlightCanvas.height);
//resize factor for image
resizeWidthVal = highlightCanvas.width/2550;
resizeHeightVal = highlightCanvas.height/4200;
//split by '~', and create an array of the splitted chars
//format: rotation~zoom~scrollx~scrolly~left~top~width~height~pageno~imagename~annotationtype~highlightcolor
const fieldHighlightData = coordinatesData[i].Default_Annotation.split(/~+/);
//indicates color and opacity of shape
//fieldHighlightData[10] is the string already in RGB format (e.g. 255,255,0)
ctx.fillStyle = `rgba(${fieldHighlightData[10]}, 0.5)`;
//uses coordinates given in coordinates text file
ctx.fillRect(fieldHighlightData[4]*resizeWidthVal,fieldHighlightData[5]*resizeHeightVal,fieldHighlightData[6]*resizeWidthVal,fieldHighlightData[7]*resizeHeightVal);
break;
}
}
}
function resizeHighlightCanvas(width, height, left){
resizeWidthVal = highlightCanvas.width*(width/highlightCanvas.width);
resizeHeightVal = highlightCanvas.height*(height/highlightCanvas.height);
highlightCanvas.style.width = resizeWidthVal;
highlightCanvas.style.height = resizeHeightVal;
highlightCanvas.style.left = `${left}px`;
}
//flips the canvas horizontally by scaling it (ctx.scale) to its reverse x position
function flipXHighlightCanvas(idVal){
ctx.translate(highlightCanvas.width, 0);
ctx.scale(-1, 1);
highlight(idVal);
}
//flips the canvas vertically by scaling it (ctx.scale) to its reverse y position
function flipYHighlightCanvas(idVal){
ctx.translate(0, highlightCanvas.height);
ctx.scale(1, -1);
highlight(idVal);
}
document.addEventListener("DOMContentLoaded", function(event) {
//tab traversal event listener
$(document).on('keyup', '.select2.select2-container', function (e) {
if (e.which == 9) {
//gets the id of the focused select element by using Tab key
const idArr = e.target.childNodes[0].id.split(/-container|select2-/);
//array created ALWAYS has empty characters on its first and last chars ["", "Civil Status", ""],
//so index 1 is used to get select element ID
highlight(idArr[1]);
currIdVal = idArr[1];
}
});
window.addEventListener("keydown", (e) => {
if (e.ctrlKey && e.shiftKey && e.key === "H") {
flipXHighlightCanvas(currIdVal);
isInitialPositioning = false;
}
})
window.addEventListener("keydown", (e) => {
if (e.ctrlKey && e.shiftKey && e.key === "V") {
flipYHighlightCanvas(currIdVal);
}
})
//waits for flip buttons to be created before adding event listeners for adjusting highlights
const flipBtnObserver = new MutationObserver(function (mutations, mutationInstance){
const flipBtnX = document.getElementById("TiffViewer_FlipX");
const flipBtnY = document.getElementById("TiffViewer_FlipY");
if(flipBtnX){
flipBtnX.addEventListener("click", function(){
flipXHighlightCanvas(currIdVal);
});
flipBtnY.addEventListener("click", function(){
flipYHighlightCanvas(currIdVal);
});
mutationInstance.disconnect();
}
});
flipBtnObserver.observe(document, {
childList: true,
subtree: true
});
//waits for fields to be created before adding event listeners
const fieldObserver = new MutationObserver(function (mutations, mutationInstance) {
//find input elements inside div element with id='fields'
const fields = document.getElementById('fields').querySelectorAll('input');
if (fields.length>0) {
document.getElementById('fields').querySelectorAll('input').forEach((field) => {
//event listener when a field is focused
field.addEventListener('focus', (e) =>{
// flippedH = false;
highlight(e.target.id);
currIdVal = e.target.id;
})
});
//open dropdown list event listener
//find select elements in div with id='fields'
$('#fields').find('select').each(function() {
$(this).on('select2:open', function (e) {
highlight($(this)[0].id);
currIdVal = $(this)[0].id;
});
});
mutationInstance.disconnect();
}
});
fieldObserver.observe(document, {
childList: true,
subtree: true
});
//waits until TIFF image is loaded, since its size is based on the displayed TIFF image
const observer = new MutationObserver(function (mutations, mutationInstance) {
const TIFFimg = document.getElementById('IMG1');
if (TIFFimg) {
//waits until width and height has been assigned
var sizeObserver = new window.ResizeObserver(entries => {
if(isCanvasNotCreated){
rect = document.getElementById("IMG1").getBoundingClientRect();
createHighlight(entries[0].contentRect.width, entries[0].contentRect.height);
isCanvasNotCreated = false;
ctx.clearRect(0, 0, highlightCanvas.width, highlightCanvas.height);
}
else{
rect = document.getElementById("IMG1").getBoundingClientRect();
if(isInitialPositioning){
resizeHighlightCanvas(entries[0].contentRect.width, entries[0].contentRect.height, (rect.left-263));
}
else{
resizeHighlightCanvas(entries[0].contentRect.width, entries[0].contentRect.height, (rect.left));
isInitialPositioning = true;
}
}
});
sizeObserver.observe(TIFFimg);
mutationInstance.disconnect();
}
});
observer.observe(document, {
childList: true,
subtree: true
});
});
fetch("./src/highlight/dbSchema_anno.xlsx")
.then(res => {
return res.arrayBuffer();
}).then(res => {
var workbook = XLSX.read(new Uint8Array(res), {
type: "array"
});
data = workbook.Sheets["Sheet5"]
const importRange = "B3:C109";
const headers = ["FieldName", "Default_Annotation"];
coordinatesData = XLSX.utils.sheet_to_json(data, {range: importRange, header: headers});
});
\ No newline at end of file
{
"SECTION":
{
"Surname":
{
"fieldLabel": "Surname",
"validation":
{
"fieldLength": 30,
"collection": "alphanumeric",
"invalidchar": "`~!@#&$%^*._={}[]:;/\"|\\<>",
"mandatory": true
}
},
"Religion":
{
"fieldLabel": "Religion",
"validation":
{
"fieldLength": 30,
"collection": "alphabet"
}
},
"Place_of_Birth":
{
"fieldLabel": "Place of Birth",
"validation":
{
"fieldLength": 50,
"collection": "alphanumeric",
"mandatory": true,
"invalidchar": "`~!@#&$%^*_={}[]:;/\"|\\<>"
}
},
"Birthdate":
{
"fieldLabel": "Birthdate",
"validation":
{
"fieldLength": 10,
"collection": "datepicker",
"regexformat": "(^0[0-9]|^1[012])[-](0[0-9]|[12][0-9]|3[01])[-]((19\\d\\d)|(200[0-9])|(201[0-9])|(202[0])|0000)",
"mandatory": true
}
},
"Age":
{
"fieldLabel": "Age",
"validation":
{
"fieldLength": 2,
"collection": "numeric",
"mandatory": true
}
},
"Gender":
{
"fieldLabel": "Gender",
"validation":
{
"fieldLength": 1,
"collection": "dropdown",
"options": ["M", "F"],
"mandatory": true
}
},
"Civil_Status":
{
"fieldLabel": "Civil Status",
"validation":
{
"fieldLength": 15,
"collection": "dropdown",
"options": ["Single", "Married", "Widowed"],
"mandatory": true
}
},
"Nationality":
{
"fieldLabel": "Nationality",
"validation":
{
"fieldLength": 15,
"collection": "dropdown",
"options": ["Filipino", "Foreigner"],
"mandatory": true
}
},
"Height_in_Cm":
{
"fieldLabel": "Height (in cm)",
"validation":
{
"fieldLength": 3,
"collection": "numeric"
}
},
"Weight_in_Kg":
{
"fieldLabel": "Weight (in kg)",
"validation":
{
"fieldLength": 3,
"collection": "numeric"
}
}
}
}
\ No newline at end of file
{
"SECTION":
{
"Surname":
{
"fieldLabel": "Surname",
"validation":
{
"fieldLength": 30,
"collection": "alphanumeric",
"invalidchar": "`~!@#&$%^*._={}[]:;/\"|\\<>",
"mandatory": true
}
},
"House_Number":
{
"fieldLabel": "House Number",
"validation":
{
"fieldLength": 15,
"collection": "alphanumeric",
"invalidchar": "`~!@&$%^*_={}[]:;\"|\\<>"
}
},
"Street":
{
"fieldLabel": "Street",
"validation":
{
"fieldLength": 30,
"collection": "alphanumeric",
"invalidchar": "`~!@#&$%^*_={}[]:;/\"|\\<>"
}
},
"Village_Subdivision":
{
"fieldLabel": "Village/Subdivision",
"validation":
{
"fieldLength": 30,
"collection": "alphanumeric",
"invalidchar": "`~!@#&$%^*_={}[]:;/\"|\\<>"
}
},
"Municipality_City_Province":
{
"fieldLabel": "Municipality/City/Province",
"validation":
{
"fieldLength": 30,
"collection": "alphanumeric",
"mandatory": true,
"invalidchar": "`~!@#&$%^*_={}[]:;/\"|\\<>"
}
},
"Years_of_Stay":
{
"fieldLabel": "Years of Stay",
"validation":
{
"fieldLength": 2,
"collection": "numeric"
}
},
"Religion":
{
"fieldLabel": "Religion",
"validation":
{
"fieldLength": 30,
"collection": "alphabet"
}
},
"Place_of_Birth":
{
"fieldLabel": "Place of Birth",
"validation":
{
"fieldLength": 50,
"collection": "alphanumeric",
"mandatory": true,
"invalidchar": "`~!@#&$%^*_={}[]:;/\"|\\<>"
}
},
"Birthdate":
{
"fieldLabel": "Birthdate",
"validation":
{
"fieldLength": 10,
"collection": "datepicker",
"regexformat": "(^0[0-9]|^1[012])[-](0[0-9]|[12][0-9]|3[01])[-]((19\\d\\d)|(200[0-9])|(201[0-9])|(202[0])|0000)",
"mandatory": true
}
},
"Age":
{
"fieldLabel": "Age",
"validation":
{
"fieldLength": 2,
"collection": "numeric",
"mandatory": true
}
},
"Gender":
{
"fieldLabel": "Gender",
"validation":
{
"fieldLength": 1,
"collection": "dropdown",
"options": ["M", "F"],
"mandatory": true
}
},
"Civil_Status":
{
"fieldLabel": "Civil Status",
"validation":
{
"fieldLength": 15,
"collection": "dropdown",
"options": ["Single", "Married", "Widowed"],
"mandatory": true
}
},
"Nationality":
{
"fieldLabel": "Nationality",
"validation":
{
"fieldLength": 15,
"collection": "dropdown",
"options": ["Filipino", "Foreigner"],
"mandatory": true
}
},
"Height_in_Cm":
{
"fieldLabel": "Height (in cm)",
"validation":
{
"fieldLength": 3,
"collection": "numeric"
}
},
"Weight_in_Kg":
{
"fieldLabel": "Weight (in kg)",
"validation":
{
"fieldLength": 3,
"collection": "numeric"
}
}
}
}
\ No newline at end of file
{
"SECTION":
{
"Surname":
{
"fieldLabel": "Surname",
"validation":
{
"fieldLength": 30,
"collection": "alphanumeric",
"invalidchar": "`~!@#&$%^*._={}[]:;/\"|\\<>",
"mandatory": true
}
},
"Middle_Name":
{
"fieldLabel": "Middle Name",
"validation":
{
"fieldLength": 30,
"collection": "alphanumeric",
"invalidchar": "`~!@#&$%^*_={}[]:;/\"|\\<>",
"mandatory": true
}
},
"Nickname":
{
"fieldLabel": "Nickname",
"validation":
{
"fieldLength": 15,
"collection": "alphanumeric",
"invalidchar": "`~!@#&$%^*_={}[]:;/\"|\\<>"
}
},
"Email_Address":
{
"fieldLabel": "Email Address",
"validation":
{
"fieldLength": 30,
"collection": "alphanumeric"
}
},
"Mobile_Number":
{
"fieldLabel": "Mobile Number",
"validation":
{
"fieldLength": 15,
"collection": "numeric"
}
},
"Telephone_Number":
{
"fieldLabel": "Telephone Number",
"validation":
{
"fieldLength": 15,
"collection": "numeric"
}
},
"House_Number":
{
"fieldLabel": "House Number",
"validation":
{
"fieldLength": 15,
"collection": "alphanumeric",
"invalidchar": "`~!@&$%^*_={}[]:;\"|\\<>"
}
},
"Street":
{
"fieldLabel": "Street",
"validation":
{
"fieldLength": 30,
"collection": "alphanumeric",
"invalidchar": "`~!@#&$%^*_={}[]:;/\"|\\<>"
}
},
"Village_Subdivision":
{
"fieldLabel": "Village/Subdivision",
"validation":
{
"fieldLength": 30,
"collection": "alphanumeric",
"invalidchar": "`~!@#&$%^*_={}[]:;/\"|\\<>"
}
},
"Municipality_City_Province":
{
"fieldLabel": "Municipality/City/Province",
"validation":
{
"fieldLength": 30,
"collection": "alphanumeric",
"mandatory": true,
"invalidchar": "`~!@#&$%^*_={}[]:;/\"|\\<>"
}
},
"Years_of_Stay":
{
"fieldLabel": "Years of Stay",
"validation":
{
"fieldLength": 2,
"collection": "numeric"
}
},
"Religion":
{
"fieldLabel": "Religion",
"validation":
{
"fieldLength": 30,
"collection": "alphabet"
}
},
"Place_of_Birth":
{
"fieldLabel": "Place of Birth",
"validation":
{
"fieldLength": 50,
"collection": "alphanumeric",
"mandatory": true,
"invalidchar": "`~!@#&$%^*_={}[]:;/\"|\\<>"
}
},
"Birthdate":
{
"fieldLabel": "Birthdate",
"validation":
{
"fieldLength": 10,
"collection": "datepicker",
"regexformat": "(^0[0-9]|^1[012])[-](0[0-9]|[12][0-9]|3[01])[-]((19\\d\\d)|(200[0-9])|(201[0-9])|(202[0])|0000)",
"mandatory": true
}
},
"Age":
{
"fieldLabel": "Age",
"validation":
{
"fieldLength": 2,
"collection": "numeric",
"mandatory": true
}
},
"Gender":
{
"fieldLabel": "Gender",
"validation":
{
"fieldLength": 1,
"collection": "dropdown",
"options": ["M","F"],
"mandatory": true
}
},
"Civil_Status":
{
"fieldLabel": "Civil Status",
"validation":
{
"fieldLength": 15,
"collection": "dropdown",
"options": ["Single", "Married", "Widowed"]
}
},
"Nationality":
{
"fieldLabel": "Nationality",
"validation":
{
"fieldLength": 15,
"collection": "dropdown",
"options": ["Filipino", "Foreigner"],
"mandatory": true
}
},
"Height_in_Cm":
{
"fieldLabel": "Height (in cm)",
"validation":
{
"fieldLength": 3,
"collection": "numeric"
}
},
"Weight_in_Kg":
{
"fieldLabel": "Weight (in kg)",
"validation":
{
"fieldLength": 3,
"collection": "numeric"
}
}
}
}
\ No newline at end of file
{
"SECTION":
{
"Surname":
{
"fieldLabel": "Surname",
"validation":
{
"fieldLength": 30,
"collection": "alphanumeric",
"invalidchar": "`~!@#&$%^*._={}[]:;/\"|\\<>",
"mandatory": true
}
},
"Religion":
{
"fieldLabel": "Religion",
"validation":
{
"fieldLength": 30,
"collection": "alphabet"
}
},
"Birthdate":
{
"fieldLabel": "Birthdate",
"validation":
{
"fieldLength": 10,
"collection": "datepicker",
"mandatory": true
}
},
"Age":
{
"fieldLabel": "Age",
"validation":
{
"fieldLength": 2,
"collection": "numeric",
"mandatory": true
}
},
"Civil_Status":
{
"fieldLabel": "Civil Status",
"validation":
{
"fieldLength": 15,
"collection": "dropdown",
"options": ["Single", "Married", "Widowed"],
"mandatory": true
}
}
}
}
\ No newline at end of file
{
"SECTION":
{
"Surname":
{
"fieldLabel": "Surname",
"validation":
{
"fieldLength": 30,
"collection": "alphanumeric",
"invalidchar": "`~!@#&$%^*._={}[]:;/\"|\\<>",
"mandatory": true
}
},
"First_Name":
{
"fieldLabel": "First Name",
"validation":
{
"fieldLength": 30,
"collection": "alphanumeric",
"invalidchar": "`~!@#&$%^*_={}[]:;/\"|\\<>",
"mandatory": true
}
},
"Middle_Name":
{
"fieldLabel": "Middle Name",
"validation":
{
"fieldLength": 30,
"collection": "alphanumeric",
"invalidchar": "`~!@#&$%^*_={}[]:;/\"|\\<>",
"mandatory": true
}
},
"Nickname":
{
"fieldLabel": "Nickname",
"validation":
{
"fieldLength": 15,
"collection": "alphanumeric",
"invalidchar": "`~!@#&$%^*_={}[]:;/\"|\\<>"
}
},
"Email_Address":
{
"fieldLabel": "Email Address",
"validation":
{
"fieldLength": 30,
"collection": "alphanumeric"
}
},
"Mobile_Number":
{
"fieldLabel": "Mobile Number",
"validation":
{
"fieldLength": 15,
"collection": "numeric"
}
},
"Telephone_Number":
{
"fieldLabel": "Telephone Number",
"validation":
{
"fieldLength": 15,
"collection": "numeric"
}
},
"House_Number":
{
"fieldLabel": "House Number",
"validation":
{
"fieldLength": 15,
"collection": "alphanumeric",
"invalidchar": "`~!@&$%^*_={}[]:;\"|\\<>"
}
},
"Street":
{
"fieldLabel": "Street",
"validation":
{
"fieldLength": 30,
"collection": "alphanumeric",
"invalidchar": "`~!@#&$%^*_={}[]:;/\"|\\<>"
}
},
"Village_Subdivision":
{
"fieldLabel": "Village/Subdivision",
"validation":
{
"fieldLength": 30,
"collection": "alphanumeric",
"invalidchar": "`~!@#&$%^*_={}[]:;/\"|\\<>"
}
},
"Municipality_City_Province":
{
"fieldLabel": "Municipality/City/Province",
"validation":
{
"fieldLength": 30,
"collection": "alphanumeric",
"mandatory": true,
"invalidchar": "`~!@#&$%^*_={}[]:;/\"|\\<>"
}
},
"Years_of_Stay":
{
"fieldLabel": "Years of Stay",
"validation":
{
"fieldLength": 2,
"collection": "numeric"
}
},
"Religion":
{
"fieldLabel": "Religion",
"validation":
{
"fieldLength": 30,
"collection": "alphabet"
}
},
"Place_of_Birth":
{
"fieldLabel": "Place of Birth",
"validation":
{
"fieldLength": 50,
"collection": "alphanumeric",
"mandatory": true,
"invalidchar": "`~!@#&$%^*_={}[]:;/\"|\\<>"
}
},
"Birthdate":
{
"fieldLabel": "Birthdate",
"validation":
{
"fieldLength": 10,
"collection": "datepicker",
"regexformat": "(^0[0-9]|^1[012])[-](0[0-9]|[12][0-9]|3[01])[-]((19\\d\\d)|(200[0-9])|(201[0-9])|(202[0])|0000)",
"mandatory": true
}
},
"Age":
{
"fieldLabel": "Age",
"validation":
{
"fieldLength": 2,
"collection": "numeric",
"mandatory": true
}
},
"Gender":
{
"fieldLabel": "Gender",
"validation":
{
"fieldLength": 1,
"collection": "dropdown",
"options": ["M", "F"],
"mandatory": true
}
},
"Civil_Status":
{
"fieldLabel": "Civil Status",
"validation":
{
"fieldLength": 15,
"collection": "dropdown",
"options": ["Single", "Married", "Widowed"],
"mandatory": true
}
},
"Nationality":
{
"fieldLabel": "Nationality",
"validation":
{
"fieldLength": 15,
"collection": "dropdown",
"options": ["Filipino", "Foreigner"],
"mandatory": true
}
},
"Height_in_Cm":
{
"fieldLabel": "Height (in cm)",
"validation":
{
"fieldLength": 3,
"collection": "numeric"
}
},
"Weight_in_Kg":
{
"fieldLabel": "Weight (in kg)",
"validation":
{
"fieldLength": 3,
"collection": "numeric"
}
}
}
}
\ No newline at end of file
{
"SECTION":
{
"Surname":
{
"validation":
{
"fieldLength": 30,
"collection": "alphanumeric",
"invalidchar": "`~!@#&$%^*._={}[]:;/\"|\\<>",
"mandatory": true
}
},
"Gender":
{
"fieldLabel": "Gender",
"validation":
{
"fieldLength": 1,
"collection": "dropdown",
"options": [],
"mandatory": true
}
},
"Middle_Name":
{
"fieldLabel": "Middle Name"
},
"fieldLabel": "Nickname",
"validation":
{
"fieldLength": 15,
"collection": "alphanumeric",
"invalidchar": "`~!@#&$%^*_={}[]:;/\"|\\<>"
},
"Email_Address":
{
"fieldLabel": "Email Address",
"validation":
{
"fieldLength": 30,
"collection": "alphanumeric"
}
}
}
}
\ No newline at end of file
{
"Surname":
{
"fieldLabel": "Surname",
"validation":
{
"fieldLength": 30,
"collection": "alphanumeric",
"invalidchar": "`~!@#&$%^*._={}[]:;/\"|\\<>",
"mandatory": true
}
},
"Middle_Name":
{
"fieldLabel": "Middle Name",
"validation":
{
"fieldLength": 30,
"collection": "alphanumeric",
"invalidchar": "`~!@#&$%^*_={}[]:;/\"|\\<>",
"mandatory": true
}
},
"Nickname":
{
"fieldLabel": "Nickname",
"validation":
{
"fieldLength": 15,
"collection": "alphanumeric",
"invalidchar": "`~!@#&$%^*_={}[]:;/\"|\\<>"
}
},
"Email_Address":
{
"fieldLabel": "Email Address",
"validation":
{
"fieldLength": 30,
"collection": "alphanumeric"
}
},
"Mobile_Number":
{
"fieldLabel": "Mobile Number",
"validation":
{
"fieldLength": 15,
"collection": "numeric"
}
},
"Telephone_Number":
{
"fieldLabel": "Telephone Number",
"validation":
{
"fieldLength": 15,
"collection": "numeric"
}
},
"House_Number":
{
"fieldLabel": "House Number",
"validation":
{
"fieldLength": 15,
"collection": "alphanumeric",
"invalidchar": "`~!@&$%^*_={}[]:;\"|\\<>"
}
},
"Street":
{
"fieldLabel": "Street",
"validation":
{
"fieldLength": 30,
"collection": "alphanumeric",
"invalidchar": "`~!@#&$%^*_={}[]:;/\"|\\<>"
}
},
"Village_Subdivision":
{
"fieldLabel": "Village/Subdivision",
"validation":
{
"fieldLength": 30,
"collection": "alphanumeric",
"invalidchar": "`~!@#&$%^*_={}[]:;/\"|\\<>"
}
},
"Municipality_City_Province":
{
"fieldLabel": "Municipality/City/Province",
"validation":
{
"fieldLength": 30,
"collection": "alphanumeric",
"mandatory": true,
"invalidchar": "`~!@#&$%^*_={}[]:;/\"|\\<>"
}
},
"Years_of_Stay":
{
"fieldLabel": "Years of Stay",
"validation":
{
"fieldLength": 2,
"collection": "numeric"
}
},
"Religion":
{
"fieldLabel": "Religion",
"validation":
{
"fieldLength": 30,
"collection": "alphabet"
}
},
"Place_of_Birth":
{
"fieldLabel": "Place of Birth",
"validation":
{
"fieldLength": 50,
"collection": "alphanumeric",
"mandatory": true,
"invalidchar": "`~!@#&$%^*_={}[]:;/\"|\\<>"
}
},
"Birthdate":
{
"fieldLabel": "Birthdate",
"validation":
{
"fieldLength": 10,
"collection": "datepicker",
"regexformat": "(^0[0-9]|^1[012])[-](0[0-9]|[12][0-9]|3[01])[-]((19\\d\\d)|(200[0-9])|(201[0-9])|(202[0])|0000)",
"mandatory": true
}
},
"Age":
{
"fieldLabel": "Age",
"validation":
{
"fieldLength": 2,
"collection": "numeric",
"mandatory": true
}
},
"Gender":
{
"fieldLabel": "Gender",
"validation":
{
"fieldLength": 1,
"collection": "dropdown",
"options": [],
"mandatory": true
}
},
"Civil_Status":
{
"fieldLabel": "Civil Status",
"validation":
{
"fieldLength": 15,
"collection": "dropdown",
"options": ["Single", "Married", "Widowed"],
"mandatory": true
}
},
"Nationality":
{
"fieldLabel": "Nationality",
"validation":
{
"fieldLength": 15,
"collection": "dropdown",
"options": ["Filipino", "Foreigner"],
"mandatory": true
}
},
"Height_in_Cm":
{
"fieldLabel": "Height (in cm)",
"validation":
{
"fieldLength": 3,
"collection": "numeric"
}
},
"Weight_in_Kg":
{
"fieldLabel": "Weight (in kg)",
"validation":
{
"fieldLength": 3,
"collection": "numeric"
}
}
}
\ No newline at end of file
const submitForm = (e) => {
try {
const Form = Settings.SrcElement(e);
const { elements } = Form
let error = false
// Validate all elements again
for(let element of elements) {
const { id, value,type } = element
const { valid } = validateInput(id, value)
// Skip submit button
if(type==='submit') continue
// Update display of input field if input is not valid
if(!valid) {
error = true
if(type==='select-one') {
continue
}
const field = document.getElementById(id)
const newEvent = new Event('focusout')
field.dispatchEvent(newEvent)
}
}
// Update display of dropdown field if input is not valid
const dropdowns = $('.dropdown-input').select2();
for(let dropdown of dropdowns) {
const newEvent = new Event('select2:close')
dropdown.dispatchEvent(newEvent)
}
if(error) {
alert('Invalid or Missing data on highlighted fields!')
return false
}
else {
const metrics = stopMetricCapture()
WriteForm(e, metrics)
return true
}
} catch(err) {
console.log(err)
return false
}
}
\ No newline at end of file
//Run TIFF Viewer Widget
// (async () => {
// console.log("waiting for variable");
// while (url == undefined) // define the condition as you like
// await new Promise(resolve => setTimeout(resolve, 1000));
// window.addEventListener("load", loadDoc("input/SVI Internship Application Form - FELIZARDO, BRYLLE.TIFF", TIFFViewer), false);
// console.log("variable is defined");
// })();
//Get Modal as Variables
const TiffViewer_Header = document.getElementById("TiffModalHeader");
const TiffViewer_Body = document.getElementById("TiffModalBody");
const TiffViewer_Footer = document.getElementById("TiffModalFooter");
// Get the modal
var modal = document.getElementById("TiffViewerModal");
// Get the button that opens the modal
var btn = document.getElementById("TestBtn");
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("TiffModalClose")[0];
// CHANGED: commented out onClick function to display modal upon page load
// When the user clicks the button, open the modal
// btn.onclick = function() {
// modal.style.display = "block";
// }
// When the user clicks on <span> (x), close the modal
// span.onclick = function() {
// modal.style.display = "none";
// }
// // When the user clicks anywhere outside of the modal, close it
// window.onclick = function(event) {
// if (event.target == modal) {
// modal.style.display = "none";
// }
// }
// // When the user presses down the ESC key on the keyboard, close the modal
// document.addEventListener("keydown", function(event) {
// const key = event.key; // Or const {key} = event; in ES6+
// if (key === "Escape") {
// modal.style.display = "none";
// }
// });
//XHR to Load Test TIFF Image
function loadDoc(url, cFunction,filename) {
Tiff.initialize({ TOTAL_MEMORY: 16777216 * 10 });
var xhr = new XMLHttpRequest();
xhr.responseType = 'arraybuffer';
xhr.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
var startIndex = (xhr.responseURL.indexOf('\\') >= 0 ? xhr.responseURL.lastIndexOf('\\') : xhr.responseURL.lastIndexOf('/'));
var TiffViewerImageName = xhr.responseURL.substring(startIndex);
if (TiffViewerImageName.indexOf('\\') === 0 || TiffViewerImageName.indexOf('/') === 0) {
if (TiffViewerImageName.length > 40) {
TiffViewerImageName = decodeURI(TiffViewerImageName); /* ADDED: replaces the %20 that replaces the spaces when file name is displayed */
TiffViewerImageName = TiffViewerImageName.substring(1, 40);
TiffViewerImageName = TiffViewerImageName.concat("...");
} else {
TiffViewerImageName = TiffViewerImageName.substring(1);
}
}
cFunction(xhr.response, filename);
}
};
xhr.open('GET', url, true);
xhr.send();
}
//Main Widget
function TIFFViewer(xhr, TiffViewerImageName) {
var buffer = xhr;
var TiffViewerImageName = TiffViewerImageName;
var flippedX = new Array(), flippedY = new Array(), rot = new Array(), checker = new Array();
var width = 0, height = 0; //changing variable for width and height
var origwidth = 0, origheight = 0, changedwidth = 0; changedheight = 0;
var setwidth = 0, setheight = 0; //constant variable for width and height
var editedwidth = 0, editedheight = 0; //checker of width and height change
var hpercent = 0, wpercent = 0; //set of percent increase or decrease per zoom
var hzoom = new Array(), wzoom = new Array(); //zoom data per page
let changed = false;
let TiffViewer_pages = 0; //page count
let TiffViewer_current = 1; // TiffViewer_current page number
//declaration of HTML Contents
const TiffViewer_detailcont = document.createElement("div");
TiffViewer_detailcont.id = "TiffViewerDetailscontainer";
TiffViewer_detailcont.classList.add("TiffViewercontainer");
const TiffViewer_filedetail = document.createElement('p');
TiffViewer_filedetail.id = "TiffViewerImageName";
TiffViewer_filedetail.style.display = "none";
TiffViewer_filedetail.innerHTML = "Filename: ";
const TiffViewer_pagedetail = document.createElement('p');
TiffViewer_pagedetail.id = "TiffViewer_PageCount";
TiffViewer_pagedetail.style.display = "none";
TiffViewer_pagedetail.innerHTML = "Page: ";
const TiffViewer_filecont = document.createElement("div");
TiffViewer_filecont.id = "TiffViewer_FileContainer";
TiffViewer_filecont.classList.add("TiffViewercontainer");
const TiffViewer_scrncont = document.createElement("div");
TiffViewer_scrncont.id = "TiffViewer_Screen";
const TiffViewer_imgcont = document.createElement("div");
TiffViewer_imgcont.id = "TiffViewer_ImageContainer"
const TiffViewer_btncont = document.createElement("div");
TiffViewer_btncont.id = "TiffViewer_ButtonContainer";
TiffViewer_btncont.classList.add("TiffViewercontainer");
const TiffViewer_hflip = document.createElement("button");
TiffViewer_hflip.id = "TiffViewer_FlipX";
TiffViewer_hflip.classList.add("TiffViewer_ButtonClass");
TiffViewer_hflip.innerHTML = "Flip Horizontally";
const TiffViewer_vflip = document.createElement("button");
TiffViewer_vflip.id = "TiffViewer_FlipY";
TiffViewer_vflip.classList.add("TiffViewer_ButtonClass");
TiffViewer_vflip.innerHTML = "Flip Vertically";
const TiffViewer_Rrotate = document.createElement("button");
TiffViewer_Rrotate.id = "TiffViewer_RotateR";
TiffViewer_Rrotate.classList.add("TiffViewer_ButtonClass");
TiffViewer_Rrotate.innerHTML = "Rotate to right";
const TiffViewer_Lrotate = document.createElement("button");
TiffViewer_Lrotate.id = "TiffViewer_RotateL";
TiffViewer_Lrotate.classList.add("TiffViewer_ButtonClass");
TiffViewer_Lrotate.innerHTML = "Rotate to left";
const TiffViewer_Pzoom = document.createElement("button");
TiffViewer_Pzoom.id = "TiffViewer_ZoomP";
TiffViewer_Pzoom.classList.add("TiffViewer_ButtonClass");
TiffViewer_Pzoom.innerHTML = "Zoom in";
const TiffViewer_Mzoom = document.createElement("button");
TiffViewer_Mzoom.id = "TiffViewer_ZoomM";
TiffViewer_Mzoom.classList.add("TiffViewer_ButtonClass");
TiffViewer_Mzoom.innerHTML = "Zoom out";
const TiffViewer_Pbtn = document.createElement("button");
TiffViewer_Pbtn.id = "TiffViewer_PrevButton";
TiffViewer_Pbtn.classList.add("TiffViewer_ButtonClass");
TiffViewer_Pbtn.innerHTML = "Previous";
TiffViewer_Pbtn.style.display = "none";
const TiffViewer_Nbtn = document.createElement("button");
TiffViewer_Nbtn.id = "TiffViewer_NextButton";
TiffViewer_Nbtn.classList.add("TiffViewer_ButtonClass");
TiffViewer_Nbtn.innerHTML = "Next";
TiffViewer_Nbtn.style.display = "none";
const TiffViewer_Fscrn = document.createElement("button");
TiffViewer_Fscrn.id = "TiffViewer_FullscreenButton";
TiffViewer_Fscrn.classList.add("TiffViewer_ButtonClass");
TiffViewer_Fscrn.innerHTML = "Fullscreen";
const TiffViewer_Fit = document.createElement("button");
TiffViewer_Fit.id = "TiffViewer_FitButton";
TiffViewer_Fit.classList.add("TiffViewer_ButtonClass");
TiffViewer_Fit.innerHTML = "Fit Content";
TiffViewer_Fit.style.display = "none";
//append all content declarations to modal
TiffViewer_Header.append(TiffViewer_detailcont);
TiffViewer_Body.append(TiffViewer_filecont);
TiffViewer_Footer.append(TiffViewer_btncont);
//append Contents to containers
TiffViewer_detailcont.append(TiffViewer_filedetail, TiffViewer_pagedetail);
TiffViewer_filecont.appendChild(TiffViewer_scrncont);
TiffViewer_scrncont.appendChild(TiffViewer_imgcont);
TiffViewer_btncont.append(TiffViewer_Fscrn, TiffViewer_Fit, TiffViewer_hflip, TiffViewer_vflip, TiffViewer_Rrotate, TiffViewer_Lrotate, TiffViewer_Pzoom, TiffViewer_Mzoom, TiffViewer_Pbtn, TiffViewer_Nbtn);
//get Content placeholders
const wrapper = document.querySelector("#TiffViewer_Screen"), header = wrapper.querySelector("#TiffViewer_ImageContainer");
var TiffViewer_scrn = document.getElementById('TiffViewer_Screen');
var TiffViewer_file = document.getElementById("TiffViewerImageName");
TiffViewer_file.append(TiffViewerImageName); //Append Filename to div placeholder
TiffViewer_file.style.display = "block"; //Show Filename
var tiff = new Tiff({ buffer: buffer }); //get TIFF data via buffer
TiffViewer_pages = tiff.countDirectory(); //count TIFF image TiffViewer_pages
//if TIFF page is greater than one, display Previous and TiffViewer_NextButton buttons
if (TiffViewer_pages > 1) {
document.getElementById("TiffViewer_PrevButton").style.display = "block";
document.getElementById("TiffViewer_NextButton").style.display = "block";
var TiffViewer_PageCount = document.getElementById("TiffViewer_PageCount");
var pageappend = TiffViewer_current + " / " + TiffViewer_pages;
TiffViewer_PageCount.append(pageappend); //display of page number
TiffViewer_PageCount.style.display = "block";
}
document.getElementById('TestTIFFDisplay').src = tiff.toCanvas().toDataURL();
//creating blank image containers for each page and setting TIFF data as image source
for (var i = 0; i < TiffViewer_pages; ++i) {
var img = document.createElement('img');
img.id = `IMG${i + 1}`;
if (i != 0) {
img.style.display = "none";
wzoom[TiffViewer_current - 1] = changedwidth; /*ADDED: to fit large TIFF files*/
hzoom[TiffViewer_current - 1] = changedheight;
Edited();
}
img.classList.add("TiffViewer_imgclass");
document.getElementById('TiffViewer_ImageContainer').append(img);
tiff.setDirectory(i);
var canvas = tiff.toCanvas().toDataURL();
document.getElementById(`IMG${i + 1}`).src = canvas;
}
//setting the style per page
for (var j = 1; j <= TiffViewer_pages; ++j) {
var img = document.getElementById("IMG" + j);
getMeta(canvas, function (width, height) {
wzoom[TiffViewer_current - 1] = changedwidth; /*ADDED: to fit large TIFF files*/
hzoom[TiffViewer_current - 1] = changedheight;
Edited(); origheight = height;
origwidth = width;
setwidth = width;
setheight = height;
if (setheight > 800 && setwidth > 1000) {
if (setheight > setwidth) {
img.style = "width: 600; height: 800";
} else {
img.style = "width: 800; height: 600";
}
changed = true;
} else if (setwidth > 1000 && setheight <= 800) {
img.style = "width: 1000;";
changed = true;
} else if (setheight > 800 && setwidth <= 1000) {
img.style = "width: 800;";
changed = true;
}
if (changed) {
setwidth = parseInt(img.style.width, 10);
setheight = parseInt(img.style.height, 10);
document.getElementById("TiffViewer_FitButton").style.display = "block";
}
changedheight = setheight;
changedwidth = setwidth;
hpercent = (parseInt(setheight, 10) * (15 / 100));
wpercent = (parseInt(setwidth, 10) * (15 / 100));
hzoom.push(parseInt(setheight, 10));
wzoom.push(parseInt(setwidth, 10));
TiffViewer_scrn.style = `width: ${setwidth}; height: ${setheight};`;
document.getElementById("TiffViewer_FileContainer").style = `width: ${setwidth}; height: ${setheight}; border: 1px solid black;`;
TiffViewer_ImageContainer.style = `width: ${setwidth}; height: ${setheight};`;
});
checker.push(0);
flippedX.push(1);
flippedY.push(1);
rot.push(0);
if (j === 1) {
img.style.display = "flex";
}
}
//getting the metadata of each TIFF page
function getMeta(url, callback) {
var img = new Image();
img.src = url;
img.onload = function () { callback(this.width, this.height); }
}
//display image in fullscreen
document.getElementById("TiffViewer_FullscreenButton").onclick = function () {
var image = document.getElementById(`IMG${TiffViewer_current}`);
if (image.requestFullscreen) {
image.requestFullscreen();
}
else if (image.msRequestFullscreen) {
imagej.msRequestFullscreen();
}
else if (divObj.mozRequestFullScreen) {
image.mozRequestFullScreen();
}
else if (image.webkitRequestFullscreen) {
image.webkitRequestFullscreen();
} else {
console.log("Fullscreen API is not supported");
}
};
//Flip Horizontal
const flipH = document.getElementById("TiffViewer_FlipX");
flipH.addEventListener("click", flipHorizontal);
document.addEventListener("keydown", (e) => {
if (e.ctrlKey && e.shiftKey && e.key === "H") {
e.preventDefault();
flipHorizontal();
}
})
function flipHorizontal() {
if (flippedX[TiffViewer_current - 1] == 1) {
flippedX[TiffViewer_current - 1] = -1;
Edited();
}
else {
flippedX[TiffViewer_current - 1] = 1;
Edited();
}
};
//Flip Vertical
const flipV = document.getElementById("TiffViewer_FlipY");
flipV.addEventListener("click", flipVertical);
document.addEventListener("keydown", (e) => {
if (e.ctrlKey && e.shiftKey && e.key === "V") {
e.preventDefault();
flipVertical();
}
})
function flipVertical() {
if (flippedY[TiffViewer_current - 1] == '1') {
flippedY[TiffViewer_current - 1] = -1;
Edited();
}
else {
flippedY[TiffViewer_current - 1] = 1;
Edited();
}
};
//Rotate 90 degrees
const rotateR = document.getElementById("TiffViewer_RotateR");
rotateR.addEventListener("click", rotateClockwise);
document.addEventListener("keydown", (e) => {
if (e.ctrlKey && e.key === ".") {
e.preventDefault();
rotateClockwise();
}
})
function rotateClockwise() {
rot[TiffViewer_current - 1] += 90;
if ((rot[TiffViewer_current - 1] % 360) == 0) {
rot[TiffViewer_current - 1] = 0
}
Edited();
};
//Rotate -90 degrees
const rotateL = document.getElementById("TiffViewer_RotateL");
rotateL.addEventListener("click", rotateCounterClockwise);
document.addEventListener("keydown", (e) => {
if (e.ctrlKey && e.key === ",") {
e.preventDefault();
rotateCounterClockwise();
}
})
function rotateCounterClockwise() {
rot[TiffViewer_current - 1] -= 90;
if (rot[TiffViewer_current - 1] < 0) {
checker[TiffViewer_current - 1] = rot[TiffViewer_current - 1] * (-1);
}
if ((checker[TiffViewer_current - 1] % 360) == 0) {
rot[TiffViewer_current - 1] = 0
}
Edited();
};
//Zoom In
const zoomP = document.getElementById("TiffViewer_ZoomP");
zoomP.addEventListener("click", zoomIn);
document.addEventListener("keydown", (e) => {
if (e.shiftKey && e.key === "+") {
e.preventDefault();
zoomIn();
}
})
function zoomIn() {
hzoom[TiffViewer_current - 1] += hpercent;
wzoom[TiffViewer_current - 1] += wpercent;
Edited();
};
//Zoom Out
const zoomM = document.getElementById("TiffViewer_ZoomM");
zoomM.addEventListener("click", zoomOut);
document.addEventListener("keydown", (e) => {
if (e.shiftKey && e.key == "_") {
e.preventDefault();
zoomOut();
}
})
function zoomOut() {
hzoom[TiffViewer_current - 1] -= hpercent;
wzoom[TiffViewer_current - 1] -= wpercent;
if (wzoom[TiffViewer_current - 1] < wpercent && hzoom[TiffViewer_current - 1] < hpercent) {
hzoom[TiffViewer_current - 1] = hpercent;
wzoom[TiffViewer_current - 1] = wpercent;
}
Edited();
};
//Previous Page
const prevB = document.getElementById("TiffViewer_PrevButton");
prevB.addEventListener("click", previousPage);
document.addEventListener("keydown", (e) => {
if (e.shiftKey && e.keyCode == 37) {
e.preventDefault();
previousPage();
}
})
function previousPage() {
if (TiffViewer_pages > 1) {
if (TiffViewer_current != 1) {
document.getElementById("TiffViewer_ImageContainer").classList.remove("active");
document.getElementById(`IMG${TiffViewer_current}`).style.display = "none";
TiffViewer_current--;
document.getElementById("TiffViewer_PageCount").innerHTML = "Page: " + TiffViewer_current + " / " + TiffViewer_pages;
Edited();
}
}
};
//Next Page
const nextB = document.getElementById("TiffViewer_NextButton");
nextB.addEventListener("click", nextPage);
document.addEventListener("keydown", (e) => {
if (e.shiftKey && e.keyCode == 39) {
e.preventDefault();
nextPage();
}
})
function nextPage() {
if (TiffViewer_pages > 1) {
if (TiffViewer_current != TiffViewer_pages) {
document.getElementById("TiffViewer_ImageContainer").classList.remove("active");
document.getElementById(`IMG${TiffViewer_current}`).style = "display: none";
TiffViewer_current++;
document.getElementById("TiffViewer_PageCount").innerHTML = "Page: " + TiffViewer_current + " / " + TiffViewer_pages;
Edited();
}
}
};
//Fit Content
const fitB = document.getElementById("TiffViewer_FitButton");
fitB.addEventListener("click", fitResize);
// document.addEventListener("keydown", (e) => {
// if (e.shiftKey && e.key === "F") {
// fitResize();
// }
// })
function fitResize() {
var FitText = this.textContent || this.innerHTML;
document.getElementById("TiffViewer_ImageContainer").classList.remove("active");
if (FitText === "Fit Content") {
setheight = origheight;
setwidth = origwidth;
wzoom[TiffViewer_current - 1] = origwidth;
hzoom[TiffViewer_current - 1] = origheight;
this.innerHTML = "Resize Content";
} else {
setheight = changedheight;
setwidth = changedwidth;
wzoom[TiffViewer_current - 1] = changedwidth;
hzoom[TiffViewer_current - 1] = changedheight;
this.innerHTML = "Fit Content";
}
Edited();
}
//Set Style per button click
function Edited() {
var TiffViewer_imgclass = document.getElementById("TiffViewer_FileContainer");
var TiffViewer_Screen = document.getElementById("TiffViewer_Screen");
var TiffViewer_ImageContainer = document.getElementById("TiffViewer_ImageContainer");
var image = document.getElementById(`IMG${TiffViewer_current}`);
//if the image is rotated 90 degrees
if (rot[TiffViewer_current - 1] == 90 || rot[TiffViewer_current - 1] == 270 || rot[TiffViewer_current - 1] == -90 || rot[TiffViewer_current - 1] == -270) {
image.style = `display: flex;
width: ${wzoom[TiffViewer_current] - 1};
height: ${hzoom[TiffViewer_current - 1]};
border: 1px groove white;
transform: rotate(${rot[TiffViewer_current - 1]}deg) scaleX(${flippedX[TiffViewer_current - 1]}) scaleY(${flippedY[TiffViewer_current - 1]});`;
image.style = `display: flex;
width: ${wzoom[TiffViewer_current - 1]};
height: ${hzoom[TiffViewer_current - 1]};
border: 1px groove white;
-ms-transform: rotate(${rot[TiffViewer_current - 1]}deg) scaleX(${flippedX[TiffViewer_current - 1]}) scaleY(${flippedY[TiffViewer_current - 1]});`; // IE
image.style = `display: flex;
width: ${wzoom[TiffViewer_current - 1]};
height: ${hzoom[TiffViewer_current - 1]};
border: 1px groove white;
-webkit-transform: rotate(${rot[TiffViewer_current - 1]}deg) scaleX(${flippedX[TiffViewer_current - 1]}) scaleY(${flippedY[TiffViewer_current - 1]});`; //Safari
TiffViewer_ImageContainer.style = `display: flex;
width: ${setheight};
height: ${setwidth};
position: relative;
justify-content: center;
align-items: center;`;
TiffViewer_Screen.style = `display: flex;
width: ${setheight};
height: ${setwidth};
position: relative;
justify-content: center;
align-items: center;`;
TiffViewer_imgclass.style = `display: flex;
width: ${setheight};
height: ${setwidth};
position: relative;
justify-content: center;
align-items: center;`;
width = TiffViewer_Screen.clientHeight;
height = TiffViewer_Screen.clientWidth;
} else {
image.style = `display: flex;
width: ${wzoom[TiffViewer_current - 1]};
height: ${hzoom[TiffViewer_current - 1]};
border: 1px groove white;
transform: rotate(${rot[TiffViewer_current - 1]}deg) scaleX(${flippedX[TiffViewer_current - 1]}) scaleY(${flippedY[TiffViewer_current - 1]});`;
image.style = `display: flex;
width: ${wzoom[TiffViewer_current - 1]};
height: ${hzoom[TiffViewer_current - 1]};
border: 1px groove white;
-ms-transform: rotate(${rot[TiffViewer_current - 1]}deg) scaleX(${flippedX[TiffViewer_current - 1]}) scaleY(${flippedY[TiffViewer_current - 1]});`;// IE
image.style = `display: flex;
width: ${wzoom[TiffViewer_current - 1]};
height: ${hzoom[TiffViewer_current - 1]};
border: 1px groove white;
-webkit-transform: rotate(${rot[TiffViewer_current - 1]}deg) scaleX(${flippedX[TiffViewer_current - 1]}) scaleY(${flippedY[TiffViewer_current - 1]});`;//Safari
TiffViewer_ImageContainer.style = `display: flex;
width: ${setwidth};
height: ${setheight};
position: relative;
justify-content: center;
align-items: center;`;
TiffViewer_Screen.style = `display: flex;
width: ${setwidth};
height: ${setheight};
position: relative;
justify-content: center;
align-items: center;`;
TiffViewer_imgclass.style = `display: flex;
width: ${setwidth};
height: ${setheight};
position: relative;
justify-content: center;
align-items: center;`;
width = TiffViewer_Screen.clientWidth;
height = TiffViewer_Screen.clientHeight;
}
editedwidth = image.clientWidth;
editedheight = image.clientHeight;
}
/* ADDED:
keyboard shortcut for fit/resize content
checks if the if it is the input field and if it is an alphanumeric/alphabet type
if so, keyboard shortcut will not bind
otherwise, the function will work
*/
document.addEventListener("keydown", function (e) {
if (e.shiftKey && e.key == 'F') {
if(e.target.tagName == "INPUT"){
// REMOVE COMMENT ONLY WHEN SPECIFIC FIELDS ARE NEEDED
// for (const key in getSection) {
// const validation = getValidation(key);
// if (`${key}` == e.target.id) {
// if (validation.collection == "alphanumeric" || validation.collection == "alphabet"){
// return;
// } else {
// console.log(`${key}`)
// console.log(e.target.id);
// fitResize();
// }
// }
// }
return;
}else{
fitResize();
}
}});
//scrolling shortcuts
document.addEventListener('keydown', function (e) {
let div = document.getElementById('TiffModalBody');
if (e.ctrlKey && e.keyCode === 37) {
e.preventDefault();
div.scrollLeft -= 20;
} else if (e.ctrlKey && e.keyCode === 38) {
e.preventDefault();
div.scrollTop -= 20;
} else if (e.ctrlKey && e.keyCode === 39) {
e.preventDefault();
div.scrollLeft += 20;
} else if (e.ctrlKey && e.keyCode === 40) {
e.preventDefault();
div.scrollTop += 20;
}
});
}
/**
* AUTHOR: btsfelizardo
* DATE: 15 July 2022
* DESCRIPTION: WG-20: User: Validate input based on lookup tables and rules in schema. The main function
* is validateInput(fieldID, value), which checks if the validation is available for a given field
* fieldID then validates the value based on the collection stated in the validation. The function
* will always return an object with at keys: valid (Boolean) and errors (List). Value will specify
* whether the given parameter value is valid or not. errors will contain all errors detected if
* valid is false.
*/
/**
*
* @param {*} fieldID
* Key of input field in schema. Expected to be ID of the element.
* @param {*} value
* Actual input value
* @returns
* object containg:
* valid - true if no errors found after validation
* errors - list of errors found during validation
*/
// const validateInput = (fieldName, value, schema) => {
const validateInput = (fieldID, value) => {
try {
const { valid, error } = validateSchema()
if(!valid) return { valid: false, error: [`${error}`]}
const validation = getValidation(fieldID)
if(!validation) return { valid: false, error: [`FieldName: '${fieldID}' not in schema`] }
switch(validation.collection) {
case 'alphanumeric':
return validateAlphanumeric(validation, value)
case 'alphabet':
return validateAlphabet(validation, value)
case 'specific':
case 'dropdown':
return validateSpecific(validation, value)
case 'numeric':
return validateNumeric(validation, value)
case 'date':
case 'datepicker':
// console.log('date')
return validateDate(validation, value)
break
default:
return { valid: false, error: [`Collection of allowed values for field: ${fieldID} not found`]}
}
} catch(err) {
return { valid: false, error: [err]}
}
}
/**
*
* @param {*} fieldID
* Key of input field in schema. Expected to be ID of the element.
* @returns
* validation of given key in schema
*/
const getValidation = (fieldID) => {
const { SECTION } = schema
try{
if(!SECTION) return null
return SECTION[fieldID].validation
} catch(err) {
return null
}
}
/**
*
* @param {*} validation
* object containing rules for validating alphanumeric inputs
* @param {*} value
* input to be checked
* @returns
* object containg:
* valid - true if no errors found after validation
* errors - list of errors found during validation
*/
const validateAlphanumeric = (validation, value) => {
let errors = []
const { mandatory, fieldLength, invalidchar } = validation
try {
if(mandatory && (value.length===0 || !value.match(/\S/g))) return { valid: false, errors: ['Field is empty'] }
if(fieldLength && value.length>fieldLength) errors = [...errors, 'Input exceed maximum characters']
if(invalidchar) {
// method for escaping characters
// source: https://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
const escaped_pattern = invalidchar.replace(/[-[\]{}()*+!<=:?.\/\\^$|#\s,]/g, '\\$&')
const pattern = new RegExp(`[${escaped_pattern}]`)
if(pattern.test(value)) errors = [...errors, 'Contain invalid character/s']
}
return {
valid: errors.length===0,
errors
}
} catch(err) {
throw err
}
}
/**
*
* @param {*} validation
* object containing rules for validating alphabet inputs
* @param {*} value
* input to be checked
* @returns
* object containg:
* valid - true if no errors found after validation
* errors - list of errors found during validation
*/
const validateAlphabet = (validation, value) => {
const PATTERN_ALPHABET = /[^A-Za-z\s]/g
let errors = []
const { mandatory, fieldLength } = validation
if(mandatory && (value.length===0 || !value.match(/\S/g))) return { valid: false, errors: ['Field is empty'] }
if(fieldLength && value.length>fieldLength) errors = [...errors, 'Input exceed maximum characters']
if(PATTERN_ALPHABET.test(value)) errors = [...errors, 'Contain invalid character/s']
return {
valid: errors.length===0,
errors
}
}
/**
*
* @param {*} validation
* object containing rules for validating numeric inputs
* @param {*} value
* input to be checked
* @returns
* object containg:
* valid - true if no errors found after validation
* errors - list of errors found during validation
*/
const validateNumeric = (validation, value) => {
const PATTERN_NUMERIC = /[^0-9/-]/g
let errors = []
const { mandatory, fieldLength } = validation
try {
if(mandatory && (value.length===0 || !value.match(/\S/g))) return { valid: false, errors: ['Field is empty'] }
if(fieldLength && value.length>fieldLength) errors = [...errors, 'Input exceed maximum characters']
if(PATTERN_NUMERIC.test(value)) errors = [...errors, 'Contain invalid character/s']
return {
valid: errors.length===0,
errors
}
} catch(err) {
throw err
}
}
/**
*
* @param {*} validation
* object containing rules for validating date inputs
* @param {*} value
* input to be checked
* @returns
* object containg:
* valid - true if no errors found after validation
* errors - list of errors found during validation
*/
const validateDate = (validation, value) => {
const { mandatory, regexformat } = validation
try{
if(mandatory && (value.length===0 || !value.match(/\S/g))) return { valid: false, errors: ['Field is empty'] }
return { valid: true }
} catch(err) {
throw err
}
}
/**
*
* @param {*} validation
* object containing rules for validating specific or dropdown inputs
* @param {*} value
* input to be checked
* @returns
* object containg:
* valid - true if no errors found after validation
* errors - list of errors found during validation
*/
const validateSpecific = (validation, value) => {
const { mandatory, validchars, options } = validation
try {
if(mandatory && (value.length===0 || !value.match(/\S/g))) return { valid: false, errors: ['Field is empty'] }
if(validchars && validchars.includes(value)) return { valid: true }
if(options && options.includes(value)) return {valid: true }
if(!mandatory) return { valid: true }
return { valid: false, errors: ['Not an option'] }
} catch(err) {
throw err
}
}
\ No newline at end of file
const validateSchema = () => {
const { SECTION } = schema
if(!SECTION) return { valid: false, error: 'SECTION is missing!' }
return { valid: true }
}
\ No newline at end of file
html {
min-height: 100vh;
}
#with-config {
margin: 0;
grid-template-columns: auto auto 375px;
min-height: 100vh;
grid-template-areas:
"main main sidebar";
bottom: 0;
margin: 0;
padding: 0;
left: 0;
top: 0;
/* position: relative; */
overflow-y: hidden;
}
/* For the right pane */
.sidebar {
grid-area: sidebar;
display: flex;
position: sticky;
flex-direction: column;
max-height: 100vh;
right: 0;
}
/* For the login credentials */
#username {
padding-left: 5px;
background-color: blue;
height: 30px;
display: inline-block;
margin-top: 0;
}
#user-settings {
left: 0;
height: 30px;
width: 30px;
border-radius: 100%;
}
#username-text {
float: right;
padding: 10px;
color: white;
}
/* For the project description */
#project-description {
padding-left: 5px;
background-color: pink;
min-height: 250px;
}
#project-description:after {
content: "";
display: table;
clear: both;
}
#column {
float: left;
width: 50%;
}
/* For the fields */
#fields {
padding-left: 5px;
width: auto;
display: flex;
flex: 1;
max-height: 100vh;
background-color: peachpuff;
display: inline-block;
overflow-y: scroll;
}
/* For the viewer */
main#viewer {
grid-area: main;
background-color: gray;
height: 100vh;
width: auto;
margin: 0;
padding: 0;
border: 0;
bottom: 0;
display: grid;
position: inherit;
}
.TiffViewercontainer {
margin-top: 10;
padding-left: 0;
padding-right: 0;
margin-left: auto;
margin-right: auto;
padding: 1px;
}
#TiffViewer_ButtonContainer {
/* CHANGED: changed to make button container scrollable when window is resized */
overflow-x: auto;
height: auto;
position: relative;
justify-content: center;
display: flex;
align-items: center;
}
/* ADDED: added to adjust button container when window is resized */
@media only screen and (max-width: 1150px) {
#TiffViewer_ButtonContainer {
justify-content: start;
}
}
#TiffViewerDetailscontainer {
/* overflow: hidden; */
height: auto;
width: auto;
position: relative;
justify-content: space-around;
display: flex;
align-items: center;
}
#TiffViewer_ButtonContainer>.TiffViewer_ButtonClass:not(:last-child) {
margin-right: 5px;
}
#TiffViewer_Screen {
clear: both;
position: relative;
}
.TiffViewer_imgclass {
justify-content: center;
-webkit-user-drag: none;
-khtml-user-drag: none;
-moz-user-drag: none;
-o-user-drag: none;
}
.TiffViewer_FullscreenButton:-webkit-fullscreen {
width: auto !important;
height: auto !important;
margin: auto !important;
}
.TiffViewer_FullscreenButton:-moz-fullscreen {
width: auto !important;
height: auto !important;
margin: auto !important;
}
.fullscreen:-ms-fullscreen {
width: auto !important;
height: auto !important;
margin: auto !important;
}
body {
overflow-y: auto;
margin: 0;
max-height: 100vh;
bottom: 0;
/* justify-content: center; */
}
body>div>button {
margin: 0;
position: absolute;
left: 50%;
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
/* CHANGED: changed to none, so that it will not display */
#TestTIFFDisplay {
display: none;
/* max-width: 0%;
max-height: 0%; */
}
/* The Modal (background) */
#TiffViewerModal {
display: block;
/* Hidden by default */
/* CHANGED: block by default */
position: relative;
/* Stay in place */
/* z-index: 1; */
/* Sit on top */
/* padding-top: 10px; */
/* Location of the box */
left: 0;
top: 0;
margin: 0;
border: 0;
width: 100%;
/* Full width */
max-height: 100vh;
/* Full height */
overflow: auto;
/* Enable scroll if needed */
background-color: rgb(0, 0, 0);
/* Fallback color */
background-color: rgba(0, 0, 0, 0.4);
/* Black w/ opacity */
}
/* Modal Content */
.TiffModalContent {
position: relative;
background-color: #fefefe;
margin: auto;
padding: 5;
border: 1px solid #888;
width: 90%;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
-webkit-animation-name: animatetop;
-webkit-animation-duration: 0.4s;
animation-name: animatetop;
animation-duration: 0.4s;
display: flex;
flex-direction: column;
overflow: auto;
max-height: 100vh
}
/* Add Animation */
@-webkit-keyframes animatetop {
from {
top: -300px;
opacity: 0
}
to {
top: 0;
opacity: 1
}
}
@keyframes animatetop {
from {
top: -300px;
opacity: 0
}
to {
top: 0;
opacity: 1
}
}
/* The Close Button */
.TiffModalClose {
color: black;
float: right;
font-size: 28px;
font-weight: bold;
}
.TiffModalClose:hover,
.TiffModalClose:focus {
color: red;
text-decoration: none;
cursor: pointer;
}
#TiffModalHeader {
font-family: Arial, Helvetica, sans-serif;
padding: 2px 16px;
background-color: white;
color: black;
}
#TiffModalBody {
display: inline-block;
align-items: center;
overflow: auto;
margin: auto;
width: 100%;
/* height: 90%; */
flex: 1;
}
#TiffModalFooter {
padding: 2px 16px;
background-color: white;
color: black;
/* overflow-x: auto; */
}
.bar {
position: relative;
display: flex;
justify-content: center;
align-items: center;
}
#inputs {
display: flex;
flex-direction: column;
min-width: 500px;
}
.fieldContainer {
/* layout config */
display: flex;
flex-direction: row;
/* border config */
border-style: solid;
border-width: thin;
border-color: black;
padding: 5px;
}
.labelContainer {
display: flex;
flex-direction: row;
justify-content: flex-end;
width: 50%;
padding-right: 3px;
}
.inputContainer {
display: flex;
flex-direction: row;
justify-content: flex-start;
width: 50%;
padding-left: 3px;
}
.input-invalid {
border-color: #ff3333 !important;
border-radius: 3px;
border-style: solid;
border-width: medium;
}
.input-valid {
border-color: #000000 !important;
border-radius: 3px;
border-style: solid;
border-width: thin;
}
input[type=text] {
width: 90%;
}
select {
width: 90%;
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment