Formidable Pro – Datatables Tutorial

Last Revised 1/11/2017

Introduction

This tutorial covers how to add the datatables jquery table enhancements. Many things can be accomplished with this plugin, but we are going to cover a simple version of it as needed for exporting.

Prerequisites (other than the datatables plugin files): Access to file management for your server so that you can put the plugin files where they need to be. HTML/CSS Knowledge

Part 1
Part 2
Part 3
Part 4
Part 5

Part 1

First of all we need to download the datatables core and upload it to your server from http://datatables.net/download/index. In using the download builder we will select the following:
Main Libraries
JQuery – No JQuery (It comes bundled with WordPress by default)
Styling – DataTables
DataTables – DataTables (of course you need this)
Extensions
Buttons – Buttons
Other Button options will appear…
Buttons – HTML5 export
Buttons – JSZip
Buttons – pdfmake
Buttons – Print Preview
Responsive

Packaging Options: I recommend getting the minified version in a single, local file.

We are using WordPress so in this example I’ve extracted the download contents into the wp-content folder under datatables.
Example: Your-url-here/wp-content/datatables.
I’ve also went ahead and renamed these folders as to shorten and less complicate the titles. (i.e., Buttons-1.1.0 becomes simply buttons)

That’s the hard part! We’re pretty much almost there. Next we have to load the appropriate files for loading styles and scripts required by the plugin.

Part 2

In your view your going to add something like the following into the “Before Content” area of the view. Fix the URL and note the #tablescroll style for keeping the table inside the content of your theme.

<style type="text/css" title="currentStyle">
@import "[siteurl]/wp-content/datatables/css/jquery.dataTables.min.css";
@import "[siteurl]/wp-content/datatables/css/responsive.dataTables.min.css";
@import "[siteurl]/wp-content/datatables/buttons/css/buttons.dataTables.min.css";
.lb {
    float: left;
    clear: both;
}
</style>
<script type="text/javascript" src="[siteurl]/wp-content/datatables/js/jquery.dataTables.min.js"></script >
<script type="text/javascript" src="[siteurl]/wp-content/datatables/js/dataTables.responsive.min.js"></script >
<script type="text/javascript" src="[siteurl]/wp-content/datatables/buttons/js/dataTables.buttons.min.js"></script >
<script type="text/javascript" src="[siteurl]/wp-content/datatables/buttons/js/buttons.html5.min.js"></script >
<script type="text/javascript" src="[siteurl]/wp-content/datatables/buttons/js/buttons.print.min.js"></script >
<script type="text/javascript" src="[siteurl]/wp-content/datatables/pdfmake/build/pdfmake.min.js"></script >
<script type="text/javascript" src="[siteurl]/wp-content/datatables/pdfmake/build/vfs_fonts.js"></script >
<script type="text/javascript" src="[siteurl]/wp-content/datatables/jszip/jszip.min.js"></script >


Part 3

Now we will add the opening HTML table tags along with the table head and foot information followed by an opening table body tag.

In step 5 I’ve added some JQuery that will redefine the table ID of “table” by adding an auto increment variable by ones (e.g. table1, table2, etc.) to allow initialization of multiple datatables on a single page. Additionally note the necessary class attributes added to support responsive tables on mobile devices. Also note that I’ve duplicated the head and foot with an additional table row with a id of “filterrow” that will be used to generate individual column input filtering.

<table cellpadding="0" cellspacing="0" border="0" class="display responsive nowrap" id="table" width="100%">
        <thead>
          <tr>
            <th>Rendering engine</th>
            <th>Browser</th>
            <th>Platform(s)</th>
            <th>Engine version</th>
            <th>CSS grade</th>
          </tr>
          <tr class="filterrow">
            <th>Rendering engine</th>
            <th>Browser</th>
            <th>Platform(s)</th>
            <th>Engine version</th>
            <th>CSS grade</th>
          </tr>
        </thead>
        <tfoot>
          <tr class="filterrow">
            <th>Rendering engine</th>
            <th>Browser</th>
            <th>Platform(s)</th>
            <th>Engine version</th>
            <th>CSS grade</th>
          </tr>
          <tr>
            <th>Rendering engine</th>
            <th>Browser</th>
            <th>Platform(s)</th>
            <th>Engine version</th>
            <th>CSS grade</th>
          </tr>
        </tfoot>
        <tbody>


Everything above this line prefixes the “Before Content” with the appropriate plugin files, initializes the plugin script, and prefixes the table to be generated in the view.

Part 4

Next we add the appropriate table rows and table columns that we will use to generate the repeating content in the “Content” area of the view.

<tr>	 	 
<td>Trident</td>	 	 
<td>Internet Explorer 4.0</td>	 	 
<td>Win 95+</td>	 	 
<td class="center"> 4</td>	 	 
<td class="center">X</td>	 	 
</tr>	 	 
<tr>	 	 
<td>Trident</td>	 	 
<td>Internet Explorer 5.0</td>	 	 
<td>Win 95+</td>	 	 
<td class="center">5</td>	 	 
<td class="center">C</td>	 	 
</tr>	 	 
<tr>	 	 
<td>Trident</td>	 	 
<td>Internet Explorer 5.5</td>	 	 
<td>Win 95+</td>	 	 
<td class="center">5.5</td>	 	 
<td class="center">A</td>	 	 
</tr>	 	 
<tr>	 	 
<td>Trident</td>	 	 
<td>Internet Explorer 6</td>	 	 
<td>Win 98+</td>	 	 
<td class="center">6</td>	 	 
<td class="center">A</td>	 	 
</tr>	 	 
<tr>	 	 
<td>Trident</td>	 	 
<td>Internet Explorer 7</td>	 	 
<td>Win XP SP2+</td>	 	 
<td class="center">7</td>	 	 
<td class="center">A</td>	 	 
</tr>	 	 
<tr>	 	 
<td>Trident</td>	 	 
<td>AOL browser (AOL desktop)</td>	 	 
<td>Win XP</td>	 	 
<td class="center">6</td>	 	 
<td class="center">A</td>	 	 
</tr>	 	 
<tr>	 	 
<td>Gecko</td>	 	 
<td>Firefox 1.0</td>	 	 
<td>Win 98+ / OSX.2+</td>	 	 
<td class="center">1.7</td>	 	 
<td class="center">A</td>	 	 
</tr>	 	 
<tr>	 	 
<td>Gecko</td>	 	 
<td>Firefox 1.5</td>	 	 
<td>Win 98+ / OSX.2+</td>	 	 
<td class="center">1.8</td>	 	 
<td class="center">A</td>	 	 
</tr>	 	 
<tr>	 	 
<td>Gecko</td>	 	 
<td>Firefox 2.0</td>	 	 
<td>Win 98+ / OSX.2+</td>	 	 
<td class="center">1.8</td>	 	 
<td class="center">A</td>	 	 
</tr>	 	 
<tr>	 	 
<td>Gecko</td>	 	 
<td>Firefox 3.0</td>	 	 
<td>Win 2k+ / OSX.3+</td>	 	 
<td class="center">1.9</td>	 	 
<td class="center">A</td>	 	 
</tr>	 	 
<tr>	 	 
<td>Gecko</td>	 	 
<td>Camino 1.0</td>	 	 
<td>OSX.2+</td>	 	 
<td class="center">1.8</td>	 	 
<td class="center">A</td>	 	 
</tr>	 	 
<tr>	 	 
<td>Gecko</td>	 	 
<td>Camino 1.5</td>	 	 
<td>OSX.3+</td>	 	 
<td class="center">1.8</td>	 	 
<td class="center">A</td>	 	 
</tr>	 	 
<tr>	 	 
<td>Gecko</td>	 	 
<td>Netscape 7.2</td>	 	 
<td>Win 95+ / Mac OS 8.6-9.2</td>	 	 
<td class="center">1.7</td>	 	 
<td class="center">A</td>	 	 
</tr>	 	 
<tr>	 	 
<td>Gecko</td>	 	 
<td>Netscape Browser 8</td>	 	 
<td>Win 98SE+</td>	 	 
<td class="center">1.7</td>	 	 
<td class="center">A</td>	 	 
</tr>	 	 
<tr>	 	 
<td>Gecko</td>	 	 
<td>Netscape Navigator 9</td>	 	 
<td>Win 98+ / OSX.2+</td>	 	 
<td class="center">1.8</td>	 	 
<td class="center">A</td>	 	 
</tr>	 	 
<tr>	 	 
<td>Gecko</td>	 	 
<td>Mozilla 1.0</td>	 	 
<td>Win 95+ / OSX.1+</td>	 	 
<td class="center">1</td>	 	 
<td class="center">A</td>	 	 
</tr>	 	 
<tr>	 	 
<td>Gecko</td>	 	 
<td>Mozilla 1.1</td>	 	 
<td>Win 95+ / OSX.1+</td>	 	 
<td class="center">1.1</td>	 	 
<td class="center">A</td>	 	 
</tr>	 	 
<tr>	 	 
<td>Gecko</td>	 	 
<td>Mozilla 1.2</td>	 	 
<td>Win 95+ / OSX.1+</td>	 	 
<td class="center">1.2</td>	 	 
<td class="center">A</td>	 	 
</tr>	 	 
<tr>	 	 
<td>Gecko</td>	 	 
<td>Mozilla 1.3</td>	 	 
<td>Win 95+ / OSX.1+</td>	 	 
<td class="center">1.3</td>	 	 
<td class="center">A</td>	 	 
</tr>	 	 
<tr>	 	 
<td>Gecko</td>	 	 
<td>Mozilla 1.4</td>	 	 
<td>Win 95+ / OSX.1+</td>	 	 
<td class="center">1.4</td>	 	 
<td class="center">A</td>	 	 
</tr>	 	 
<tr>	 	 
<td>Gecko</td>	 	 
<td>Mozilla 1.5</td>	 	 
<td>Win 95+ / OSX.1+</td>	 	 
<td class="center">1.5</td>	 	 
<td class="center">A</td>	 	 
</tr>	 	 


Note: The example above is just a “filler” example for this demonstration and is not what would be used to generate repeated content that you might normally use for a view.

Part 5

And finally we close the table in the “After Content” area of the view. Here we actually initialize the datatables plugin. Make note of the comments in the code below as to what each function or line of code does to the table.

</tbody>
</table>

<script>
jQuery(document).ready( function () {
var count = 0;
jQuery("table").each( function () {
    var tableID = jQuery(this).attr("id");
    count++;
    var modTableID = tableID + count;
    jQuery(this).attr("ID", modTableID);
    var newTableID = jQuery(this).attr("id"); 

    // Setup - add a text input to each header cell
    jQuery('#' + newTableID + ' thead tr.filterrow th').each( function () {
        var title = jQuery('#' + newTableID + ' thead th').eq( jQuery(this).index() ).text();
        jQuery(this).html( '<input type="text" onclick="stopPropagation(event);" placeholder="Search '+title+'" />' );
    } );

    // Setup - add a text input to each footer cell
    jQuery('#' + newTableID + ' tfoot tr.filterrow th').each( function () {
        var title = jQuery('#' + newTableID + ' tfoot th').eq( jQuery(this).index() ).text();
        jQuery(this).html( '<input type="text" onclick="stopPropagation(event);" placeholder="Search '+title+'" />' );
    } );
 
    // DataTable
var table = jQuery('#' + newTableID).DataTable( {
    orderCellsTop: true,
                aLengthMenu: [[-1, 10, 25, 50, 100, 200, 300, 400, 500],[ "All", 10, 25, 50, 100, 200, 300, 400, 500]],
                iDisplayLength: 25,
		dom: 'B<"lb">lrtip',
                responsive: 'true',
                destroy: 'true',
        buttons: [
            { extend: 'copy',
                oSelectorOpts: {
                    filter: 'applied'
                }
            },
            { extend: 'csv',
                oSelectorOpts: {
                    filter: 'applied'
                }
            },
            { extend: 'pdfHtml5',
                oSelectorOpts: {
                    filter: 'applied'
                }
            },
            { extend: 'print',
                autoPrint: false,
                oSelectorOpts: {
                    filter: 'applied'
                }
            }
            ]
} );
     
    // Apply the filter
    jQuery("#" + newTableID + " thead input").on( 'keyup change', function () {
        table
            .column( jQuery(this).parent().index()+':visible' )
            .search( this.value )
            .draw();
    } );
    jQuery("#" + newTableID + " tfoot input").on( 'keyup change', function () {
        table
            .column( jQuery(this).parent().index()+':visible' )
            .search( this.value )
            .draw();
    } );

  function stopPropagation(evt) {
		if (evt.stopPropagation !== undefined) {
			evt.stopPropagation();
		} else {
			evt.cancelBubble = true;
		}
	}
} );
} );

document.querySelector('style').textContent += "@media screen and (max-width:1024px) { #filterrow { display: none; } .dt-buttons { display: none; } }";
</script>


The options I’ve added here allow you to do a few things:
aLengthMenu = Display a specified amount of rows in the table via a selectable drop down.
iDisplayLength = The initial amount of rows displayed in the table.
dom = The initializer that will find the appropriate location to start using the jquery.
responsive = Make the table responsive.
buttons = Adds the buttons for exporting data, copying tables, and printing.
destroy = Eliminate the unnecessary duplicate initialization alert.
The other parts of the code are documented and I picked these up at the datatables forums.

This is a demonstration to get an example working for you. You will need to modify the “Content” portion of the table to fit your needs for repeatable table data. You will also have to put in the appropriate columns for the table in the “Before Content” for the table header and table footer. You do not need to be worried about the “Advanced Settings” of the view as the datatables plugin will be handling the sorting, paging and such.

Caveats
Safari doesn’t support the webkit tools as necessary to allow datatables to function fully.
Data imported into excel from CSV may need to be formatted correctly as datatables has no control of this.
The performance of the data tied to this table is limited to the resources available on your server.
The multi-column sorting capability does not work on mobile devices.

Working Demo: http://www.techmavenconsulting.com/formidable-pro-datatables-demo/ Enjoy!

FormidablePro – Fancy Radio/Checkbox Buttons

Last Revised 1/31/2017

This tutorial assumes that you are familiar with the FormidablePro framework, CSS & HTML. The CSS styling provided was written for the latest version of Firefox only. Additional styling may be required for compatibility with other web browsers. Please visit http://www.w3schools.com/ for additional resources.
Here is a demo for some fancy buttons in place of radio and check boxes. Obviously what I show here is rather simple, but it’s also much more elegant than standard radios or check boxes.

Form – Field Options

In your radio or checkbox field options you will need to add a “CSS layout classes” value of: hideinput (defined in the preceding css). This will hide the actual radio or checkbox itself.

Form Custom HTML

The actual HTML is unchanged, but in the form settings the radio and checkbox fields are set to single row as opposed to multiple row.
<div id="frm_field_[id]_container" class="frm_form_field form-field [required_class][error_class]">
    <label  class="frm_primary_label">[field_name]
        <span class="frm_required">[required_label]</span>
    </label>
    <div class="frm_opt_container">[input]</div>
    [if description]<div class="frm_description">[description]</div>[/if description]
    [if error]<div class="frm_error">[error]</div>[/if error]
</div>

The JQuery


You will need to place this in the “After Fields” section of the customize HTML.
<script type="text/javascript">
jQuery(".horizontal_radio").each(function(index) {
  jQuery(this).find('.frm_radio').addClass('button-mid');
  jQuery(this).find('.frm_radio').first().addClass('button-left').removeClass('button-mid');
  jQuery(this).find('.frm_radio').last().addClass('button-right').removeClass('button-mid');   
});

jQuery(".frm_radio label").click(function() {
 jQuery(this).parent().parent().find('.frm_radio').find('label').removeClass('checked');
 jQuery(this).addClass('checked');
});

jQuery(".horizontal_radio").each(function(index) {
  jQuery(this).find('.frm_checkbox').addClass('button-mid');
  jQuery(this).find('.frm_checkbox').first().addClass('button-left').removeClass('button-mid');
  jQuery(this).find('.frm_checkbox').last().addClass('button-right').removeClass('button-mid');   
});

jQuery( "input[type='checkbox']" ).click(function() {
        jQuery(this).parent().toggleClass('checked');
});
</script>

The CSS

/* Begin Fancy Radio/Checkbox Buttons Styling */

.button-left .frm_radio {
    padding: 0px;
    margin: 0px !important;
}

.button-mid .frm_radio {
    padding: 0px;
    margin: 0px !important;
}

.button-right .frm_radio {
    padding: 0px;
    margin: 0px !important;
}

.button-left {
    float: left;
}

.button-mid {
    float: left;
}

.button-right {
    float: left;
}

