This repository has been archived by the owner on Jan 13, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 58
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 1102369
Showing
7 changed files
with
458 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<?php | ||
class GF_Field_Repeater_End extends GF_Field { | ||
public $type = 'repeater-end'; | ||
|
||
public function get_form_editor_field_title() { | ||
return 'Repeater End'; | ||
} | ||
|
||
public function get_field_content($value, $force_frontend_label, $form) { | ||
if (is_admin()) { | ||
$admin_buttons = $this->get_admin_buttons(); | ||
$field_content = "{$admin_buttons} | ||
<div class=\"gf-pagebreak-end gf-pagebreak-container gf-repeater-end\"> | ||
<div class=\"gf-pagebreak-text-before\">end repeater</div> | ||
<div class=\"gf-pagebreak-text-main\"><span>REPEATER</span></div> | ||
<div class=\"gf-pagebreak-text-after\">end of repeater</div> | ||
</div>"; | ||
} else { | ||
$field_content = "<div class=\"gf-repeater-end\"> | ||
<img src=\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPjxzdmcgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iNTEyIiBoZWlnaHQ9IjUxMiIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxnIGlkPSJpY29tb29uLWlnbm9yZSI+PC9nPjxwYXRoIGQ9Ik0yNTYgNTEyYy0xNDEuMzc1IDAtMjU2LTExNC42MDktMjU2LTI1NnMxMTQuNjI1LTI1NiAyNTYtMjU2YzE0MS4zOTEgMCAyNTYgMTE0LjYwOSAyNTYgMjU2cy0xMTQuNjA5IDI1Ni0yNTYgMjU2ek0yNTYgNjRjLTEwNi4wMzEgMC0xOTIgODUuOTY5LTE5MiAxOTJzODUuOTY5IDE5MiAxOTIgMTkyYzEwNi4wNDcgMCAxOTItODUuOTY5IDE5Mi0xOTJzLTg1Ljk1My0xOTItMTkyLTE5MnpNMjg4IDM4NGgtNjR2LTk2aC05NnYtNjRoOTZ2LTk2aDY0djk2aDk2djY0aC05NnY5NnoiPjwvcGF0aD48L3N2Zz4=\" class=\"gf-repeater-add\" style=\"cursor:pointer; width:1em; height:1em;\" alt=\"+\"> | ||
<img src=\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPjxzdmcgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iNTEyIiBoZWlnaHQ9IjUxMiIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxnIGlkPSJpY29tb29uLWlnbm9yZSI+PC9nPjxwYXRoIGQ9Ik0yNTYgMGMtMTQxLjM3NSAwLTI1NiAxMTQuNjI1LTI1NiAyNTYgMCAxNDEuMzkxIDExNC42MjUgMjU2IDI1NiAyNTYgMTQxLjM5MSAwIDI1Ni0xMTQuNjA5IDI1Ni0yNTYgMC0xNDEuMzc1LTExNC42MDktMjU2LTI1Ni0yNTZ6TTI1NiA0NDhjLTEwNi4wMzEgMC0xOTItODUuOTY5LTE5Mi0xOTJzODUuOTY5LTE5MiAxOTItMTkyYzEwNi4wNDcgMCAxOTIgODUuOTY5IDE5MiAxOTJzLTg1Ljk1MyAxOTItMTkyIDE5MnpNMTI4IDI4OGgyNTZ2LTY0aC0yNTZ2NjR6Ij48L3BhdGg+PC9zdmc+\" class=\"gf-repeater-remove\" style=\"cursor:pointer; width:1em; height:1em;\" alt=\"-\"> | ||
</div>"; | ||
} | ||
return $field_content; | ||
} | ||
} | ||
GF_Fields::register(new GF_Field_Repeater_End()); |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
<?php | ||
class GF_Field_Repeater extends GF_Field { | ||
public $type = 'repeater'; | ||
|
||
public static function init() { | ||
if (!is_admin()) { | ||
add_action('gform_enqueue_scripts', array('GF_Field_Repeater', 'gform_enqueue_scripts'), 10, 2); | ||
} else { | ||
add_action('gform_field_standard_settings' , array('GF_Field_Repeater', 'gform_settings'), 10, 2); | ||
add_action('gform_editor_js', array('GF_Field_Repeater', 'gform_editor')); | ||
add_filter('gform_tooltips', array('GF_Field_Repeater', 'gform_tooltips')); | ||
} | ||
} | ||
|
||
public static function gform_enqueue_scripts($form, $is_ajax) { | ||
if (!empty($form)) { | ||
if (in_array('GF_Field_Repeater', $form)) { | ||
wp_enqueue_script('_gf_repeater', plugins_url('js/gf-repeater.min.js', __FILE__), array('jquery')); | ||
} | ||
} | ||
} | ||
|
||
public function get_form_editor_field_title() { | ||
return 'Repeater'; | ||
} | ||
|
||
public function get_form_editor_field_settings() { | ||
return array( | ||
'admin_label_setting' | ||
); | ||
} | ||
|
||
public static function gform_settings($position, $form_id) { | ||
if ($position == 25) { | ||
echo "<li class=\"repeater_settings field_setting\"> | ||
<label for=\"field_repeater_min\">Min "; | ||
|
||
gform_tooltip('form_field_repeater_min'); | ||
|
||
echo " </label> | ||
<input type=\"number\" id=\"field_repeater_min\" min=\"1\" value=\"1\" onchange=\"SetFieldProperty('min', this.value);\" required> | ||
</li>"; | ||
|
||
echo "<li class=\"repeater_settings field_setting\"> | ||
<label for=\"field_repeater_max\">Max "; | ||
|
||
gform_tooltip('form_field_repeater_max'); | ||
|
||
echo " </label> | ||
<input type=\"number\" id=\"field_repeater_max\" min=\"1\" onchange=\"SetFieldProperty('max', this.value);\"> | ||
</li>"; | ||
} | ||
} | ||
|
||
public static function gform_editor() { | ||
echo "<script type=\"text/javascript\"> | ||
fieldSettings['repeater'] += ', .repeater_settings'; | ||
jQuery(document).bind('gform_load_field_settings', function(event, field, form){ | ||
jQuery('#field_repeater_min').val(field['min']); | ||
jQuery('#field_repeater_max').val(field['max']); | ||
}); | ||
</script>"; | ||
} | ||
|
||
public static function gform_tooltips($tooltips) { | ||
$tooltips['form_field_repeater_min'] = "The minimum number of times the repeater is allowed to be repeated. Leaving this field blank is the same as setting it to 1."; | ||
$tooltips['form_field_repeater_max'] = "The maximum number of times the repeater is allowed to be repeated. Leaving this field blank or setting it to a number lower than the minimum field is the same as setting it to unlimited."; | ||
return $tooltips; | ||
} | ||
|
||
public function get_field_content($value, $force_frontend_label, $form) { | ||
if (is_admin()) { | ||
$admin_buttons = $this->get_admin_buttons(); | ||
$field_content = "{$admin_buttons} | ||
<div class=\"gf-pagebreak-first gf-pagebreak-container gf-repeater\"> | ||
<div class=\"gf-pagebreak-text-before\">begin repeater</div> | ||
<div class=\"gf-pagebreak-text-main\"><span>REPEATER</span></div> | ||
<div class=\"gf-pagebreak-text-after\">top of repeater</div> | ||
</div>"; | ||
} else { | ||
$field_content = "<div class=\"gf-repeater-start\"></div>{FIELD}"; | ||
} | ||
return $field_content; | ||
} | ||
|
||
public function get_field_input($form, $value = '', $entry = null) { | ||
$form_id = $form['id']; | ||
$is_entry_detail = $this->is_entry_detail(); | ||
$is_form_editor = $this->is_form_editor(); | ||
$id = (int) $this->id; | ||
$field_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$id" : 'input_' . $form_id . "_$id"; | ||
$disabled_text = $is_form_editor ? 'disabled="disabled"' : ''; | ||
$repeater_min = $this->min; | ||
$repeater_max = $this->max; | ||
return sprintf("<input name='input_%d' id='%s' type='hidden' class='gform_hidden' data-start='".$repeater_min."' data-min='".$repeater_min."' data-max='".$repeater_max."' value='' %s/>", $id, $field_id, esc_attr($value), $disabled_text); | ||
} | ||
|
||
public function get_value_save_entry($value, $form, $input_name, $lead_id, $lead) { | ||
$dataArray = json_decode($value, true); | ||
$value = Array(); | ||
|
||
for ($i = 1; $i < $dataArray['repeatCount'] + 1; $i++) { | ||
foreach ($dataArray['childrenData'] as $childData) { | ||
if (!array_key_exists('inputName', $childData)) { continue; } | ||
$childValue[$childData['label']] = rgpost($childData['inputName'].'-'.$dataArray['repeaterId'].'-'.$i); | ||
} | ||
$value[$i] = $childValue; | ||
} | ||
|
||
return maybe_serialize($value); | ||
} | ||
|
||
public function get_value_entry_list($value, $entry, $field_id, $columns, $form) { | ||
if (empty($value)) { | ||
return ''; | ||
} else { | ||
$dataArray = GFFormsModel::unserialize($value); | ||
$arrayCount = count($dataArray); | ||
if ($arrayCount > 1) { $returnText = $arrayCount.' entries'; } else { $returnText = $arrayCount.' entry'; } | ||
return $returnText; | ||
} | ||
} | ||
|
||
public function get_value_entry_detail($value, $currency = '', $use_text = false, $format = 'html', $media = 'screen') { | ||
if (empty($value)) { | ||
return ''; | ||
} else { | ||
$dataArray = GFFormsModel::unserialize($value); | ||
$arrayCount = count($dataArray); | ||
$output = ""; | ||
$count = 0; | ||
foreach ($dataArray as $key=>$value) { | ||
$output .= "<table cellspacing=\"0\" class=\"widefat fixed entry-detail-view\">\n"; | ||
foreach ($value as $childKey=>$childValue) { | ||
if (!$childValue) { continue; } else { $count++; } | ||
$output .= "<tr>\n<td colspan=\"2\" class=\"entry-view-field-name\">".$childKey."</td>\n</tr>\n"; | ||
$output .= "<tr>\n<td colspan=\"2\" class=\"entry-view-field-value\">".$childValue."</td>\n</tr>\n"; | ||
} | ||
$output .= "</table>\n"; | ||
} | ||
} | ||
if ($count !== 0) { return $output; } else { return ''; } | ||
} | ||
} | ||
GF_Fields::register(new GF_Field_Repeater()); |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
var gfRepeater_debug = false; | ||
var gfRepeater_repeaters = {}; | ||
|
||
/* | ||
gfRepeater_getRepeaters() | ||
Collects all repeater info and stores it inside of the global array "gfRepeater_repeaters". - First phase of setup. | ||
*/ | ||
function gfRepeater_getRepeaters() { | ||
var repeaterFound = 0; | ||
var repeaterId = 1; | ||
var repeaterChildren = []; | ||
var repeaterChildrenData = []; | ||
var dataElement; | ||
|
||
jQuery('.gfield').each(function(){ | ||
if (repeaterFound == 0) { | ||
if (jQuery(this).has('.gf-repeater-start').length) { | ||
if (gfRepeater_debug) { console.log('Repeater #'+repeaterId+' - Start: '+jQuery(this).attr('id')); } | ||
dataElement = jQuery('#'+this.id+' input.gform_hidden'); | ||
repeaterFound = 1; | ||
} | ||
} else { | ||
if (jQuery(this).has('.gf-repeater-end').length) { | ||
if (gfRepeater_debug) { | ||
console.log('Repeater #'+repeaterId+' - End: '+jQuery(this).attr('id')); | ||
console.log('Repeater #'+repeaterId+' - Children Found: '+repeaterChildren.length); | ||
} | ||
var addElement = jQuery('#'+this.id+' .gf-repeater-end .gf-repeater-add'); | ||
var removeElement = jQuery('#'+this.id+' .gf-repeater-end .gf-repeater-remove'); | ||
jQuery(addElement).attr('onClick', 'gfRepeater_repeatRepeater('+repeaterId+');'); | ||
jQuery(removeElement).attr('onClick', 'gfRepeater_unrepeatRepeater('+repeaterId+');'); | ||
var repeaterStart = dataElement.attr('data-start'); | ||
var repeaterMin = dataElement.attr('data-min'); | ||
var repeaterMax = dataElement.attr('data-max'); | ||
if (!repeaterStart) { repeaterStart = 1; } | ||
if (!repeaterMin) { repeaterMin = 1; } | ||
if (repeaterMin > repeaterMax) { repeaterMax = null; } | ||
gfRepeater_repeaters[repeaterId] = {count:1,start:repeaterStart,min:repeaterMin,max:repeaterMax,add:addElement,remove:removeElement,data:dataElement,children:repeaterChildren,childrenData:repeaterChildrenData}; | ||
gfRepeater_updateDataElement(repeaterId); | ||
repeaterId += 1; | ||
repeaterChildren = []; | ||
repeaterChildrenData = []; | ||
repeaterFound = 0; | ||
} else { | ||
repeaterChildren.push(jQuery(this)); | ||
var childLabel = jQuery(this).children('.gfield_label').text(); | ||
var childInputId = jQuery('#' + this.id + ' .ginput_container').children().first().attr('id'); | ||
var childInputName = jQuery('#' + this.id + ' .ginput_container').children().first().attr('name'); | ||
if (gfRepeater_debug) { console.log('Repeater #'+repeaterId+' - Child Found: '+childInputName); } | ||
repeaterChildrenData.push({inputId:childInputId,inputName:childInputName,label:childLabel}); | ||
} | ||
} | ||
}); | ||
if (gfRepeater_debug) { console.log('Repeaters Found: '+(repeaterId-1)); } | ||
} | ||
|
||
/* | ||
gfRepeater_setRepeaterChildAttrs(repeaterChildElement, repeaterId, repeatCount) | ||
Adds the repeater ID number and Count number to the end of repeater child ID and name. | ||
repeaterChildElement The child element to run the function for. | ||
repeaterId The repeater ID to assign the child to. | ||
repeatCount (Optional) The repeat count number to assign the child to. If a number is not specified, one will be automatically assigned. A 1 is required the first time this function is used during the setup process. | ||
*/ | ||
function gfRepeater_setRepeaterChildAttrs(repeaterChildElement, repeaterId, repeatCount) { | ||
if (!repeatCount) { var repeatCount = gfRepeater_repeaters[repeaterId]['count'] + 1; } | ||
var oldRootId = jQuery(repeaterChildElement).attr('id'); | ||
var newRootId = oldRootId.split('-')[0]+'-'+repeaterId+'-'+repeatCount; | ||
jQuery(repeaterChildElement).attr('id', newRootId); | ||
var inputElement = jQuery('#' + newRootId + ' .ginput_container').children().first(); | ||
var oldInputName = jQuery(inputElement).attr('name'); | ||
if (oldInputName) { | ||
var newInputName = oldInputName.split('-')[0]+'-'+repeaterId+'-'+repeatCount; | ||
jQuery(inputElement).attr('name', newInputName); | ||
} | ||
var oldInputId = jQuery(inputElement).attr('id'); | ||
if (oldInputId) { | ||
var newInputId = oldInputId.split('-')[0]+'-'+repeaterId+'-'+repeatCount; | ||
jQuery(inputElement).attr('id', newInputId); | ||
} | ||
jQuery(repeaterChildElement).children('.gfield_label').attr('for', newInputId); | ||
} | ||
|
||
/* | ||
gfRepeater_repeatRepeater(repeaterId) | ||
Repeats the repeater once. | ||
repeaterId The repeater ID number to repeat. | ||
*/ | ||
function gfRepeater_repeatRepeater(repeaterId) { | ||
if (gfRepeater_repeaters[repeaterId]['max'] && gfRepeater_repeaters[repeaterId]['count'] >= gfRepeater_repeaters[repeaterId]['max']) { return; } | ||
var lastElement = gfRepeater_repeaters[repeaterId]['children'][gfRepeater_repeaters[repeaterId]['children'].length - 1]; | ||
lastElement = lastElement.attr('id'); | ||
lastElement = jQuery('#'+lastElement.slice(0, -1)+gfRepeater_repeaters[repeaterId]['count']); | ||
jQuery.each(gfRepeater_repeaters[repeaterId]['children'], function(key, value){ | ||
var clonedElement = jQuery(this).clone(); | ||
var inputElement = jQuery(clonedElement).find('.ginput_container').children().first(); | ||
jQuery(inputElement).val(''); | ||
jQuery(clonedElement).insertAfter(lastElement); | ||
gfRepeater_setRepeaterChildAttrs(jQuery(clonedElement), repeaterId); | ||
lastElement = clonedElement; | ||
}); | ||
gfRepeater_repeaters[repeaterId]['count'] += 1; | ||
gfRepeater_updateDataElement(repeaterId); | ||
gfRepeater_updateRepeaterControls(repeaterId); | ||
if (gfRepeater_debug) { console.log('Repeater #'+repeaterId+' repeated'); } | ||
} | ||
|
||
/* | ||
gfRepeater_unrepeatRepeater(repeaterId, repeaterChildId) | ||
Un-repeats the repeater once. | ||
repeaterId The repeater ID number to unrepeat. | ||
repeaterChildId (Optional) The repeater child ID number to unrepeat. If an ID number is not specified, the last one will be chosen. | ||
*/ | ||
function gfRepeater_unrepeatRepeater(repeaterId, repeaterChildId) { | ||
if (gfRepeater_repeaters[repeaterId]['count'] <= gfRepeater_repeaters[repeaterId]['min']) { return; } | ||
if (!repeaterChildId) { var repeaterChildId = gfRepeater_repeaters[repeaterId]['count']; } | ||
jQuery.each(gfRepeater_repeaters[repeaterId]['children'], function(key, value){ | ||
var thisId = jQuery(this).attr('id'); | ||
var childElement = jQuery('#'+thisId.slice(0, -1)+repeaterChildId); | ||
jQuery(childElement).remove(); | ||
}); | ||
gfRepeater_repeaters[repeaterId]['count'] -= 1; | ||
gfRepeater_updateDataElement(repeaterId); | ||
gfRepeater_updateRepeaterControls(repeaterId); | ||
if (gfRepeater_debug) { console.log('Repeater #'+repeaterId+' unrepeated'); } | ||
} | ||
|
||
/* | ||
gfRepeater_updateRepeaterControls(repeaterId) | ||
Updates the add and remove buttons for the repeater. If the minimum repeat number has been reached, the remove button is hidden. If the maximum number has been reached, the add button is hidden. | ||
repeaterId The repeater ID number to update the controls for. | ||
*/ | ||
function gfRepeater_updateRepeaterControls(repeaterId) { | ||
if (gfRepeater_repeaters[repeaterId]['max']) { | ||
if (gfRepeater_repeaters[repeaterId]['count'] == gfRepeater_repeaters[repeaterId]['max']) { | ||
jQuery(gfRepeater_repeaters[repeaterId]['add']).hide(); | ||
} else { | ||
jQuery(gfRepeater_repeaters[repeaterId]['add']).show(); | ||
} | ||
} | ||
if (gfRepeater_repeaters[repeaterId]['count'] == gfRepeater_repeaters[repeaterId]['min']) { | ||
jQuery(gfRepeater_repeaters[repeaterId]['remove']).hide(); | ||
} else { | ||
jQuery(gfRepeater_repeaters[repeaterId]['remove']).show(); | ||
} | ||
} | ||
|
||
/* | ||
gfRepeater_updateDataElement(repeaterId) | ||
Updates the data element for the repater. The data element stores information that is passed to PHP for processing. | ||
repeaterId The repeater ID number to update the data element for. | ||
*/ | ||
function gfRepeater_updateDataElement(repeaterId) { | ||
var dataElement = jQuery(gfRepeater_repeaters[repeaterId]['data']); | ||
var dataArray = JSON.stringify({repeaterId:repeaterId,repeatCount:gfRepeater_repeaters[repeaterId]['count'],childrenData:gfRepeater_repeaters[repeaterId]['childrenData']}); | ||
jQuery(dataElement).val(dataArray); | ||
} | ||
|
||
/* | ||
gfRepeater_start() | ||
Runs the gfRepeater_setRepeaterChildAttrs function for the first set of repeater children and then repeats the repeater a number of times depending on the repeater setting. - Second phase of setup. | ||
*/ | ||
function gfRepeater_start() { | ||
jQuery.each(gfRepeater_repeaters, function(key, value){ | ||
var repeaterId = key; | ||
jQuery.each(gfRepeater_repeaters[repeaterId]['children'], function(key, value){ gfRepeater_setRepeaterChildAttrs(jQuery(this), repeaterId, 1); }); | ||
for (i = 0; i < gfRepeater_repeaters[repeaterId]['start'] - 1; i++) { | ||
gfRepeater_repeatRepeater(repeaterId); | ||
} | ||
gfRepeater_updateRepeaterControls(repeaterId); | ||
}); | ||
} | ||
|
||
// Initiation | ||
jQuery(document).ready(function($) { | ||
gfRepeater_getRepeaters(); | ||
gfRepeater_start(); | ||
}); | ||
|
||
// Debug function - Display a table filled with the contents of "gfRepeater_repeaters" in the developer console if the "Up" arrow is pressed on the keyboard. | ||
if (gfRepeater_debug) { | ||
jQuery(window).keydown(function(event){ | ||
if (event.which == 38) { console.table(gfRepeater_repeaters); } | ||
}); | ||
} |
Oops, something went wrong.