Twitter bootstrap, fly out contact or feedback form with validation and Ajax submission

Ok, I have taken a look at several of the contact or feedback forms on the internet in the past few weeks and they all work great, however, they require varying numbers of includes, and in some cases images, or even completely different versions of JQuery to get them up and running. The solutions that take advantage of HTML and the latest version of bootstrap.js are practically non-existent.  So I thought why not roll my own then pass it on, after all it comes in at six lines of JavaScript code for the toggle (I added a form validation and ajax submit for those that need help there) , some CSS, and a good old fashioned HTML form tag. At the very least will introduce you to a few JavaScript features that you may not have been used to seeing.

Ingredients

Twitter bootstap -> http://twitter.github.io/bootstrap/index.html

Let’s start with the end first (here’s what you are getting yourself into):

Screen Shot 2013-05-05 at 12.16.11 PM

I am posting the code to github as well as including it in this post, so feel free to pull it down from there and *hint* *hint* fork it and improve the validation methods if can ….  as it will probably come down in a cleaner format than cut and paste would have given you.

https://github.com/jmcdonald69124/jQuery-Bootstrap-Feedback-Sliding-Form

.rotate {
/* Safari, Chrome */
-webkit-transform: rotate(-90deg);
/* Firefox */
-moz-transform: rotate(-90deg);
/* IE */
-ms-transform: rotate(-90deg);
/* Opera */
-o-transform: rotate(-90deg);
/* Older versions of IE */
	filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);
/* CSS3 standard as defined here: http://www.w3.org/TR/css3-transforms/ */
	transform: rotate(-90deg);
}
		
.required {
	background-color:#F2DEDE !important;
	border: 1px #F00 solid !important;
}
		
.feedback {
	position	: fixed; /* This will never scroll out of view */
	background-color: #2F96B4;
	border		: 5px solid #333;
	color		: #FFF;
	font-weight	: bold;
	font-size	: 16px;
	padding	: 15px;
}
		
.feedback-form-wrapper {
/*
This is the CSS for the feedback div that is fixed to the top left hand side
of the screen. 
*/
display		: block;
	z-index		: 9999; /* Make sure it floats a little higher than the feedback form div below */
	top		: 100px;	
	left		: -395px; /* Bring the div in and hide the left (top) border */
	width		: 350px;
}
		
/* This will put some distance between the input box and the next label */
.feedback input{
	margin-bottom:5px;	
}
		
.feedback legend{
	color		: #FFF;	
}
		
.feedback-toggle {
/*
This is the CSS for the feedback div that is fixed to the top left hand side
of the screen. This div should slide with the form so that it provides a 
close button when the form is slid into view.
*/
left		: -49px; /* Bring the div in and hide the left (top) border */
	left		: -10px\9; /* Less Than IE9 Hack - Bring the div in and hide the left (top) border */
	top			: 200px;
	cursor		: pointer;
	padding-left: -75px;
	width		: 90px; /* Since this is getting rotated width appears as height to the eye*/
	height		: 15px; /* Since this is getting rotated height appears as width to the eye*/
	text-align	: center;
	border-top	: 5px solid #2F96B4;
	border-left	: 4px solid #333;
	border-right: 4px solid #333;
	z-index		: 10000; /* Make sure it floats above the content */
}

Of course, before I explain it would be nice to see the HTML that this code is modifying.

<!-- 
	This is the feedback form that gets toggles in and out of view
	based on the user clicking the 'feedback_toggle' div.
-->
<!-- **************************************************************  --> 

<div class="feedback feedback-toggle rotate" >Feedback</div>
<div class="feedback feedback-form-wrapper">
<form id="feedback-form" class="form-horizontal">
      <legend>Please give us feedback .. </legend>
          	<div class="alert alert-error" 	style="display:none">
	<h4>Uh-Oh</h4> 
                    Looks like some of the required fields are not complete!
	</div>
                <div class="alert alert-success" 	style="display:none">
	<h4>Thanks!</h4> 
                    Your feedback has been submitted, we'll get back to you as soon as we can!
	</div>
                <div class="alert alert-block" 	style="display:none">
                  <h4>Warning!</h4>
                  Something happened and the form did not get submitted...
                </div>
            	<label>Name</label>
                    <input type="text" id="username"  	data-validation='{"required":true,"type":"text"}' 	name="username" class="input-block-level"   >
                <label>Email</label>
                    <input type="email" 	name="email"  	data-validation='{"required":true,"type":"email"}'  class="input-block-level"  >
                <label>Message</label>
                    <textarea id="comment" 	name="comment"  data-validation='{"required":true,"type":"text"}' 	class="input-block-level" style="margin-bottom:10px;"  rows="4" cols="30"></textarea>
                <button class="btn btn-inverse btn-large pull-right"  float="right">Send</button>
 </form>
</div>
<!-- **************************************************************  -->

And finally, the JavaScript that is needed to make all of this work:

// This is the Feedback toggle functionality it slides the feedback form in and out
// of view when the user clicks the div with the class .feedback-toggle
$('.feedback-toggle').click( function(){
	var 	left = parseFloat($('.feedback')[0].style.left.match(/[0-9]+/g)) || 49,
		tgl	 = '+=390';
	      	(left > 49)  ? tgl = '-=390' : tgl = '+=390';
		$('.feedback').animate({ left: tgl}, 500);
});
		
/*
This is the custom validation for the feedback form 
	I have left the types open in the switch statement feel free 
	to add.
*/
validate = function(form,element){
    var isValid = false, // Assume that everything starts off invalid
          fields  = $(form).find('[data-validation]'), //<-- Should return all input elements in that specific form.
         data,
         validationProps;
       $.each(fields, function(index, value){
	validationProps 	= $(value).data('validation');
  
	if(validationProps.required){
	      ($(value).val().length > 0 )? $(value).removeClass("required") : $(value).addClass("required");	
	}
					  
	if(!typeof validationProps.minlength === 'undefined' && parseFloat(validationProps.minlength) > 0){
	      ($(value).val().length > parseFloat(validationProps.minlength))? $(value).removeClass("required") : $(value).addClass("required");
  }
					  
 switch(validationProps.type)
{
	case "email":
		var re = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/;  
		//console.log(validationProps.type);
		//console.log($(value).val().match(re));
		 ($(value).val().match(re))? $(value).removeClass("required") : $(value).addClass("required");	
	break;
	case "phone":
		// add code here 
	 break;
	case "numeric":
		// add code here 
	break;
	default:
	}
});
	isValid = ($(form).children().is('.required'))? false : true;	
	 (isValid)? $(form).find('.alert-error').fadeOut('fast') : $(form).find('.alert-error').fadeIn('fast') ;
	return isValid;
}
		
// This handles the on focus and on focus lost validation
$('input,textarea').on('blur', function(){
  	validate($(this).parent('form'),$(this).attr('id'));
}).on('focus', function(){
  	$(this).removeClass("required");
});
		
// This is the form submission AJAX code which also
// hides the feednack form.
		
$("#feedback-form .btn").click(function() {
	var url  	= "path/to/your/script.php", // the script where you handle the form input.
	data 	= $("#feedback-form").serialize(),
	isValid   = validate("#feedback-form");
	if(isValid){
		$.ajax({
			type	: "POST",
			url	: url,
			data	: data , // serializes the form's elements.
			success	: function(data){
				$('.feedback').find('.alert-error').fadeIn('fast');
				$('.feedback').animate({ left: '-=390'}, 500);
			},
			error	: function(data){
				$('.feedback').find('.alert-block').fadeIn('fast');
				return false;  
			}
		});
	}
	return false; // avoid to execute the actual submit of the form.
});

Ok, now for the explanation, rotate is pretty simple, as it just rotates the div that will serve as the ‘tab’ for the feedback page. It’s important to wrap your head around this concept, once the div is rotated the left hand side of the div is the bottom, the right the top, and the top the left, you get the idea, so if you want to make changes to the height, as you see it, you are making changes to the width.

The CSS

