Skip to content

Commit

Permalink
Address some buggy display-if cases
Browse files Browse the repository at this point in the history
- Allow numeric values to be used as the display-if 'value'
- Allow checkboxes to be used as display-if triggers
- Allow autocompletes to be used as display-if triggers
- Improve some cases of handling field visibility on load
  • Loading branch information
dlh01 committed Feb 20, 2016
1 parent 6b51fa1 commit b9be6d7
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 17 deletions.
11 changes: 9 additions & 2 deletions js/fieldmanager-autocomplete.js
Expand Up @@ -34,7 +34,7 @@ fm.autocomplete = {
custom_data = custom_result;
}
}

$.post( ajaxurl, {
action: $el.data( 'action' ),
fm_context: $el.data( 'context' ),
Expand All @@ -57,7 +57,14 @@ fm.autocomplete = {
$hidden.val( '' );
$el.val( '' );
}
}
};

// Handle the user deleting the input text, which is not an AC 'change'.
$( this ).on( 'keyup', function( e ) {
if ( e.target && '' === $( e.target ).val() ) {
$hidden.val( '' ).trigger( 'change' );
}
});
} else {
$( this ).on( 'keyup', function( e ) {
if ( e.keyCode == 27 || e.keyCode == 13 ) {
Expand Down
69 changes: 59 additions & 10 deletions js/fieldmanager.js
Expand Up @@ -107,6 +107,25 @@ var fm_renumber = function( $wrappers ) {
} );
}

/**
* Get data attribute display-value(s).
*
* Accounts for jQuery converting string to number automatically.
*
* @param HTMLDivElement el Wrapper with the data attribute.
* @return string|number|array Single string or number, or array if data attr contains CSV.
*/
var getCompareValues = function( el ) {
var values = $( el ).data( 'display-value' );
try {
values = values.split( ',' );
} catch( e ) {
// If jQuery already converted string to number.
values = [ values ];
}
return values;
};

var match_value = function( values, match_string ) {
for ( var index in values ) {
if ( values[index] == match_string ) {
Expand Down Expand Up @@ -173,27 +192,57 @@ $( document ).ready( function () {

// Initializes triggers to conditionally hide or show fields
$( '.display-if' ).each( function() {
var val;
var src = $( this ).data( 'display-src' );
var values = $( this ).data( 'display-value' ).split( ',' );
var trigger = $( this ).siblings( '.fm-' + src + '-wrapper' ).find( '.fm-element' );
var val = trigger.val();
if ( trigger.is( ':radio' ) && trigger.filter( ':checked' ).length ) {
val = trigger.filter( ':checked' ).val();
var values = getCompareValues( this );
// Wrapper divs sometimes receive .fm-element, but don't use them as
// triggers. Also don't use autocomplete inputs as triggers, because the
// value is in their sibling hidden fields (which this still matches).
var trigger = $( this ).siblings( '.fm-' + src + '-wrapper' ).find( '.fm-element' ).not( 'div, .fm-autocomplete' );
if ( trigger.is( ':checkbox' ) ) {
if ( trigger.is( ':checked' ) ) {
// If checked, use the checkbox value.
val = trigger.val();
} else {
// Otherwise, use the hidden sibling field with the "unchecked" value.
val = trigger.siblings( 'input[type=hidden][name="' + trigger.attr( 'name' ) + '"]' ).val();
}
} else if ( trigger.is( ':radio' ) ) {
if ( trigger.filter( ':checked' ).length ) {
val = trigger.filter( ':checked' ).val();
} else {
// On load, there might not be any selected radio, in which case call the value blank.
val = '';
}
} else {
val = trigger.val().split( ',' );
}
trigger.addClass( 'display-trigger' );
if ( !match_value( values, val ) ) {
if ( ! match_value( values, val ) ) {
$( this ).hide();
}
} );

// Controls the trigger to show or hide fields
$( document ).on( 'change', '.display-trigger', function() {
var val = $( this ).val().split(',');
var name = $( this ).attr('name');
var val;
var $this = $( this );
var name = $this.attr( 'name' );
if ( $this.is( ':checkbox' ) ) {
if ( $this.is( ':checked' ) ) {
val = $this.val();
} else {
val = $this.siblings( 'input[type=hidden][name="' + name + '"]' ).val();
}
} else if ( $this.is( ':radio' ) ) {
val = $this.filter( ':checked' ).val();
} else {
val = $this.val().split( ',' );
}
$( this ).closest( '.fm-wrapper' ).siblings().each( function() {
if ( $( this ).hasClass( 'display-if' ) ) {
if( name.match( $( this ).data( 'display-src' ) ) != null ) {
if ( match_value( $( this ).data( 'display-value' ).split( ',' ), val ) ) {
if ( name && name.match( $( this ).data( 'display-src' ) ) != null ) {
if ( match_value( getCompareValues( this ), val ) ) {
$( this ).show();
} else {
$( this ).hide();
Expand Down
35 changes: 33 additions & 2 deletions tests/js/index.html
Expand Up @@ -88,7 +88,6 @@
<div class="display-always">display</div>
</div><!-- #displayif-blanks -->

<!-- Doesn't work: The data attribute is treated as a number, not a string
<div id="displayif-numbers">
<div class="fm-test-displayif-wrapper">
<input class="fm-element" value="789" />
Expand All @@ -97,7 +96,39 @@
<div id="di-456" class="display-if" data-display-src="test-displayif" data-display-value="456">456</div>
<div id="di-789" class="display-if" data-display-src="test-displayif" data-display-value="789">789</div>
</div>
-->

<div id="displayif-boolean-checkbox">
<div class="fm-wrapper fm-test-boolean-checkbox-wrapper">
<div class="fm-item fm-test-boolean-checkbox fm-element">
<input type="hidden" name="test-boolean-checkbox" value="">
<input class="fm-element display-trigger" type="checkbox" name="test-boolean-checkbox" value="1">
</div>
</div>
<div id="di-when-boolean-checkbox-true" class="display-if" data-display-src="test-boolean-checkbox" data-display-value="1">Display when checked</div>
<div id="di-when-boolean-checkbox-false" class="display-if" data-display-src="test-boolean-checkbox" data-display-value="0">Display when unchecked</div>
</div>

<div id="displayif-string-checkbox">
<div class="fm-wrapper fm-test-string-checkbox-wrapper">
<div class="fm-item fm-test-string-checkbox fm-element">
<input type="hidden" name="test-string-checkbox" value="wrong">
<input class="fm-element display-trigger" type="checkbox" name="test-string-checkbox" value="right">
</div>
</div>
<div id="di-when-string-checkbox-wrong" class="display-if" data-display-src="test-string-checkbox" data-display-value="wrong">Display when "wrong"</div>
<div id="di-when-string-checkbox-right" class="display-if" data-display-src="test-string-checkbox" data-display-value="right">Display when "right"</div>
</div>

<div id="displayif-radio">
<div class="fm-wrapper fm-test-displayif-radio-wrapper">
<div class="fm-item fm-test-displayif-radio">
<div class="fm-option"><input class="fm-element display-trigger" type="radio" value="a" name="test-displayif-radio"></div>
<div class="fm-option"><input class="fm-element display-trigger" type="radio" value="b" name="test-displayif-radio"></div>
<div class="fm-option"><input class="fm-element display-trigger" type="radio" value="c" name="test-displayif-radio"></div>
</div>
</div>
<div id="di-when-displayif-radio-b" class="display-if" data-display-src="test-displayif-radio" data-display-value="b">Display when radio is "b"</div>
</div>

<div id="renumbered" class="fm-wrapper" data-fm-array-position="1">
<div class="fm-item">
Expand Down
31 changes: 28 additions & 3 deletions tests/js/test-fieldmanager.js
Expand Up @@ -60,9 +60,34 @@
assert.ok( $( this ).is( ':visible' ), 'non display-if field is visible after changes (parent #' + $( this ).parent().attr( 'id' ) + ')' );
});

// assert.ok( $( '#di-789' ).is( ':visible' ), "show display-if value of '789'" );
// assert.ok( $( '#di-123' ).not( ':visible' ), "hide display-if value of '123'" );
// assert.ok( $( '#di-456' ).is( ':visible' ), "hide display-if value of '456'" );
assert.ok( $( '#di-789' ).is( ':visible' ), "show display-if value of '789'" );
assert.ok( $( '#di-123' ).not( ':visible' ), "hide display-if value of '123'" );
assert.ok( $( '#di-456' ).not( ':visible' ), "hide display-if value of '456'" );

// The boolean and "wrong"/"right" checkboxs are unchecked by default.
assert.notOk( $( '#di-when-boolean-checkbox-true:visible' ).length );
assert.ok( $( '#di-when-boolean-checkbox-false:visible' ).length );
assert.notOk( $( '#di-when-string-checkbox-right:visible' ).length );
assert.ok( $( '#di-when-string-checkbox-wrong:visible' ).length );

// Now, check the boxes.
$( '.fm-test-boolean-checkbox-wrapper' ).find( 'input[type=checkbox]' ).attr( 'checked', 'checked' ).trigger( 'change' );
assert.ok( $( '#di-when-boolean-checkbox-true:visible' ).length );
assert.notOk( $( '#di-when-boolean-checkbox-false:visible' ).length );
$( '.fm-test-string-checkbox-wrapper' ).find( 'input[type=checkbox]' ).attr( 'checked', 'checked' ).trigger( 'change' );
assert.ok( $( '#di-when-string-checkbox-right:visible' ).length );
assert.notOk( $( '#di-when-string-checkbox-wrong:visible' ).length );

// No radio is selected by default.
assert.notOk( $( '#di-when-displayif-radio-b:visible' ).length );

// Select the radio button.
$( '.fm-test-displayif-radio' ).find( 'input[value=b]' ).prop( 'checked', true ).trigger( 'change' );
assert.ok( $( '#di-when-displayif-radio-b:visible' ).length );

// Select a different radio.
$( '.fm-test-displayif-radio' ).find( 'input[value=c]' ).prop( 'checked', true ).trigger( 'change' );
assert.notOk( $( '#di-when-displayif-radio-b:visible' ).length );
});

QUnit.test( 'Renumber', function( assert ) {
Expand Down

0 comments on commit b9be6d7

Please sign in to comment.