#Code Exercise
Explore tagged Tumblr posts
infernal-lamb · 1 year ago
Text
Tumblr media
Searching your eyes for the saint is an act of futility
something that's just been on my mind recently!
10K notes · View notes
scealaiscoite · 1 year ago
Text
reasons for there to be only one bed ˗ˏˋ ꒰ 🍊 ꒱
¹⁾ they’re undercover as a married couple, and as such need to act like one
²⁾ there’s technically two beds available, but it’s freezing cold and everybody knows body heat works best
³⁾ it’s a camping trip, and one character’s forgotten their sleeping bag
⁴⁾ a character goes to their friend’s house after an emotional upheaval in search of comfort, and ends up staying the night - but refuses to kick the homeowner out of their own bed, resulting in the two of them sharing it
⁵⁾ in a roommate scenario, one character’s bedroom has been rendered unusable - and with the couch being unsustainable in the long run, they proffer sharing the one remaining bed as a solution
⁶⁾ there are two beds, but only one blanket
⁷⁾ a character’s taken ill, and the other party worries too much to leave them alone for even a minute
⁸⁾ in a fit of anger after a mission gone wrong, both characters sleep in the only available bed because no one was chivalrous to offer to take the floor
⁹⁾ a character’s had a nightmare, and needs company to feel safe enough to go back to sleep
¹⁰⁾ the weather takes a tumultuous turn, meaning a late night hangout has to turn into a sleepover when a character gets stranded there for the night
¹¹⁾ it’s a late night at work and when they both grow too tired to continue on, the only option is the lone office couch
¹²⁾ a threat’s been made against one/all character(s) involved, and so under the guise of safety in numbers it’s deemed safest if they stay together - everywhere
¹³⁾ one character joins the other for a late-night conversation, and ends up getting comfortable in their bed next to them - evidently too comfortable, as the char in bed falls asleep on the visitor and effectively traps them there
¹⁴⁾ there’s no bed in the shoddy refuge they’ve found after things went sideways, so when it comes time to sleep the only real choice is to stay close together
and, of course,
¹⁵⁾ it’s the last room available at the hotel after a long trip
6K notes · View notes
keferon · 2 months ago
Note
Isn’t Vortex a fucking torture freak tho? 👀👀👀
Yep. He is. He is a lot of things actually. The more you learn about him the more fucked up it gets
196 notes · View notes
divorcedwife · 4 months ago
Text
Tumblr media Tumblr media
putting them in the 18th century
284 notes · View notes
catspawcreates · 1 month ago
Text
Tumblr media Tumblr media Tumblr media
One week of silly SaMS expression emoji challenge practice!
Made extra KC versions, because this is me… but I uploaded a variety to my discord server and I’m very pleased with how they look!
**ORIGINAL ARTIST FOUND!
Check out the original post HERE! By trans-eevee
65 notes · View notes
ratwithhands · 2 months ago
Text
Tumblr media Tumblr media
I had this AU archived off my accounts for a few years, but I'm thinking about it a lot more these days so I'm digging it up for sketches.
This is Kudari from Codebreaker, functionally the starting antagonist for the story when Emmet accidentally collides with him and takes parts of his body.
For a little debrief, the main idea of Codebreaker is that Emmet discovers that he exists in a false reality, and that there is a parallel plane where all of the instructions for his reality exist. He finds his way to this plane by accident after walking back from another lonely day at work, and is hellbent on learning how to manipulate it in the hopes that he can recover Ingo with that knowledge. Kudari is his own set of instructions, who he partly dismantles, allowing him to actually interact with the code. This leaves a hollowed out shell that starts trying to find his own way to get his body back from Emmet.
I'd been thinking about the Beta Submas leaks which lead me to sketching him again. Here's the first rough warmup sketch I did with a fight between him and Emmet.
Tumblr media
From there I just started reworking his old design to be worse 💀
Let me know if you guys want more of this freak, he's honestly really fun to sketch.
105 notes · View notes
codingcorgi · 1 year ago
Text
Tumblr media
Day 3 of coding for a year. I'm a bit late posting this, because I passed out 😅
Last night I worked on the backend of getting the tasks implemented and my husband was getting notifications to work correctly. We had some snags with notifications since we've never done that before (I'm thankful for friends and videos online)
Today I'll be hooking up the tasks with front end work using xaml and testing.
47 notes · View notes
vexacarnivorous · 2 years ago
Note
Can u teach me python from basic 🙄pls
ok the problem with this question is that it would simply take too long for me to explain to u the basics of programming like functions, statements, loops, variables etc. but i CAN direct u to some good resources that would help u in ur python journey and explain all this stuff
freecodecamp (i think the person for this course explains it nicely here)
pythonprogramming
i especially recommend u look at this website called fullstackpython, which has HEAPS of python beginner recs that seem very useful
u should also be doing projects & exercises to really hammer in what you're learning, so i'd recommend project euler (also found on freecodecamp) or that u search up 'coding exercises' on google. there are some projects listed in fullstackpython i believe as well
114 notes · View notes
skyfallscotland · 5 months ago
Text
the discourse about katie ledecky and pots in mainstream media makes me want to punt someone through a wall and i'm not sorry about it
13 notes · View notes
dkettchen · 6 months ago
Text
I've learnt how to input in python I will be unstoppable now
Tumblr media
9 notes · View notes
projectbatman193 · 5 months ago
Text
youtube
That's what Project Batman is all about!!
7 notes · View notes
deadrlngers · 1 year ago
Text
WIP DAY
i was tagged by @moonmothers @devilbrakers @flymmcargo @nuclearstorms + @hibernationsuit thank you guys so much!! <3
tagging: @morvaris @faarkas @shadowglens @voerman @faerune @ladyshar @liurnia @halsin @gortash @risingsh0t @necroticpetals @druidgroves @malefiicarum @feypacts @florbelles @calenhads @thedeadthree and anyone else i missed! can't remember exactly who writes or not so if you see this just say i tagged you
disclosing my violante/ruven/gortash (pre-game events) agenda,,even if it's mainly vio here but if i added any more of the wip in here you guys would kill me bc it's already so long. anyways who doesn't like masked balls?
“Dare I ask who I'm in the presence of?” The gems nestled in the fine silver net adorning her hair made a gentle tinkling sound as Violante tilted her head forward in a courteous bow tasked to open the dance. When she rose to meet her partner’s gaze once more, she resumed: “And most of all, is it friend or is it foe?”
Even beneath the mask, the wicked shine of Enver’s dark eyes appeared brighter than the play of light on the golden wings that stretched from the front of the mask to his hair. “Vicare, the only human man that could fly.”
Vicare – Violante wished to laugh. Was his arrogance the cause of her amusement? Or perhaps it was his full, unabashed, commitment to that little theatrical play they were staging? Whichever the reason, she found that trying to conceal her smile around him was beginning to verge on the impossible. Disgraceful…but thrilling, she couldn’t wait to let Ruven hear of it.
The music carried their voices along the notes like they were part of the sheets; it was a concerto of violins, lutes and harps. Violante could hear the distinct sound of a few wind instruments as well but failed to recognize them. The melody was slow and soothing, inviting the dancers to know one another, play their coy games before dealing their full hand when the culmination of the song would strike.
They stood shoulder to shoulder, barely letting the fabrics of their clothes brush one another as they drew a circle on the floor with their steps: a dance that resembled more the stalk of two wolves ready to attack, reach for the throat and sink sharp teeth in the flesh and let fate settle who was going to bleed out first and declare the other victorious.
“The name holds a familiar sound.” She spoke calmly, voice just above a whisper but carrying confidence, pride. A pride soon betrayed; a quick glance stolen with the tail of her eye to the dark haired man, searching for any hint on his half covered face that would reveal his thoughts to her. She hoped for the stars, yet she was no astronomer at all. Whatever Enver Gortash was thinking, from amusement to annoyance, remained a well guarded secret. “I’d like to hear the tale of the man of the golden feathers, if he’s willing to share.”
The violins played a grave note and as if spells were casted, each performing pair jumped into position – facing each other, one arm up as the back of their hands brushed the one of their partner in a gentle kiss of the knuckles. His hand to her waist, her touch above his shoulder. "Do I have to tell? I'm sure you know well how the story goes. The one that dreamt of flying too high in the sky – accused of free will, punished with the amputation of his wings.” He leaned forward, a cunning smile curling his lips upwards charmingly. “They used shears, if I remember correctly, to make me never wish to fly again. Quite the gruesome spectacle it was.”
Enver’s back was straight, tense as the string of a bow ready to let its arrow strike the prey, yet the movement of his steps was nothing but light and elegant as they spun in unison with the other dancers like a gentle breeze barely caressing the marble under his feet. He was a great dancer, Violante couldn’t deny it.
“Yet you persist, don’t you? Behind those walls you still look up for the cobalt sky.” A swirl, restrained in perfect graciousness learned in years of training with a certain drow, the rich crimson fabric of her gown twisting around her body like a tail. “Which amount of punishment is enough to make you learn, I wonder.”
His eyes narrowed yet that wicked grin didn't falter. “Flying is a thought, and nothing can stop an idea. The wind reached me even when my feet were bound to the ground." They waltzed into an outside spin and moved into the next step with a final touch of the wrist, pulse against pulse. “Besides – I can take a fair amount of penance, if rewarding.” His fingers twitched against hers, nothing more than a controlled and quick brush tauntingly demure, yet just enough to make Violante wonder, take the hint of that touch and let her mind carry it on as it pleased. The power of a thought, wasn’t it? 
Enver appeared no less pleased, be it the quick flash of her surprised expression or the sudden rigidity of her muscles. “Now that I’ve answered your question, allow one for myself: who are you in turn?”
Violins stood out from the choir of instruments with a strident sound this time, separating the couples as if the touch of one another was akin to reaching for a flame with naked skin. Violante arms rose up in a fluid movement, like the fluttering of a bird’s wings or the stroke of a brush, while Enver’s form bended in a half-bow, one arm behind his back and the other circling his waist.
“Death.” She expressed sharply, excited as if her time in this play had finally come. “And if I recall correctly, even Vicare couldn’t escape Death.”
44 notes · View notes
cesarescabinet · 11 months ago
Text
Caligari's been on the brain lately, and since I keep seeing talks about remakes and theoretical recasting--I'm kind of curious to see if anybody on Tumblr has any ideas. For fun, here's some actors who I think could make for an interesting Cesare;
Tom Sturridge (Able to convey sad wet and pathetic with a dash of menace perfectly)
Dev Patel (Imo he conveys a level of kindness I think he could imbue into the role. Idk I'm just curious to see his take on it)
Lee Joon Gi (Could match the physicality needed. Could ALSO emotionally stomp my heart into the dirt at the tragedy of it all.)
Doug Jones (he NEEDS a second chance!!)
And it doesn't even have to be just casting--I'm very curious to see how people on here would approach the aesthetics or the story with a new lens!
16 notes · View notes
jcmarchi · 11 days ago
Text
How to Create Multi-Step Forms With Vanilla JavaScript and CSS
New Post has been published on https://thedigitalinsider.com/how-to-create-multi-step-forms-with-vanilla-javascript-and-css/
How to Create Multi-Step Forms With Vanilla JavaScript and CSS
Multi-step forms are a good choice when your form is large and has many controls. No one wants to scroll through a super-long form on a mobile device. By grouping controls on a screen-by-screen basis, we can improve the experience of filling out long, complex forms.
But when was the last time you developed a multi-step form? Does that even sound fun to you? There’s so much to think about and so many moving pieces that need to be managed that I wouldn’t blame you for resorting to a form library or even some type of form widget that handles it all for you.
But doing it by hand can be a good exercise and a great way to polish the basics. I’ll show you how I built my first multi-step form, and I hope you’ll not only see how approachable it can be but maybe even spot areas to make my work even better.
We’ll walk through the structure together. We’ll build a job application, which I think many of us can relate to these recent days. I’ll scaffold the baseline HTML, CSS, and JavaScript first, and then we’ll look at considerations for accessibility and validation.
I’ve created a GitHub repo for the final code if you want to refer to it along the way.
The structure of a multi-step form
Our job application form has four sections, the last of which is a summary view, where we show the user all their answers before they submit them. To achieve this, we divide the HTML into four sections, each identified with an ID, and add navigation at the bottom of the page. I’ll give you that baseline HTML in the next section.
Navigating the user to move through sections means we’ll also include a visual indicator for what step they are at and how many steps are left. This indicator can be a simple dynamic text that updates according to the active step or a fancier progress bar type of indicator. We’ll do the former to keep things simple and focused on the multi-step nature of the form.,
The structure and basic styles
We’ll focus more on the logic, but I will provide the code snippets and a link to the complete code at the end.
Let’s start by creating a folder to hold our pages. Then, create an index.html file and paste the following into it:
Open HTML
<form id="myForm"> <section class="group-one" id="one"> <div class="form-group"> <div class="form-control"> <label for="name">Name <span style="color: red;">*</span></label> <input type="text" id="name" name="name" placeholder="Enter your name"> </div> <div class="form-control"> <label for="idNum">ID number <span style="color: red;">*</span></label> <input type="number" id="idNum" name="idNum" placeholder="Enter your ID number"> </div> </div> <div class="form-group"> <div class="form-control"> <label for="email">Email <span style="color: red;">*</span></label> <input type="email" id="email" name="email" placeholder="Enter your email"> </div> <div class="form-control"> <label for="birthdate">Date of Birth <span style="color: red;">*</span></label> <input type="date" id="birthdate" name="birthdate" max="2006-10-01" min="1924-01-01"> </div> </div> </section> <section class="group-two" id="two"> <div class="form-control"> <label for="document">Upload CV <span style="color: red;">*</span></label> <input type="file" name="document" id="document"> </div> <div class="form-control"> <label for="department">Department <span style="color: red;">*</span></label> <select id="department" name="department"> <option value="">Select a department</option> <option value="hr">Human Resources</option> <option value="it">Information Technology</option> <option value="finance">Finance</option> </select> </div> </section> <section class="group-three" id="three"> <div class="form-control"> <label for="skills">Skills (Optional)</label> <textarea id="skills" name="skills" rows="4" placeholder="Enter your skills"></textarea> </div> <div class="form-control"> <input type="checkbox" name="terms" id="terms"> <label for="terms">I agree to the terms and conditions <span style="color: red;">*</span></label> </div> <button id="btn" type="submit">Confirm and Submit</button> </section> <div class="arrows"> <button type="button" id="navLeft">Previous</button> <span id="stepInfo"></span> <button type="button" id="navRight">Next</button> </div> </form> <script src="script.js"></script>
Looking at the code, you can see three sections and the navigation group. The sections contain form inputs and no native form validation. This is to give us better control of displaying the error messages because native form validation is only triggered when you click the submit button.
Next, create a styles.css file and paste this into it:
Open base styles
:root --primary-color: #8c852a; --secondary-color: #858034; body font-family: sans-serif; line-height: 1.4; margin: 0 auto; padding: 20px; background-color: #f4f4f4; max-width: 600px; h1 text-align: center; form background: #fff; padding: 40px; border-radius: 5px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); display: flex; flex-direction: column; .form-group display: flex; gap: 7%; .form-group > div width: 100%; input:not([type="checkbox"]), select, textarea width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; .form-control margin-bottom: 15px; button display: block; width: 100%; padding: 10px; color: white; background-color: var(--primary-color); border: none; border-radius: 4px; cursor: pointer; font-size: 16px; button:hover background-color: var(--secondary-color); .group-two, .group-three display: none; .arrows display: flex; justify-content: space-between align-items: center; margin-top: 10px; #navLeft, #navRight width: fit-content; @media screen and (max-width: 600px) .form-group flex-direction: column;
Open up the HTML file in the browser, and you should get something like the two-column layout in the following screenshot, complete with the current page indicator and navigation.
Adding functionality with vanilla JavaScript
Now, create a script.js file in the same directory as the HTML and CSS files and paste the following JavaScript into it:
Open base scripts
const stepInfo = document.getElementById("stepInfo"); const navLeft = document.getElementById("navLeft"); const navRight = document.getElementById("navRight"); const form = document.getElementById("myForm"); const formSteps = ["one", "two", "three"]; let currentStep = 0; function updateStepVisibility() formSteps.forEach((step) => document.getElementById(step).style.display = "none"; ); document.getElementById(formSteps[currentStep]).style.display = "block"; stepInfo.textContent = `Step $currentStep + 1 of $formSteps.length`; navLeft.style.display = currentStep === 0 ? "none" : "block"; navRight.style.display = currentStep === formSteps.length - 1 ? "none" : "block"; document.addEventListener("DOMContentLoaded", () => navLeft.style.display = "none"; updateStepVisibility(); navRight.addEventListener("click", () => if (currentStep < formSteps.length - 1) currentStep++; updateStepVisibility(); ); navLeft.addEventListener("click", () => if (currentStep > 0) currentStep--; updateStepVisibility(); ); );
This script defines a method that shows and hides the section depending on the formStep values that correspond to the IDs of the form sections. It updates stepInfo with the current active section of the form. This dynamic text acts as a progress indicator to the user.
It then adds logic that waits for the page to load and click events to the navigation buttons to enable cycling through the different form sections. If you refresh your page, you will see that the multi-step form works as expected.
Multi-step form navigation
Let’s dive deeper into what the Javascript code above is doing. In the updateStepVisibility() function, we first hide all the sections to have a clean slate:
formSteps.forEach((step) => document.getElementById(step).style.display = "none"; );
Then, we show the currently active section:
document.getElementById(formSteps[currentStep]).style.display = "block";`
Next, we update the text that indicators progress through the form:
stepInfo.textContent = `Step $currentStep + 1 of $formSteps.length`;
Finally, we hide the Previous button if we are at the first step and hide the Next button if we are at the last section:
navLeft.style.display = currentStep === 0 ? "none" : "block"; navRight.style.display = currentStep === formSteps.length - 1 ? "none" : "block";
Let’s look at what happens when the page loads. We first hide the Previous button as the form loads on the first section:
document.addEventListener("DOMContentLoaded", () => navLeft.style.display = "none"; updateStepVisibility();
Then we grab the Next button and add a click event that conditionally increments the current step count and then calls the updateStepVisibility() function, which then updates the new section to be displayed:
navRight.addEventListener("click", () => if (currentStep < formSteps.length - 1) currentStep++; updateStepVisibility(); );
Finally, we grab the Previous button and do the same thing but in reverse. Here, we are conditionally decrementing the step count and calling the updateStepVisibility():
navLeft.addEventListener("click", () => if (currentStep > 0) currentStep--; updateStepVisibility(); );
Handling errors
Have you ever spent a good 10+ minutes filling out a form only to submit it and get vague errors telling you to correct this and that? I prefer it when a form tells me right away that something’s amiss so that I can correct it before I ever get to the Submit button. That’s what we’ll do in our form.
Our principle is to clearly indicate which controls have errors and give meaningful error messages. Clear errors as the user takes necessary actions. Let’s add some validation to our form. First, let’s grab the necessary input elements and add this to the existing ones:
const nameInput = document.getElementById("name"); const idNumInput = document.getElementById("idNum"); const emailInput = document.getElementById("email"); const birthdateInput = document.getElementById("birthdate") const documentInput = document.getElementById("document"); const departmentInput = document.getElementById("department"); const termsCheckbox = document.getElementById("terms"); const skillsInput = document.getElementById("skills");
Then, add a function to validate the steps:
Open validation script
function validateStep(step)
Here, we check if each required input has some value and if the email input has a valid input. Then, we set the isValid boolean accordingly. We also call a showError() function, which we haven’t defined yet.
Paste this code above the validateStep() function:
function showError(input, message) const formControl = input.parentElement; const errorSpan = formControl.querySelector(".error-message"); input.classList.add("error"); errorSpan.textContent = message;
Now, add the following styles to the stylesheet:
Open validation styles
input:focus, select:focus, textarea:focus outline: .5px solid var(--primary-color); input.error, select.error, textarea.error outline: .5px solid red; .error-message font-size: x-small; color: red; display: block; margin-top: 2px; .arrows color: var(--primary-color); font-size: 18px; font-weight: 900; #navLeft, #navRight display: flex; align-items: center; gap: 10px; #stepInfo color: var(--primary-color);
If you refresh the form, you will see that the buttons do not take you to the next section till the inputs are considered valid:
Finally, we want to add real-time error handling so that the errors go away when the user starts inputting the correct information. Add this function below the validateStep() function:
Open real-time validation script
function setupRealtimeValidation() nameInput.addEventListener("input", () => if (nameInput.value.trim() !== "") clearError(nameInput); ); idNumInput.addEventListener("input", () => if (idNumInput.value.trim() !== "") clearError(idNumInput); ); emailInput.addEventListener("input", () => if (emailInput.validity.valid) clearError(emailInput); ); birthdateInput.addEventListener("change", () => if (birthdateInput.value !== "") clearError(birthdateInput); ); documentInput.addEventListener("change", () => if (documentInput.files[0]) clearError(documentInput); ); departmentInput.addEventListener("change", () => if (departmentInput.value !== "") clearError(departmentInput); ); termsCheckbox.addEventListener("change", () => if (termsCheckbox.checked) clearError(termsCheckbox); );
This function clears the errors if the input is no longer invalid by listening to input and change events then calling a function to clear the errors. Paste the clearError() function below the showError() one:
function clearError(input) const formControl = input.parentElement; const errorSpan = formControl.querySelector(".error-message"); input.classList.remove("error"); errorSpan.textContent = "";
And now the errors clear when the user types in the correct value:
The multi-step form now handles errors gracefully. If you do decide to keep the errors till the end of the form, then at the very least, jump the user back to the erroring form control and show some indication of how many errors they need to fix.
Handling form submission
In a multi-step form, it is valuable to show the user a summary of all their answers at the end before they submit and to offer them an option to edit their answers if necessary. The person can’t see the previous steps without navigating backward, so showing a summary at the last step gives assurance and a chance to correct any mistakes.
Let’s add a fourth section to the markup to hold this summary view and move the submit button within it. Paste this just below the third section in index.html:
Open HTML
<section class="group-four" id="four"> <div class="summary-section"> <p>Name: </p> <p id="name-val"></p> <button type="button" class="edit-btn" id="name-edit"> <span>✎</span> <span>Edit</span> </button> </div> <div class="summary-section"> <p>ID Number: </p> <p id="id-val"></p> <button type="button" class="edit-btn" id="id-edit"> <span>✎</span> <span>Edit</span> </button> </div> <div class="summary-section"> <p>Email: </p> <p id="email-val"></p> <button type="button" class="edit-btn" id="email-edit"> <span>✎</span> <span>Edit</span> </button> </div> <div class="summary-section"> <p>Date of Birth: </p> <p id="bd-val"></p> <button type="button" class="edit-btn" id="bd-edit"> <span>✎</span> <span>Edit</span> </button> </div> <div class="summary-section"> <p>CV/Resume: </p> <p id="cv-val"></p> <button type="button" class="edit-btn" id="cv-edit"> <span>✎</span> <span>Edit</span> </button> </div> <div class="summary-section"> <p>Department: </p> <p id="dept-val"></p> <button type="button" class="edit-btn" id="dept-edit"> <span>✎</span> <span>Edit</span> </button> </div> <div class="summary-section"> <p>Skills: </p> <p id="skills-val"></p> <button type="button" class="edit-btn" id="skills-edit"> <span>✎</span> <span>Edit</span> </button> </div> <button id="btn" type="submit">Confirm and Submit</button> </section>
Then update the formStep in your Javascript to read:
const formSteps = ["one", "two", "three", "four"];
Finally, add the following classes to styles.css:
.summary-section display: flex; align-items: center; gap: 10px; .summary-section p:first-child width: 30%; flex-shrink: 0; border-right: 1px solid var(--secondary-color); .summary-section p:nth-child(2) width: 45%; flex-shrink: 0; padding-left: 10px; .edit-btn width: 25%; margin-left: auto; background-color: transparent; color: var(--primary-color); border: .7px solid var(--primary-color); border-radius: 5px; padding: 5px; .edit-btn:hover border: 2px solid var(--primary-color); font-weight: bolder; background-color: transparent;
Now, add the following to the top of the script.js file where the other consts are:
const nameVal = document.getElementById("name-val"); const idVal = document.getElementById("id-val"); const emailVal = document.getElementById("email-val"); const bdVal = document.getElementById("bd-val") const cvVal = document.getElementById("cv-val"); const deptVal = document.getElementById("dept-val"); const skillsVal = document.getElementById("skills-val"); const editButtons = "name-edit": 0, "id-edit": 0, "email-edit": 0, "bd-edit": 0, "cv-edit": 1, "dept-edit": 1, "skills-edit": 2 ;
Then add this function in scripts.js:
function updateSummaryValues() nameVal.textContent = nameInput.value; idVal.textContent = idNumInput.value; emailVal.textContent = emailInput.value; bdVal.textContent = birthdateInput.value; const fileName = documentInput.files[0]?.name; if (fileName) const extension = fileName.split(".").pop(); const baseName = fileName.split(".")[0]; const truncatedName = baseName.length > 10 ? baseName.substring(0, 10) + "..." : baseName; cvVal.textContent = `$truncatedName.$extension`; else cvVal.textContent = "No file selected"; deptVal.textContent = departmentInput.value; skillsVal.textContent = skillsInput.value || "No skills submitted"; }
This dynamically inserts the input values into the summary section of the form, truncates the file names, and offers a fallback text for the input that was not required.
Then update the updateStepVisibility() function to call the new function:
function updateStepVisibility() formSteps.forEach((step) => document.getElementById(step).style.display = "none"; ); document.getElementById(formSteps[currentStep]).style.display = "block"; stepInfo.textContent = `Step $currentStep + 1 of $formSteps.length`; if (currentStep === 3) updateSummaryValues(); navLeft.style.display = currentStep === 0 ? "none" : "block"; navRight.style.display = currentStep === formSteps.length - 1 ? "none" : "block";
Finally, add this to the DOMContentLoaded event listener:
Object.keys(editButtons).forEach((buttonId) => const button = document.getElementById(buttonId); button.addEventListener("click", (e) => currentStep = editButtons[buttonId]; updateStepVisibility(); ); );
Running the form, you should see that the summary section shows all the inputted values and allows the user to edit any before submitting the information:
And now, we can submit our form:
form.addEventListener("submit", (e) => e.preventDefault(); if (validateStep(2)) alert("Form submitted successfully!"); form.reset(); currentFormStep = 0; updateStepVisibility(); );
Our multi-step form now allows the user to edit and see all the information they provide before submitting it.
Accessibility tips
Making multi-step forms accessible starts with the basics: using semantic HTML. This is half the battle. It is closely followed by using appropriate form labels.
Other ways to make forms more accessible include giving enough room to elements that must be clicked on small screens and giving meaningful descriptions to the form navigation and progress indicators.
Offering feedback to the user is an important part of it; it’s not great to auto-dismiss user feedback after a certain amount of time but to allow the user to dismiss it themselves. Paying attention to contrast and font choice is important, too, as they both affect how readable your form is.
Let’s make the following adjustments to the markup for more technical accessibility:
Add aria-required="true" to all inputs except the skills one. This lets screen readers know the fields are required without relying on native validation.
Add role="alert" to the error spans. This helps screen readers know to give it importance when the input is in an error state.
Add role="status" aria-live="polite" to the .stepInfo. This will help screen readers understand that the step info keeps tabs on a state, and the aria-live being set to polite indicates that should the value change, it does not need to immediately announce it.
In the script file, replace the showError() and clearError() functions with the following:
function showError(input, message) const formControl = input.parentElement; const errorSpan = formControl.querySelector(".error-message"); input.classList.add("error"); input.setAttribute("aria-invalid", "true"); input.setAttribute("aria-describedby", errorSpan.id); errorSpan.textContent = message; function clearError(input) const formControl = input.parentElement; const errorSpan = formControl.querySelector(".error-message"); input.classList.remove("error"); input.removeAttribute("aria-invalid"); input.removeAttribute("aria-describedby"); errorSpan.textContent = "";
Here, we programmatically add and remove attributes that explicitly tie the input with its error span and show that it is in an invalid state.
Finally, let’s add focus on the first input of every section; add the following code to the end of the updateStepVisibility() function:
const currentStepElement = document.getElementById(formSteps[currentStep]); const firstInput = currentStepElement.querySelector( "input, select, textarea" ); if (firstInput) firstInput.focus();
And with that, the multi-step form is much more accessible.
Conclusion
There we go, a four-part multi-step form for a job application! As I said at the top of this article, there’s a lot to juggle — so much so that I wouldn’t fault you for looking for an out-of-the-box solution.
But if you have to hand-roll a multi-step form, hopefully now you see it’s not a death sentence. There’s a happy path that gets you there, complete with navigation and validation, without turning away from good, accessible practices.
And this is just how I approached it! Again, I took this on as a personal challenge to see how far I could get, and I’m pretty happy with it. But I’d love to know if you see additional opportunities to make this even more mindful of the user experience and considerate of accessibility.
References
Here are some relevant links I referred to when writing this article:
How to Structure a Web Form (MDN)
Multi-page Forms (W3C.org)
Create accessible forms (A11y Project)
2 notes · View notes
kissingarthurclaus · 9 months ago
Text
Sigh...the way I'm playing around with a self insert idea
Tumblr media
9 notes · View notes
giggly-argent · 9 months ago
Text
is this thing on 🎤🎤
Tumblr media Tumblr media Tumblr media
that dumb game dropped the cutest sleepiest boy to Ever do it and I have a few hcs for him ( that i wrote high as fuck Several weeks ago when I first stuck this post in the drafts 💖💖 )
Tumblr media
8 notes · View notes