.button-left label {
    background-color: #F00;
    padding: 5px 10px;
    float: left;
    border-radius: 5px 0 0 5px;
    font-weight: bold !important;
    color: #fff !important;
    margin-bottom: 10px !important;
}

.button-mid label {
    background-color: #F00;
    padding: 5px 10px;
    float: left;
    font-weight: bold !important;
    color: #fff !important;
    margin-bottom: 10px !important;
}

.button-right label {
    background-color: #F00;
    padding: 5px 10px;
    border-radius: 0 5px 5px 0;
    float: left;
    font-weight: bold !important;
    color: #fff !important;
    margin-bottom: 10px !important;
}

.button-left .checkbox {
    margin: 0px !important;
}

.button-mid .checkbox {
    margin: 0px !important;
}

.button-right .checkbox {
    margin: 0px !important;
}

div .hideinput input[type="checkbox"] {
    display: none;
}

div .hideinput input[type="radio"] {
    display: none;
}

.checked {
    background-color: green !important;
    font-weight: bold !important;
    color: #fff !important;
}

.frm_style_formidable-style.with_frm_style .horizontal_radio .frm_radio {
	margin: 0px;
}

.horizontal_radio .frm_checkbox {
	margin-right: 0px;
}

/* End Fancy Radio/Checkbox Buttons Styling */
Note: Some additional styling may have been added to this demo and you may need to make adjustments according to your needs, but this will get you close.

Finished Product

Formidable Pro – JQuery Tour Demo

This is an example of implementing the Bootstrap JQuery Tour script into a Formidable Pro form. Demo available after documentation.

Build your form as you always would and then do the following: Go to the “Customize HTML” section of your form. In the “Before Fields” subsection we add the following (just to add some visual improvements to the tour) before anything else:
<style>
.btn.btn-default {
    border-color: #ffffff !important;
}

.tour-step-background {
    background: #ffffff !important;
}
</style>
Next we wrap each of our fields in the div tags that the jquery script will point to like so:
<div id="step1">
<div id="frm_field_[id]_container" class="frm_form_field form-field [required_class][error_class]">
    <label for="field_[key]" class="frm_primary_label">[field_name]
        <span class="frm_required">[required_label]</span>
    </label>
    [input]
    [if description]<div class="frm_description">[description]</div>[/if description]
    [if error]<div class="frm_error">[error]</div>[/if error]
</div>
</div>
And our next field…
<div id="step2">
<div id="frm_field_[id]_container" class="frm_form_field form-field [required_class][error_class]">
    <label for="field_[key]" class="frm_primary_label">[field_name]
        <span class="frm_required">[required_label]</span>
    </label>
    [input]
    [if description]<div class="frm_description">[description]</div>[/if description]
    [if error]<div class="frm_error">[error]</div>[/if error]
</div>
</div>
And so on…

Note that we are really only adding opening div tags (with a defined ID) and a closing div tag:
<div id="name-here">
....Original field styling here....
</div>
Finally in the “After Fields” subsection we add the following:
<script src="http://www.techmavenconsulting.com/wp-content/themes/nullcoreII/tour/js/bootstrap-tour-standalone.min.js"></script>
<script>
jQuery(document).ready(function(){
 
    var tour = new Tour({
        storage : false,
  template: "<div class='popover tour'><div class='arrow'></div><h3 class='popover-title'></h3><div class='popover-content'></div><div class='popover-navigation'><button class='btn btn-default' data-role='prev'>« Prev</button><span data-role='separator'>|</span><button class='btn btn-default' data-role='next'>Next »</button><button class='btn btn-default end' data-role='end'>End tour</button></div></div>",
  backdrop: true,
  backdropPadding: 10,
    });
 
   tour.addSteps([
       {
        element: "#step1",
        placement: "top",
        title: "Step 1",
        content: "This tour will guide you through some of the features we'd like to point out."
      },
      {
        element: "#step2",
        placement: "top",
        title: "Step 2",
        content: "Here are the sections of this page, easily laid out."
      },
      {
        element: "#step3",
        placement: "top",
        backdrop: true,
        title: "Step 3",
        content: "This is a section that you can read. It has valuable information."
      },
      {
        element: "#step4",
        placement: "top",
        backdrop: true,
        title: "Step 4",
        content: "This is a section that you can read. It has valuable information."
      },
      {
        element: "#step5",
        placement: "top",
        backdrop: true,
        title: "Last Step",
        content: "This is the end of the tour. Please review the preceding documentation for setting up a tour on your site."
      },
 
    ]);

// Initialize the tour
tour.init();

jQuery('#tour').click(function () {
        // Start the tour
        tour.restart();
});
 
}());
</script>
Looking at the code above you should now be able to easily add additional steps. Refer to the Bootstrap documentation to understand how to add additional features or take your users across different pages throughout your site.

