<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.2.0/css/bootstrap.min.css">
<link rel="stylesheet" href="rd-form-automator.css">
<link rel="stylesheet" href="example.css">
<title>RD Form Automator - Modal example</title>
</head>
<body>
<div class="container">
<div class="rd-example-call">
<h1>RD Form Automator</h1>
<p>RD Form Automator is a lightweight jQuery plugin (~4kb - minified version) that lets you easily create forms.</p>
</div>
<div class="row">
<div id="rd-form"
class="col-md-6"></div>
</div>
</div>
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="vendor/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="vendor/respond/1.4.2/respond.min.js"></script>
<![endif]-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.3/jquery.min.js" type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.2.0/js/bootstrap.min.js" type="text/javascript"></script>
<script src="rd-form-automator.min.js" type="text/javascript" data-template-folder=""></script>
<script>
$(document).ready(function() {
var options = {
'token': '62bb61431348e22850828a5829c4373faafe29c1',
'secret': '51a266c2844ccd5cac83d88de88d82d05358aa51',
'fields': [
{
'name': 'name',
'label': 'Nome',
'required': true,
'type': 'input',
'value': ''
},
{
'name': 'email',
'label': 'E-mail',
'required': true,
'type': 'input',
'value': ''
},
{
'name': 'state',
'label': 'Estado',
'type': 'select',
'value': ['PI','PR','SC','SP','RS']
},
{
'name': 'level',
'label': 'NĂvel',
'type': 'select',
'value': ['Rookie','Intermediate','Pro','Ninja']
},
{
'name': 'phone',
'label': 'Telefone',
'type': 'input',
'value': ''
}
],
'endpoint': 'http://www.brunopoeta.com/api.php'
};
$('#rd-form').RDAutomateForm(options);
});
</script>
</body>
</html>
.rd-example-call p{margin-bottom:24px}.rd-example-list{list-style-type:none;padding:0}.rd-example-list>li{font-size:1.2em;margin-bottom:1em}
/**
* RD Form Automator
* Created by Bruno Poeta.
* http://www.brunopoeta.com
*/
/* global angular, console */
/* jshint unused:false */
/* jshint latedef:false */
$(document).ready(function() {
// InvalidFields function returns all invalid fields in a form
$.fn.invalidFields = function() {
var invalid = [];
this.find('[required]').each(function() {
if($(this).val() === '') { invalid.push(this); }
});
return invalid;
};
$.fn.RDAutomateForm = function(options) {
var form,
// Button texts
button = (options.button) ? options.button : {
error: 'Error!',
send: 'Send message',
sending: 'Sending message...',
sent: 'Message sent!'
},
folder = $('script[data-template-folder]').data('template-folder'),
// Feedback messages
messages = (options.messages) ? options.messages : {
error: 'There was an error sending your message. Please try again in a few moments.',
required: 'Please fill all the indicated fields.',
success: 'Thank you for sending a message! We will be getting in touch with you soon!'
},
wrapper = this;
// We add the .rd-form class to our wrapper
wrapper.addClass('rd-form');
// Resets form fields and
function clearForm() {
// Clear this attribute so the user can send a message again
form.attr('data-status','');
form.find('.rd-form-message').removeClass('visible success');
form.find('button[type=submit]').removeClass('sent').text(button.send);
form.find('select.form-control').each(function() {
var $this = $(this);
$this.find('option:nth-child(1)').attr("selected",true);
});
form.find('input.form-control').each(function() {
var $this = $(this);
$this.val('');
});
}
function createForm(template,modal) {
if(modal) {
wrapper.find('.modal-content').append(template);
} else {
wrapper.append(template);
console.log('Append template');
}
form = wrapper.find('form');
// We iterate through user options
for(var i=0;i<options.fields.length;i++) {
// In case the field type is select, we do this
if(options.fields[i].type === 'select') {
// We add data-rd-field and data-name to make this elements easy to fetch later
var select = '<div class="form-group" data-rd-field data-name="' + options.fields[i].name + '">';
select += '<label class="control-label">' + options.fields[i].label + '</label>';
select += '<select class="form-control">';
// And another loop to iterate through the select options
for(var j=0;j<options.fields[i].value.length;j++) {
select += '<option>' + options.fields[i].value[j] + '</option>';
}
select += '</select>';
select += '</div>';
form.find('.user-fields').append(select);
}
// In case the field type is input, we do this
if(options.fields[i].type === 'input') {
var input = '<div class="form-group" data-rd-field data-name="' + options.fields[i].name + '">';
// Check if field is required
var required = (options.fields[i].required) ? ' required' : '';
input += '<label class="control-label">' + options.fields[i].label + '</label>';
input += '<input class="form-control" type="text" placeholder="' + options.fields[i].label +'"'+ required +'>';
input += '</div>';
form.find('.user-fields').append(input);
}
}
// Click button to submit our form
form.find('button[type=submit]').click(function(event) {
event.preventDefault();
sendForm(this);
});
// And add a watcher function to our required fields
watchRequiredFields();
}
// This function transforms all the fields (plus secret and token keys) into a readable JSON object to send in our sendForm function
function getData() {
var data = '{';
// Each field that has data-rd-field in page
$('form [data-rd-field]').each(function() {
var $this = $(this);
// Will be added to our string
data += '"' + $this.data('name') + '":"' + $this.find('input,select').val() + '",';
});
// Along with secret and token keys
data += '"secret":"' + options.secret + '",';
data += '"token":"' + options.token + '"}';
// And then we just return the
return JSON.parse(data);
}
function getFormTemplate(modal) {
$.get('form.html',function(template) {
// After we get our form.html template, we fetch settings from settings.json
createForm(template,modal);
});
}
function getModalTemplate() {
$.get('modal.html',function(template) {
// Append modal to wrapper
wrapper.append(template);
// Set title and subtitle
wrapper.find('.modal-header h1').text(options.modal_title);
wrapper.find('.modal-header span').text(options.modal_subtitle);
getFormTemplate(true);
swapModalToggle();
});
}
function sendForm() {
// First we check if there is any required fields that weren't filled
if(form.invalidFields().length > 0) {
// If there is, we add class visible to our message
form.find('.rd-form-message').addClass('visible error').text(messages.required);
// Since invalidFields returns the fields, we create a loop on them
for(var i=0;i<form.invalidFields().length;i++) {
var $field = $(form.invalidFields()[i]);
// And in every field we add the has-error class
$field.parent().addClass('has-error');
}
// Return false so we can break this function's cycle
return false;
}
// Checking for multiple sends
if(form.data('status') === 'sending') {
return false;
}
// Give feedback to the user
form.find('button[type="submit"]').addClass('sending').text(button.sending);
form.find('.rd-form-message').removeClass('visible');
// To avoid multiple sends, we add this
form.attr('data-status','sending');
$.ajax({
type: 'POST',
url: options.endpoint,
data: getData(), // Transform our fields into JSON data
error: function() {
form.find('button[type="submit"]').removeClass('sending').addClass('error').text(button.error);
form.find('.rd-form-message').addClass('visible error').text(messages.error);
setTimeout(function() {
form.find('button[type="submit"]').removeClass('error').text(button.send);
form.find('.rd-form-message').addClass('visible error').text(messages.error);
},2000);
},
success: function() {
form.find('button[type="submit"]').removeClass('sending').addClass('sent').text(button.sent);
form.find('.rd-form-message').addClass('visible success').text(messages.success);
setTimeout(function() {
clearForm();
},5000);
// console.log('teste');
}
});
}
// This function changes the way modal is toggled to work with RD Form Automator
function swapModalToggle() {
$('[data-toggle="modal"]').click(function(event) {
event.stopPropagation();
$($(this).data('target') + ' .modal').modal('toggle');
});
}
function watchRequiredFields() {
form.find('[required]').each(function() {
var $this = $(this);
// Append * to our label to give feedback to the user
$this.parent().find('label').append(' *');
// Add jquery input watcher to the required field
$this.on('input',function() {
// In case the field is empty we add the has-error class.
// Otherwise we remove the class.
if($this.val() === '') {
$this.parent().addClass('has-error');
} else {
$this.parent().removeClass('has-error');
}
// If there aren't any empty required fields, we can remove the class visible from the message.
if(form.invalidFields().length === 0) {
form.find('.rd-form-message').removeClass('visible error');
}
});
});
}
// Calls
if(!options.modal) {
getFormTemplate();
} else {
getModalTemplate();
}
};
});
<form novalidate>
<span class="rd-form-message"></span>
<div class="rd-form-elements">
<div class="user-fields"></div>
<button class="rd-form-button"
type="submit">Enviar</button>
</div>
</form>
/*
Bourbon
*/
/*
Helpers
*/
/*
Color variables
*/
/*
Partials
*/
/*
Form
*/
.rd-form {
color: #333;
}
.rd-form.success .modal-header {
border-radius: 6px;
}
.rd-form.success form {
display: none;
}
/*
Form button
*/
.rd-form-button {
border: solid 1px;
border-bottom: solid 3px;
border-radius: 4px;
font-size: 1.1em;
padding: 12px 16px;
background: #6087B4;
border-color: #486e99;
border-bottom-color: #507aaa;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), inset 0 -1px 0 #486e99;
color: #FFF;
text-shadow: 0 1px 1px #486e99;
}
.rd-form-button:hover {
background: #83a1c4;
border-bottom-color: #7194bc;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4), inset 0 -1px 0 #6087B4;
color: #FFF;
text-shadow: 0 1px 1px #6087B4;
}
.rd-form-button:active {
background: #507aaa;
border-bottom: none;
border-top: solid 3px #406188;
box-shadow: none;
color: #f2f2f2;
text-shadow: 0 1px 1px #507aaa;
}
.rd-form-button.error {
background: #CC512F;
border-color: #a34125;
border-bottom-color: #b7492a;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), inset 0 -1px 0 #a34125;
color: #FFF;
text-shadow: 0 1px 1px #a34125;
}
.rd-form-button.error:hover {
background: #d87256;
border-bottom-color: #d36141;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4), inset 0 -1px 0 #CC512F;
color: #FFF;
text-shadow: 0 1px 1px #CC512F;
}
.rd-form-button.error:active {
background: #b7492a;
border-bottom: none;
border-top: solid 3px #8e3821;
box-shadow: none;
color: #f2f2f2;
text-shadow: 0 1px 1px #b7492a;
}
.rd-form-button.sending {
background: #b5c3cb;
border-color: #97aab6;
border-bottom-color: #a6b6c0;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), inset 0 -1px 0 #97aab6;
color: #FFF;
text-shadow: 0 1px 1px #97aab6;
-webkit-animation: blinking 2s infinite;
-moz-animation: blinking 2s infinite;
animation: blinking 2s infinite;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
animation-timing-function: linear;
}
.rd-form-button.sending:hover {
background: #d3dbe0;
border-bottom-color: #c4cfd5;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4), inset 0 -1px 0 #b5c3cb;
color: #FFF;
text-shadow: 0 1px 1px #b5c3cb;
}
.rd-form-button.sending:active {
background: #a6b6c0;
border-bottom: none;
border-top: solid 3px #889eab;
box-shadow: none;
color: #f2f2f2;
text-shadow: 0 1px 1px #a6b6c0;
}
@-webkit-keyframes blinking {
0% {
opacity: 1;
}
50% {
opacity: 0.5;
}
100% {
opacity: 1;
}
}
@-moz-keyframes blinking {
0% {
opacity: 1;
}
50% {
opacity: 0.5;
}
100% {
opacity: 1;
}
}
@keyframes blinking {
0% {
opacity: 1;
}
50% {
opacity: 0.5;
}
100% {
opacity: 1;
}
}
.rd-form-button.sent {
background: #3CB216;
border-color: #2d8510;
border-bottom-color: #349b13;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), inset 0 -1px 0 #2d8510;
color: #FFF;
text-shadow: 0 1px 1px #2d8510;
}
.rd-form-button.sent:hover {
background: #4bdf1c;
border-bottom-color: #44c919;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4), inset 0 -1px 0 #3CB216;
color: #FFF;
text-shadow: 0 1px 1px #3CB216;
}
.rd-form-button.sent:active {
background: #349b13;
border-bottom: none;
border-top: solid 3px #256e0e;
box-shadow: none;
color: #f2f2f2;
text-shadow: 0 1px 1px #349b13;
}
/*
Form styling (inputs, selects)
*/
.rd-form input.form-control {
border-radius: 2px;
padding: 8px;
}
.rd-form input.form-control:hover {
background-color: #F9F9F9;
}
.rd-form input.form-control:hover:focus {
background-color: #FFF;
}
.rd-form label.control-label {
color: #6087B4;
}
.rd-form select.form-control {
-webkit-appearance: none;
-moz-appearance: none;
-ms-appearance: none;
-o-appearance: none;
appearance: none;
border-radius: 2px;
background-image: url(http://www.brunopoeta.com/wp-content/themes/brunopoeta/common/images/temp/caret-down.png);
background-repeat: no-repeat;
padding: 8px;
background-position: right 0;
}
.rd-form select.form-control:hover {
background-color: #F9F9F9;
}
.rd-form select.form-control:hover:focus {
background-color: #FFF;
}
/*
Form message (user feedback)
*/
.rd-form .rd-form-message {
border: solid 1px;
border-radius: 4px;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4);
display: none;
font-weight: 700;
margin-bottom: 24px;
padding: 15px;
}
.rd-form .rd-form-message.error {
background: #f5dad2;
border-color: #b7492a;
color: #CC512F;
}
.rd-form .rd-form-message.success {
background: #c7f6b7;
border-color: #349b13;
color: #3CB216;
}
.rd-form .rd-form-message.visible {
display: block;
}
/*
Form validation
*/
.rd-form .has-error input {
background: #f5dad2;
border-color: #ebb7a9;
}
.rd-form .has-error input::-webkit-input-placeholder {
color: #b7492a;
}
.rd-form .has-error input::-moz-placeholder {
color: #b7492a;
}
.rd-form .has-error input:-moz-placeholder {
color: #b7492a;
}
.rd-form .has-error input:-ms-input-placeholder {
color: #b7492a;
}
.rd-form .has-error input:hover {
background: #f9ebe7;
}
.rd-form .has-error input:focus {
background: #f5dad2;
border-color: #e2957f;
}
.rd-form .has-error label {
color: #d87256;
}
/*
Modal styles
*/
.rd-form .modal-content {
border-radius: 8px;
}
.rd-form .modal-content .rd-form-elements {
padding: 15px;
}
.rd-form .modal-content .rd-form-message {
border-left: none;
border-radius: 0;
border-right: none;
margin: 0;
}
.rd-form .modal-header {
background: #6087B4;
border: none;
border-top-left-radius: 6px;
border-top-right-radius: 6px;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2);
text-shadow: 0 1px 1px #385576;
}
.rd-form .modal-header h1 {
color: #FFF;
margin: 0 0 0.2em;
}
.rd-form .modal-header span {
color: #e7edf3;
}