<form id="chat" method="post" action="/my-backend-script">
<input type="text" placeholder="What's on your mind?" />
<input type="submit" value="Post" />
</form>
/*
All the basic style definition implement
a "disabled" status, where you can't
actually send in the message.
The user is required to write a message
before the "POST" button becomes visible.
*/
#chat {
display: flex;
}
#chat input[type="text"],
#chat input[type="submit"] {
padding: 5px 10px;
border: 1px solid #666;
outline: none;
}
#chat input[type="text"] {
flex: 1;
}
#chat input[type="text"]:focus {
border-color: #369;
}
#chat input[type="submit"] {
display: none;
text-transform: uppercase;
}
#chat input[type="submit"]:active {
border-color: #369;
background-color: #369;
color: #fff;
}
/*
By adding a simple "is-valid" class to the
chat's FORM - that wraps all the other
components - then we can easily fix the
style to display a "ready to sent" UI.
It's Javascript that implements the logic
to add or remove the "is-valid" class.
*/
#chat.is-valid input[type="submit"] {
display: block;
}
#chat.is-valid input[type="text"] {
margin-right: 10px;
}
/*
LIBRARY FUNCTIONS
small and easy to understand code blocks
that solve very specific problems.
we will use those functions later on
to create the App's logic
*/
const getChat = () =>
document
.getElementById('chat')
const getChatInput = () =>
document
.querySelector('#chat input[type="text"]')
const getChatButton = () =>
document
.querySelector('#chat input[type="submit"]')
const getChatMessage = () =>
getChatInput().value
const resetChatInput = () => {
const input = getChatInput()
input.value = ''
input.focus()
}
const messageIsValid = text =>
text.length > 0
const sendMessage = text =>
alert(`Send: ${text}`)
const showError = () =>
alert('Please type the message you want to sent')
const cancelEvent = (event) => {
event.preventDefault()
event.stopPropagation()
}
/*
MAIN APP LOGIC
handle user input & events
*/
const onFormSubmit = (event) => {
cancelEvent(event)
const message = getChatMessage()
messageIsValid(message)
? sendMessage(message)
: showError()
resetChatInput()
}
// This doesn't look like an event handler
// because we don't use the "event" param.
//
// It still works because any function can
// be assigned as event handlers!
//
// It's up to you - the engineer - to create
// the correct valuable logic for it.
const updateChatStatus = () => {
const className = 'is-valid'
const classList = getChat().classList
const message = getChatMessage()
messageIsValid(message)
? classList.add(className)
: classList.remove(className)
}
getChat().addEventListener('submit', onFormSubmit)
// We can observe 2 different events that are
// related to the user input.
//
// This way we can correctly update the UI after
// each keystroke and also after the "resetChat()"
getChatInput().addEventListener('input', updateChatStatus)
getChatInput().addEventListener('change', updateChatStatus)
// But we can also simply call the newly created
// function when the App starts, so to be sure
// that the UI starts in the correct state.
//
// CHALLENGE:
// try to start the app with a pre-defined
// message using the "input value" attribute.
// then see how the app behave with or without
// this initial call!
updateChatStatus()
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.