Skip to content

Instantly share code, notes, and snippets.

@vfontjr
Last active September 20, 2021 14:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vfontjr/e92bcccdc72930e9f9887dd4b1d42f26 to your computer and use it in GitHub Desktop.
Save vfontjr/e92bcccdc72930e9f9887dd4b1d42f26 to your computer and use it in GitHub Desktop.
<script>
jQuery(document).ready(function ($) {
"use strict";
/* conditions to trigger show or hide checkboxes:
* 1. if current value is checked in this row, do nothing
* 2. if current value is checked in previous row, hide value in this row
* 3. if current value is checked in future row, hide value in this row
* 4. if current value is unchecked in this row, is it hidden because it was checked in another row? If so, is it now unchecked in the other row, then show it.
* 5. if user removes row, all checked boxes in that row need to be shown again in all remaining rows.
*/
/* initialize varibles for repeater section and field ids to pass to the repeater_row_init function
* and use in all functions that access the checkbox inputs
*/
var _repeater_section = "295",
_field_id = "297",
_safari_workaround = "";
/* setup an array of repeater callback functions */
/* you'll want a different callback for each repeater section */
var callbacks = {
repeater_section_295_init : function() {
var rowids = get_row_ids( _repeater_section ), // get all of the row ids
min_row_id = Math.min.apply( Math, rowids ),
max_row_id = Math.max.apply( Math, rowids ),
checked_values = get_checked_values( rowids, max_row_id );
/* now that we have the row ids for this section, we can loop through the array and apply the code to each of the correct elements */
$.each(rowids, function( index, row_id ) {
/* if a new row has been added, initialize it */
if( row_id == max_row_id && row_id > min_row_id ) {
init_new_295_repeater_row( row_id, checked_values );
}
/* if an item is checked or unchecked, reinitialize all rows to show/hide values as appropriate */
$('input[name="item_meta[' + _repeater_section + '][' + row_id + '][' + _field_id + '][]"]').on("change", function() {
var checked_values_with_rowids = get_new_checked_values( rowids, true ),
target_val = $(this).val(),
input_name = $(this).prop('name');
checked_values = get_new_checked_values( rowids, false );
reinit_295_repeater_row( rowids, checked_values, checked_values_with_rowids, row_id, target_val, input_name );
maybe_disable_repeater( min_row_id, max_row_id );
});
});
},
add_repeater_row_295_init : function() {
$('a.frm_add_form_row').on('click', function() {
_safari_workaround = $(this).data('parent');
});
},
remove_repeater_row_295_init : function() {
var rowids = get_row_ids( _repeater_section );
$('a.frm_remove_form_row').on('click', function() {
var key = $(this).data('key'),
checked_vals = get_checked_values_this_row(key);
clear_unchecked_values_this_row( rowids, checked_vals );
});
}
};
function clear_all_checkboxes( row_ids ) {
/* show all checkboxes in all rows */
$.each( row_ids, function( index, val ){
var row_id = val;
$.each( $('input[name="item_meta[' + _repeater_section + '][' + row_id + '][' + _field_id + '][]"]'), function() {
$(this).prop('disabled','');
$(this).parent('label').show();
});
});
}
function clear_unchecked_values( row_ids, checked_values ) {
/* loop through the input fields that have the row_ids and push them into an array */
$.each( row_ids, function( index, val ){
var row_id = val;
$.each( $('input[name="item_meta[' + _repeater_section + '][' + row_id + '][' + _field_id + '][]"]' ), function(){
var input_id = 'input#' + $(this).prop('id'),
input_value = $(this).val(),
input_checked = $(this).prop('checked'),
input_hidden = $(this).is(':hidden'),
input_name = $(this).prop('name');
/* Is the checked value not found in the checked values array */
if ( !input_checked && input_hidden && $.inArray(input_value, checked_values) == -1 ) {
$(input_id).prop('disabled','');
$(input_id).parent('label').show();
}
});
});
}
function clear_unchecked_values_this_row( row_ids, checked_values ) {
/* loop through the input fields that have the row_ids and push them into an array */
$.each( row_ids, function( index, val ){
var row_id = val;
$.each( $('input[name="item_meta[' + _repeater_section + '][' + row_id + '][' + _field_id + '][]"]' ), function(){
var input_id = 'input#' + $(this).prop('id'),
input_value = $(this).val(),
input_checked = $(this).prop('checked'),
input_hidden = $(this).is(':hidden'),
input_name = $(this).prop('name');
/* Is the value found in the checked values array */
if ( !input_checked && input_hidden && $.inArray(input_value, checked_values) > -1 ) {
$(input_id).prop('disabled','');
$(input_id).parent('label').show();
}
});
});
}
function get_checked_values( row_ids, max_row_id ) {
/* loop through the input fields that have the row_ids and push them into an array */
var checked_vals = [];
$.each( row_ids, function( index, val ){
var row_id = val;
if ( row_id < max_row_id ) {
$.each( $('input[name="item_meta[' + _repeater_section + '][' + row_id + '][' + _field_id + '][]"]:checked' ), function(){
checked_vals.push( $(this).val() );
});
}
});
return checked_vals;
}
function get_checked_values_this_row( key ) {
/* for the removed row only, loop through the input fields that have the row_ids and push them into an array */
var checked_vals = [];
$.each( $('input[name="item_meta[' + _repeater_section + '][' + key + '][' + _field_id + '][]"]:checked' ), function(){
checked_vals.push( $(this).val() );
});
return checked_vals;
}
function get_new_checked_values( row_ids, include_rows ) {
/* loop through the input fields that have the row_ids and push them into an array */
var checked_vals = [];
$.each( row_ids, function( index, val ){
var row_id = val;
$.each( $('input[name="item_meta[' + _repeater_section + '][' + row_id + '][' + _field_id + '][]"]:checked' ), function(){
if ( include_rows ) {
checked_vals.push( row_id + '-' + $(this).val() );
} else {
checked_vals.push( $(this).val() );
}
});
});
return checked_vals;
}
function get_row_ids( section_id ) {
/* loop through the hidden fields that have the row_ids and push them into an array */
var row_ids = [];
$('input[name^="item_meta[' + section_id + '][row_ids]"]').each(function(index, el) {
row_ids.push( $(this).val() );
});
/* return the rowi_ids array to the calling init function */
return row_ids;
}
function init_new_295_repeater_row( row_id, checked_vals ) {
/* hide the values we don't want */
$.each( $('input[name="item_meta[' + _repeater_section + '][' + row_id + '][' + _field_id + '][]"]'), function() {
if ( $.inArray( $(this).val(), checked_vals ) > -1 ) {
$(this).prop('disabled','true');
$(this).parent('label').hide();
}
});
}
function maybe_disable_repeater( min_row_id, max_row_id ) {
var total_checkboxes = $('input[name="item_meta[' + _repeater_section + '][' + min_row_id + '][' + _field_id + '][]"]').length,
total_checked = $("[type='checkbox']:checked").length,
parent_id = '#frm_section_' + _repeater_section + '-' + max_row_id;
if ( total_checked == total_checkboxes ) {
$(parent_id).children().children('a.frm_add_form_row').hide();
/* if you want to hide the remove row button, uncomment this code block
$('a.frm_remove_form_row').each( function() {
$(this).hide();
});
*/
} else {
$(parent_id).children().children('a.frm_add_form_row').show();
/* if you want to show a hidden remove row button, uncomment this code block
$('a.frm_remove_form_row').each( function() {
$(this).show();
});
*/
}
}
function reinit_295_repeater_row( row_ids, checked_vals, checked_vals_with_rows, this_row, targetval, inputname ) {
/* if nothing is checked, there's no reason to hide nything.
* make sure all checkboxes are visible in all rows.
*/
if ( checked_vals.length == 0 ) {
clear_all_checkboxes( row_ids );
return;
}
/* first, loop through the row ids */
$.each( row_ids, function( index, val ){
var row_id = val;
/* next, for each row, loop through the checkbox inputs */
$.each( $('input[name="item_meta[' + _repeater_section + '][' + row_id + '][' + _field_id + '][]"]'), function() {
var input_id = 'input#' + $(this).prop('id'),
input_value = $(this).val(),
input_checked = $(this).prop('checked'),
input_hidden = $(this).is(':hidden'),
input_name = $(this).prop('name'),
input_value_with_row = row_id + '-' + input_value;
/* satisfies condition 1. if current value is checked in this row, do nothing */
if ( input_checked && $.inArray( input_value_with_row, checked_vals_with_rows ) > -1 ) {
return;
}
/* satisfies condition 2. if current value is checked in previous row, hide value in this row */
/* satisfies condition 3. if current value is checked in future row, hide value in this row */
if ( $.inArray( input_value, checked_vals ) > -1 && $.inArray( input_value_with_row, checked_vals_with_rows ) == -1 ) {
$(input_id).prop('disabled','true');
$(input_id).parent('label').hide();
}
/* satisfies condition 4. if current value is unchecked in this row, is it hidden because it was checked in another row? If so, is it now unchecked in the other row, then show it. */
if ( !input_checked && input_hidden && row_id !== this_row && $.inArray( input_value, checked_vals ) == -1 ) {
$(input_id).prop('disabled','false');
$(input_id).parent('label').show();
}
});
});
}
/* These our the init functions */
function add_row_init( repeater_section ) {
/* construct the callback function name */
var fnName = "add_repeater_row_" + repeater_section + "_init";
/* invoke the appropriate callback function, don't use eval here */
callbacks[fnName]();
}
function remove_row_init( repeater_section ) {
/* construct the callback function name */
var fnName = "remove_repeater_row_" + repeater_section + "_init";
/* invoke the appropriate callback function, don't use eval here */
callbacks[fnName]();
}
function repeater_row_init( repeater_section ) {
/* construct the callback function name */
var fnName = "repeater_section_" + repeater_section + "_init";
/* invoke the appropriate callback function, don't use eval here */
callbacks[fnName]();
}
function is_safari() {
return navigator.userAgent.indexOf('Safari') > -1 ? true : false;
}
/* initialize the repeater for the initial load */
repeater_row_init( _repeater_section );
add_row_init( _repeater_section );
remove_row_init( _repeater_section );
/* initialize the repeater for every added row */
$( document ).ajaxComplete( function( event, xhr, settings ) {
var complete_event = jQuery.makeArray(event);
/* when testing this code, we discovered that Safari has an incomplete jQuery implementation
* Safari's jQuery does not populate the ['dataset'] object. Every other browser populates this object, even Microsoft Edge.
* Safari did work once. It's unknown when the Apple developers broke jQuery.
*/
var active_elem = (is_safari) ? _safari_workaround : complete_event[0]['target']['activeElement']['dataset']['parent'];
if ( active_elem == _repeater_section ) {
repeater_row_init( _repeater_section );
add_row_init( _repeater_section );
remove_row_init( _repeater_section );
/* reset this variable so it only has a value when the add row button is clicked
* this will prevent unexpected results for other Ajax complete events */
_safari_workaround = "";
}
});
});
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment