├── README.md ├── example.html ├── examplealtstate.html ├── exampletabs.html ├── jquery.multipage.css └── jquery.multipage.js /README.md: -------------------------------------------------------------------------------- 1 | # jQuery Multipage Form Plugin 2 | 3 | Sometimes, you have a lot of form fields, and you need 4 | to break them up into multiple pages. This plugin does that! 5 | 6 | [Get it from Github](https://github.com/xoxco/jQuery-multipage-form) 7 | 8 | [View Demo](http://xoxco.com/projects/code/multipage/) 9 | 10 | [Test it yourself using this jsFiddle Demo](http://jsfiddle.net/eJKQn/) 11 | 12 | Created by [XOXCO](http://xoxco.com) 13 | 14 | 15 | By default, it will take all of the `
` tags in your form, 16 | and turn them into individual pages. The user will start at 17 | the first page, and be stepped through each page, until they 18 | reach the final page. The plugin will even generate clever 19 | "Next" and "Back" buttons based on your tags. 20 | 21 | You can optionally pass in functions to generate different kinds 22 | of navigation. It is easy (and examples are provided) to make 23 | a tabbed form instead of a paginated form, for example. You can 24 | replace the navigation, the state handling function, even the 25 | transition between one page and another. 26 | 27 | ## Instructions 28 | 29 | First, add the Javascript and CSS files to your tag: 30 | 31 | 32 | 33 | 34 | Then, make sure you wrap your the elements in your form within `
` tags 35 | that represent the pages you want to create. Each fieldset should have a 36 | an id attribute, which you can use to target the page, and a tag, 37 | which defines the page's title. 38 | 39 | Inside each fieldset, you can design your form as per usual! 40 | 41 | At the very end of your form, include a submit button that is OUTSIDE 42 | of the last `
` tag. If you don't, one will be provided for you. 43 | 44 | 45 | Now, your form is set! To turn it into a multipage form, call the multipage 46 | jQuery method: 47 | 48 | $('#myform').multipage(); 49 | 50 | You may also call multipage() with a variety of options. 51 | The full set of options is as follows: 52 | 53 | $('#myform').multipage({ 54 | 'stayLinkable': false, // whether or not the id of the page will be appended to the url as a hashtag for permalinking purposes 55 | 'submitLabel': 'Submit', // default label for the last page's submit button, if not included in form 56 | 'hideLegend': false, // should the plugin hide the tags? useful in concert with externally generated nav 57 | 'hideSubmit': true, // should the plugin hide the submit button? 58 | 'generateNavigation': true, // should the plugin generate its own navigation buttons? 59 | 'activeDot': ' ●', // the dot used to represent an active page in the nav 60 | 'inactiveDot': ' ·', // the dot used to represent an inactive page in the nav 61 | 'navigationFunction': function(pages){}, // a function that generates the nav, receives array of pages 62 | 'stateFunction': function(page){}, // a function that shows what page the user is viewing, receives current page # 63 | 'transitionFunction': function(from,to){} // a function that transitions from one page $(from) to another $(to) 64 | }); 65 | 66 | 67 | Once you've turned your form into a magical multipager, you can 68 | access the pages via the following functions: 69 | 70 | // go to the first page 71 | $('#myform').gotofirst(); 72 | 73 | // go to the last page 74 | $('#myform').gotolast(); 75 | 76 | // go to page by number or id 77 | $('#myform').gotopage(1); 78 | $('#myform').gotogopage(2); 79 | $('#myform').gotopage('#about'); 80 | 81 | 82 | // go to the next page 83 | $('#myform').nextpage(); 84 | 85 | // go to the previous page 86 | $('#myform').prevpage(); 87 | 88 | // get an array of pages 89 | var pages = $('#myform').getPages(); 90 | 91 | 92 | ## Feature Roadmap 93 | 94 | * Form should be able to validate on a page by page basis 95 | * Validation function should receive the whole fieldset AND the page # 96 | * Option to turn off "always forward" style progression where you have to validate first before proceeding 97 | * Option to disable next button til form is valid 98 | 99 | * Tab order should make sense 100 | -------------------------------------------------------------------------------- /example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 40 | 49 |
50 |
51 | Basic Details 52 |

53 | 54 | 55 |

56 |

57 | 58 | 59 |

60 |
61 |
62 | About You 63 |

64 | 65 | 66 |

67 | 68 |

69 | 70 | 71 |

72 | 73 |

74 | 76 | 77 |

78 |
79 |
80 | Stuff 81 |

82 | 83 | 84 |

85 |

86 | 87 | 88 |

89 |
90 | 91 |
92 | -------------------------------------------------------------------------------- /examplealtstate.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 43 | 53 | 54 | 55 | 56 |

jQuery Multipage Form Plugin

57 |

Add custom transitions to your form

58 | 59 | 60 | Turn into multipage form
61 | OR
62 | Turn into tabbed form 63 | 64 | 65 |
66 |
67 |
68 | Basic Details 69 |

70 | 71 | 72 |

73 |

74 | 75 | 76 |

77 |
78 |
79 | About You 80 |

81 | 82 | 83 |

84 | 85 |

86 | 87 | 88 |

89 | 90 |

91 | 93 | 94 |

95 |
96 |
97 | Stuff 98 |

99 | 100 | 101 |

102 |

103 | 104 | 105 |

106 |
107 | 108 |
109 |
110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /exampletabs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 43 | 53 | 54 | 55 | 56 |

jQuery Multipage Form Plugin

57 |

Navigate options by tabs

58 | 59 | 60 | Turn into multipage form
61 | OR
62 | Turn into multipage form with an alternate state handler and transition handler
63 | 64 |
65 |
66 |
67 | Basic Details 68 |

69 | 70 | 71 |

72 |

73 | 74 | 75 |

76 |
77 |
78 | About You 79 |

80 | 81 | 82 |

83 | 84 |

85 | 86 | 87 |

88 | 89 |

90 | 92 | 93 |

94 |
95 |
96 | Stuff 97 |

98 | 99 | 100 |

101 |

102 | 103 | 104 |

105 |
106 | 107 |
108 |
109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /jquery.multipage.css: -------------------------------------------------------------------------------- 1 | .multipage_nav { border-top:1px solid #CCC; padding-top:10px;} 2 | .multipage_nav a { font-weight: bold; display:block; padding: 10px 20px; color: #FFF; text-shadow: #333 1px 1px 5px; text-decoration:none; -moz-box-shadow: 0px 0px 5px #333; -webkit-box-shadow: 0px 0px 5px #333; } 3 | .multipage_nav .multipage_next { float:right; 4 | background: #a9db80; /* old browsers */ 5 | background: -moz-linear-gradient(top, #a9db80 0%, #96c56f 100%); /* firefox */ 6 | 7 | background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#a9db80), color-stop(100%,#96c56f)); /* webkit */ 8 | 9 | filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#a9db80', endColorstr='#96c56f',GradientType=0 ); /* ie */ 10 | } 11 | 12 | .multipage_nav .multipage_back { 13 | float:left; 14 | background: #a9db80; /* old browsers */ 15 | background: -moz-linear-gradient(top, #a9db80 0%, #96c56f 100%); /* firefox */ 16 | 17 | background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#a9db80), color-stop(100%,#96c56f)); /* webkit */ 18 | 19 | filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#a9db80', endColorstr='#96c56f',GradientType=0 ); /* ie */ 20 | } 21 | 22 | .multipage_nav .submit { 23 | 24 | background: #fceabb; /* old browsers */ 25 | background: -moz-linear-gradient(top, #fceabb 0%, #fccd4d 50%, #f8b500 51%, #fbdf93 100%); /* firefox */ 26 | 27 | background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#fceabb), color-stop(50%,#fccd4d), color-stop(51%,#f8b500), color-stop(100%,#fbdf93)); /* webkit */ 28 | 29 | filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#fceabb', endColorstr='#fbdf93',GradientType=0 ); /* ie */ 30 | } 31 | 32 | .multipage_nav .multipage_state { display: block; text-align:center; width:100px; margin-left:auto;margin-right:auto; font-size:18px;} 33 | .multipage fieldset { border:0px; padding:10px; margin:0px; } 34 | 35 | div.clearer{ 36 | display: block; 37 | visibility: hidden; 38 | clear: both; 39 | height:0; 40 | border-width:0; 41 | margin:0; 42 | padding:0; 43 | } 44 | 45 | ul.multipage_tabs { list-style-type: none; margin:0px; padding:0px; border-bottom:1px solid #CCC; margin-bottom:20px;} 46 | ul.multipage_tabs li { display:block; float: left; margin-right:20px;} 47 | ul.multipage_tabs li a { display:block; padding:10px; } 48 | ul.multipage_tabs li.active { background: #CCC; } -------------------------------------------------------------------------------- /jquery.multipage.js: -------------------------------------------------------------------------------- 1 | (function($) { 2 | 3 | 4 | var curpage = 1; 5 | var id = null; 6 | var settings = null; 7 | 8 | jQuery.fn.transitionPage = function(from,to) { 9 | 10 | if (settings.transitionFunction) { 11 | settings.transitionFunction(from,to); 12 | } else { 13 | $(from).hide(); 14 | $(to).show(); 15 | } 16 | $(id + ' fieldset').removeClass('active'); 17 | $(to).addClass('active'); 18 | } 19 | 20 | jQuery.fn.showState = function(page) { 21 | 22 | if (settings.stateFunction) { 23 | return settings.stateFunction(id+"_nav .multipage_state",page,settings.pages.length); 24 | } 25 | var state = ''; 26 | for (x = 1; x <= settings.pages.length; x++) { 27 | if(x==page) { 28 | state = state + settings.activeDot; 29 | } else { 30 | state = state + settings.inactiveDot; 31 | } 32 | } 33 | $(id+"_nav .multipage_state").html(state); 34 | } 35 | 36 | 37 | jQuery.fn.gotopage = function(page) { 38 | $(id + '_nav .multipage_next').html('Next'); 39 | 40 | if (isNaN(page)) { 41 | q = page; 42 | page = 1; 43 | $(id+' fieldset').each(function(index) { 44 | if ('#'+$(this).attr('id')==q) { 45 | curpage = page = index+1; 46 | } 47 | }); 48 | } 49 | 50 | var np = null; 51 | var cp = $(id+' fieldset.active'); 52 | // show the appropriate page. 53 | $(id+' fieldset').each(function(index) { 54 | index++; 55 | if (index==page) { 56 | np = this; 57 | } 58 | }); 59 | 60 | $(this).transitionPage(cp,np); 61 | 62 | $(this).showState(page); 63 | 64 | $(id + '_nav .multipage_next').removeClass('submit'); 65 | 66 | // is there a legend tag for this fieldset? 67 | // if so, pull it out. 68 | page_title = settings.pages[page-1].title; 69 | 70 | if (settings.stayLinkable) { 71 | hashtag = '#' + settings.pages[page-1].id; 72 | document.location.hash = hashtag; 73 | } 74 | if (page==1) { 75 | // set up for first page 76 | $(id + '_nav .multipage_back').hide(); 77 | $(id + '_nav .multipage_next').show(); 78 | if (settings.pages[page].title) { 79 | $(id + '_nav .multipage_next').html('Next: ' + settings.pages[page].title); 80 | } else { 81 | $(id + '_nav .multipage_next').html('Next'); 82 | } 83 | 84 | } else if (page==settings.pages.length) { 85 | // set up for last page 86 | $(id + '_nav .multipage_back').show(); 87 | $(id + '_nav .multipage_next').show(); 88 | 89 | if (settings.pages[page-2].title) { 90 | $(id + '_nav .multipage_back').html('Back: ' + settings.pages[page-2].title); 91 | } else { 92 | $(id + '_nav .multipage_back').html('Back'); 93 | } 94 | 95 | $(id + '_nav .multipage_next').addClass('submit'); 96 | $(id + '_nav .multipage_next').html(settings.submitLabel); 97 | 98 | } else { 99 | if (settings.pages[page-2].title) { 100 | $(id + '_nav .multipage_back').html('Back: ' + settings.pages[page-2].title); 101 | } else { 102 | $(id + '_nav .multipage_back').html('Back'); 103 | } 104 | if (settings.pages[page].title) { 105 | $(id + '_nav .multipage_next').html('Next: ' + settings.pages[page].title); 106 | } else { 107 | $(id + '_nav .multipage_next').html('Next'); 108 | } 109 | 110 | $(id + '_nav .multipage_back').show(); 111 | $(id + '_nav .multipage_next').show(); 112 | 113 | } 114 | 115 | $(id + ' fieldset.active input:first').focus(); 116 | curpage=page; 117 | return false; 118 | 119 | } 120 | 121 | jQuery.fn.validatePage = function(page) { 122 | return true; 123 | } 124 | 125 | 126 | jQuery.fn.validateAll = function() { 127 | for (x = 1; x <= settings.pages.length; x++) { 128 | if (!$(this).validatePage(x)) { 129 | $(this).gotopage(x); 130 | return false; 131 | } 132 | } 133 | return true; 134 | } 135 | 136 | 137 | jQuery.fn.gotofirst = function() { 138 | curpage = 1; 139 | $(this).gotopage(curpage); 140 | return false; 141 | } 142 | jQuery.fn.gotolast = function() { 143 | curpage = settings.pages.length; 144 | $(this).gotopage(curpage); 145 | return false; 146 | } 147 | 148 | jQuery.fn.nextpage = function() { 149 | // validate the current page 150 | if ($(this).validatePage(curpage)) { 151 | curpage++; 152 | 153 | if (curpage > settings.pages.length) { 154 | // submit! 155 | $(this).submit(); 156 | curpage = settings.pages.length; 157 | return false; 158 | } 159 | $(this).gotopage(curpage); 160 | } 161 | return false; 162 | 163 | } 164 | 165 | jQuery.fn.getPages = function() { 166 | return settings.pages; 167 | } 168 | 169 | jQuery.fn.prevpage = function() { 170 | 171 | curpage--; 172 | 173 | if (curpage < 1) { 174 | curpage = 1; 175 | } 176 | $(this).gotopage(curpage); 177 | return false; 178 | 179 | } 180 | 181 | 182 | jQuery.fn.multipage = function(options) { 183 | 184 | settings = jQuery.extend({stayLinkable:false,submitLabel:'Submit',hideLegend:false,hideSubmit:true,generateNavigation:true,activeDot:' ●',inactiveDot:' ·'},options); 185 | id = '#' + $(this).attr('id'); 186 | var form = $(this); 187 | 188 | form.addClass('multipage'); 189 | 190 | form.submit(function(e) { 191 | if (!$(this).validateAll()) { 192 | e.preventDefault() 193 | }; 194 | }); 195 | 196 | // hide all the pages 197 | $(id +' fieldset').hide(); 198 | if (settings.hideSubmit) { 199 | $(id+' input[type="submit"]').hide(); 200 | } 201 | 202 | if ($(id+' input[type="submit"]').val()!='') { 203 | settings.submitLabel = $(id+' input[type="submit"]').val(); 204 | } 205 | 206 | settings.pages = new Array(); 207 | 208 | $(this).children('fieldset').each(function(index) { 209 | label = $(this).children('legend').html(); 210 | settings.pages[index] = {number:index+1,title:label,id:$(this).attr('id')}; 211 | }); 212 | 213 | 214 | if (settings.hideLegend) { 215 | // hide legend tags 216 | $(id+' fieldset legend').hide(); 217 | } 218 | 219 | // show the first page. 220 | $(id+' fieldset:first').addClass('active'); 221 | 222 | $(id+' fieldset:first').show(); 223 | 224 | if (settings.generateNavigation) { 225 | if (settings.navigationFunction) { 226 | settings.navigationFunction($(this).getPages()); 227 | } else { 228 | // insert navigation 229 | var id_name = $(this).attr('id'); 230 | $('').insertAfter(this); 231 | } 232 | } 233 | 234 | if (document.location.hash) { 235 | $(this).gotopage('#'+document.location.hash.substring(1,document.location.hash.length)); 236 | } else { 237 | $(this).gotopage(1); 238 | } 239 | return false; 240 | 241 | } 242 | 243 | 244 | })(jQuery); 245 | --------------------------------------------------------------------------------