diff --git a/README.md b/README.md index faf51c1..15d992e 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,35 @@ # json.validator (WIP) -Basic type of json validation tool to validate and format json data +Basic type of json validation tool to validate and format, download json (jsontoxml) data + +# Features + +- Validate + > Green color if okay + > Red color if error +- Basic error message to fix json +- Option to download as file (appears after validate) in .json and .xml +- Automatic data reset in 1 min (if focus lost on textarea) +- Manual clear to clear/reset everything +- Line numbers (Planned) # Open for - Contributions, enhancements etc - Support me (sponsor) or star the repo +# Changes + +## 14-06-2024 + +- Added basic formatting for json +- Added option to download as a file (both as .json and .xml ) +- Auto data reset + +# Credit + +- json2xml via https://github.com/nashwaan/xml-js + # License -This project is licensed under the [MIT Licence](https://github.com/jayantur13/json.validator/blob/master/LICENSE.md) \ No newline at end of file +This project is licensed under the [MIT License](https://github.com/jayantur13/json.validator/blob/master/LICENSE.md) diff --git a/index.html b/index.html index 3c19e6c..4c52fa6 100644 --- a/index.html +++ b/index.html @@ -5,14 +5,14 @@ - JSON Validator | JSON Formatter | JSON Lint + JSON Validator: Validate, Format, Download @@ -25,11 +25,11 @@ /> - +

JSON Validator

+
Data clears in 1 min,to avoid click textarea
-
Watch this space for error!
+ > +
Watch this space for information!
+
+ +
+ + +
+
- + + diff --git a/js/script.js b/js/script.js index b52590e..4b02e8a 100644 --- a/js/script.js +++ b/js/script.js @@ -1,54 +1,146 @@ const validateBtn = document.getElementById("submit-btn"); const clearBtn = document.getElementById("clear-btn"); -let defaultErrMsg = "Watch this space for error!"; +const dlJsonBtn = document.getElementById("dl-json-btn"); +const dlXMLtn = document.getElementById("dl-xml-btn"); +let visible = document.getElementById("download-btn-dropdown"); +const jsonDataInput = document.getElementById("jsonDataArea"); +let defaultInfoMsg = "Watch this space for information!"; const validateJSON = () => { const jsonDataInput = document.getElementById("jsonDataArea").value.trim(); - let boolState; - if (jsonDataInput.length == 0 || jsonDataInput == " ") { - alert("Enter json data to validate"); - } else { - try { - boolState = JSON.parse(jsonDataInput, null, 2); - if (boolState) { - document.getElementById("jsonDataArea").style.backgroundColor = - "#D1FFBD"; - let errorMsg = document.getElementById("errorMsg"); - if (errorMsg != "Watch this space for error!") { - document.getElementById("errorMsg").innerText = defaultErrMsg; - } - } - } catch (error) { - if (error) { - document.getElementById("jsonDataArea").style.backgroundColor = - "#FFF7F7"; - document.getElementById("errorMsg").innerText = error; - } + let colorState = "pass"; + try { + let jsonObject = JSON.parse(jsonDataInput); + const prettyJsonString = JSON.stringify(jsonObject, null, 2); + document.getElementById("jsonDataArea").value = prettyJsonString; + visible.style.display = "inline-block"; + return colorState; + } catch (error) { + if (error) { + colorState = error; + return colorState; } } }; const clearEntireThing = () => { let jsonDataInput = document.getElementById("jsonDataArea").value; - let errorMsg = document.getElementById("errorMsg").innerText; + let infoArea = document.getElementById("infoArea").innerText; if ( jsonDataInput.length != 0 || - (jsonDataInput != " " && errorMsg === "Watch this space for error!") + (jsonDataInput != " " && infoArea === "Watch this space for information!") ) { document.getElementById("jsonDataArea").value = ""; document.getElementById("jsonDataArea").style.backgroundColor = "#FFFFFF"; + document.getElementById("infoArea").style.background = "#FFFFFF"; } if ( jsonDataInput.length != 0 || - (jsonDataInput != " " && errorMsg != "Watch this space for error!") + (jsonDataInput != " " && infoArea != "Watch this space for information!") ) { document.getElementById("jsonDataArea").value = ""; - document.getElementById("errorMsg").innerText = defaultErrMsg; + document.getElementById("infoArea").innerText = defaultInfoMsg; document.getElementById("jsonDataArea").style.backgroundColor = "#FFFFFF"; + document.getElementById("infoArea").style.background = "#FFFFFF"; + } + visible.style.display = "none"; +}; + +const checkThenWarn = () => { + const jsonDataInput = document.getElementById("jsonDataArea").value; + if ( + jsonDataInput.length == 0 || + jsonDataInput == "" || + jsonDataInput == " " + ) { + alert("Enter json data to validate"); + } else { + let res = validateJSON(); + if (res != "pass") { + //error if not pass + document.getElementById("jsonDataArea").style.backgroundColor = "#FFF7F7"; + document.getElementById("infoArea").style.backgroundColor = "#FFF7F7"; + document.getElementById("infoArea").innerText = res; + } else { + //okay if pass + document.getElementById("jsonDataArea").style.backgroundColor = "#D1FFBD"; + let infoArea = document.getElementById("infoArea"); + if (infoArea != "Watch this space for information!") { + document.getElementById("infoArea").style.backgroundColor = "#D1FFBD"; + document.getElementById("infoArea").innerText = "JSON is valid!"; + } + } + } +}; + +const downloadJSONFile = () => { + const jsonDataInput = document.getElementById("jsonDataArea").value; + if ( + jsonDataInput.length == 0 || + jsonDataInput == "" || + jsonDataInput == " " + ) { + alert("Enter json data to validate"); + } else { + const fileName = "download.json"; + + const blob = new Blob([jsonDataInput], { type: "text/json" }); + const downloadLink = document.createElement("a"); + downloadLink.href = URL.createObjectURL(blob); + downloadLink.download = fileName; + document.body.appendChild(downloadLink); + downloadLink.click(); + document.body.removeChild(downloadLink); + } +}; + +const structJSONToXMLdownload = () => { + const jsonDataInput = document.getElementById("jsonDataArea").value; + if ( + jsonDataInput.length == 0 || + jsonDataInput == "" || + jsonDataInput == " " + ) { + alert("Enter json data to validate"); + } else { + const xml = json2xml(jsonDataInput, { compact: true, spaces: 4 }); + const fileName = "download.xml"; + + const blob = new Blob([xml], { type: "text/xml" }); + const downloadLink = document.createElement("a"); + downloadLink.href = URL.createObjectURL(blob); + downloadLink.download = fileName; + document.body.appendChild(downloadLink); + downloadLink.click(); + document.body.removeChild(downloadLink); } }; -validateBtn.addEventListener("click", validateJSON); +let cleanerTimeout; + +//Focus moved +document.getElementById("jsonDataArea").addEventListener("blur", () => { + //Clear everything in 1 min + if (cleanerTimeout) { + clearTimeout(cleanerTimeout); + } + cleanerTimeout = setTimeout(clearEntireThing, 60000); +}); + +// Add focus +document.getElementById("jsonDataArea").addEventListener("focus", () => { + // Clear the timeout if the input regains focus + if (cleanerTimeout) { + clearTimeout(cleanerTimeout); + cleanerTimeout = null; // Clear the timeout ID + } +}); + +validateBtn.addEventListener("click", checkThenWarn); clearBtn.addEventListener("click", clearEntireThing); + +dlJsonBtn.addEventListener("click", downloadJSONFile); + +dlXMLtn.addEventListener("click", structJSONToXMLdownload); diff --git a/styling/style.css b/styling/style.css index 3b37d6b..3875c61 100644 --- a/styling/style.css +++ b/styling/style.css @@ -3,12 +3,16 @@ padding: 0; } +html, +body { + height: 100%; +} body { margin-bottom: 50px; } .container { - margin: auto; + margin: 0 auto; width: 50%; padding: 10px; } @@ -30,7 +34,7 @@ body { border-radius: 5px; } -#errorMsg { +#infoArea { margin-top: 10px; text-align: justify; font-size: 15px; @@ -39,7 +43,6 @@ body { white-space: break-spaces; width: 100%; height: max-content; - background-color: #fff7f7; border-radius: 5px; padding: 1%; } @@ -55,7 +58,6 @@ body { #submit-btn { border: none; - color: #ffffff; padding: 10px; background-color: #7ad8f8; border-radius: 5px; @@ -64,19 +66,74 @@ body { #clear-btn { border: none; - color: #ffffff; padding: 10px; - background-color: red; + background-color: rgb(211, 132, 132); border-radius: 5px; font-weight: 700; } -.footer { - position: fixed; - padding: 10px 10px 0px 10px; - bottom: 0; +/* Dropdown Button */ +.download-btn { + border: none; + padding: 10px; + border-radius: 5px; + font-weight: 700; +} + +/* The container
- needed to position the dropdown content */ +#download-btn-dropdown { + position: relative; + display: none; +} + +/* Dropdown Content (Hidden by Default) */ +.download-btn-content { + display: none; + position: absolute; + background-color: #f1f1f1; + min-width: 85px; + font-size: small; + box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2); + z-index: 1; +} + +/* Links inside the dropdown */ +.download-btn-content button { + color: black; + border: none; + padding: 10px; + border-radius: 5px; + display: block; +} + +/* Show the dropdown menu on hover */ +#download-btn-dropdown:hover .download-btn-content { + display: block; +} + +/* Change the background color of the dropdown button when the dropdown content is shown */ +#download-btn-dropdown:hover .download-btn { + background-color: #ddd; +} + +body > .footer { + position: sticky; + display: inline-block; + top: 100vh; width: 100%; - height: 40px; + bottom: 0; + box-sizing: border-box; background: #fff7f7; text-align: center; + padding: 10px; + font-size: large; + font-family: 'Times New Roman', Times, serif; } + +.footer a { + text-decoration: none; +} + +.footer a:hover { + border-bottom: 1px solid; +} \ No newline at end of file