The feedback class contains the background color, font color and size, and border color / size for both the tab and the main form. The feedback form wrapper class contains the code that will be applied to a div that surrounds the actual web form, this CSS will bring the feedback form above the actual page by setting the z-index to 9999, and will position the form outside of the viewable area of the page by setting the value of left to be at -395. Notice the width is 350 pixels. To give the effect of having the tab the toggle area is raised above the form wrapper with a z-index of 10000, and is given a left that positions the top of the div (remember it’s been rotated) right off of the left hand side of the screen. There is a hack here to deal with IE versions less than 9. Ok, so now our CSS is set up and everything should be positioned right when we start to place out HTML code into the page.

The HTML

Ok, the form tag uses the bootstrap CSS class form-horizontal and has the ID feed-back form, the ID will be instrumental in the operation of this widget later on when we get into the JavaScript part of the tutorial. Under the legend tag are three DIVs that contain three different messages which we will use to indicate a successful AJAX submission, an unsuccessful AJAX submission, and finally, a problem with the required input AKA a validation error. Moving on to the input and text area elements, you will notice that they all have the class input-block-level, which also comes from the bootstrap CSS and just makes the element scale to the width of the container, and gives it that cool rounded look.

One thing that may strike you is the use of the HTML5 data attribute, and the fact that is some JSON in the value, this will be used to tell the JavaScript what type of validation should be done on each of these elements. I will explain this in the JavaScript explanation section. The button has several classes applied to it, and all of them come from the bootstrap CSS. Again, it looks cool, that’s why you decided to use it, right! Anyway, this is how you get that great button in no time flat.

The JavaScript

Ok, now for the JavaScript, which will come in and do all of the heavy lifting. First, we need to be able to slide the form into the page and back out again. The trick here is that the tab needs to be attached and needs to slide in at exactly the same time as the main form. This takes only six lines of code.

<br />
$('.feedback-toggle').click( function(){<br />
	var left = parseFloat($('.feedback')[0].style.left.match(/[0-9]+/g)) || 49,<br />
		tgl	 = '+=390';<br />
		 (left &gt; 49)  ? tgl = '-=390' : tgl = '+=390';<br />
		$('.feedback').animate({ left: tgl}, 500);<br />
});<br />

Ok, so line one we attach the function to the feedback-toggle div, nothing fancy, remember that we have the class feedback which controlled the font and background properties. Breaking these common elements out into a separate class was great in itself, but now we are going to use it to sort of tie the form to the tag by making the slide out / in code act on the feedback class. The second line gets the current value for the left hand position of the feedback DIV, the variable tgl is set by default to +=390 which will be the amount that we want to increase the CSS value of left for that DIV. The line after that contains a ternary operator which tests for left greater than 49, if that is true set tgl to -+390 otherwise, well, you know. Finally, the line $('.feedback').animate({ left: tgl}, 500); is what actually does the sliding.

Moving on we come to the custom validation part of the form, I needed to do this, because , once again, there seemed to be no good validation plugin that worked with the latest version of jQuery which is bundled with bootstrap. I plan to reuse it so it just takes the form id as a parameter, the form element is something I want to expand on in a later post. Notice the lines below:

<br />
// This handles the on focus and on focus lost validation<br />
    $('input,textarea').on('blur', function(){<br />
        validate($(this).parent('form'),$(this).attr('id'));<br />
    }).on('focus', function(){<br />
                $(this).removeClass("required");<br />
            });<br />

This code attaches the validate event to all of the textareas and input elements on the page. You could easily change it to be form specific by placing a dom selector before the first section of code. Basically, this calls the validate event on focus and on lose focus of each of those elements. The form id is being passed to the function as well as the attribute id.

Once the code hits the validate function, it checks to see if there is a value in the data attribute data-validation. The code is set up to take a JSON string that contains the basic validation settings, so far, these are:

required -> true or false

minlegth -> number only

type -> email, phone, or numeric, of which only email has been coded as of yet.

Tests are made against the values in the input elements based on the settings above, and a simple true or false boolean is returned.

Finally, the code to submit the form data is fairly straightforward, first, check to see if the form is valid before submitting, then post the values to some server side script, and display the appropriate message to the user depending on what happened with the validation and submission. If all goes well hide the form by sliding it back out.

