Initial Commit

Base files and version 1 of code.
This commit is contained in:
Caleb Braaten 2020-02-12 07:42:16 -08:00
commit efb9fcbb61
6 changed files with 236 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
.DS_Store

51
README.md Normal file
View File

@ -0,0 +1,51 @@
A Utility web component to send form data to a callback function instead of HTTP endpoint
# spa-form
spa-form is a utility component that progressively enhances html forms from a Multi-Page App to a Single-Page App
![Example gif](./example.gif)
**Left Side:**
The *base behavior* where the HTML form uses its native behavior of sending the data to an endpoint and getting a response. The animation is showing a new page being loaded.
**Right Side:**
The *enhanced behavior* where the HTML form instead passes the form data to a defined callback function as an object of key value pairs. The animation is showing the form data being passed to a developer defined callback function that activates the modal.
## Installation
```
npm install spa-form
```
## Usage
### Overview
Use as a normal form element and add the attribute `is="spa-form"`
```html
<form is="spa-form" data-callback="myCallbackFunction" action="/endpoint" >
```
Include a script tag that defines the component for the browser. If JS is not available then the form will continue working as normal and not be progressively enhanced into an SPA
```html
<script src="./spa-form.js"></script>
```
### API (Attributes)
| Attribute | Description |
| --------- | :---------- |
| Inherited Attributes | Everything that the form element has: [MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form)
| `data-callback` | The function name, located in the global scope, that should be called on form submit. It will receive the form fields as a JS Object where the name attributes are the key. |
| `retainOnSubmit` | Add as an attribute to stop the form from resetting to default values when submitted. |
## Demo
To try the demo file yourself and explore the API do the following steps.
1. Clone the Repo
2. Open the demo.html file in your browser. No web server needed!
## Contributing
Feedback and pull requests are welcome! Please open issues so we can discuss any feature ideas or bugs found.
## License
[MIT](https://choosealicense.com/licenses/mit/)

129
demo.html Normal file
View File

@ -0,0 +1,129 @@
<!DOCTYPE html>
<html>
<head>
<title>Feedback | spa-form Demo</title>
<style>
body {
font-family: 'Open Sans', arial, sans-serif!important;
/* Permalink - use to edit and share this gradient: http://colorzilla.com/gradient-editor/#0096dc+0,2989d8+13,a641a1+100 */
background: #0096dc;
}
form {
max-width: 500px;
margin: 0 auto;
margin-top: 50px;
margin-bottom: 70px;
border-radius: 25px;
background-color: white;
padding: 65px;
}
input[type=submit], button{
font-family: 'Open Sans', arial, sans-serif!important;
background-image: none;
background-color: #0096dc;
background-size: 100% 200%;
text-shadow: none;
border: 0;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
color: #ffffff!important;
cursor: pointer;
padding: 8px 15px 8px;
-webkit-transition: background .2s ease-out;
-moz-transition: background .2s ease-out;
-ie-transition: background .2s ease-out;
-o-transition: background .2s ease-out;
transition: background .2s ease-out;
width: 50%;
font-size: 1em;
}
input[type=submit]:hover, button:hover {
background-color: #a641a1;
}
input, textarea {
width: 100%;
margin-bottom: 25px;
line-height: 30px;
margin-top: 5px;
}
label {
width: 100%;
font-weight: bold;
}
label text {
display: inline-block;
text-align: right;
}
.modal {
position: absolute;
left: 0;
right: 0;
margin: auto;
top: 150px;
box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
text-align: center;
max-width: 300px;
border-radius: 25px;
background-color: rgb(220, 233, 253);
padding: 50px;
opacity: 0;
z-index: 1;
padding-left: 25px;
padding-right: 25px;
visibility: hidden;
transition: visibility 0s lineaer 0.1s, opacity 0.3s ease;
}
.modal.open {
background-color: aliceblue;
position: absolute;
visibility: visible;
opacity: 1;
transition-delay: 0s;
}
.modal button{
flex-direction: row-reverse;
}
</style>
</head>
<body>
<form is='spa-form' data-callback="myCallbackFunction" id='myForm' retainOnSubmit
action="https://api.cbraaten.dev/returnQueryAsJSON" >
<label for="userName"><b>Name: </b></label>
<input type="text" placeholder="Name" name="userName" autocomplete="yes" required>
<label for="email"><b>Email: </b></label>
<input type="email" placeholder="Enter Email" name="email" autocomplete="yes" required>
<label for="message"><b>Feedback</b></label>
<textarea form="myForm" placeholder="Your Feedback..." name="message" required></textarea>
<input type="submit">
</form>
<div id="modal" class="modal"></div>
</body>
<script src="./spa-form.js"></script>
<script>
function myCallbackFunction(formData){
const modal = document.getElementById("modal");
modal.innerHTML = `
<p>Thank you <b>${formData.userName}</b> for submitting the following feedback: </p>
<p><em>${formData.message}</em></p>
<p>We will followup with you at the email address <b>${formData.email}</b></p>
<button onclick="hideModal()">Exit</button>
`;
modal.className += " open";
}
function hideModal(){
const modal = document.getElementById("modal");
modal.className = "modal";
}
</script>
</html>

BIN
example.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

27
package.json Normal file
View File

@ -0,0 +1,27 @@
{
"name": "spa-form",
"version": "1.0.0",
"description": "A Utility web component to send form data to a callback function instead of HTTP endpoint",
"main": "spa-form.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/CalebBraaten/spa-form.git"
},
"keywords": [
"WebComponents",
"FunctionalWebComponent",
"VanillaJS",
"NoFramework",
"SPA",
"Components"
],
"author": "Caleb Braaten",
"license": "MIT",
"bugs": {
"url": "https://github.com/CalebBraaten/spa-form/issues"
},
"homepage": "https://github.com/CalebBraaten/spa-form#readme"
}

28
spa-form.js Normal file
View File

@ -0,0 +1,28 @@
class spaForm extends HTMLFormElement{
constructor(){
super();
this.onsubmit = this.submit;
this.callback = this.getAttribute("data-callback");
this.retainOnSubmit = this.getAttribute("retainOnSubmit") != null ? false : true;
}
// Called on Submit
submit(event) {
event.preventDefault();
let data = {};
for(let i = 0; i < this.elements.length; i++){
data[this.elements[i].getAttribute("name")] = this.elements[i].value;
}
if(this.retainOnSubmit){
this.clearForm();
}
// Make call to callback function
window[this.callback](data);
}
clearForm(){
this.reset();
}
}
customElements.define('spa-form', spaForm, {extends: 'form'});