Notes:
Line 1: You will need to modify the url of the directory where you will keep your bootstrap script.
Lines 52-55: These lines call the necessary JQuery to start the tour. ‘#tour’ is the name of the link or button ID that will start the tour. We use the “restart()” script as opposed to the “start()” script as it will fire more than once.

Enjoy!



 

Formiable Pro – Tooltips Tutorial

Hey everyone, this is a long overdue tutorial as part of what I originally planned as a series of tutorials. My apologies and I can’t promise any urgency on anything else, but here it is. I previously wrote a tutorial on adding tooltips to Formidable Pro form fields. Redoing it is pretty easy really. Go to https://github.com/chinchang/hint.css and download  the Full Build “minified” css to generate the tooltips. Upload the onto your server somewhere that you can reference it.

Customizing the HTML and applying tooltips to your fields

Add
<link rel="stylesheet" href="[hint.css location here]"></link>
My Example (below):
<link rel="stylesheet" href="http://techmavenconsulting.com/wp-content/themes/nullcoreII/css/hint.min.css"></link>
To the “Before Fields” text area at the top in the “Customize HTML” section of the form settings above everything else. Then just add the appropriate class to each input object for each field like so:
<div id="frm_field_[id]_container" class="frm_form_field form-field [required_class][error_class]">
    <label for="field_[key]" class="frm_primary_label">[field_name]
        <span class="frm_required">[required_label]</span>
    </label>
    <span class="hint--right" data-hint="My tooltip here">[input]</span>
    [if description]<div class="frm_description">[description]</div>[/if description]
    [if error]<div class="frm_error">[error]</div>[/if error]
</div>
If the field is a radio or checkbox you have to define each option like so:
<div id="frm_field_[id]_container" class="frm_form_field form-field [required_class][error_class]">
    <label for="field_[key]" class="frm_primary_label">[field_name]
        <span class="frm_required">[required_label]</span>
    </label>
    <div class="frm_opt_container"><span class="hint--right" data-hint="Tooltip Option 1 text">[input opt=1]</span></div>
    <div class="frm_opt_container"><span class="hint--right" data-hint="Tooltip Option 2 text">[input opt=2]</span></div>
    [if description]<div class="frm_description">[description]</div>[/if description]
    [if error]<div class="frm_error">[error]</div>[/if error]
</div>
Notes: Depending on the theme you are using you may have to do some additional CSS changes/modifications per form for it to look nice. I had to add a CSS override to the before fields section to make it so that the tooltips CSS doesn’t overwrite the formidable css input box widths. The example below includes my original examples hint library style link:
<link rel="stylesheet" href="http://techmavenconsulting.com/wp-content/themes/nullcoreII/css/hint.min.css"></link>
<style>.with_frm_style input[type="text"], .with_frm_style input[type="password"], .with_frm_style input[type="email"], .with_frm_style input[type="number"], .with_frm_style input[type="url"], .with_frm_style input[type="tel"], .with_frm_style select, .with_frm_style textarea, .frm_form_fields_style, .with_frm_style .frm_scroll_box .frm_opt_container, .frm_form_fields_active_style, .frm_form_fields_error_style, .with_frm_style .chosen-container-multi .chosen-choices, .with_frm_style .chosen-container-single .chosen-single {
  width: 550px !important;
}
</style>
For horizontally aligned radios and checkbox, you’ll need to add the following. Note: Checkbox fields use the “horizontal radio” class.
.horizontal_radio .frm_opt_container {
    float: left !important;
    margin-right: 12px;
}
This doesn’t work with CSS layout classes that you can define when building the form, nor is it responsive. I plan to provide a workaround at some point in the future.

Working Example:

 
That’s it. Enjoy!