Skip to content

Commit

Permalink
Implement form reset after comment submission via amp-bind and amp-state
Browse files Browse the repository at this point in the history
  • Loading branch information
westonruter committed Jan 30, 2018
1 parent 5ee1709 commit 9e7e6ea
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 33 deletions.
8 changes: 2 additions & 6 deletions includes/class-amp-theme-support.php
Original file line number Diff line number Diff line change
Expand Up @@ -191,10 +191,7 @@ public static function register_hooks() {
add_action( 'template_redirect', array( __CLASS__, 'start_output_buffering' ), 0 );

add_filter( 'wp_list_comments_args', array( __CLASS__, 'amp_set_comments_walker' ), PHP_INT_MAX );
// Wrap fields in a hidable div. Closed in `contact_form` action.
add_action( 'comment_form_top', function() {
echo '<div id="amp-live-comments-list-' . get_queried_object_id() . '-fields">'; // WPCS: XSS OK.
}, PHP_INT_MAX );

add_action( 'comment_form', array( __CLASS__, 'add_amp_comment_form_templates' ), PHP_INT_MAX );

// @todo Add character conversion.
Expand Down Expand Up @@ -389,9 +386,8 @@ public static function amp_set_comments_walker( $args ) {
* Adds the form submit success and fail templates.
*/
public static function add_amp_comment_form_templates() {
// The close div closes the field wrapper opened in `comment_form_top` action.
// @todo Add validation messages.
?>
</div>
<div submit-success>
<template type="amp-mustache">
<?php esc_html_e( 'Your comment has been posted, but may be subject to moderation.', 'amp' ); ?>
Expand Down
107 changes: 80 additions & 27 deletions includes/sanitizers/class-amp-comments-sanitizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,43 +12,96 @@
*/
class AMP_Comments_Sanitizer extends AMP_Base_Sanitizer {

/**
* Tag.
*
* @var string HTML <form> tag to identify and process.
*
* @since 0.7
*/
public static $tag = 'amp-live-list';

/**
* Sanitize the comments list from the HTML contained in this instance's DOMDocument.
*
* @since 0.7
*/
public function sanitize() {

/**
* Node list.
*
* @var DOMNodeList $node
*/
$nodes = $this->dom->getElementsByTagName( self::$tag );
$num_nodes = $nodes->length;
// @todo Core patch on comment_form() should allow additional attributes to be supplied as an $attr arg. This would eliminat ethe need for the following.
foreach ( $this->dom->getElementsByTagName( 'form' ) as $comment_form ) {
/**
* Comment form.
*
* @var DOMElement $comment_form
*/
$action = $comment_form->getAttribute( 'action-xhr' );
if ( ! $action ) {
$action = $comment_form->getAttribute( 'action' );
}
$action_path = wp_parse_url( $action, PHP_URL_PATH );
if ( ! preg_match( '#/wp-comments-post\.php$#', $action_path ) ) {
continue;
}

if ( 0 === $num_nodes ) {
return;
}
$amp_state = $this->dom->createElement( 'amp-state' );
$state_id = sanitize_key( $comment_form->getAttribute( 'id' ) ) . 'Values';
$amp_state->setAttribute( 'id', $state_id );

$node = $nodes->item( 0 );
if ( ! $node instanceof DOMElement ) {
return;
}
$script = $this->dom->createElement( 'script' );
$script->setAttribute( 'type', 'application/json' );
$amp_state->appendChild( $script );

$form_state = array();

foreach ( $comment_form->getElementsByTagName( 'input' ) as $input ) {
/**
* Input.
*
* @var DOMElement $input
*/
$name = $input->getAttribute( 'name' );
if ( ! $name ) {
continue;
}

// @todoRadio and checkbox inputs are not supported yet.
$type = strtolower( $input->getAttribute( 'type' ) );
if ( 'radio' === $type || 'checkbox' === $type ) {
continue;
}

$form_state[ $name ] = $input->getAttribute( 'value' );
if ( ! isset( $form_state[ $name ] ) ) {
$form_state[ $name ] = '';
}

$input->setAttribute( AMP_DOM_Utils::get_amp_bind_placeholder_prefix() . 'value', "$state_id.$name" );
}
foreach ( $comment_form->getElementsByTagName( 'textarea' ) as $textarea ) {
/**
* Textarea.
*
* @var DOMElement $textarea
*/
$name = $textarea->getAttribute( 'name' );
if ( ! $name ) {
continue;
}
$form_state[ $name ] = $textarea->textContent;

$textarea->setAttribute( AMP_DOM_Utils::get_amp_bind_placeholder_prefix() . 'text', "$state_id.$name" );

// Update the state in response to changing the input.
$textarea->setAttribute( 'on', sprintf(
'change:AMP.setState({ %s: { %s: event.value } })',
$state_id,
wp_json_encode( $name )
) );
}

$script->appendChild( $this->dom->createTextNode( wp_json_encode( $form_state ) ) );
$comment_form->insertBefore( $amp_state, $comment_form->firstChild );

$form = $this->dom->getElementById( 'commentform' );
if ( $form instanceof DOMElement ) {
$list_id = $node->getAttribute( 'id' ) . '-fields';
$form->setAttribute( 'on', 'submit-success:' . $list_id . '.hide' );
// Reset the form when successful.
$reset_state = $form_state;
unset( $reset_state['author'], $reset_state['email'], $reset_state['url'] ); // These remain the same after a submission.
$comment_form->setAttribute( 'on', sprintf(
'submit-success:AMP.setState( { %s: %s } )',
wp_json_encode( $state_id ),
wp_json_encode( $reset_state )
) );
}
}
}

0 comments on commit 9e7e6ea

Please sign in to comment.