let dateOptions = {month: 'short', year: 'numeric'}; let textareaLoaded = false; let editors = {}; let posts = null; document.addEventListener('DOMContentLoaded', () => { // check if the userData is logged in, if not redirect to log in fetch('/api/user/isLoggedIn').then(res => { if (!res.ok) { window.location.href = './'; } }); document.querySelector("#dateFromE").max = new Date().toISOString().split("T")[0]; document.querySelector("#dateFromW").max = new Date().toISOString().split("T")[0]; fetch("/api/timelineData/edu").then(res => res.json().then(json => { if (res.ok) { for (let i = 0; i < json.length; i++) { addEduData(json[i].ID, json[i].startPeriod, json[i].endPeriod, json[i].grade, json[i].course); } return; } document.querySelector("#edu").innerHTML = "No education data found"; })); fetch("/api/timelineData/work").then(res => res.json().then(json => { if (res.ok) { for (let i = 0; i < json.length; i++) { let endPeriod = json[i].endPeriod === "0000-00-00" ? "Present" : json[i].endPeriod; addWorkData(json[i].ID, json[i].startPeriod, endPeriod, json[i].companyName, json[i].area, json[i].title); } return; } document.querySelector("#edu").innerHTML = "No education data found"; })); fetch("/api/projectData").then(res => res.json().then(json => { if (res.ok) { json.forEach(item => { addProject(item["ID"], (item["isMainProject"] === 1 ? "true" : "false"), (item["imgLocation"] === "") ? "../imgs/placeholder.png" : item["imgLocation"], item["title"], item["information"], item["projectLink"], item["gitLink"]); }) return; } document.querySelector("#projList").innerHTML = "No project data found"; })) fetch("/api/blog/post").then(res => res.json().then(json => { if (res.ok) { posts = json; json.forEach(item => { addPostInfo(item["ID"], item["title"], item["dateCreated"], item["dateModified"]); }) } })); // CKEditor stuff createEditors("CKEditorAddPost", "CKEditorEditPost"); }); document.querySelector("body").addEventListener("click", () => { if (textareaLoaded) { return; } const tx = document.querySelectorAll("main.editor textarea"); for (let i = 0; i < tx.length; i++) { console.log("height: " + tx[i].scrollHeight + "px"); tx[i].setAttribute("style", "height:" + (tx[i].scrollHeight) + "px;overflow-y:hidden;"); tx[i].oninput = e => { e.target.style.height = "0"; e.target.style.height = (e.target.scrollHeight + 15) + "px"; }; } textareaLoaded = true; }); document.querySelector("#navOpen").addEventListener("click", e => { document.querySelector("nav.sideNav").style.removeProperty("width"); document.querySelector("main.editor").style.removeProperty("margin-left"); e.target.style.removeProperty("visibility"); }); document.querySelector("#navClose").addEventListener("click", () => { document.querySelector("nav.sideNav").style.width = "0"; document.querySelector("main.editor").style.marginLeft = "0"; document.querySelector("#navOpen").style.visibility = "visible"; }); document.querySelector("#addEdu").addEventListener("submit", e => { e.preventDefault(); let data = new FormData(); data.append("dateFrom", document.querySelector("#dateFromE").value); data.append("dateTo", document.querySelector("#dateToE").value); data.append("grade", document.querySelector("#grade").value); data.append("course", document.querySelector("#courseTitle").value); fetch("/api/timelineData/edu", { method: "POST", body: data, headers: { "Authorization": "Bearer " + localStorage.getItem("token") } }).then(res => res.json().then(json => { if (res.ok) { addEduData(json.ID, data.get("dateFrom"), data.get("dateTo"), data.get("grade"), data.get("course"), true); document.querySelector("#addEdu").reset(); return; } if (res.status === 401) { window.location.href = "./"; return; } showErrorMessage(json.error, "edu"); })); }); document.querySelector("#addWork").addEventListener("submit", e => { e.preventDefault(); let data = new FormData(); data.append("dateFrom", document.querySelector("#dateFromW").value); data.append("dateTo", document.querySelector("#dateToW").value); data.append("companyName", document.querySelector("#company").value); data.append("area", document.querySelector("#area").value); data.append("title", document.querySelector("#jobTitle").value); fetch("/api/timelineData/work", { method: "POST", body: data, headers: { "Authorization": "Bearer " + localStorage.getItem("token") } }).then(res => res.json().then(json => { if (res.ok) { let endPeriod = data.get("dateTo") === "" ? "Present" : data.get("dateTo "); addWorkData(json.ID, data.get("dateFrom"), endPeriod, data.get("companyName"), data.get("area"), data.get("title"), true); document.querySelector("#addWork").reset(); return; } if (res.status === 401) { window.location.href = "./"; return; } showErrorMessage(json.error, "work"); })); }); document.querySelector("#addProj").addEventListener("submit", e => { e.preventDefault(); let data = new FormData(); data.append("title", document.querySelector("#projTitle").value); data.append("isMainProject", document.querySelector("#isMainProject").checked ? "true" : "false"); data.append("information", document.querySelector("#projInfo").value); data.append("projectLink", (document.querySelector("#projLink").value) ? document.querySelector("#projLink").value : "N/A"); data.append("gitLink", document.querySelector("#gitLink").value); let imgData = new FormData(); imgData.append("img", document.querySelector("#projImg").files[0]); let newProjectID = 0; fetch("/api/projectData", { method: "POST", body: data, headers: { "Authorization": "Bearer " + localStorage.getItem("token") } }).then(res => res.json().then(newProjectData => { if (res.ok) { if (imgData.get("img") === "undefined") { addProject(newProjectData.ID, data.get("isMainProject"),"../imgs/placeholder.png", data.get("title"), data.get("information"), data.get("projectLink"), data.get("gitLink")); document.querySelector("#addProj").reset(); return; } newProjectID = newProjectData.ID; return fetch("/api/projectImage/" + newProjectData.ID, { method: "POST", body: imgData, headers: { "Authorization": "Bearer " + localStorage.getItem("token") } }); } if (res.status === 401) { window.location.href = "./"; return; } showErrorMessage(newProjectData.error, "proj"); }).then(res => res.json().then(newProjectImage => { if (res.ok) { addProject(newProjectID, data.get("isMainProject"), newProjectImage.imgLocation, data.get("title"), data.get("information"), data.get("projectLink"), data.get("gitLink")); document.querySelector("#addProj").reset(); return; } if (res.status === 401) { window.location.href = "./"; return; } showErrorMessage(newProjectImage.error, "proj"); }))); }); document.querySelector("#addPostForm").addEventListener("submit", e => { e.preventDefault(); if (editors["CKEditorAddPost"].getData() === "") { showErrorMessage("Post body cannot be empty", "addPost"); return; } let data = new FormData(); data.append("title", document.querySelector("#postTitle").value); data.append("featured", document.querySelector("#isFeatured").checked ? "1" : "0"); data.append("abstract", document.querySelector("#postAbstract").value); data.append("body", editors["CKEditorAddPost"].getData()); data.append("dateCreated", new Date().toISOString().slice(0, 19).replace('T', ' ')); data.append('categories', document.querySelector('#postCategories').value.toLowerCase()); data.append("headerImg", document.querySelector("#headerImg").files[0]); fetch("/api/blog/post", { method: "POST", body: data, headers: { "Authorization": "Bearer " + localStorage.getItem("token") } }).then(res => res.json().then(json => { if (res.ok) { document.querySelector("#addPostForm").reset(); editors["CKEditorAddPost"].setData(""); addPostInfo(json.ID, data.get("title"), data.get("dateCreated"), data.get("dateModified")); showSuccessMessage("Post added successfully", "addPost"); return; } if (res.status === 401) { window.location.href = "./"; return; } res.json().then(json => showErrorMessage(json.error, "addPost")); })); }); document.querySelector("#editPostForm").addEventListener("submit", e => { e.preventDefault(); let id = document.querySelector("#editPostForm input[type='submit']").id; if (id === "") { showErrorMessage("Currently not editing any post", "editPost"); return; } if (editors["CKEditorEditPost"].getData() === "") { showErrorMessage("Post body cannot be empty", "editPost"); return; } let data = {}; data["title"] = document.querySelector("#editPostTitle").value; data["featured"] = document.querySelector("#editIsFeatured").checked ? "1" : "0"; data["abstract"] = document.querySelector("#editPostAbstract").value; data["body"] = editors["CKEditorEditPost"].getData(); data["dateModified"] = new Date().toISOString().slice(0, 19).replace('T', ' '); data['categories'] = document.querySelector('#editPostCategories').value.toLowerCase(); let imgData = new FormData(); imgData.append("headerImg", document.querySelector("#editHeaderImg").files[0]); fetch("/api/blog/post/" + id, { method: "PATCH", body: JSON.stringify(data), headers: { "Content-Type": "application/json", "Authorization": "Bearer " + localStorage.getItem("token") } }).then(res => { if (res.ok) { if (imgData.get("headerImg") === "undefined") { document.querySelector("#editPostForm").reset(); document.querySelector("#editPostForm input[type='submit']").id = ""; editors["CKEditorEditPost"].setData(""); showSuccessMessage("Post edited successfully", "editPost"); return; } return fetch("/api/blog/headerImage/" + id, { method: "POST", body: imgData, headers: { "Authorization": "Bearer " + localStorage.getItem("token") } }); } if (res.status === 401) { window.location.href = "./"; return; } res.json().then(json => showErrorMessage(json.error, "editPost")); }).then(res => res.json().then(json => { if (res.ok) { document.querySelector("#editPostForm").reset(); document.querySelector("#editPostForm input[type='submit']").id = ""; editors["CKEditorEditPost"].setData(""); showSuccessMessage("Post edited successfully", "editPost"); return; } if (res.status === 401) { window.location.href = "./"; return; } showErrorMessage(json.error.message, "editPost"); })); }); document.querySelector("#goToCV").addEventListener("click", () => { textareaLoaded = false; addActiveClass("goToCV"); goToPage("curriculumVitae"); }); document.querySelector("#goToProjects").addEventListener("click", () => { textareaLoaded = false; addActiveClass("goToProjects"); goToPage("projects"); }); document.querySelector("#blog").addEventListener("click", () => { // document.querySelector("#blog").classList.add("active"); document.querySelector("nav.sideNav ul li.dropdown ul").classList.toggle("active"); document.querySelector("#blog i.fa").classList.toggle("fa-caret-down"); document.querySelector("#blog i.fa").classList.toggle("fa-caret-right"); }); document.querySelector("#goToAddPost").addEventListener("click", () => { textareaLoaded = false; addActiveClass("goToAddPost"); goToPage("addPost"); document.querySelector("#blog").classList.add("active"); }); document.querySelector("#goToEditPost").addEventListener("click", () => { textareaLoaded = false; addActiveClass("goToEditPost"); goToPage("editPost"); document.querySelector("#blog").classList.add("active"); }); document.querySelector("#logout").addEventListener("click", () => { fetch("/api/user/logout").then(res => { if (res.ok) { window.location.reload(); } }); }); document.querySelector("#eduError .close").addEventListener("click", () => document.querySelector("#eduError").classList.toggle("hidden")); document.querySelector("#workError .close").addEventListener("click", () => document.querySelector("#workError").classList.toggle("hidden")); document.querySelector("#projError .close").addEventListener("click", () => document.querySelector("#projError").classList.toggle("hidden")); document.querySelector("#addPostError .close").addEventListener("click", () => document.querySelector("#addPostError").classList.toggle("hidden")); document.querySelector("#addPostSuccess .close").addEventListener("click", () => document.querySelector("#addPostSuccess").classList.toggle("hidden")); document.querySelector("#editPostError .close").addEventListener("click", () => document.querySelector("#editPostError").classList.toggle("hidden")); document.querySelector("#editPostSuccess .close").addEventListener("click", () => document.querySelector("#editPostSuccess").classList.toggle("hidden")); /** * Goes to the page with the given id of the section * @param {string} id - The id of the section to go to */ function goToPage(id) { document.querySelectorAll(".editor section").forEach(element => { element.style.display = "none"; if (element.id === id) { element.style.display = "flex"; } }); } /** * Removes the active class from all nav items and adds it to the one with the given id * @param {string} id - The id to add the active class to */ function addActiveClass(id) { document.querySelectorAll("nav.sideNav ul li a").forEach(element => { element.classList.remove("active"); if (element.id === id) { element.classList.add("active"); } }); } /** * Toggles the editing mode of the project item with the given id * @param id {number} - the id of the project item from the database */ function editProjectItem(id) { document.querySelector(`#projectItem${id}`).classList.toggle("editing"); document.querySelector(`#title${id}proj`).toggleAttribute("disabled"); document.querySelector(`#info${id}proj`).toggleAttribute("disabled"); } /** * Creates new CKEditor instances * @param ids {string[]} - the ids of the divs to create editors for */ function createEditors(...ids) { ids.forEach(id => { ClassicEditor.create(document.querySelector(`#${id}`), { placeholder: "Write something amazing...", simpleUpload: { uploadUrl: '/api/blog/uploadPostImage', headers: { Authorization: "Bearer " + localStorage.getItem("token") } }, style: { definitions: [ { name: "Button Primary", element: "a", classes: ["btn", "btnPrimary"] }, { name: "Button Primary", element: "button", classes: ["btn", "btnPrimary"] }, ] }, codeBlock: { languages: [ {language: 'plaintext', label: 'Plain text'}, {language: 'abap', label: 'ABAP'}, {language: 'abnf', label: 'ABNF'}, {language: 'actionscript', label: 'ActionScript'}, {language: 'ada', label: 'Ada'}, {language: 'agda', label: 'Agda'}, {language: 'al', label: 'AL'}, {language: 'antlr4', label: 'ANTLR4'}, {language: 'apacheconf', label: 'Apache Configuration'}, {language: 'apex', label: 'Apex'}, {language: 'apl', label: 'APL'}, {language: 'applescript', label: 'AppleScript'}, {language: 'aql', label: 'AQL'}, {language: 'arduino', label: 'Arduino'}, {language: 'arff', label: 'ARFF'}, {language: 'asciidoc', label: 'AsciiDoc'}, {language: 'aspnet', label: 'ASP.NET (C#)'}, {language: 'asm6502', label: '6502 Assembly'}, {language: 'autohotkey', label: 'AutoHotkey'}, {language: 'autoit', label: 'AutoIt'}, {language: 'bash', label: 'Bash'}, {language: 'basic', label: 'BASIC'}, {language: 'batch', label: 'Batch'}, {language: 'bbcode', label: 'BBcode'}, {language: 'bison', label: 'Bison'}, {language: 'bnf', label: 'BNF'}, {language: 'brainfuck', label: 'Brainfuck'}, {language: 'brightscript', label: 'BrightScript'}, {language: 'bro', label: 'Bro'}, {language: 'c', label: 'C'}, {language: 'concurnas', label: 'Concurnas'}, {language: 'csharp', label: 'C#'}, {language: 'cpp', label: 'C++'}, {language: 'cil', label: 'CIL'}, {language: 'clojure', label: 'Clojure'}, {language: 'cmake', label: 'CMake'}, {language: 'coffeescript', label: 'CoffeeScript'}, {language: 'concurnas', label: 'Concurnas'}, {language: 'crystal', label: 'Crystal'}, {language: 'css-extras', label: 'CSS Extras'}, {language: 'css', label: 'CSS'}, {language: 'd', label: 'D'}, {language: 'dart', label: 'Dart'}, {language: 'dax', label: 'DAX'}, {language: 'dhall', label: 'Dhall'}, {language: 'diff', label: 'Diff'}, {language: 'django', label: 'Django/Jinja2'}, {language: 'dns-zone-file', label: 'DNS zone file'}, {language: 'docker', label: 'Docker'}, {language: 'ebnf', label: 'EBNF'}, {language: 'editorconfig', label: 'EditorConfig'}, {language: 'eiffel', label: 'Eiffel'}, {language: 'ejs', label: 'EJS'}, {language: 'elixir', label: 'Elixir'}, {language: 'elm', label: 'Elm'}, {language: 'etlua', label: 'Embedded Lua'}, {language: 'erb', label: 'ERB'}, {language: 'erlang', label: 'Erlang'}, {language: 'excel-formula', label: 'Excel Formula'}, {language: 'fsharp', label: 'F#'}, {language: 'factor', label: 'Factor'}, {language: 'firestore-security-rules', label: 'Firestore security rules'}, {language: 'flow', label: 'Flow'}, {language: 'fortran', label: 'Fortran'}, {language: 'ftl', label: 'FreeMarker Template Language'}, {language: 'gcode', label: 'G-code'}, {language: 'gdscript', label: 'GDScript'}, {language: 'gedcom', label: 'GEDCOM'}, {language: 'gherkin', label: 'Gherkin'}, {language: 'git', label: 'Git'}, {language: 'glsl', label: 'GLSL'}, {language: 'gml', label: 'GameMaker Language'}, {language: 'go', label: 'Go'}, {language: 'graphql', label: 'GraphQL'}, {language: 'groovy', label: 'Groovy'}, {language: 'haml', label: 'Haml'}, {language: 'handlebars', label: 'Handlebars'}, {language: 'haskell', label: 'Haskell'}, {language: 'haxe', label: 'Haxe'}, {language: 'hcl', label: 'HCL'}, {language: 'hlsl', label: 'HLSL'}, {language: 'http', label: 'HTTP'}, {language: 'hpkp', label: 'HTTP Public-Key-Pins'}, {language: 'hsts', label: 'HTTP Strict-Transport-Security'}, {language: 'ichigojam', label: 'IchigoJam'}, {language: 'icon', label: 'Icon'}, {language: 'ignore', label: 'Ignore'}, {language: 'inform7', label: 'Inform 7'}, {language: 'ini', label: 'Ini'}, {language: 'io', label: 'Io'}, {language: 'j', label: 'J'}, {language: 'java', label: 'Java'}, {language: 'javadoc', label: 'JavaDoc'}, {language: 'javadoclike', label: 'JavaDoc-like'}, {language: 'javascript', label: 'JavaScript'}, {language: 'javastacktrace', label: 'Java stack trace'}, {language: 'jolie', label: 'Jolie'}, {language: 'jq', label: 'JQ'}, {language: 'js-extras', label: 'JS Extras'}, {language: 'js-templates', label: 'JS Templates'}, {language: 'jsdoc', label: 'JSDoc'}, {language: 'json', label: 'JSON'}, {language: 'json5', label: 'JSON5'}, {language: 'jsonp', label: 'JSONP'}, {language: 'jsstacktrace', label: 'JS stack trace'}, {language: 'jsx', label: 'React JSX'}, {language: 'julia', label: 'Julia'}, {language: 'keyman', label: 'Keyman'}, {language: 'kotlin', label: 'Kotlin'}, {language: 'latex', label: 'LaTeX'}, {language: 'latte', label: 'Latte'}, {language: 'less', label: 'Less'}, {language: 'lilypond', label: 'LilyPond'}, {language: 'liquid', label: 'Liquid'}, {language: 'lisp', label: 'Lisp'}, {language: 'livescript', label: 'LiveScript'}, {language: 'llvm', label: 'LLVM IR'}, {language: 'log', label: 'Log file'}, {language: 'lolcode', label: 'LOLCODE'}, {language: 'lua', label: 'Lua'}, {language: 'makefile', label: 'Makefile'}, {language: 'markdown', label: 'Markdown'}, {language: 'markup-templating', label: 'Markup templating'}, {language: 'matlab', label: 'MATLAB'}, {language: 'mel', label: 'MEL'}, {language: 'mizar', label: 'Mizar'}, {language: 'mongodb', label: 'MongoDB'}, {language: 'monkey', label: 'Monkey'}, {language: 'moonscript', label: 'MoonScript'}, {language: 'n1ql', label: 'N1QL'}, {language: 'n4js', label: 'N4JS'}, {language: 'nand2tetris-hdl', label: 'Nand To Tetris HDL'}, {language: 'nasm', label: 'NASM'}, {language: 'neon', label: 'NEON'}, {language: 'nginx', label: 'nginx'}, {language: 'nim', label: 'Nim'}, {language: 'nix', label: 'Nix'}, {language: 'nsis', label: 'NSIS'}, {language: 'objectivec', label: 'Objective-C'}, {language: 'ocaml', label: 'OCaml'}, {language: 'opencl', label: 'OpenCL'}, {language: 'oz', label: 'Oz'}, {language: 'parigp', label: 'PARI/GP'}, {language: 'parser', label: 'Parser'}, {language: 'pascal', label: 'Pascal'}, {language: 'pascaligo', label: 'Pascaligo'}, {language: 'pcaxis', label: 'PC-Axis'}, {language: 'peoplecode', label: 'PeopleCode'}, {language: 'perl', label: 'Perl'}, {language: 'php', label: 'PHP'}, {language: 'phpdoc', label: 'PHPDoc'}, {language: 'php-extras', label: 'PHP Extras'}, {language: 'plsql', label: 'PL/SQL'}, {language: 'powerquery', label: 'PowerQuery'}, {language: 'powershell', label: 'PowerShell'}, {language: 'processing', label: 'Processing'}, {language: 'prolog', label: 'Prolog'}, {language: 'properties', label: '.properties'}, {language: 'protobuf', label: 'Protocol Buffers'}, {language: 'pug', label: 'Pug'}, {language: 'puppet', label: 'Puppet'}, {language: 'pure', label: 'Pure'}, {language: 'purebasic', label: 'PureBasic'}, {language: 'python', label: 'Python'}, {language: 'q', label: 'Q (kdb+ database)'}, {language: 'qml', label: 'QML'}, {language: 'qore', label: 'Qore'}, {language: 'r', label: 'R'}, {language: 'racket', label: 'Racket'}, {language: 'jsx', label: 'React JSX'}, {language: 'tsx', label: 'React TSX'}, {language: 'reason', label: 'Reason'}, {language: 'regex', label: 'Regex'}, {language: 'renpy', label: 'Ren\'py'}, {language: 'rest', label: 'reST (reStructuredText)'}, {language: 'rip', label: 'Rip'}, {language: 'roboconf', label: 'Roboconf'}, {language: 'robotframework', label: 'Robot Framework'}, {language: 'ruby', label: 'Ruby'}, {language: 'rust', label: 'Rust'}, {language: 'sas', label: 'SAS'}, {language: 'sass', label: 'Sass (Sass)'}, {language: 'scss', label: 'Sass (Scss)'}, {language: 'scala', label: 'Scala'}, {language: 'scheme', label: 'Scheme'}, {language: 'shell-session', label: 'Shell session'}, {language: 'smali', label: 'Smali'}, {language: 'smalltalk', label: 'Smalltalk'}, {language: 'smarty', label: 'Smarty'}, {language: 'solidity', label: 'Solidity (Ethereum)'}, {language: 'solution-file', label: 'Solution file'}, {language: 'soy', label: 'Soy (Closure Template)'}, {language: 'sparql', label: 'SPARQL'}, {language: 'splunk-spl', label: 'Splunk SPL'}, {language: 'sqf', label: 'SQF: Status Quo Function (Arma 3)'}, {language: 'sql', label: 'SQL'}, {language: 'stan', label: 'Stan'}, {language: 'stata', label: 'Stata'}, {language: 'step21', label: 'STEP Part 21'}, {language: 'stylus', label: 'Stylus'}, {language: 'swift', label: 'Swift'}, {language: 'tap', label: 'TAP'}, {language: 'tcl', label: 'Tcl'}, {language: 'textile', label: 'Textile'}, {language: 'toml', label: 'TOML'}, {language: 'tt2', label: 'Template Toolkit 2'}, {language: 'turtle', label: 'Turtle'}, {language: 'twig', label: 'Twig'}, {language: 'typescript', label: 'TypeScript'}, {language: 't4-cs', label: 'T4 Text Templates (C#)'}, {language: 't4-vb', label: 'T4 Text Templates (VB)'}, {language: 't4-templating', label: 'T4 templating'}, {language: 'unrealscript', label: 'UnrealScript'}, {language: 'vala', label: 'Vala'}, {language: 'vbnet', label: 'VB.Net'}, {language: 'velocity', label: 'Velocity'}, {language: 'verilog', label: 'Verilog'}, {language: 'vhdl', label: 'VHDL'}, {language: 'vim', label: 'vim'}, {language: 'visual-basic', label: 'Visual Basic'}, {language: 'warpscript', label: 'WarpScript'}, {language: 'wasm', label: 'WebAssembly'}, {language: 'wiki', label: 'Wiki markup'}, {language: 'xeora', label: 'Xeora'}, {language: 'xojo', label: 'Xojo (REALbasic)'}, {language: 'xquery', label: 'XQuery'}, {language: 'yaml', label: 'YAML'}, {language: 'zephir', label: 'Zephir'}, ], }, }).then(CKEditor => { editors[id] = CKEditor; }).catch(error => { console.error('Oops, something went wrong!'); console.error('Please, report the following error on https://github.com/ckeditor/ckeditor5/issues with the build id and the error stack trace:'); console.warn('Build id: 1eo8ioyje2om-vgar4aghypdm'); console.error(error); }); }) } /** * Edits the post with the given id * @param {number} id - the id of the post from the database */ function editPostItem(id) { posts.forEach(post => { if (post.ID === id) { document.querySelector("#editPostTitle").value = post.title; document.querySelector("#editIsFeatured").checked = (post.featured === 1); document.querySelector("#editPostCategories").value = post.categories; document.querySelector("#editPostAbstract").value = post.abstract; editors["CKEditorEditPost"].setData(post.body); document.querySelector("#editPostForm input[type='submit']").id = id; } }) } /** * Shows respective error message for form * @param {string} message - The error message to show * @param {string} form - The form to show the error message for */ function showErrorMessage(message, form) { document.querySelector(`#${form}Error`).classList.remove("hidden"); document.querySelector(`#${form}Error div`).innerText = message; } /** * Shows respective success message for form * @param message - The success message to show * @param form - The form to show the success message for */ function showSuccessMessage(message, form) { document.querySelector(`#${form}Success`).classList.remove("hidden"); document.querySelector(`#${form}Success div`).innerText = message; } /** * Switches the timeline item between edit and view mode * @param id - the id of the timeline item from the database */ function editCVItem(id) { textareaLoaded = false; document.querySelector(`#timelineItem${id}`).classList.toggle("editing"); if (id.includes("e")) { document.querySelector(`#grade${id}`).toggleAttribute("disabled"); document.querySelector(`#course${id}`).toggleAttribute("disabled"); return; } document.querySelector(`#companyName${id}`).toggleAttribute("disabled"); document.querySelector(`#area${id}`).toggleAttribute("disabled"); document.querySelector(`#jobTitle${id}`).toggleAttribute("disabled"); } /** * Updates the education timeline item with the given id * @param {number} ID - the id of the course timeline item from the database * @param {string} startPeriod - the start date of the course * @param {string} endPeriod - the end date of the course * @param {string} grade - the grade of the course * @param {string} course - the name of the course * @param {boolean} prepend - whether to prepend the timeline item to the timeline */ function addEduData(ID, startPeriod, endPeriod, grade, course, prepend=false) { let id = ID + "e"; let timelineItem = document.createElement("form") timelineItem.id = "timelineItem" + id; timelineItem.classList.add("timelineItem"); timelineItem.onsubmit = e => updateEduItem(ID, e); timelineItem.innerHTML = `