Skip to content
This repository has been archived by the owner on Jan 13, 2018. It is now read-only.

Commit

Permalink
Initial Commit
Browse files Browse the repository at this point in the history
  • Loading branch information
kodie committed Oct 12, 2015
0 parents commit 1102369
Show file tree
Hide file tree
Showing 7 changed files with 458 additions and 0 deletions.
27 changes: 27 additions & 0 deletions class-gf-field-repeater-end.php
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());
145 changes: 145 additions & 0 deletions class-gf-field-repeater.php
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());
189 changes: 189 additions & 0 deletions js/gf-repeater.js
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); }
});
}
Loading

0 comments on commit 1102369

Please sign in to comment.