Home Blog Joomla Creating branching logic in multi-page RS Form Pro

Creating branching logic in multi-page RS Form Pro

Joomla

RS Forms is a great component. Its got all the hooks in the admin to be able to add any kind of advanced dynamic functionality that you want. A recent version of RS Form introduced the concept of 'pagination' or - breaking your form onto seperate pages. This can be a handy feature if you feel that your form is too ominous in it's entireity.

What we wanted to do however was build special logic into the sequencing of the pages. So based on how the user answers a question in RS Form, we direct them to the next question we want them to see. In the form builder world, this is sometimes refered to as branching logic. Understandably, the makers of RS Forms have not added this feature because it's possibly hard to administer. However by adding some jquery to the form, we can add the functionality we need.

Here's how you do it...

 

First you have to add the fields to your form.

Here's a picture of how our form looks:

rsform_components2

Take special note of your field names. You will need to manually reference every one of those names in your layout. We've built logic into our JavaScript to handle checkboxes, radios and pulldowns. These are the only fields you can use to affect logic that guides the form. You can add other fields but they'll just be used to store information.

Use RS Form's pagination to add your page breaks. Our JS uses them to control the form. You have to name then 1,2,3 etc as our form uses that to control everything. Don't forget to add a submit button on the final page.

Next add your layout:

It's helpful if you are 100% sure that you've got all your fields before you start customizing your layout. We've done a custom layout that uses a special design controlled by CSS. The different field elements are placed around the page.

Here's the layout for our sample form:

{error}
<div id="cost">
 <table>
 <thead><tr><th colspan="3">Cost</th></tr></thead>
 <tfoot>
 <tr class="footer">
 <td>Total Cost</td>
 <td colspan="2"><span class="currency">$</span><span class="value">0</span></td>
 </tr>
 </tfoot>
 <tbody>

 </tbody>
 </table>
</div>
<div class="formHeader">{global:formtitle}</div>
<div id="formWrapper">
 <!-- Do not remove this ID, it is used to identify the page so that the pagination script can work correctly -->
 <div id="rsform_7_page_0" class="questionParts">
 <div class="paginator">
 <div class="heading">Question 1 of X</div>
 <div class="nextPrev">{1:body}</div>
 <div class="clr"></div>
 </div>
 <div class="questionWrapper">
 <div class="question">{question1:caption} (*)</div>
 <div class="radioOptions">
 {question1:body}
 {question1:validation}
 </div>
 <div class="clr"></div>
 </div>
 <div class="description">{question1:description}</div>
 </div>
 <!-- Do not remove this ID, it is used to identify the page so that the pagination script can work correctly -->
 <div id="rsform_7_page_1" class="questionParts">
 <div class="paginator">
 <div class="heading">Question 2 of X</div>
 <div class="nextPrev">{2:body}</div>
 <div class="clr"></div>
 </div>
 <div class="questionWrapper">
 <div class="question">{question2:caption} (*)</div>
 <div class="radioOptions">
 {question2:body}
 {question2:validation}
 </div>
 <div class="clr"></div>
 </div>
 <div class="description">{question2:description}</div>
 </div>
 <!-- Do not remove this ID, it is used to identify the page so that the pagination script can work correctly -->
 <div id="rsform_7_page_2" class="questionParts">
 <div class="paginator">
 <div class="heading">Question 3 of X</div>
 <div class="nextPrev">{3:body}</div>
 <div class="clr"></div>
 </div>
 <div class="questionWrapper">
 <div class="question">{question3:caption}</div>
 <div class="radioOptions">
 {question3:body}
 {question3:validation}
 </div>
 <div class="clr"></div>
 </div>
 <div class="description">{question3:description}</div>
 </div>
 <!-- Do not remove this ID, it is used to identify the page so that the pagination script can work correctly -->
 <div id="rsform_7_page_3" class="questionParts">
 <div class="paginator">
 <div class="heading">Question 4 of X</div>
 <div class="nextPrev">{4:body}</div>
 <div class="clr"></div>
 </div>
 <div class="questionWrapper">
 <div class="question">{question4:caption}</div>
 <div class="radioOptions">
 {question4:body}
 {question4:validation}</div>
 <div class="clr"></div>
 </div>
 <div class="description">{question4:description}</div>
 </div>
 
 <!-- Do not remove this ID, it is used to identify the page so that the pagination script can work correctly -->
 <div id="rsform_7_page_4" class="questionParts">
 <div class="paginator">
 <div class="heading">Conclusion</div>
 <div class="nextPrev">{submit:body}</div>
 <div class="clr"></div>
 </div>
 <div class="questionWrapper">
{conclusion:body}
<table>
<tr><td>
{Name:caption} * 
</td><td>
{Name:body}
{Name:validation}
</td></tr>
<tr><td>
{Email:caption} * 
</td><td>
{Email:body}
{Email:validation}
</td></tr>
<tr><td>
{Notes:caption}
</td><td>
{Notes:body}
{Notes:validation}
</td></tr>
<tr><td>
{Contact:caption}
</td><td>
{Contact:body}
{Contact:validation}
</td></tr>
<tr><td>
{Number:caption}
</td><td>
{Number:body}
{Number:validation}
</td></tr>
<tr><td>
{Company:caption}
</td><td>
{Company:body}
{Company:validation}
</td></tr>
</table>
{submit:body}

 <!--div class="question">{xxx:caption}</div>
 <div class="radioOptions">
 {xxx:body}
 {xxx:validation}</div-->
 <div class="clr"></div>
 </div>
 <div class="description">{conclusion_info:body}</div>
 </div>

