358 lines
13 KiB
JavaScript
358 lines
13 KiB
JavaScript
var GFPageConditionalLogic = function (args) {
|
|
var self = this,
|
|
$ = jQuery;
|
|
|
|
/**
|
|
* Initialize Feed Ordering
|
|
*/
|
|
self.init = function () {
|
|
|
|
// Assign options to instance.
|
|
self.options = args;
|
|
|
|
self.paginationType = self.options.pagination.type;
|
|
|
|
self.triggerInputIds = self.getTriggerInputIds(self.options.pages);
|
|
|
|
self.formWrapper = '#gform_wrapper_' + self.options.formId;
|
|
|
|
if (self.paginationType === 'steps') {
|
|
self.originalCurrentPage = parseInt($(self.formWrapper + ' .gf_step_active .gf_step_number').text(), 10);
|
|
} else if (self.paginationType === 'percentage') {
|
|
self.originalCurrentPage = parseInt($(self.formWrapper + ' .gf_step_current_page').text(), 10);
|
|
self.originalProgress = parseInt($(self.formWrapper + ' .gf_progressbar_percentage span').text(), 10);
|
|
}
|
|
|
|
self.startAtZero = $(self.formWrapper + ' .gf_progressbar_wrapper').data('startAtZero');
|
|
|
|
self.evaluatePages();
|
|
|
|
self.bindEvents();
|
|
|
|
};
|
|
|
|
self.bindEvents = function () {
|
|
|
|
gform.addAction('gform_input_change', function (elem, formId, inputId) {
|
|
|
|
var fieldId = parseInt(inputId, 10) + '';
|
|
var isTriggeredInput = $.inArray(inputId, self.triggerInputIds) !== -1 || $.inArray(fieldId, self.triggerInputIds) !== -1;
|
|
|
|
if (self.options.formId == formId && isTriggeredInput) {
|
|
self.evaluatePages();
|
|
}
|
|
});
|
|
|
|
};
|
|
|
|
self.evaluatePages = function () {
|
|
|
|
var page, stepNumber, isMatch, isVisible, progress, visibleStepNumber = 1, currentPage = self.originalCurrentPage;
|
|
|
|
for (var i = 0; i < self.options.pages.length; i++) {
|
|
|
|
page = self.options.pages[i];
|
|
stepNumber = i + 2; // plus 2 because the first page field is actually Step 2.
|
|
isMatch = self.evaluatePage(page, self.options.formId);
|
|
isVisible = self.isPageVisible(page);
|
|
|
|
if (!isMatch && isVisible !== false) {
|
|
self.hidePage(page, stepNumber);
|
|
} else if (isMatch && !isVisible) {
|
|
self.showPage(page, stepNumber);
|
|
}
|
|
|
|
// check if the page is visible and
|
|
// available as a step after evaluation.
|
|
isVisible = self.isPageVisible(page);
|
|
if (isVisible) {
|
|
visibleStepNumber++;
|
|
|
|
if (self.paginationType === 'steps') {
|
|
$('#gf_step_' + self.options.formId + '_' + stepNumber).find('.gf_step_number').html(visibleStepNumber);
|
|
} else if (self.paginationType === 'percentage' && self.originalCurrentPage == stepNumber) {
|
|
currentPage = visibleStepNumber;
|
|
$(self.formWrapper + ' .gf_step_current_page').html(currentPage);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if (self.paginationType === 'percentage') {
|
|
currentPage = self.options.pagination.display_progressbar_on_confirmation === true || self.startAtZero ? ( currentPage - 1 ) : currentPage;
|
|
} else {
|
|
currentPage = parseInt($(self.formWrapper + ' .gf_step_active .gf_step_number').text(), 10);
|
|
if(self.startAtZero) {
|
|
currentPage -= 1;
|
|
}
|
|
}
|
|
|
|
progress = Math.floor( currentPage / visibleStepNumber * 100 );
|
|
|
|
if (self.paginationType === 'percentage') {
|
|
var progressPercent = progress + '%';
|
|
|
|
$(self.formWrapper + ' .gf_step_page_count').html(visibleStepNumber);
|
|
$(self.formWrapper + ' .gf_progressbar_percentage span').html(progressPercent);
|
|
$(self.formWrapper + ' .gf_progressbar_percentage').removeClass('percentbar_' + self.originalProgress).addClass('percentbar_' + progress).css('width', progressPercent);
|
|
}
|
|
|
|
// Update the form button based on progress
|
|
if ( progress === 100 ) {
|
|
// Treat the current page as the last one.
|
|
self.updateButtonToSubmitText( self.originalCurrentPage - 1, isMatch );
|
|
} else {
|
|
// Update the button on the current page.
|
|
$( '[id^=gform_next_button_' + self.options.formId + '_]' ).each( function ( e, element ) {
|
|
if ( $( element ).is(':visible') ) {
|
|
self.updateButtonToNextText( self.options.pages[ e ] );
|
|
}
|
|
});
|
|
|
|
// Update the button on the last page.
|
|
self.updateButtonToSubmitText( undefined, isMatch );
|
|
}
|
|
|
|
/**
|
|
* Fires after the conditional logic on the form has been evaluated.
|
|
*
|
|
* @since 2.5
|
|
*
|
|
* @param array $pages A collection of page field objects.
|
|
* @param int $formId The form id.
|
|
*/
|
|
gform.doAction('gform_frontend_pages_evaluated', self.options.pages, self.options.formId, self);
|
|
gform.doAction('gform_frontend_pages_evaluated_{0}'.gformFormat(self.options.formId), self.options.pages, self.options.formId, self);
|
|
|
|
};
|
|
|
|
self.evaluatePage = function (page, formId) {
|
|
|
|
// Pages with no configured conditional logic always a match.
|
|
if (!page.conditionalLogic) {
|
|
return true;
|
|
}
|
|
|
|
return gf_get_field_action(formId, page.conditionalLogic) === 'show';
|
|
};
|
|
|
|
self.getTriggerInputIds = function () {
|
|
var inputIds = [];
|
|
for (var i = 0; i < self.options.pages.length; i++) {
|
|
|
|
var page = self.options.pages[i];
|
|
|
|
if (!page.conditionalLogic) {
|
|
continue;
|
|
}
|
|
|
|
for (var j = 0; j < page.conditionalLogic.rules.length; j++) {
|
|
var rule = self.options.pages[i].conditionalLogic.rules[j];
|
|
if ($.inArray(rule.fieldId, inputIds) === -1) {
|
|
inputIds.push(rule.fieldId);
|
|
}
|
|
}
|
|
|
|
}
|
|
return inputIds;
|
|
};
|
|
|
|
self.isPageVisible = function (page) {
|
|
|
|
if (typeof page != 'object') {
|
|
page = self.getPage(page);
|
|
if (!page) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return typeof page.isVisible != 'undefined' ? page.isVisible : null;
|
|
};
|
|
|
|
self.getPage = function (fieldId) {
|
|
for (var i = 0; i < self.options.pages.length; i++) {
|
|
var page = self.options.pages[i];
|
|
if (page.fieldId == fieldId) {
|
|
return page;
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
|
|
self.showPage = function (page, stepNumber) {
|
|
|
|
var isVisible = self.isPageVisible(page);
|
|
|
|
if (isVisible === true) {
|
|
return;
|
|
}
|
|
|
|
page.isVisible = true;
|
|
$('#gf_step_' + self.options.formId + '_' + stepNumber).removeClass('gf_step_hidden');
|
|
|
|
/**
|
|
* Fires after the conditional logic on the form has been evaluated and the page has been found to be visible.
|
|
*
|
|
* @since 2.5
|
|
*
|
|
* @param array $pages A collection of page field objects.
|
|
* @param int $formId The form id.
|
|
*/
|
|
gform.doAction('gform_frontend_page_visible', page, self.options.formId);
|
|
gform.doAction('gform_frontend_page_visible_{0}'.gformFormat(self.options.formId), page, self.options.formId);
|
|
|
|
};
|
|
|
|
self.hidePage = function (page, stepNumber) {
|
|
|
|
var isVisible = self.isPageVisible(page);
|
|
|
|
if (isVisible === false) {
|
|
return;
|
|
}
|
|
|
|
page.isVisible = false;
|
|
$('#gf_step_' + self.options.formId + '_' + stepNumber).addClass('gf_step_hidden');
|
|
|
|
/**
|
|
* Fires after the conditional logic on the form has been evaluated and the page has become hidden.
|
|
*
|
|
* @since 2.5
|
|
*
|
|
* @param array $pages A collection of page field objects.
|
|
* @param int $formId The form id.
|
|
*/
|
|
gform.doAction('gform_frontend_page_hidden', page, self.options.formId);
|
|
gform.doAction('gform_frontend_page_hidden_{0}'.gformFormat(self.options.formId), page, self.options.formId);
|
|
|
|
};
|
|
|
|
/**
|
|
* The lastPageIndex might get miscalculated at some point during the flow. If it's outside the bounds of
|
|
* the page numbers, this resets it to the last natural page.
|
|
*
|
|
* @since 2.5.3
|
|
*
|
|
* @param {number|undefined} lastPageIndex The calculated last page of the form.
|
|
* @return {number} The calculated last page number.
|
|
*/
|
|
self.getValidatedLastPageIndex = function( lastPageIndex ) {
|
|
if ( lastPageIndex === undefined || lastPageIndex < 0 || lastPageIndex >= self.options.pages.length ) {
|
|
return self.options.pages.length - 1;
|
|
}
|
|
|
|
return lastPageIndex;
|
|
};
|
|
|
|
/**
|
|
* Checks whether the page the user is on is also considered to be the last page.
|
|
*
|
|
* Without conditional logic, forms have cardinal page numbers: 1, 2, 3, 4, 5, 6.
|
|
* With conditional logic, a "last page" of a form might not be the last page. e.g., 4 is the "submit" page.
|
|
*
|
|
* @since 2.5.3
|
|
*
|
|
* @param {number|string} targetPageNumber Next page to be shown.
|
|
* @param {number|string} lastPageNumber Actual last page of the form without conditional logic.
|
|
* @param {number|undefined} lastPageIndex In the scenario above, lastPageIndex is 4.
|
|
* @return {boolean} True or false whether the current page is the last calculated page.
|
|
*/
|
|
self.currentPageIsLastPage = function( targetPageNumber, lastPageNumber, lastPageIndex ) {
|
|
return targetPageNumber === lastPageNumber || lastPageIndex !== undefined;
|
|
};
|
|
|
|
/**
|
|
* Updates the text of the next button to be submit text on a paginated form.
|
|
*
|
|
* This method changes the text of the next button to the text of
|
|
* the submit button on the form if the user is on the page
|
|
* determined to be the last page of the form.
|
|
*
|
|
* @since Unknown
|
|
*
|
|
* @param {number|undefined} lastPageIndex The calculated last page of the form.
|
|
* @param {boolean} isMatch Whether the current conditional logic condition has been met.
|
|
* @return {void}
|
|
*/
|
|
self.updateButtonToSubmitText = function ( lastPageIndex, isMatch) {
|
|
var targetPageNumber = parseInt($('#gform_target_page_number_' + self.options.formId).val(), 10),
|
|
lastPageNumber = self.options.pages.length + 1;
|
|
|
|
// No need to update the button, we're not on the last page.
|
|
if ( ! self.currentPageIsLastPage( targetPageNumber, lastPageNumber, lastPageIndex ) ) {
|
|
return;
|
|
}
|
|
|
|
var calculatedLastPageIndex = self.getValidatedLastPageIndex( lastPageIndex );
|
|
|
|
var lastPageField = self.options.pages[ calculatedLastPageIndex ],
|
|
lastNextButton = $('#gform_next_button_' + self.options.formId + '_' + lastPageField.fieldId),
|
|
isLastPageVisible = self.isPageVisible(lastPageField),
|
|
formButton = $('#gform_submit_button_' + self.options.formId);
|
|
|
|
if (! isLastPageVisible ) {
|
|
if (formButton.attr('type') === 'image') {
|
|
// Cache last next button image alt.
|
|
if (lastNextButton.attr('type') === 'image') {
|
|
lastNextButton.data('alt', lastNextButton.attr('alt'));
|
|
}
|
|
lastNextButton.attr('type', 'image').attr('src', formButton.attr('src')).attr('alt', formButton.attr('alt')).addClass('gform_image_button').removeClass('button');
|
|
} else {
|
|
lastNextButton.attr('type', 'button').val(formButton.val()).addClass('button').removeClass('gform_image_button');
|
|
}
|
|
|
|
// Set a mark on the page, so later on we can reset the button when evaluating pages.
|
|
self.options.pages[ calculatedLastPageIndex ].isUpdated = true;
|
|
} else {
|
|
self.updateButtonToNextText( lastPageField );
|
|
}
|
|
|
|
// if actual submit button has conditional logic rules, apply them to the next button
|
|
if ( formButton.attr( 'data-conditional-logic' ) === 'hidden' ) {
|
|
var nextButton = $('#gform_next_button_' + self.options.formId + '_' + lastPageField.fieldId);
|
|
if( isMatch ) {
|
|
gf_show_button( nextButton );
|
|
} else {
|
|
gf_hide_button( nextButton );
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
/**
|
|
* Updates the text of the submit button to be next text on a paginated form.
|
|
*
|
|
* This method changes the text of the submit button to the text of
|
|
* the next button on the form if the user is on the page
|
|
* determined to not be the last page of the form.
|
|
*
|
|
* @since Unknown
|
|
*
|
|
* @param {number|undefined} page The current page of the form.
|
|
* @return {void}
|
|
*/
|
|
self.updateButtonToNextText = function ( page ) {
|
|
// No need to reset if the button hasn't been updated.
|
|
if ( ! page.hasOwnProperty( 'isUpdated' ) ) {
|
|
return;
|
|
}
|
|
|
|
delete page.isUpdated;
|
|
|
|
var nextButton = $('#gform_next_button_' + self.options.formId + '_' + page.fieldId);
|
|
if (page.nextButton.type === 'image') {
|
|
nextButton.attr('type', 'image').attr('src', page.nextButton.imageUrl).attr('alt', nextButton.data('alt')).addClass('gform_image_button').removeClass('button');
|
|
} else {
|
|
nextButton.attr('type', 'button').val(page.nextButton.text).addClass('button').removeClass('gform_image_button');
|
|
}
|
|
|
|
// formButton = $('#gform_submit_button_' + self.options.formId);
|
|
// if ( formButton.attr( 'data-conditional-logic' ) === 'visible' ) {
|
|
// var nextButton = $('#gform_next_button_' + self.options.formId + '_' + lastPageField.fieldId);
|
|
// gf_show_button( nextButton );
|
|
// }
|
|
}
|
|
|
|
this.init();
|
|
};
|