var _wizardSettings = null, global_ui = null, Wizard = { cur_step: 0, settings: { max_steps: 0, // Gets automatically populated with the max number of tabs tab_click: 0, // Should the tabs be clickable or not (0 | 1) wizardID: 'wizard', // Defines the ID of the wizard container wizard: '', // Stores the jQuery Object of the wizard step_container: new Array(), // Stores all the IDs of every single step of the wizard nextButton: '', // Stores the jQuery Object for the generated Next Button nextButtonID: 'button_next', // Stores the ID of the generated Next Button nextButtonMarkup: '', // Stores the Markup for the generated Next Button prevButton: '', // Stores the jQuery Object for the generated Prev Button prevButtonID: 'button_prev', // Stores the ID of the generated Next Button prevButtonMarkup: '', // Stores the Markup for the generated Prev Button progressBar: '', // Stores the jQuery Object for the generated Progress Bar progressBarID: 'progress-bar', // Stores the ID of the generated Progress Bar progressBarMarkup: '', // Stores the Markup for the generated Progress Bar wizardNavID: 'wizard-nav', // Stores the ID of the Wizard Navigation container which contains the Prev and Next Buttons navPosition: 'bottom', // Should the navigation be on the bottom or on the top? stepsCallbacks: {}, // Object of callbacks per Step. ID of the step container as key and the function name as string as value. // Function must be defined before initializing the wizard summary: true, // Defines if a summary tab should be generated and populated automatically (will fetch all form inputs // from all the tabs like: input, select, textarea etc. Title inside the summary tab is defined by //the label element for each form input element) summaryTitle: 'Summary', // Title of the summary tab. Will be used inside the tab as Headline as well as the Caption for the tab. validate: true, // Defines if the tabs should be validated with the Form Validator or not (must also be included if true) edited: false, // Was any of the form fields edited? debug: false // Defines if debug outputs should be logged to the Browser Console or not. Will look for a _log function. // If none exists it falls back to console.log. If you define a _log function you can write your own logging. // The function should be compatible to the console.log syntax. }, init: function(initSettings){ _wizardSettings = this.settings; if(initSettings !== null){ for(var key in initSettings){ if(_wizardSettings.hasOwnProperty(key)) _wizardSettings[key] = initSettings[key]; } this.log('InitSettings received'); this.log(initSettings); } _wizardSettings.wizard = $('#'+this.settings.wizardID); this.log('Initialization started.'); this.modifyUI(); this.bindUIActions(); this.log('Initialization done.'); }, modifyUI: function(){ this.log('modifyUI started.'); if(_wizardSettings.summary){ $(_wizardSettings.wizard).find('ul:first-child').append('
  • '+_wizardSettings.summaryTitle+'
  • '); var summary_content = '

    Please verify that all the information you provided is correct

    '; _wizardSettings.wizard.append(summary_content); } $(_wizardSettings.wizard).find('ul:first-child li a:first-child').each(function(){ if($(this).attr('href').slice(0,1) == '#'){ _wizardSettings.step_container.push($(this).attr('href').slice(1)); } }); _wizardSettings.max_steps = _wizardSettings.step_container.length-1; this.log('Building Buttons start'); this.buildButtons(); this.log('Building Buttons end'); this.log('Build ProgressBar start'); this.buildProgressBar(); this.updateProgressBar(0); this.log('Build ProgressBar end'); this.log('Modifying Form Fields start'); this.modifyFormFields(); this.log('Modifying Form Fields end'); this.log('Initializing tabs on wizard start'); if(_wizardSettings.tab_click == 0){ _wizardSettings.wizard.tabs({event: null}); }else{ _wizardSettings.wizard.tabs(); } this.log('Initializing tabs on wizard end'); this.log('modifyUi done.'); }, bindUIActions: function(){ this.log('bindUIActions started.'); $(_wizardSettings.wizard).find('ul li').each(function(){ $(this).on('click', function(){ // return false; //Wizard.gotoStep($(this).parent().index()+1); }); }); $(_wizardSettings.wizard).find('input[type!="submit"], select').each(function(){ $(this).on('change', function(){ _wizardSettings.edited = true; }); }); $(_wizardSettings.wizard).find("form").submit(function(){ _wizardSettings.edited = false; }); $(window).on('beforeunload', function(){ if(_wizardSettings.edited === true){ return "You have unsaved changes. These will be lost if you leave the page now. Please complete the wizard to update your data."; } }); _wizardSettings.nextButton.on('click', function(){ Wizard.nextStep(); }); _wizardSettings.prevButton.on('click', function(){ Wizard.prevStep(); }); $(_wizardSettings.wizard).on('tabsactivate', function(event, ui){ // _log('Tabs active:'); // _log(Wizard.cur_step+1); // _log(_wizardSettings.validate); Wizard.gotoStep($(ui.newTab[0]).index()); }); this.log('bindUIActions done.'); }, buildButtons: function(){ _wizardSettings.nextButtonMarkup = ''; _wizardSettings.prevButtonMarkup = ''; if(_wizardSettings.navPosition == 'top'){ _wizardSettings.wizard.before('
    '+_wizardSettings.nextButtonMarkup+_wizardSettings.prevButtonMarkup+'
    '); }else{ _wizardSettings.wizard.after('
    '+_wizardSettings.nextButtonMarkup+_wizardSettings.prevButtonMarkup+'
    '); } _wizardSettings.nextButton = $('#'+_wizardSettings.nextButtonID); _wizardSettings.prevButton = $('#'+_wizardSettings.prevButtonID); }, buildProgressBar: function(){ _wizardSettings.progressBarMarkup = '
    Completion: 0%
    '; _wizardSettings.wizard.find('ul:first-child').after(_wizardSettings.progressBarMarkup); _wizardSettings.progressBar = $('#'+_wizardSettings.progressBarID); }, updateProgressBar: function(cur_step){ this.log('updateProgressBar started.'); var prog_val = Math.floor(100*((cur_step+1)/(_wizardSettings.max_steps+1))); this.log('CurStep Value: '+cur_step); this.log('MaxStep Value: '+_wizardSettings.max_steps); this.log('Calculated progress Value: '+prog_val); $(_wizardSettings.progressBar).val(prog_val); $('#'+_wizardSettings.progressBarID+' span').width(prog_val+'%').html('Completion: '+prog_val+'%'); this.log('updateProgressBar done.'); }, modifyFormFields: function(){ $(_wizardSettings.step_container).each(function(){ Wizard.log('-Step: '+this+' start'); var step = this.toString(); $('#'+step).addClass('step'); $('#'+step).find('input, select, textarea').each(function(){ Wizard.log('--Modifying: %o',this); var name = $(this).attr('name'); var split_pos = name.indexOf('['); Wizard.log('---Name: '+name); Wizard.log('---Split Pos: '+split_pos); if(split_pos > 0){ var first_string = name.slice(0, split_pos); var last_string = name.slice(split_pos); Wizard.log('---first_string: '+first_string); Wizard.log('---last_string: '+last_string); $(this).attr('name', step+'['+first_string+']'+last_string); }else{ Wizard.log(step); $(this).attr('name', step+'['+name+']'); } Wizard.log('--Modifying END',this); }); Wizard.log('-Step: '+this+' end'); }); }, generateSummary: function(){ this.log('Generate Summary started.'); var summaryContainer = $('#'+_wizardSettings.wizardID+'-summary'); this.log(summaryContainer); $(summaryContainer).html('').append('
    '); $(_wizardSettings.step_container).each(function(){ if(this != _wizardSettings.wizardID+'-summary'){ $('#summary-content').append('

    '+$(_wizardSettings.wizard).find('a[href="#'+this+'"]').html()+'

    '); var tabSummary = $('
    '); var tabSummaryTable = $('
    '); tabSummaryTable.attr('style', 'width: 100%;'); $('#'+this).find(':input:not([type=hidden])').filter(':not(:disabled)').add('#'+this+' :input.force-summary').each(function(){ var item_name = $(this).attr('name'); var real_name = item_name.match(/\[(.*)\]/)[1]; Wizard.log('Real Name: '); Wizard.log(real_name); var label = $('label[for="'+real_name+'"]'); if($(this).is('select')){ var val = _strip_tags($(this).children('option:selected').html()); if(label.length > 0){ tabSummaryTable.append(''+_strip_tags(label.html())+''+val+''); }else{ Wizard.log('No label found for input '+item_name); tabSummaryTable.append(''+_strip_tags(item_name)+''+val+''); } }else{ var val = _strip_tags($(this).val()); if($(this).attr('type') === 'checkbox'){ if($(this).is(':checked')){ val = ''; }else{ val = ''; } } if(label.length > 0){ tabSummaryTable.append(''+_strip_tags(label.html())+''+val+''); }else{ Wizard.log('No label found for input '+item_name+' , real name '+real_name); tabSummaryTable.append(''+_strip_tags(item_name)+''+val+''); } } }); Wizard.log(tabSummaryTable); tabSummary.append(tabSummaryTable); Wizard.log(tabSummary); summaryContainer.find('#summary-content').append(tabSummary); } }); this.log('Generate Summary done.'); }, nextStep: function(){ this.log('Cur Step: '+Wizard.cur_step); Wizard.processStep(Wizard.cur_step+1, _wizardSettings.validate); }, processStep: function(step, validate){ if(step < 0){ this.log('First Step. No Prev Button required'); }else{ var ret = false; if(validate && Wizard.cur_step != _wizardSettings.max_steps){ if(this.validateStep(Wizard.cur_step)){ ret = true; }else{ ret = false; } }else{ ret = true; } if(ret){ Wizard.cur_step = step; _wizardSettings.prevButton.removeAttr('disabled'); if(Wizard.cur_step == 0){ _wizardSettings.prevButton.attr('disabled', 'disabled'); }else{ Wizard.doCallback(Wizard.cur_step); if(Wizard.cur_step == _wizardSettings.max_steps){ if(_wizardSettings.summary){ Wizard.generateSummary(); } _wizardSettings.nextButton.data('submit', 1).html('Submit').off('click').on('click', function(){ Wizard.submitWizard(); }); }else{ if(_wizardSettings.nextButton.data('submit') == 1){ _wizardSettings.nextButton.data('submit', 0).html('Next Step').off('click').on('click', function(){ Wizard.nextStep(); }); } } } $(_wizardSettings.wizard).tabs("option", "active", (Wizard.cur_step)); Wizard.updateProgressBar(Wizard.cur_step); } } return ret; }, prevStep: function(){ if(Wizard.cur_step == 0){ this.log('First Step. No Prev Button required'); }else{ this.log('Cur Step: '+Wizard.cur_step); Wizard.processStep(Wizard.cur_step-1, false); } }, gotoStep: function(step){ if((step >= 0) && (step <= _wizardSettings.max_steps)){ Wizard.processStep(step, true); $(_wizardSettings.wizard).tabs("option", "active", (Wizard.cur_step)); } }, validateStep: function(step){ this.log('validateStep Start: '+_wizardSettings.step_container[step]); var ret = true; this.log(_wizardSettings.debug); ret = Validator.validate($("#"+_wizardSettings.step_container[step].toString())); this.log('Validation Result: '+ret); this.log('validateStep End'); return ret; }, doCallback: function(step){ this.log('doCallback Start: '+_wizardSettings.step_container[step]); if(_wizardSettings.stepsCallbacks.hasOwnProperty(_wizardSettings.step_container[step])){ var fn = window[_wizardSettings.stepsCallbacks[_wizardSettings.step_container[step]]]; if(typeof fn === 'function'){ fn(step); }else{ this.log('No callback function defined for step: '+step); } } this.log('doCallback End'); }, submitWizard: function(){ $('#'+_wizardSettings.wizardID+'>form').submit(); }, log: function(message){ if(_wizardSettings.debug){ if(typeof message !== null && typeof message === 'object'){ if (typeof _log == 'function') { _log(new Date().format('d.m.Y H:i:s')+' [Wizard]: %o', message); }else{ console.log(new Date().format('d.m.Y H:i:s')+' [Wizard]: %o', message); } }else{ if (typeof _log == 'function') { _log(new Date().format('d.m.Y H:i:s')+' [Wizard]: '+message); }else{ console.log(new Date().format('d.m.Y H:i:s')+' [Wizard]: '+message); } } } } };