Blazing fast Adobe dropdown in a form with web like type ahead for very large lists

If you ever had to create adobe forms and used the drop down box that comes standard in Livecycle you may have noticed that it does not provide support for type ahead. If you have some data intensive form fields you may have already noticed that the fields which are scrollable using the bar seem to stop around 2000 entries and after that the user will have to know that they must click the small arrow and scroll through the records that way, both you and I know that this is not acceptable in real world production environments. I had a requirement to put over 3000 items in a dropdown in an adobe form, so when I found out that you can use Javascript in Livecycle I had to try and get this one working, you can see the result below. For those that want to try and replicate this I am sharing the source code and will provide an explanation, if this is not enough you can download the compiled adobe form with a compiled fragment so you can be up and running in no time here Type Ahead Sample PDF for free!

First, since there is a refresh problem with the dropdown control that prevents the list from being updated while it is opened we will have to construct a custom dropdown. This custom dropdown will be contain the following 4 objects:

1) A text field – this will be named typeAheadField

2) A list field – this will be named typeAheadList

3) A button – this will act as the trigger which toggles the visibility of the dropdown list, the button will be named typeAheadTrigger.

4) An image that will serve as the small triangle on the button face, the image takes the default name of Image1 in the fragment.

The list that we use for the sample data is the countries list that ships with adobe Livecycle in the custom section of the object library. You can download the text version of the list here
These objects will all be grouped together so that they remain in proportion to one another. Now the real fun begins, it’s time to throw some Javascript in the form. The first thing we need to do is capture the entire list in an array so that we can repopulate the list when the user clears the contents of the textfield, and also, so we can perform a search over the entire contents of the list and not the set of new values that you get when you start filtering. It is very important that this only take place once, otherwise you run the risk of filling your main list with a subset of items. The code that performs this is below:

form1.typeAheadDropDown.ta.typeAheadList::ready:form - (JavaScript, client)

a  = xfa.resolveNodes("this.items[*]");
list 	= a.item(0).nodes; 		
	
list_bak = new Array();  

if(list_bak.length < 1){	
  for (i=0;i<list.length;i++){
      list_bak.push(list.item(i).value);
  }
} 

No we have created a Javascript array named list_bak that contains all of the list items. Now that we have some Javascript in the form we can start using the built in debugger to make sure that there are no errors in our code. To find the debugger just open your form using acrobat (pro) and click view in the toolbar then hover over tools and select ‘Javascript’ from the list that appears to the right (see the image below).

Once you have clicked JavaScript you should see a menu to the right of your document the console will appear, the image below shows both the console and the tab to the right that you must click to bring the console up.

Any errors in your JavaScript code will populate the console. In addition, the code below placed in your Livecycle form will print to the console.

console.println(‘something’);

Next, in keeping with the list control we have to make sure that the typeAheadField control is populated with the text from the list selection. To do this we need to add the following code on the change event:

form1.typeAheadDropDown.ta.typeAheadList::change - (JavaScript, client)
// Add the value to the textfield
this.resolveNode("typeAheadField").rawValue = ((xfa.host.version < 8.1 || xfa.host.version >= 9) ? ($.boundItem(xfa.event.newText)) : (xfa.event.newText));
// change the background color to white as a selection has been made
this.resolveNode("typeAheadField").ui.oneOfChild.border.fill.color.value = "255,255,255";

The last thing we want to control as far as the list portion of the control is to make sure that the list hides when the mouse is not over the list, otherwise we would be stuck with a dropdown that did indeed ‘drop down’ and never went back up. The following code in the mouseExit function will make sure that the list hides when it’s supposed to.

form1.typeAheadDropDown.ta.typeAheadList::mouseExit - (JavaScript, client)

this.resolveNode("typeAheadList").presence = "invisible";

Let’s move on to the actual text box that will take the input, obviously there are two important things to consider here, first, we have to filter the box based on the characters entered into the field, and second, we need to mark the box with a different color to indicate that the selection was not on the list, since one of the drawbacks of this approach is that you MUST have the fields set to user entered OPTIONAL in order for this to work.

Fisrt we’ll look at the code below that searches the list when the user pressed a key in the text field.

