Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 56 additions & 29 deletions assets/src/js/_acf-field-button-group.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,35 +21,46 @@ import { update } from '@wordpress/icons';
},

setValue: function ( val ) {
this.$( 'input[value="' + val + '"]' )
.prop( 'checked', true )
.trigger( 'change' );
const input = this.$el[ 0 ].querySelector(
'input[value="' + val + '"]'
);
if ( input ) {
input.checked = true;
input.dispatchEvent( new Event( 'change', { bubbles: true } ) );
}
this.updateButtonStates();
},

updateButtonStates: function () {
const labels = this.$control().find( 'label' );
const input = this.$input();
labels
.removeClass( 'selected' )
.attr( 'aria-checked', 'false' )
.attr( 'tabindex', '-1' );
if ( input.length ) {
const control = this.$control()[ 0 ];
if ( ! control ) {
return;
}
const labels = control.querySelectorAll( 'label' );
const input = this.$input()[ 0 ];
labels.forEach( ( label ) => {
label.classList.remove( 'selected' );
label.setAttribute( 'aria-checked', 'false' );
label.setAttribute( 'tabindex', '-1' );
} );
if ( input ) {
// If there's a checked input, mark its parent label as selected
input
.parent( 'label' )
.addClass( 'selected' )
.attr( 'aria-checked', 'true' )
.attr( 'tabindex', '0' );
} else {
labels.first().attr( 'tabindex', '0' );
const inputLabel = input.closest( 'label' );
if ( inputLabel ) {
inputLabel.classList.add( 'selected' );
inputLabel.setAttribute( 'aria-checked', 'true' );
inputLabel.setAttribute( 'tabindex', '0' );
}
} else if ( labels.length ) {
labels[ 0 ].setAttribute( 'tabindex', '0' );
}
},
onClick: function ( e, $el ) {
this.selectButton( $el.parent( 'label' ) );
this.selectButton( $el[ 0 ].closest( 'label' ) );
},
onKeyDown: function ( event, label ) {
onKeyDown: function ( event, $label ) {
const key = event.which;
const label = $label[ 0 ];

// Space or Enter: select the button
if ( key === 13 || key === 32 ) {
Expand All @@ -61,8 +72,10 @@ import { update } from '@wordpress/icons';
// Arrow keys: move focus between buttons
if ( key === 37 || key === 39 || key === 38 || key === 40 ) {
event.preventDefault();
const labels = this.$control().find( 'label' );
const currentIndex = labels.index( label );
const labels = Array.from(
this.$control()[ 0 ].querySelectorAll( 'label' )
);
const currentIndex = labels.indexOf( label );
let nextIndex;

// Left/Up arrow: move to previous, wrap to last if at start
Expand All @@ -76,18 +89,32 @@ import { update } from '@wordpress/icons';
currentIndex < labels.length - 1 ? currentIndex + 1 : 0;
}

const nextLabel = labels.eq( nextIndex );
labels.attr( 'tabindex', '-1' );
nextLabel.attr( 'tabindex', '0' ).trigger( 'focus' );
const nextLabel = labels[ nextIndex ];
labels.forEach( ( item ) => {
item.setAttribute( 'tabindex', '-1' );
} );
nextLabel.setAttribute( 'tabindex', '0' );
nextLabel.focus();
}
},

selectButton: function ( element ) {
const inputRadio = element.find( 'input[type="radio"]' );
const isSelected = element.hasClass( 'selected' );
inputRadio.prop( 'checked', true ).trigger( 'change' );
if ( this.get( 'allow_null' ) && isSelected ) {
inputRadio.prop( 'checked', false ).trigger( 'change' );
const inputRadio = element
? element.querySelector( 'input[type="radio"]' )
: null;
const isSelected =
element && element.classList.contains( 'selected' );
if ( inputRadio ) {
inputRadio.checked = true;
inputRadio.dispatchEvent(
new Event( 'change', { bubbles: true } )
);
if ( this.get( 'allow_null' ) && isSelected ) {
inputRadio.checked = false;
inputRadio.dispatchEvent(
new Event( 'change', { bubbles: true } )
);
}
}
this.updateButtonStates();
},
Expand Down
115 changes: 69 additions & 46 deletions assets/src/js/_acf-field-checkbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,56 +33,65 @@
val = val ? [ val ] : [];
}

this.$inputs().each( function () {
const $input = $( this );
const checked = val.includes( $input.val() );
$input.prop( 'checked', checked );
const inputs = Array.from( this.$inputs() );
inputs.forEach( function ( input ) {
const checked = val.includes( input.value );
input.checked = checked;

const label = input.closest( 'label' );
if ( ! label ) {
return;
}

if ( checked ) {
$input.parent( 'label' ).addClass( 'selected' );
label.classList.add( 'selected' );
} else {
$input.parent( 'label' ).removeClass( 'selected' );
label.classList.remove( 'selected' );
}
} );

const $toggle = this.$toggle();
if ( $toggle.length ) {
const checked = this.$inputs().not( ':checked' ).length === 0;
$toggle.prop( 'checked', checked );
const toggle = this.$toggle()[ 0 ];
if ( toggle ) {
toggle.checked = inputs.every( function ( input ) {
return input.checked;
} );
}
},

getValue: function () {
var val = [];
this.$( ':checked' ).each( function () {
val.push( $( this ).val() );
} );
this.$el[ 0 ]
.querySelectorAll( ':checked' )
.forEach( function ( input ) {
val.push( input.value );
} );
return val.length ? val : false;
},

onChange: function ( e, $el ) {
// Vars.
var checked = $el.prop( 'checked' );
var $label = $el.parent( 'label' );
var $toggle = this.$toggle();
var input = $el[ 0 ];
var checked = input.checked;
var label = input.closest( 'label' );
var toggle = this.$toggle()[ 0 ];

// Add or remove "selected" class.
if ( checked ) {
$label.addClass( 'selected' );
} else {
$label.removeClass( 'selected' );
if ( label ) {
if ( checked ) {
label.classList.add( 'selected' );
} else {
label.classList.remove( 'selected' );
}
}

// Update toggle state if all inputs are checked.
if ( $toggle.length ) {
var $inputs = this.$inputs();
if ( toggle ) {
var inputs = Array.from( this.$inputs() );

// all checked
if ( $inputs.not( ':checked' ).length == 0 ) {
$toggle.prop( 'checked', true );
} else {
$toggle.prop( 'checked', false );
}
toggle.checked = inputs.every( function ( item ) {
return item.checked;
} );
}
},

Expand All @@ -91,35 +100,49 @@
'<li><input class="acf-checkbox-custom" type="checkbox" checked="checked" /><input type="text" name="' +
this.getInputName() +
'[]" /></li>';
$el.parent( 'li' ).before( html );
$el.parent( 'li' )
.parent()
.find( 'input[type="text"]' )
.last()
.trigger( 'focus' );
var li = $el[ 0 ].closest( 'li' );
li.insertAdjacentHTML( 'beforebegin', html );
var texts =
li.parentElement.querySelectorAll( 'input[type="text"]' );
if ( texts.length ) {
texts[ texts.length - 1 ].focus();
}
},

onClickToggle: function ( e, $el ) {
var $inputs = this.$inputs();
var checked = $el.prop( 'checked' );
$inputs.prop( 'checked', checked ).trigger( 'change' );
var inputs = Array.from( this.$inputs() );
var checked = $el[ 0 ].checked;

// Set all states first so listeners never observe a partial state.
inputs.forEach( function ( input ) {
input.checked = checked;
} );
inputs.forEach( function ( input ) {
input.dispatchEvent( new Event( 'change', { bubbles: true } ) );
} );
},

onClickCustom: function ( e, $el ) {
var checked = $el.prop( 'checked' );
var $text = $el.next( 'input[type="text"]' );
var input = $el[ 0 ];
var checked = input.checked;
var text = input.nextElementSibling;

// bail early if no adjacent text input
if ( ! text || ! text.matches( 'input[type="text"]' ) ) {
return;
}

// checked
if ( checked ) {
$text.prop( 'disabled', false );
text.disabled = false;

// not checked
} else {
$text.prop( 'disabled', true );
text.disabled = true;

// remove
if ( $text.val() == '' ) {
$el.parent( 'li' ).remove();
if ( text.value == '' ) {
input.closest( 'li' ).remove();
}
}
},
Expand All @@ -130,12 +153,12 @@
e.preventDefault();

// Toggle the checkbox state and trigger change event
$el.prop( 'checked', ! $el.prop( 'checked' ) ).trigger(
'change'
);
var input = $el[ 0 ];
input.checked = ! input.checked;
input.dispatchEvent( new Event( 'change', { bubbles: true } ) );

// If this is the "Select All" toggle checkbox, run the toggle logic
if ( $el.is( '.acf-checkbox-toggle' ) ) {
if ( input.classList.contains( 'acf-checkbox-toggle' ) ) {
this.onClickToggle( e, $el );
}
}
Expand Down
41 changes: 23 additions & 18 deletions assets/src/js/_acf-field-link.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,18 @@

getValue: function () {
// vars
var $node = this.$node();
var node = this.$node()[ 0 ];

// return false if empty
if ( ! $node.attr( 'href' ) ) {
if ( ! node || ! node.getAttribute( 'href' ) ) {
return false;
}

// return
return {
title: $node.html(),
url: $node.attr( 'href' ),
target: $node.attr( 'target' ),
title: node.innerHTML,
url: node.getAttribute( 'href' ),
target: node.getAttribute( 'target' ) || '',
};
},

Expand All @@ -43,29 +43,34 @@
} );

// vars
var $div = this.$control();
var $node = this.$node();
var el = this.$el[ 0 ];
var div = this.$control()[ 0 ];
var node = this.$node()[ 0 ];

// remove class
$div.removeClass( '-value -external' );
div.classList.remove( '-value', '-external' );

// add class
if ( val.url ) $div.addClass( '-value' );
if ( val.target === '_blank' ) $div.addClass( '-external' );
if ( val.url ) div.classList.add( '-value' );
if ( val.target === '_blank' ) div.classList.add( '-external' );

// update text
this.$( '.link-title' ).html( val.title );
this.$( '.link-url' ).attr( 'href', val.url ).text( val.url );
el.querySelector( '.link-title' ).innerHTML = val.title;
var linkUrl = el.querySelector( '.link-url' );
linkUrl.setAttribute( 'href', val.url );
linkUrl.textContent = val.url;

// update node
$node.html( val.title );
$node.attr( 'href', val.url );
$node.attr( 'target', val.target );
node.innerHTML = val.title;
node.setAttribute( 'href', val.url );
node.setAttribute( 'target', val.target );

// update inputs
this.$( '.input-title' ).val( val.title );
this.$( '.input-target' ).val( val.target );
this.$( '.input-url' ).val( val.url ).trigger( 'change' );
el.querySelector( '.input-title' ).value = val.title;
el.querySelector( '.input-target' ).value = val.target;
var inputUrl = el.querySelector( '.input-url' );
inputUrl.value = val.url;
inputUrl.dispatchEvent( new Event( 'change', { bubbles: true } ) );
},

onClickEdit: function ( e, $el ) {
Expand Down
Loading