{cost_table:body}
</div>

 

It's pretty obvious what is going on. The field names that you chose in the first step are reused in the layout. One thing to note especially however is rsform_7_page_4 you need to change the "7" to the ID of your actual form. Also note that the "4" is the name of the next paginator name.

 

Next put in your custom script

The first thing you want to do is jump over to the css/JavaScript tab in RS Form and style your form. Please do not (NOT) use our styling. We're making this all available for free but we'd really appreciate it if you dream up your own quote layout.

<link rel="stylesheet" rev="stylesheet" type="text/css" href="/jqueryui/jquery-ui-1.8.14.custom.css" /><style type="text/css">
 #formWrapper {float:left; width:75%;margin-bottom:10px;}
 .questionParts {}
 .paginator {-webkit-border-radius: 2px;-moz-border-radius: 2px;border-radius: 2px; border:1px solid #ECF0F3; margin-bottom:17px;}
 .paginator input {-webkit-border-radius: 2px;-moz-border-radius: 2px;border-radius: 2px; border:1px solid #ECF0F3; background-color:white; color:#7793A9; font-weight:bold; text-transform:lowercase; font-family:Arial,sans; font-size:11px; padding:5px; margin:7px;}
 .paginator input:hover {border:1px solid #ECF0F3; background-color:#7793A9; color:white; cursor:pointer;}
 .paginator .heading {float:left; height:100%; background:url(/templates/winworld/images/right-triangle.png) no-repeat center right #F0F4F7; color:#7894A9; font-size:18px; padding: 10px 33px 10px 10px; font-weight:bold;}
 .questionWrapper {-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px; border:1px solid #ECF0F3; }
 .description {-webkit-border-radius: 2px;-moz-border-radius: 2px;border-radius: 2px; border:1px solid #ECF0F3; border-top:none; padding:10px 17px; color:#7793A9; font-size:12px; text-indent:15px; background:url(/templates/winworld/images/info-icon.png) no-repeat 17px 10px;}
 .nextPrev {float:right;}
 .question {float:left; font-weight:bold;color:#506270;font-size:14px; padding:17px;}
 .radioOptions {float:right; padding:17px;}
 .checkboxOptions { clear:both; }
 .checkboxOptions input { clear:left; float:left; margin:3px 10px 3px 15px; }
 .checkboxOptions label { clear:right; display:block; line-height:17px; margin:0 15px 15px 0;}
 .formHeader {font-size:20px; color:#7894aa; font-family:District,DistrictDemi,Myriad Pro,Helvetica,Arial,sans;
 font-weight:bold; margin:40px 0 30px; padding: 0 0 0 40px; background:url(/templates/winworld/images/clip-board.png) no-repeat center left; float:left; clear:left;}
 span.pathway {display:none !important;}
 #cost {margin:30px 0 10px; -webkit-border-radius: 2px;-moz-border-radius: 2px;border-radius: 2px; border:1px solid #bbc9d4; background-color:#e4e9ed; padding:3px; float:right;width:23%;}
 #cost table {-webkit-border-radius: 2px;-moz-border-radius: 2px;border-radius: 2px; border:1px solid #839eb1; border-collapse:collapse; width:100%;}
 #cost th {background-image:none; background-color:#92a9bb; color:white; padding:15px 20px; font-size:15px; text-align:left;}
 #cost td {padding:10px 0 10px 20px; color:#7994a9; font-size:9px; border-bottom:1px solid #e5eaee;
 background-color:white;}
 #cost .number {font-weight:bold;}
 #cost tr.footer td {background-color:#dde4ea; color:#92a9bb; padding:15px 20px; font-size:15px; font-weight:bold;}
 #cost td.x {padding-right:5px;}
 .radios label { clear: right; float: left; width: 90%;}
 .radios input { float:left; clear:left;}
</style>

Note at the top there is an include for a CSS script. You'll need to put this folder in your web-root for that to work: jqueryui.zip 

Next put in the actual JavaScript

This is the trickiest part. You can't just copy and paste this part. Check out the code below:

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>
<script type="text/javascript" src="/jqueryui/jquery-ui-1.8.14.custom.min.js"></script>
<script type="text/javascript">
 jQuery.noConflict();
 (function($) {
 $(function() {
 var quest = "0",
 exclude = {},
 base_id = "#rsform_7_page_",
 cost;
 var questions ={
 1:{
 type:"radio",
 options:{
 "yes":{
 cost:{},
 next:2
 },
 "no":{
 cost:{},
 next:3
 }
 }
 },
 2:{
 type:"radio",
 options:{
 "Less than 50":{
 cost:{
 "Base":500,
 "Small Addon":1000,
 Option:"150/yr",
 Option2:"2/mo" 
 },
 message:"It sounds like you said yes and then picked your options. That's great! Now on to the next question.",
 next:3
 },
 "More than 50":{
 cost:{
 "Big Version":3000,
 Option:"150/yr",
 Option2:"2/mo"
 },
 message:"You chose the larger option so we added more money to your estimate. Give us your money.",
 next:3
 }
 }
 },
 3:{
 type:"checkboxes",
 options:{
 'No':{
 cost:{},
 next:4
 },
 'Yes':{
 cost:{
 "Base":500,
 "This Thing":500
 }
 },
 'Yes and add pie':{
 cost:{
 "Pie":0
 }
 },
 'Yes and add soda':{
 cost:{
 SSL:"150/yr",
 Soda:"2/mo"
 }
 }
 }
 },
 4:{
 type:"select",
 options:{
 "none":{
 next:"end"
 },
 "1":{
 cost:{
 "Add One":150
 },
 next:"end"
 },
 "2":{
 cost:{
 "Add Two":300
 },
 next:"end"
 },
 "3":{
 cost:{
 "Add Three":450
 },
 next:"end"
 },
 "4":{
 cost:{
 "Add Four":600
 },
 next:"end"
 }
 }
 }
 };
 $('#formWrapper input[type="button"]').removeAttr("onclick");

 //$('#formWrapper').append('<textarea style="display:none;" name="form[cost_table]" id="cost-table"></textarea>');

 function handler(q,idx,i,next){
 if(idx) idx = parseInt(idx);
 if(idx && i){
 exclude[idx] = [];
 if(q.options[i].next && q.options[i].next!="end"){
 if(q.options[i].next > idx+1){
 for(var l = idx+1;l< q.options[i].next ;l++){
 exclude[idx].push(l);
 }
 }
 }
 }
 $('#cost tbody tr').remove();
 var total = 0;
 $('.questionParts').each(function(){
 var id = parseInt($(this).attr("id").split("_").pop())+1;
 if(questions[id]){
 var ok = true;
 for(var ex in exclude){
 if($.inArray(id,exclude[ex])>-1){
 ok = false;
 break;
 }
 }
 if(ok){
 var q = questions[id];
 if(q.type=="radio"){
 var opt = $.trim($(this).find('input[type="radio"]:checked').val());
 if(q.options[opt]){
 if(q.options[opt].cost){
 for(var j in q.options[opt].cost){
 var add = true;
 $("#cost tbody .name").each(function(){
 if($(this).html()==j){
 add = false;
 }
 })
 if(add){
 total += parseFloat(q.options[opt].cost[j]);
 $("#cost tbody").append('<tr>'+
 '<td class="name">'+j+'</td>'+
 '<td class="number"><span class="currency">$</span><span class="value">'+q.options[opt].cost[j]+'</span></td><td class="x"></td>'+
 '</tr>');}
 }
 }
 }
 }else if(q.type=="select"){
 var opt = $.trim($(this).find('select').val());
 if(q.options[opt]){
 if(q.options[opt].cost){
 for(var j in q.options[opt].cost){
 var add = true;
 $("#cost tbody .name").each(function(){
 if($(this).html()==j){
 add = false;
 }
 })
 if(add){
 total += parseFloat(q.options[opt].cost[j]);
 $("#cost tbody").append('<tr>'+
 '<td class="name">'+j+'</td>'+
 '<td class="number"><span class="currency">$</span><span class="value">'+q.options[opt].cost[j]+'</span></td><td class="x"></td>'+
 '</tr>');}
 }
 }
 }
 }else if(q.type=="checkboxes"){
 $(this).find('input[type="checkbox"]:checked').each(function(){
 var opt = $.trim($(this).val());
 if(q.options[opt]){
 if(q.options[opt].cost){
 for(var j in q.options[opt].cost){
 var add = true;
 $("#cost tbody .name").each(function(){
 if($(this).html()==j){
 add = false;
 }
 })
 if(add){
 total += parseFloat(q.options[opt].cost[j]);
 $("#cost tbody").append('<tr>'+
 '<td class="name">'+j+'</td>'+
 '<td class="number"><span class="currency">$</span><span class="value">'+q.options[opt].cost[j]+'</span></td><td class="x"></td>'+
 '</tr>');}
 }
 }
 }
 });
 }
 }
 }
 });
 $("#cost tfoot .value").html(total);
 $('#cost_table').val($("#cost").html());
 if(idx && i){
 if(q.options[i].next && q.options[i].next!="end"){
 questions[q.options[i].next].prev = idx;
 }else if(q.options[i].next!="end"){
 questions[idx+1].prev = idx;
 }
 }else{
 if(idx) questions[idx+1].prev = idx;
 }
 if(next){
 if(i){
 $(".questionParts").hide();
 if(q.options[i].next!="end"){
 $(base_id+(q.options[i].next-1)).show();
 }else{
 $(base_id+(idx)).show();
 }
 }else if(idx){
 $(".questionParts").hide();
 $(base_id+(idx)).show();
 }
 }
 }

 $.each(questions, function(idx, q) {
 if(q.type==="radio"){
 $(base_id+(idx-1)+" input[type='radio']").click(function(){
 var $this = $(this);
 var i;
 for(i in q.options){
 if($.trim(i).toLowerCase()==$.trim($this.val()).toLowerCase()){
 break;
 }
 }
 if(q.options[i].message){
 $('<div id="info'+idx+'" title="Info">'+q.options[i].message+'</div>').dialog({
 modal:true,
 resizable:false,
 buttons:{
 Ok:function(){
 handler(q,idx,i,true);
 $(this).dialog("close");
 }
 },
 close:function(){
 $(this).dialog("destroy").remove();
 }
 });
 }else{
 handler(q,idx,i,true);
 }

 })
 }else if(q.type==="select"){
 $(base_id+(idx-1)+" select").change(function(){
 var i;
 for(i in q.options){
 if($.trim(i).toLowerCase()==$.trim($(this).val()).toLowerCase()){
 break;
 }
 }
 if(q.options[i].message){
 $('<div id="info'+idx+'" title="Info">'+q.options[i].message+'</div>').dialog({
 modal:true,
 resizable:false,
 buttons:{
 Ok:function(){
 handler(q,idx,i,true);
 $(this).dialog("close");
 }
 },
 close:function(){
 $(this).dialog("destroy").remove();
 }
 });
 }else{
 handler(q,idx,i,true);
 }
 })
 }else if(q.type==="checkboxes"){
 $(base_id+(idx-1)+" input[type='checkbox']").click(function(){
 handler(q,idx);
 })
 }
 });

 $('.nextPrev').click(function(e){
 var $target = $(e.target);
 if($target.is('input[value="Next"]')){
 var id = $target.attr("id").split("Next")[0];
 var question = questions[id];
 if(question.type=="radio"){
 var val = $.trim($(base_id+(id-1)+" input:checked").val()).toLowerCase();
 if(val!==null && val!==undefined && val!=""){
 handler(questions.id,id,null,true);
 }
 }else if(question.type=="checkboxes"){
 handler(questions.id,id,null,true);
 }else if(question.type=="select"){
 var val = $.trim($(base_id+(id-1)+" select").val()).toLowerCase();
 if(val!==null && val!==undefined && val!=""){
 handler(questions.id,id,null,true);
 }
 }
 }else if($target.is('input[value="Prev"]')){
 var id = parseInt($target.parents(".questionParts:first").attr("id").split("_").pop())+1;
 if(questions[id]){
 $(".questionParts").hide();
 $(base_id+(questions[id].prev-1)).show();
 }
 }
 })
 });
 })(jQuery);
</script>

Again, note the include at the beginning, you'll want to put the above Zip folder in your webroot.

Here's how the script works. You have to make a perfect JSON object. Its a variable that holds the instructions for the whole form.

At the beginning, be sure to set your base_id. Be sure to use your actual RS Form ID.

Bracket 1 corresponds to the page prior to pagebreak 1.

Type can be radio, checkboxes or select.

Options indicate what happen if a choice is made.

Cost allows you to add things to the cost table.

Cost items with spaces in the name need to be put in quotes.

Prices with non-numerics need to be put in quotes.

If you add the same item twice it will not add it to the cost table twice.

Next designates what the next question is based on if they chose the given answer.

If this form implementation does not work for you, it is probably because of a misformatted JSON object. Be very aware of quotes and commas. You need a comma after repeating elements - all but the last. See the example.

Final Step: Set emails and thankyou messages

The rest of the steps for setting up a branching logic tree form in RS Form are the same as normal form setups. Don't forget to set your thankyou page text, your user and admin emails. Be sure to test a lot and do your own custom styling. This type of form setup can take some hours but once you have it in place, this framework is versitile because it lets you easily change things.

For those of you who have a recent version of RS Form, I have loaded an export of an example form in the following zip. If you don't have the same version, this import won't work however. Try and understand how everything is working so you can really get the most out of this form.

Download here:  rsform_instant_quote.zip

Comments (1)Add Comment
0
Demo?
written by Nick Burch, January 18, 2012
Hello, do you have a working demo of this? I am running the latest RSFrom and it seems like I might be encountering a javascript collision. When the google jquery call is in place the form will not advance past the first page.

If I comment it out... it will advance but the branching of course doe not work. Any thoughts?


Write comment

security code
Write the displayed characters


busy
Web Content Management System Web Development Technical Partners

Newsletter Signup

Signup for WinWorld's monthly newsletter
and special offers.

ARCHIVE >>
Our Web Design page on Facebook
  
Our Twitter Feed
404 - Error: 404
404 - Componente no encontrado

Es posible que no pueda visitar esta página por:

  1. un bookmark/favorito anticuado
  2. el sistema de búsqueda tieneun listado anticuado para este sitio
  3. a dirección mis-typed
  4. no disponede acceso para esta página
  5. La petición de este recurso no se encuentra
  6. Ocurrió un error al intentar procesar su solicitud.

Intentelo con alguna de estas páginas

si la dificultad persiste, contacte con el administrador de este sitio

Componente no encontrado