2014-11-20 22:25:33 +00:00
/ * j Q u e r y F o r m t o F o r m W i z a r d ( I n i t i a l : O c t 1 s t , 2 0 1 0 )
* This notice must stay intact for usage
* Author : Dynamic Drive at http : //www.dynamicdrive.com/
* Visit http : //www.dynamicdrive.com/ for full source code
* /
2014-03-10 05:18:05 +00:00
2014-11-20 22:25:33 +00:00
// Oct 21st, 2010: Script updated to v1.1, which adds basic form validation functionality, triggered each time the user goes from one page to the next, or tries to submit the form.
// jQuery.noConflict()
2014-03-10 05:18:05 +00:00
2014-11-20 22:25:33 +00:00
function FormToWizard ( options ) {
this . setting = jQuery . extend ( { fieldsetborderwidth : 2 , persistsection : false , revealfx : [ 'slide' , 500 ] ,
oninit : function ( ) { } , onpagechangestart : function ( ) { } } , options ) ;
this . currentsection = - 1 ;
2014-03-10 05:18:05 +00:00
this . init ( this . setting )
}
2014-11-20 22:25:33 +00:00
FormToWizard . prototype = {
2014-03-20 18:03:22 +00:00
loadsection : function ( rawi , bypasshooks ) {
2014-11-20 22:25:33 +00:00
//doload Boolean checks to see whether to load next section (true if bypasshooks param is true or onpagechangestart() event handler doesn't return false)
var doload = bypasshooks || this . setting . onpagechangestart ( jQuery , this . currentsection , this . sections . $sections . eq ( this . currentsection ) ) ,
tabIndex ,
thiswizard = this ;
doload = ( doload !== false ) ; //unless doload is explicitly false, set to true
if ( ! bypasshooks && this . setting . validate && false === this . validate ( this . currentsection ) )
doload = false ;
//get index of next section to show
tabIndex = ( 'prev' == rawi
? this . currentsection - 1
: ( 'next' == rawi
? this . currentsection + 1
: parseInt ( rawi ) ) ) ;
//don't exceed min/max limit
tabIndex = ( tabIndex < 0
? this . sections . count - 1
: ( tabIndex > ( this . sections . count - 1 )
? 0
: tabIndex ) ) ;
//if next section to show isn't the same as the current section shown
if ( tabIndex < this . sections . count && doload ) {
//dull current 'step' text then highlight next 'step' text
this . $thesteps . eq ( this . currentsection ) . addClass ( 'disabledstep' ) . end ( ) . eq ( tabIndex ) . removeClass ( 'disabledstep' ) ;
if ( 'slide' == this . setting . revealfx [ 0 ] ) {
this . sections . $sections . css ( 'visibility' , 'visible' ) ;
//animate fieldset wrapper's height to accommodate next section's height
this . sections . $outerwrapper . stop ( ) . animate ( { height : this . sections . $sections . eq ( tabIndex ) . outerHeight ( ) } , this . setting . revealfx [ 1 ] ) ;
//slide next section into view
this . sections . $innerwrapper . stop ( ) . animate ( { left : - tabIndex * this . maxfieldsetwidth } , this . setting . revealfx [ 1 ] , function ( ) {
thiswizard . sections . $sections . each ( function ( thissec ) {
//hide fieldset sections currently not in view, so tabbing doesn't go to elements within them (and mess up layout)
if ( tabIndex != thissec )
thiswizard . sections . $sections . eq ( thissec ) . css ( 'visibility' , 'hidden' )
2014-03-20 18:03:22 +00:00
} )
} )
}
2014-11-20 22:25:33 +00:00
else if ( 'fade' == this . setting . revealfx [ 0 ] ) { //if fx is 'fade'
this . sections . $sections . eq ( this . currentsection ) . hide ( ) . end ( ) . eq ( tabIndex ) . fadeIn ( this . setting . revealfx [ 1 ] , function ( ) {
2014-03-20 18:03:22 +00:00
if ( document . all && this . style && this . style . removeAttribute )
2014-11-20 22:25:33 +00:00
//fix IE clearType problem
this . style . removeAttribute ( 'filter' ) ;
2014-03-20 18:03:22 +00:00
} )
2014-11-20 22:25:33 +00:00
} else {
this . sections . $sections . eq ( this . currentsection ) . hide ( ) . end ( ) . eq ( tabIndex ) . show ( )
2014-03-20 18:03:22 +00:00
}
2014-11-20 22:25:33 +00:00
//update current page status text
this . paginatediv . $status . text ( 'step ' + ( tabIndex + 1 ) + ' / ' + this . sections . count ) ;
this . paginatediv . $navlinks . css ( 'visibility' , 'visible' ) ;
if ( 0 == tabIndex ) //hide 'prev' link
this . paginatediv . $navlinks . eq ( 0 ) . css ( 'visibility' , 'hidden' ) ;
else if ( ( this . sections . count - 1 ) == tabIndex )
//hide 'next' link
this . paginatediv . $navlinks . eq ( 1 ) . css ( 'visibility' , 'hidden' ) ;
2014-03-20 18:03:22 +00:00
if ( this . setting . persistsection ) //enable persistence?
2014-11-20 22:25:33 +00:00
FormToWizard . routines . setCookie ( this . setting . formid + '_persist' , tabIndex ) ;
this . currentsection = tabIndex ;
if ( 0 === tabIndex ) {
setTimeout ( function ( ) {
$ ( '#nameToSearch' ) . focus ( ) ;
} , 250 ) ;
}
2014-03-20 18:03:22 +00:00
}
} ,
addvalidatefields : function ( ) {
2014-11-20 22:25:33 +00:00
var $ = jQuery ,
setting = this . setting ,
theform = this . $theform . get ( 0 ) ,
validatefields = setting . validate ; //array of form element ids to validate
for ( var i = 0 ; i < validatefields . length ; i ++ ) {
var el = theform . elements [ validatefields [ i ] ] ; //reference form element
if ( el ) {
//find fieldset.sectionwrap this form element belongs to
var $section = $ ( el ) . parents ( 'fieldset.sectionwrap:eq(0)' ) ;
//if element is within a fieldset.sectionwrap element
if ( $section . length == 1 ) {
//cache this element inside corresponding section
$section . data ( 'elements' ) . push ( el ) ;
2014-03-20 18:03:22 +00:00
}
}
}
} ,
validate : function ( section ) {
2014-11-20 22:25:33 +00:00
//reference elements within this section that should be validated
var elements = this . sections . $sections . eq ( section ) . data ( 'elements' ) ;
var validated = true , invalidtext = [ 'Please fill out the following fields:' + "\n" ] ;
2014-03-20 18:03:22 +00:00
function invalidate ( el ) {
2014-11-20 22:25:33 +00:00
validated = false ;
invalidtext . push ( '- ' + ( el . id || el . name ) )
2014-03-20 18:03:22 +00:00
}
2014-11-20 22:25:33 +00:00
for ( var i = 0 ; i < elements . length ; i ++ ) {
if ( /(text)/ . test ( elements [ i ] . type ) && elements [ i ] . value == '' ) {
//text and textarea elements
2014-03-20 18:03:22 +00:00
invalidate ( elements [ i ] )
2014-11-20 22:25:33 +00:00
} else if ( /(select)/ . test ( elements [ i ] . type ) && ( elements [ i ] . selectedIndex == - 1 || elements [ i ] . options [ elements [ i ] . selectedIndex ] . text == '' ) ) {
//select elements
2014-03-20 18:03:22 +00:00
invalidate ( elements [ i ] )
2014-11-20 22:25:33 +00:00
} else if ( undefined == elements [ i ] . type && 0 < elements [ i ] . length ) {
//radio and checkbox elements
var onechecked = false ;
for ( var r = 0 ; r < elements [ i ] . length ; r ++ ) {
if ( elements [ i ] [ r ] . checked == true ) {
onechecked = true ;
2014-03-20 18:03:22 +00:00
break
}
}
if ( ! onechecked ) {
invalidate ( elements [ i ] [ 0 ] )
}
}
}
if ( ! validated )
2014-11-20 22:25:33 +00:00
alert ( invalidtext . join ( "\n" ) ) ;
2014-03-20 18:03:22 +00:00
return validated
} ,
init : function ( setting ) {
2014-11-20 22:25:33 +00:00
var thiswizard = this ;
2014-03-20 18:03:22 +00:00
jQuery ( function ( $ ) { //on document.ready
2014-11-20 22:25:33 +00:00
var $theform = $ ( '#' + setting . formid ) ,
//create Steps Container to house the 'steps' text
$stepsguide = $ ( '<div class="stepsguide" />' ) ,
//find all fieldsets within form and hide them initially
$sections = $theform . find ( 'fieldset.sectionwrap' ) . hide ( ) ,
$sectionswrapper = '' ,
$sectionswrapper _inner = '' ;
if ( 0 == $theform . length )
//if form with specified ID doesn't exist, try name attribute instead
$theform = $ ( 'form[name=' + setting . formid + ']' ) ;
if ( 'slide' == setting . revealfx [ 0 ] ) {
//create outer DIV that will house all the fieldset.sectionwrap elements
//add DIV above the first fieldset.sectionwrap element
$sectionswrapper = $ ( '<div class="step-outer" style="position:relative"></div>' ) . insertBefore ( $sections . eq ( 0 ) ) ;
//create inner DIV of $sectionswrapper that will scroll to reveal a fieldset element
$sectionswrapper _inner = $ ( '<div class="step-inner" style="position:absolute; left:0"></div>' ) ;
2014-03-20 18:03:22 +00:00
}
2014-11-20 22:25:33 +00:00
//variable to get width of widest fieldset.sectionwrap
var maxfieldsetwidth = $sections . eq ( 0 ) . outerWidth ( ) ;
//loop through $sections (starting from 2nd one)
$sections . slice ( 1 ) . each ( function ( ) {
maxfieldsetwidth = Math . max ( $ ( this ) . outerWidth ( ) , maxfieldsetwidth )
} ) ;
//add default 2px or param px to final width to reveal fieldset border (if not removed via CSS)
maxfieldsetwidth += setting . fieldsetborderwidth ;
thiswizard . maxfieldsetwidth = maxfieldsetwidth ;
//loop through $sections again
$sections . each ( function ( i ) {
var $section = $ ( this ) ;
if ( 'slide' == setting . revealfx [ 0 ] ) {
//set fieldset position to 'absolute' and move it to inside sectionswrapper_inner DIV
$section . data ( 'page' , i ) . css ( { position : 'absolute' , left : maxfieldsetwidth * i } ) . appendTo ( $sectionswrapper _inner ) ;
2014-03-20 18:03:22 +00:00
}
2014-11-20 22:25:33 +00:00
//empty array to contain elements within this section that should be validated for data (applicable only if validate option is defined)
$section . data ( 'elements' , [ ] ) ;
//create each 'step' DIV and add it to main Steps Container:
2015-11-19 22:05:19 +00:00
var $stepwords = [ 'first' , 'then' , 'finally' ] ,
$thestep = $ ( '<div class="step disabledstep" />' ) . data ( 'section' , i ) . html ( ( $stepwords [ i ] ) +
'<div class="smalltext">' + $section . find ( 'legend:eq(0)' ) . text ( ) + '<p></p></div>' ) . appendTo ( $stepsguide ) ;
2014-11-20 22:25:33 +00:00
//assign behavior to each step div
$thestep . click ( function ( ) {
2014-03-20 18:03:22 +00:00
thiswizard . loadsection ( $ ( this ) . data ( 'section' ) )
} )
2014-11-20 22:25:33 +00:00
} ) ;
if ( 'slide' == setting . revealfx [ 0 ] ) {
$sectionswrapper . width ( maxfieldsetwidth ) ; //set fieldset wrapper to width of widest fieldset
$sectionswrapper . append ( $sectionswrapper _inner ) ; //add $sectionswrapper_inner as a child of $sectionswrapper
$stepsguide . append ( '<div style="clear:both"> </div>' )
2014-03-20 18:03:22 +00:00
}
2014-11-20 22:25:33 +00:00
//add $thesteps div to the beginning of the form
$theform . prepend ( $stepsguide ) ;
2014-03-20 18:03:22 +00:00
//$stepsguide.insertBefore($sectionswrapper) //add Steps Container before sectionswrapper container
2014-11-20 22:25:33 +00:00
var $thesteps = $stepsguide . find ( 'div.step' ) ;
2014-03-20 18:03:22 +00:00
//create pagination DIV and add it to end of form:
2014-11-20 22:25:33 +00:00
var $paginatediv = $ ( '<div class="formpaginate">'
+ '<span class="prev" style="float:left">Prev</span>'
+ ' <span class="status">step 1 of </span>'
+ ' <span class="next" style="float:right">Next</span>'
+ '</div>' ) ;
$theform . append ( $paginatediv ) ;
thiswizard . $theform = $theform ;
if ( 'slide' == setting . revealfx [ 0 ] ) {
//remember various parts of section container
thiswizard . sections = {
$outerwrapper : $sectionswrapper ,
$innerwrapper : $sectionswrapper _inner ,
$sections : $sections ,
count : $sections . length
} ;
2014-03-20 18:03:22 +00:00
thiswizard . sections . $sections . show ( )
2014-11-20 22:25:33 +00:00
} else {
//remember various parts of section container
thiswizard . sections = {
$sections : $sections ,
count : $sections . length
} ;
2014-03-20 18:03:22 +00:00
}
2014-11-20 22:25:33 +00:00
thiswizard . $thesteps = $thesteps ;
//remember various parts of pagination DIV
thiswizard . paginatediv = {
$main : $paginatediv ,
$navlinks : $paginatediv . find ( 'span.prev, span.next' ) ,
$status : $paginatediv . find ( 'span.status' )
} ;
//assign behavior to pagination buttons
thiswizard . paginatediv . $main . click ( function ( e ) {
2014-03-20 18:03:22 +00:00
if ( /(prev)|(next)/ . test ( e . target . className ) )
thiswizard . loadsection ( e . target . className )
2014-11-20 22:25:33 +00:00
} ) ;
var i = ( setting . persistsection ? FormToWizard . routines . getCookie ( setting . formid + '_persist' ) : 0 ) ;
//show the first section
thiswizard . loadsection ( i || 0 , true ) ;
//call oninit event handler
thiswizard . setting . oninit ( $ , i , $sections . eq ( i ) ) ;
//if validate array defined
if ( setting . validate ) {
//seek out and cache form elements that should be validated
thiswizard . addvalidatefields ( ) ;
2014-03-20 18:03:22 +00:00
thiswizard . $theform . submit ( function ( ) {
2014-11-20 22:25:33 +00:00
for ( var i = 0 ; i < thiswizard . sections . count ; i ++ ) {
2014-03-20 18:03:22 +00:00
if ( ! thiswizard . validate ( i ) ) {
2014-11-20 22:25:33 +00:00
thiswizard . loadsection ( i , true ) ;
return false ;
2014-03-20 18:03:22 +00:00
}
}
2014-11-20 22:25:33 +00:00
return true ;
2014-03-20 18:03:22 +00:00
} )
}
} )
}
2014-11-20 22:25:33 +00:00
} ;
2014-03-10 05:18:05 +00:00
2014-11-20 22:25:33 +00:00
FormToWizard . routines = {
2014-03-10 05:18:05 +00:00
2014-11-20 22:25:33 +00:00
getCookie : function ( Name ) {
var re = new RegExp ( Name + '=[^;]+' , 'i' ) ; //construct RE to search for target name/value pair
2014-03-20 18:03:22 +00:00
if ( document . cookie . match ( re ) ) //if cookie found
2014-11-20 22:25:33 +00:00
return document . cookie . match ( re ) [ 0 ] . split ( '=' ) [ 1 ] ; //return its value
2014-03-20 18:03:22 +00:00
return null
} ,
2014-03-10 05:18:05 +00:00
2014-03-20 18:03:22 +00:00
setCookie : function ( name , value ) {
2014-11-20 22:25:33 +00:00
document . cookie = name + '=' + value + ';path=/' ;
2014-03-20 18:03:22 +00:00
}
2014-11-20 22:25:33 +00:00
} ;