form1.typeAheadDropDown.ta.typeAheadField::change - (JavaScript, client)

pattern = xfa.event.newText;

match = new Array();

for (n=0; n < list_bak.length; n++){
 if(list_bak[n].toLowerCase().indexOf(pattern.toLowerCase())!= -1){
   match.push(list_bak[n]);
 }
}

if (xfa.event.newText == ""){
	this.resolveNode("typeAheadList").setItems( list_bak.toString(),1);
} else {
	this.resolveNode("typeAheadList").setItems( match.toString(),1);
}

this.resolveNode("typeAheadList").presence = "visible";

The code xfa.event.newText; will contain the value that has been entered into the text field. Remember the array list_bak, we will traverse the entire array looking for matches, the code we will use allows for a match anywhere in the text, working just like a SQL LIKE%% statement. When a match is found in the original list array the node is pushed into an array of matches and this array is written to the list. If the user clears the text field then we repopulate the field with the original list. The last line of code simply shows the list when the user starts typing.

Since we are forced to go the user entered optional route in the field settings we want to add some validation, right? I know that you probably aren’t using a list because you hoped that the user would just type in their own values. The code below will turn the text field a nice adobe form blue if the value is not on the list.

form1.typeAheadDropDown.ta.typeAheadField::validate - (JavaScript, client)


var v = this.resolveNode("typeAheadField").rawValue;

if (v == ""){
	 //	app.alert( this.resolveNode("typeAheadField.caption.value.#text").value + " is a required field and the value must be on the list.");
	 	this.resolveNode("typeAheadField").ui.oneOfChild.border.fill.color.value = "153,204,255";
	} else {
		
		match = new Array();

		for (n=0; n < list_bak.length; n++){
if(list_bak[n] == v){
match.push(list_bak[n]);
}
}

if(match.length){
this.resolveNode("typeAheadField").ui.oneOfChild.border.fill.color.value = "255,255,255";			
		} else {
this.resolveNode("typeAheadField").ui.oneOfChild.border.fill.color.value = "153,204,255";
		}		
}

The code that we need to place on the button is very simple, just one line that opens the drop down list.

form1.typeAheadDropDown.ta.typeAheadTrigger::click - (JavaScript, client)

this.resolveNode("typeAheadList").presence = "visible";

There you have it enough information to be dangerous and create your own adobe type ahead dropdown box like the one shown in the video.

If you do decide to use this Type Ahead Sample PDF adobe file instead of using the tutorial above to try your hand at recreating this object you will need to know the following:

  • This method relies on a list being pasted into the values section of the dropdown; it does not work on a form that is connected to a remote database, or an embedded XML file.
  • You will have to convert the fragment to an object to change the dimensions, data, etc. You can do this by right clicking on the fragment and choosing convert to embedded object.
  • Need support or want to hire me to create your adobe form just drop me a line at joshuamcdonald69124@gmail.com.

    A look at Javascript and how benchmarks deter good programming practices

    This is a great video that shows the consequences of benchmarking something without knowing exactly what to benchmark, and I agree completely with the Java assessment. More to come later ..

    Ever wonder if your users are getting client side javascript errors that stop your new app dead in it’s tracks?

    Ok so javascript is king, or at the least it’s now being used to rework sites for tablets, phones, you name it, it’s grown to be the most important skill you can possess if you are in web development, which by the way is bleeding into app development for mobile devices.

    That being said, there is one issue that javascript has and that is the fact that it is very linear, if you make a mistake the app stops dead in it’s tracks, all bets are off as to what might happen. We have all seen the small yellow triangle in the bottom left hand corner of the browser, right?

    Guess what, something went wrong! But what? There are so many variables! Latency issues? Unexpected user input? You know, those users that fire up a browser walk off for a day or a weekend and expect their session to be active? The list goes on and only gets more esoteric as we progress through a painful amount of what-if’s. Hopefully, the following solution will give you an eye on the state of your javascript app once it gets into the wild. That’s right! You too can capture client side errors as they happen.

    First, add the following at the top of your javascript code to let the browser know that all errors raised on the client side should be passed through the custom error handler function that you will place at the bottom of your javascript code.

    window.onerror=myErrHandler;
    

    What this line does is redirects all errors to a function called myErrhandler (below), when an error occurs you normally get the line, description, page, and character place (column) where the error occurred. They’re all right there in that little box that your browser popped up, or worse, hidden behind the little yellow triangle in the left hand corner of your screen. The example below shows the box that appears when you go to msnbc.com and click on one of their articles.

    Now the trick is to get the data from the client side error messages into your server side database so that you can analyze the code and correct any issues that you would have missed.

    In fact, the only other way that you would have been notified of this error is when a customer takes the time out to contact you about it, and I bet they would rather go to a competitor instead, right! Luckily, we can use AJAX to send the data via the Ext ajax request in the function below.

    function myErrHandler (desc,page,line,chr)  {
    var errorMsg = 'Error description: \t'+ desc +'<br>Line number: \t'+line+ 'Page: \t' + page;
    	  //Handle errors here
    	  }
    Ext.Ajax.request({				   
    	url: 'some_db_update_page.php',
    	method:'post',
    	success: function(response){
    	// You probably do not want to say anything here, but just in case
    	},
    	failure:    function(response){	
    	//Whoa double errors
    errMsg('Error!',response.responseText);				
    	},				  
    	params: {'type': 'JavaScript','message': errorMsg, 'component':Ext.getCmp('tabs').layout.activeItem.id}
    });
    return true
    }
    

    In this example, I am assuming a viewport type Ext application with the main tab panel to have an ID of tabs, this lets you get even a step closer to the error by providing the actual ext component that the user was interacting with when the error occurred.

    Ext.getCmp('tabs').layout.activeItem.id
    

    Of course the ajax request should hit a page that populates your database with the error values. I hope this helps make your app more robust and less prone to errors in the future.

    Minimizing your javascript using the YUI compressor

    Once you code your masterpiece, by of course using descriptive variable names, function names, and fully indented and commented code, you are ready to upload it to your web server and put your application into production. That’s great! But all of those descriptive variable names, tabs, spaces, and eloquent coding are increasing your javascript file size. So what, right, it’s only a few bytes, how much could that harm? Well, when a user requests a page from the server they are actually requesting all of the elements (like pictures, stylesheets, javascript, flash files, etc ..) to be downloaded individually, unless some of the elements have been stored on the client’s machine. The files that are stored are in the user’s cache. Here’s the issue, most of the users that hit a site have an empty cache according to research done by Yahoo’s performance team. http://developer.yahoo.com/performance/ This is exactly why it is so important to keep your files as lightweight as possible, meaning, compress those images, and now compress those external javascript files and css files. So what does code minimization do? First, it strips out any of the comments and blank spaces, next it rewrites the variable, object, and function names using names that are as short as possible. The result is a file with one line of javascript that is usually 20% to 40% smaller than the previous file.

    How to minimize your files:

  • Download the YUI Compressor http://developer.yahoo.com/yui/compressor/
  • Extract the files to your hard drive, for example let’s say you use C:/ as the location.
  • Now run your code through the compressor by

  • open the command prompt in Windows and navigating to the folder C:/yuicompressor-2.4.6/build/
  • Copy your javascript file into the ‘build’ folder in the location above
  • Run this command in the command prompt window: java –jar yuicompressor-2.4.6.jar –your_filename_here.js –o your_filename_here-min.js
  • You should now have your source file your_filename_here.js and the minimized file your_filename_here-min.js in the build folder.
  • Cut and paste the minimized folder to your test server and try to break it
  • But wait that’s not all …

    If you read the previous article on speeding up your application you also know that scope and how you manage it could cause additional delays. In addition, with all those changes did you really go line by line and see what code your modifications may have rendered ‘dead code’, or unused code?

  • Use -v like this to output all of the dead code and scope errors in your javascript java –jar yuicompressor-2.4.6.jar –your_filename_here.js –o your_filename_here-min.js -v
  • Finally, you could view JavaScript minification as a way of security through obscurity, which will make it harder for someone to reverse engineer your code and could be used in a ‘defense in depth’ approach to security as I would not recommend this as your only line of defense.