Forked from spivurno/gw-gravity-forms-rounding.php
Created
September 5, 2016 04:51
-
-
Save phillipwilhelm/af79bf4d9492617ca2e81936d58d2883 to your computer and use it in GitHub Desktop.
Gravity Wiz // Gravity Forms // Rounding by Increment
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * Gravity Wiz // Gravity Forms // Rounding by Increment | |
| * | |
| * Provides a variety of rounding functions for Gravity Form Number fields powered by the CSS class setting for each field. Functions include: | |
| * | |
| * + rounding to an increment (i.e. increment of 100 would round 1 to 100, 149 to 100, 150 to 200, etc) | class: 'gw-round-100' | |
| * + rounding up by an increment (i.e. increment of 50 would round 1 to 50, 51 to 100, 149 to 150, etc) | class: 'gw-round-up-50' | |
| * + rounding down by an increment (i.e. increment of 25 would round 1 to 0, 26 to 25, 51 to 50, etc) | class: 'gw-round-down-25' | |
| * + rounding up to a specific minimum (i.e. min of 50 would round 1 to 50, 51 and greater would not be rounded) | class: 'gw-round-min-50' | |
| * + rounding down to a specific maximum (i.e. max of 25 would round 26 to 25, 25 and below would not be rounded) | class: 'gw-round-max-25' | |
| * | |
| * @version 1.1 | |
| * @author David Smith <[email protected]> | |
| * @license GPL-2.0+ | |
| * @link http://gravitywiz.com/rounding-increments-gravity-forms/ | |
| */ | |
| class GW_Rounding { | |
| private static $instance = null; | |
| protected static $is_script_output = false; | |
| protected $class_regex = 'gw-round-(\w+)-?(\w+)?'; | |
| public static function get_instance() { | |
| if( null == self::$instance ) | |
| self::$instance = new self; | |
| return self::$instance; | |
| } | |
| private function __construct( $args = array() ) { | |
| // make sure we're running the required minimum version of Gravity Forms | |
| if( ! property_exists( 'GFCommon', 'version' ) || ! version_compare( GFCommon::$version, '1.8', '>=' ) ) | |
| return; | |
| // time for hooks | |
| add_filter( 'gform_pre_render', array( $this, 'prepare_form_and_load_script' ) ); | |
| add_filter( 'gform_register_init_scripts', array( $this, 'add_init_script' ) ); | |
| add_filter( 'gform_enqueue_scripts', array( $this, 'enqueue_form_scripts' ) ); | |
| add_action( 'gform_pre_submission', array( $this, 'override_submitted_value' ), 10, 5 ); | |
| add_filter( 'gform_calculation_result', array( $this, 'override_submitted_calculation_value' ), 10, 5 ); | |
| } | |
| function prepare_form_and_load_script( $form ) { | |
| if( ! $this->is_applicable_form( $form ) ) { | |
| return $form; | |
| } | |
| if( ! self::$is_script_output ) { | |
| $this->output_script(); | |
| } | |
| foreach( $form['fields'] as &$field ) { | |
| if( preg_match( $this->get_class_regex(), $field['cssClass'] ) ) { | |
| $field['cssClass'] .= ' gw-rounding'; | |
| } | |
| } | |
| return $form; | |
| } | |
| function output_script() { | |
| ?> | |
| <script type="text/javascript"> | |
| var GWRounding; | |
| ( function( $ ) { | |
| GWRounding = function( args ) { | |
| var self = this; | |
| // copy all args to current object: (list expected props) | |
| for( prop in args ) { | |
| if( args.hasOwnProperty( prop ) ) | |
| self[prop] = args[prop]; | |
| } | |
| self.init = function() { | |
| self.fieldElems = $( '#gform_wrapper_' + self.formId + ' .gw-rounding' ); | |
| self.parseElemActions( self.fieldElems ); | |
| self.bindEvents(); | |
| } | |
| self.parseElemActions = function( elems ) { | |
| elems.each( function() { | |
| var cssClasses = $( this ).attr( 'class' ), | |
| roundingActions = self.parseActions( cssClasses ); | |
| $( this ).data( 'gw-rounding', roundingActions ); | |
| } ); | |
| } | |
| self.parseActions = function( str ) { | |
| var matches = getMatchGroups( String( str ), new RegExp( self.classRegex.replace( /\\/g, '\\' ), 'i' ) ), | |
| roundingActions = []; | |
| for( var i = 0; i < matches.length; i++ ) { | |
| var action = matches[i][1], | |
| actionValue = matches[i][2]; | |
| if( typeof actionValue == 'undefined' ) { | |
| actionValue = action; | |
| action = 'round'; | |
| } | |
| var roundingAction = { | |
| 'action': action, | |
| 'actionValue': actionValue | |
| }; | |
| roundingActions.push( roundingAction ); | |
| } | |
| return roundingActions; | |
| } | |
| self.bindEvents = function() { | |
| self.fieldElems.find( 'input' ).each( function() { | |
| self.applyRoundingActions( $( this ) ); | |
| } ).blur( function() { | |
| self.applyRoundingActions( $( this ) ); | |
| } ); | |
| gform.addFilter( 'gform_calculation_result', function( result, formulaField, formId, calcObj ) { | |
| var $input = $( '#input_' + formId + '_' + formulaField.field_id ) | |
| $field = $input.parents( '.gfield' ); | |
| if( $field.hasClass( 'gw-rounding' ) ) { | |
| result = self.getRoundedValue( $input, result ); | |
| } | |
| return result; | |
| } ); | |
| } | |
| self.applyRoundingActions = function( $input ) { | |
| var value = self.getRoundedValue( $input ); | |
| if( $input.val() != value ) { | |
| $input.val( value ).change(); | |
| } | |
| } | |
| self.getRoundedValue = function( $input, value ) { | |
| var $field = $input.parents( '.gfield' ), | |
| actions = $field.data( 'gw-rounding' ); | |
| // allows setting the 'gw-rounding' data for an element to null and it will be reparsed | |
| if( actions === null ) { | |
| self.parseElemActions( $field ); | |
| actions = $field.data( 'gw-rounding' ); | |
| } | |
| if( typeof actions == 'undefined' || actions === false || actions.length <= 0 ) { | |
| return; | |
| } | |
| if( typeof value == 'undefined' ) { | |
| value = $input.val(); | |
| } | |
| if( value == '' ) { | |
| value = ''; | |
| } else { | |
| for( var i = 0; i < actions.length; i++ ) { | |
| value = GWRounding.round( value, actions[i].actionValue, actions[i].action ); | |
| } | |
| } | |
| return isNaN( value ) ? '' : value; | |
| } | |
| GWRounding.round = function( value, actionValue, action ) { | |
| var interval, base, min, max; | |
| value = parseInt( value ); | |
| actionValue = parseInt( actionValue ); | |
| switch( action ) { | |
| case 'min': | |
| min = actionValue; | |
| if( value < min ) { | |
| value = min; | |
| } | |
| break; | |
| case 'max': | |
| max = actionValue; | |
| if( value > max ) { | |
| value = max; | |
| } | |
| break; | |
| case 'up': | |
| interval = actionValue; | |
| base = Math.ceil( value / interval ); | |
| value = base * interval; | |
| break; | |
| case 'down': | |
| interval = actionValue; | |
| base = Math.floor( value / interval ); | |
| value = base * interval; | |
| break; | |
| default: | |
| interval = actionValue; | |
| base = Math.round( value / interval ); | |
| value = base * interval; | |
| break; | |
| } | |
| return parseInt( value ); | |
| } | |
| self.init(); | |
| } | |
| } )( jQuery ); | |
| </script> | |
| <?php | |
| self::$is_script_output = true; | |
| } | |
| function add_init_script( $form ) { | |
| if( ! $this->is_applicable_form( $form ) ) { | |
| return; | |
| } | |
| $args = array( | |
| 'formId' => $form['id'], | |
| 'classRegex' => $this->class_regex | |
| ); | |
| $script = 'new GWRounding( ' . json_encode( $args ) . ' );'; | |
| GFFormDisplay::add_init_script( $form['id'], 'gw_rounding', GFFormDisplay::ON_PAGE_RENDER, $script ); | |
| } | |
| function enqueue_form_scripts( $form ) { | |
| if( $this->is_applicable_form( $form ) ) { | |
| wp_enqueue_script( 'gform_gravityforms' ); | |
| } | |
| } | |
| function override_submitted_value( $form ) { | |
| foreach( $form['fields'] as $field ) { | |
| if( $this->is_applicable_field( $field ) ) { | |
| $value = $this->process_rounding_actions( rgpost( "input_{$field['id']}" ), $this->get_rounding_actions( $field ) ); | |
| $_POST[ "input_{$field['id']}" ] = $value; | |
| } | |
| } | |
| } | |
| function override_submitted_calculation_value( $result, $formula, $field, $form, $entry ) { | |
| if( $this->is_applicable_field( $field ) ) { | |
| $result = $this->process_rounding_actions( $result, $this->get_rounding_actions( $field ) ); | |
| } | |
| return $result; | |
| } | |
| function process_rounding_actions( $value, $actions ) { | |
| foreach( $actions as $action ) { | |
| $value = $this->round( $value, $action['action'], $action['action_value'] ); | |
| } | |
| return $value; | |
| } | |
| function round( $value, $action, $action_value ) { | |
| $value = intval( $value ); | |
| $action_value = intval( $action_value ); | |
| switch( $action ) { | |
| case 'min': | |
| $min = $action_value; | |
| if( $value < $min ) { | |
| $value = $min; | |
| } | |
| break; | |
| case 'max': | |
| $max = $action_value; | |
| if( $value > $max ) { | |
| $value = $max; | |
| } | |
| break; | |
| case 'up': | |
| $interval = $action_value; | |
| $base = ceil( $value / $interval ); | |
| $value = $base * $interval; | |
| break; | |
| case 'down': | |
| $interval = $action_value; | |
| $base = floor( $value / $interval ); | |
| $value = $base * $interval; | |
| break; | |
| default: | |
| $interval = $action_value; | |
| $base = round( $value / $interval ); | |
| $value = $base * $interval; | |
| break; | |
| } | |
| return intval( $value ); | |
| } | |
| // # HELPERS | |
| function is_applicable_form( $form ) { | |
| foreach( $form['fields'] as $field ) { | |
| if( $this->is_applicable_field( $field ) ) { | |
| return true; | |
| } | |
| } | |
| return false; | |
| } | |
| function is_applicable_field( $field ) { | |
| return preg_match( $this->get_class_regex(), rgar( $field, 'cssClass' ) ) == true; | |
| } | |
| function get_class_regex() { | |
| return "/{$this->class_regex}/"; | |
| } | |
| function get_rounding_actions( $field ) { | |
| $actions = array(); | |
| preg_match_all( $this->get_class_regex(), rgar( $field, 'cssClass' ), $matches, PREG_SET_ORDER ); | |
| foreach( $matches as $match ) { | |
| list( $full_match, $action, $action_value ) = array_pad( $match, 3, false ); | |
| if( $action_value === false ) { | |
| $action_value = $action; | |
| $action = 'round'; | |
| } | |
| $action = array( | |
| 'action' => $action, | |
| 'action_value' => $action_value | |
| ); | |
| $actions[] = $action; | |
| } | |
| return $actions; | |
| } | |
| } | |
| function gw_rounding() { | |
| return GW_Rounding::get_instance(); | |
| } | |
| gw_rounding(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment