Simple Comment Editing for WordPress 3.5+
Simple Comment Editing is a stripped down version of Ajax Edit Comments.
The biggest differences:
- Only anonymous users (and logged in users who don't have permission to edit comments) can edit their comments for a period of time (the default is 5 minutes).
- There are no styles included with this plugin. For most themes, the appearance is acceptable. For advanced customization, see the "Styles" section.
- Settings control the editing timer, labels, deletion behavior, and optional Quicktags toolbar. Some defaults can also be overwritten using filters.
- Just unzip and upload the "simple-comment-editor" folder to your '/wp-content/plugins/' directory
- Activate the plugin through the 'Plugins' menu in WordPress
PHPUnit integration tests target PHP 7.4+ and run against real WordPress users, comments, AJAX handlers, and a disposable database. See tests/README.md for setup, commands, the compatibility matrix, and coverage instructions.
Bundled translations provide the default frontend labels and countdown text when no WordPress.org language pack is installed, including German and German Formal. WordPress.org and Loco translations can still override the bundled defaults. Labels customized in Settings are saved site values, so they are not translated automatically; update those saved values directly when changing site languages.
Plain-text textarea editing remains the default. To add WordPress's native HTML toolbar, enable Quicktags Toolbar in Settings → Simple Comment Editing. The option loads WordPress's Quicktags assets only on pages where SCE loads and creates one editor per open comment. It does not add TinyMCE, CKEditor, or any third-party editor dependency.
External editors can use the textarea lifecycle instead. Leave Quicktags
disabled for that textarea, then register actions with an application-specific
wp.hooks namespace. Each action receives one object with textarea,
commentId, and postId; reset also receives the previously saved content.
const namespace = 'my-plugin/comment-editor';
const editors = new Map();
wp.hooks.addAction( 'sce.comment.editor.show', namespace, ( { textarea, commentId } ) => {
editors.set( commentId, mountMyEditor( textarea, textarea.value ) );
} );
wp.hooks.addAction( 'sce.comment.editor.save.pre', namespace, ( { textarea, commentId } ) => {
textarea.value = editors.get( commentId ).getContent();
} );
wp.hooks.addAction( 'sce.comment.editor.reset', namespace, ( { content, commentId } ) => {
editors.get( commentId ).setContent( content );
} );
wp.hooks.addAction( 'sce.comment.editor.destroy', namespace, ( { commentId } ) => {
editors.get( commentId ).destroy();
editors.delete( commentId );
} );sce.comment.editor.save.pre runs before SCE reads the textarea, so an adapter
must synchronously copy its editor value there. The same lifecycle is also
emitted as document events: sceEditTextareaShow, sceCommentSavePre,
sceCommentEditorReset, sceCommentEditorDestroy, and
sceCommentQuicktagsInit. The existing sceCommentSavePost event remains
available after a successful save.
SCE initializes on DOM readiness, including when its script executes after the page has loaded. A DOM observer initializes newly inserted SCE controls. Custom loaders can also call the public, root-scoped initializer after attaching their markup:
// insertedComment is the connected comment element, not an HTML string.
window.SCE.init( insertedComment );
// Omitting the root initializes the current document.
window.SCE.init();Repeated calls reuse the same handlers and countdown, including while the time
request is pending. Replacing a comment cancels the old countdown and releases
its editor; stale responses cannot initialize the replacement. A failed time
request can be retried by calling the initializer again. Existing
window.initEditCommentButton( button ), window.SCE_comments_updated( commentUrl ),
and the wpacAfterUpdateComments document event remain available.
The initializer does not create edit markup or grant permission. The submitter
or lazy loader must render through WordPress's native comment_text() path and
return the current visitor's response, not shared cached author markup. Timer,
save, and delete requests still require the existing nonce and ownership checks.
Ordinary WordPress submissions establish the editing cookie while the comment
is created. AJAX submitters using admin-ajax.php must explicitly opt in during
their existing validated creation flow. The following fragment belongs in
that handler, after its nonce, anti-spam, rate-limit, and submission checks and
before any response output:
// Opt in only around this handler's real WordPress comment creation.
add_filter( 'sce_ajax_comment_submission', '__return_true' );
try {
$comment = wp_handle_comment_submission( wp_unslash( $_POST ) );
} finally {
remove_filter( 'sce_ajax_comment_submission', '__return_true' );
}
// Continue the submitter's existing WP_Error/success response handling.
// On success, render the new comment using comment_text(), not raw content.This is not a new endpoint or a complete submission handler. The filter is
evaluated by SCE's comment_post callback for a newly created comment only.
Never call comment_posted() or generate_cookie_data() with a client-supplied
comment ID, and never bypass sce_can_edit or cookie verification. The original
response sets the guest's cookie and can render their permission-checked
controls immediately. Repeated creation callbacks preserve the original key.
The browser must accept that same-origin response's cookies; another browser
does not acquire ownership from knowing the comment ID or copying its markup.
Logged-in comment authors continue to use WordPress authentication.
- WP Ajaxify Comments: the existing event and URL callback are retained and use the repeat-safe initializer. Its normal WordPress submission route does not require an arbitrary-comment cookie endpoint.
- Lazy Load for Comments: inserted markup is covered by the DOM observer;
there is no dependency on a private lazy-loader event. Rendering must still
use
comment_text()and send the commenter's cookies. This describes the integration contract, not an end-to-end verification claim for every version. - BuddyBoss: premium-theme integration is unverified. In its documented
post-insertion callback, call
window.SCE.init( insertedComment )only after its comment element is connected. Its server adapter must follow the validated submission/ownership route above and render native comment text. The initializer alone cannot add SCE to a separate comment renderer.
Browser-verified on WordPress 7.1.3 multisite, PHP 8.4.25, Twenty Twenty-Five
1.4, and Chromium 147: Ajaxify Comments 3.2.2 supports guest/subscriber submission
and immediate saving without a page reload; Lazy Load for Comments 2.1.0
supports guest-owner controls and saving after REST-loaded insertion. Cancel
restores the saved text. Separate non-owner browsers receive no controls and
cannot save or delete another guest's comment. Replacing controls and repeating
the initializer/callbacks produces one time request and one countdown.
For Twenty Twenty-Five, configure Ajaxify's comments-container selector as
.wp-block-comments; its default also matches the #comments heading and
falls back to reloading. These checks do not verify BuddyBoss or a custom
admin-ajax.php submission adapter.
For release verification, test the actual AJAX and lazy-loading plugins with separate commenter and non-owner browsers. Confirm one time request/countdown, one save per click, successful immediate editing, denied non-owner requests, and no browser-console or WordPress-log errors. Source-compatible callbacks alone are not evidence of a verified plugin-version combination.
SCE preloads assets on singular views with open comments or existing comments, so a first-time guest can use controls inserted after page load. Logged-in visitors, editing cookies, and WP Ajaxify remain loading signals. Archives and unrelated guest views with neither comments nor a form do not load these assets. In Settings → Simple Comment Editing, two opt-in policies can reduce that surface; both policies remain disabled by default:
- Load frontend assets on WordPress posts only loads SCE on the built-in
posttype only. It excludes ordinary pages, WooCommerce products, and all custom post types. - Load frontend assets only when comments are available omits SCE when the current singular content has no open comment form, existing comments, or known editable-comment session. It keeps assets for closed content with an existing editable comment, logged-in commenters with a pending comment, and supported Ajaxify Comments lazy-loading flows.
Both policies apply before the documented sce_load_scripts filter. A developer
can therefore return true to load SCE on an otherwise excluded singular view,
or return false to suppress both dist/sce-editing.js and
dist/sce-frontend.css.
SCE loads its frontend assets on singular content when the sce_load_scripts
filter allows them. It initializes existing controls on DOM readiness and newly
inserted controls through its observer or window.SCE.init( root ). A cache, optimization plugin,
proxy, migration, or dynamically replaced comment list can therefore make an
otherwise valid installation appear broken. These checks isolate the observed
failure; they do not establish a historical support report's root cause.
Use a private/incognito window with the browser developer tools open, then leave a new test comment and reload the page. Test as the commenter, not as an administrator, and remove the test comment afterwards.
- No edit markup: inspect the rendered comment for
.sce-edit-commentand.sce-edit-button. If those elements are absent, capture the page URL, the comment status, the visitor's login state, and the timer/settings in effect. A custom comment loop must call WordPress'scomment_text()path; copyingcomment_contentomits SCE's generated controls. - Markup is present but JavaScript is missing or errors: in the Network
and Console panels, confirm that
dist/sce-editing.jsreturns JavaScript (not an HTML error page) and thatwp-i18nandwp-hooksload before it. When Quicktags Toolbar is enabled,wp-editormust also load first. Record the first console error and the response/status for the failed asset. - Controls are hidden or disappear: inspect the timer request and its response before changing settings. SCE intentionally removes controls when the server says the commenter cannot edit or the timer has expired. Do not expose those controls with cached markup or client-side changes: the server must continue to enforce nonce and comment-ownership checks.
- Save or delete fails: inspect the
admin-ajax.phprequest, its status, and its response while preserving the current comment text. Verify that the request uses the current site's HTTP/HTTPS origin and carries the commenter's cookies and nonce. A 403/nonce/auth response is not a reason to disable anti-spam or other security protections. - A server error occurs: obtain the complete exception and stack trace from the server's WordPress/PHP error log, along with WordPress, PHP, theme, SCE, and active cache/optimization-plugin versions. Do not post cookies, nonces, full request bodies, credentials, or private comment content in a public support thread.
If another plugin replaces or lazy-loads comments after the original page load,
the observer initializes inserted SCE controls. Its documented integration point
can also call window.SCE.init( insertedComment ) explicitly; repeated calls are
safe. See the AJAX-submission ownership requirements above when markup is absent.
Purge every relevant layer before each retest: the WordPress/cache-plugin cache, the reverse-proxy or CDN cache, and the browser cache. Then test one change at a time and re-enable it after recording the result. Do not serve a shared cache entry that contains an authenticated or edit-author response to other visitors.
For W3 Total Cache and similar tools, exclude these already-built files from JavaScript minification, combination, defer/delay rewriting, and re-minification while testing:
dist/sce-editing.js
dist/integrations-admin.js
Purge the cache, load a newly created comment as its author, and confirm the asset responses and timer request again. If that restores the controls, add optimizations back one at a time to identify the conflicting transform instead of leaving all optimizations disabled.
For Cloudflare or another proxy, separately test script optimization (including defer/delay or similar script rewriting), cached HTML, the origin's HTTP/HTTPS scheme, and client-IP forwarding. These are plausible integration points, not a known single root cause. Keep the proxy's security and anti-spam controls in place; make the narrowest documented exclusion needed for the affected asset or path, then purge and retest.
Confirm WordPress Address and Site Address use the expected canonical scheme
and host. Compare the page URL and admin-ajax.php request origin, then check
the commenter's cookies for the expected domain, path, and secure flag. Clear
old browser cookies and every cache layer before creating a fresh test comment.
If the controls work intermittently, collect a HAR or the failing request's URL,
status, response headers, and first console error with cookies and request
payloads removed.
For a reproducible report, include the smallest standard-theme reproduction, the exact sequence, the active optimization/proxy settings, versions, and the privacy-safe browser evidence above. Cross-check dynamic comment replacement against the initialization guidance above and AJAX failures against the request/response checks before concluding that SCE itself is at fault.
It's impossible to style an inline comment editor for every theme. We've included basic HTML markup that is easily stylable to fit your theme.
Log in to your Dashboard and open Settings → Simple Comment Editing.
See "Styles" section.
- IE 6-10
- Latest versions of Chrome, Firefox, and Safari
- iOS Safari
- Twenty Ten
- Twenty Eleven
- Twenty Twelve
- Twenty Thirteen
- Genesis
- Genesis Mindstream
WP ULike does not automatically render its frontend comment buttons in SCE's
admin-AJAX Save response. SCE retains the existing automatic .wpulike controls
for the edited comment instead of discarding them with the old text. Their DOM
nodes, vote state and handlers remain intact, including top, bottom and
top-and-bottom placement. Returned copies are removed to avoid duplicates.
Controls for the post or other comments are not moved. No extra permission or
Save requests are introduced, and Cancel does not replace comment content.
/**
* Filter: sce_loading_img
*
* Replace the loading image with a custom version.
*
* @since 1.0.0
*
* @param string $image_url URL path to the loading image.
*/Example:
//Simple Comment Editing
add_filter( 'sce_loading_img', 'edit_sce_loading_img' );
function edit_sce_loading_img( $default_url ) {
return 'http://domain.com/new_loading_image.gif';
}/**
* Filter: sce_comment_check_errors
*
* Return a custom error message based on the saved comment
*
* @since 1.2.4
*
* @param bool $custom_error Default custom error. Overwrite with a string
* @param array $comment_to_save Associative array of comment attributes
*/Here's an example:
add_filter( 'sce_comment_check_errors', 'custom_sce_check_comment_length', 15, 2 );
function custom_sce_check_comment_length( $return = false, $comment = array() ) {
$comment_content = trim( wp_strip_all_tags( $comment[ 'comment_content' ] ) );
$comment_length = strlen( $comment_content );
if ( $comment_length < 50 ) {
return 'Comment must be at least 50 characters';
}
return false;
}/**
* Filter: sce_allow_delete
*
* Determine if users can delete their comments
*
* @since 1.1.0
*
* @param bool $allow_delete True allows deletion, false does not
*/Example:
// Disable delete functionality
add_filter( 'sce_allow_delete', '__return_false' );/**
* Filter: sce_allow_delete_confirmation
*
* Boolean to decide whether to show a delete confirmation
*
* @since 2.1.7
*
* @param bool true to show a confirmation, false if not
*/Example:
add_filter( 'sce_allow_delete_confirmation', '__return_false' );This is only used when retrieving a comment via Ajax and can be used by third-party plugins who post comments using Ajax
/**
* Filter: sce_get_comment
*
* Modify comment object
*
* @since 1.5.0
*
* @param object Comment Object
*//**
* Filter: sce_extra_fields
*
* Filter to add additional form fields
*
* @since 1.4.0
*
* @param string Empty string
* @param int post_id POST ID
* @param int comment_id Comment ID
*/Use sce_extra_fields_pre when a field belongs before the comment textarea;
use sce_extra_fields for fields after it. Both filters receive the post and
comment IDs, and sce_extra_fields_pre also receives the current comment. Give
each field an ID derived from $comment_id, then read it from that comment's
editor in the JavaScript filter. This prevents two open editors from sharing a
field value.
The example below adds an optional title and a 1–5 rating. It uses the current
WordPress hooks signature—wp.hooks.addFilter( name, namespace, callback )—and
only adds values to the request when their fields exist and are non-empty.
add_filter( 'sce_extra_fields_pre', function( $content, $post_id, $comment_id, $comment ) {
$title = (string) get_comment_meta( $comment_id, '_my_sce_title', true );
$rating = absint( get_comment_meta( $comment_id, '_my_sce_rating', true ) );
return sprintf(
'<p><label for="my-sce-title-%1$d">Title</label> <input id="my-sce-title-%1$d" class="my-sce-title" type="text" value="%2$s" maxlength="120" /></p><p><label for="my-sce-rating-%1$d">Rating</label> <input id="my-sce-rating-%1$d" class="my-sce-rating" type="number" min="1" max="5" value="%3$d" /></p>',
absint( $comment_id ),
esc_attr( $title ),
$rating
);
}, 10, 4 );
add_action( 'sce_save_after', function( $comment_to_save, $post_id, $comment_id ) {
if ( isset( $_POST['my_sce_title'] ) ) {
$title = sanitize_text_field( wp_unslash( $_POST['my_sce_title'] ) );
// HTML maxlength counts UTF-16 code units, including two for astral characters.
$title_length = preg_match_all( '/[\s\S]/u', $title );
$supplementary_character_count = preg_match_all( '/[\x{10000}-\x{10FFFF}]/u', $title );
if (
'' !== $title
&& false !== $title_length
&& false !== $supplementary_character_count
&& ( $title_length + $supplementary_character_count ) <= 120
) {
update_comment_meta( $comment_id, '_my_sce_title', $title );
}
}
if ( isset( $_POST['my_sce_rating'] ) ) {
$raw_rating = wp_unslash( $_POST['my_sce_rating'] );
if ( is_string( $raw_rating ) && preg_match( '/^[1-5]$/D', $raw_rating ) ) {
$rating = absint( $raw_rating );
update_comment_meta( $comment_id, '_my_sce_rating', $rating );
}
}
}, 10, 3 );wp.hooks.addFilter(
'sce.comment.save.data',
'my-plugin/comment-fields',
( ajaxSaveParams ) => {
const editor = document.querySelector( `#sce-edit-comment${ ajaxSaveParams.comment_id }` );
if ( ! editor ) {
return ajaxSaveParams;
}
const title = editor.querySelector( '.my-sce-title' );
const rating = editor.querySelector( '.my-sce-rating' );
if ( title && title.value.trim() ) {
ajaxSaveParams.my_sce_title = title.value.trim();
}
if ( rating && rating.value ) {
ajaxSaveParams.my_sce_rating = rating.value;
}
return ajaxSaveParams;
}
);SCE performs its normal nonce and comment-ownership checks before
sce_save_after runs. The callback must still sanitize and validate every
request value. Its title check uses the same UTF-16 code units as the input's
maxlength, and its rating check rejects values outside 1–5 before conversion.
Do not delete or overwrite existing metadata when an optional field is absent:
that can happen when a theme does not render the extra field.
SCE attaches its editor through WordPress's native comment_text filter. A
custom loop should call comment_text( $comment ) rather than echoing
$comment->comment_content; the latter bypasses formatting and the editor.
foreach ( get_comments( array( 'post_id' => get_the_ID() ) ) as $comment ) {
?>
<article id="comment-<?php echo esc_attr( $comment->comment_ID ); ?>" <?php comment_class( '', $comment ); ?>>
<?php comment_text( $comment ); ?>
</article>
<?php
}Keep the comment object available to comment_text() and do not manually copy
SCE's nonce, AJAX URL, or controls. SCE supplies them only when the current
visitor may edit that specific comment.
/**
* Filter: sce_buttons
*
* Filter to add button content
*
* @since 1.3.0
*
* @param string $textarea_buttons Button HTML
* @param int $comment_id Comment ID
*/sce_buttons receives the complete generated button markup, so use it for
safe, intentional HTML additions such as an icon or a help link. The
sce_text_save, sce_text_cancel, and sce_text_delete filters are for text
labels; SCE escapes their values before rendering.
add_filter( 'sce_buttons', function( $buttons, $comment_id ) {
return $buttons . '<span class="my-sce-help" data-comment-id="' . absint( $comment_id ) . '">Need help?</span>';
}, 10, 2 );/**
* Filter: sce_content
*
* Filter to overral sce output
*
* @since 1.3.0
*
* @param string $sce_content SCE content
* @param int $comment_id Comment ID of the comment
*//**
* Filter: sce_save_before
*
* Allow third parties to modify comment
*
* @since 1.4.0
*
* @param object $comment_to_save The Comment Object
* @param int $post_id The Post ID
* @param int $comment_id The Comment ID
*//**
* Filter: sce_can_edit
*
* Determine if a user can edit the comment
*
* @since 1.3.2
*
* @param bool true If user can edit the comment
* @param object $comment Comment object user has left
* @param int $comment_id Comment ID of the comment
* @param int $post_id Post ID of the comment
*/Example: https://gist.github.com/ronalfy/6b4fec8b3ac55bc47f3f
/**
* Filter: sce_security_key_min
*
* Determine how many security keys should be stored as post meta before garbage collection
*
* @since 1.0.0
*
* @param int $num_keys How many keys to store
*//**
* Filter: sce_load_scripts
*
* Boolean to decide whether to load SCE scripts or not. The filter runs after
* the optional asset-loading policies, so an explicit value takes precedence.
*
* @since 1.5.0
*
* @param bool $load_scripts True to load scripts, false to suppress both SCE JS and CSS.
*//**
* Filter: sce_comment_time
*
* How long in minutes to edit a comment
*
* @since 1.0.0
*
* @param int $minutes Time in minutes
*/Example:
//Simple Comment Editing
add_filter( 'sce_comment_time', 'edit_sce_comment_time' );
function edit_sce_comment_time( $time_in_minutes ) {
return 60;
}/**
* Filter: sce_show_timer
*
* Filter allow you to hide the timer
*
* @since 2.3.0
*
* @param bool Whether to show the timer or not
*/Example:
//Simple Comment Editing - Disable the timer
add_filter( 'sce_show_timer', '__return_false' );/**
* Filter: sce_text_edit
*
* Filter allow editing of edit text
*
* @since 2.0.0
*
* @param string Translated click to edit text
*/Example:
add_filter( 'sce_text_edit', function( $translated_text ) {
return "Custom Edit Text";
} );/**
* Filter: sce_text_save
*
* Filter allow editing of save text
*
* @since 2.0.0
*
* @param string Translated save text
*/Example:
add_filter( 'sce_text_save', function( $translated_text ) {
return "Custom Save";
} );/**
* Filter: sce_text_cancel
*
* Filter allow editing of cancel text
*
* @since 2.0.0
*
* @param string Translated cancel text
*/Example:
add_filter( 'sce_text_cancel', function( $translated_text ) {
return "Custom Cancel";
} );/**
* Filter: sce_text_delete
*
* Filter allow editing of delete text
*
* @since 2.0.0
*
* @param string Translated delete text
*/Example:
add_filter( 'sce_text_delete', function( $translated_text ) {
return "Custom Delete";
} );Useful for custom comment fields
/**
* Action: sce_save_after
*
* Allow third parties to save content after a comment has been updated
*
* @since 1.4.0
*
* @param object $comment_to_save The Comment Object
* @param int $post_id The Post ID
* @param int $comment_id The Comment ID
*//**
* Event: sce.comment.save.pre
*
* Event triggered before a comment is saved
*
* @since 1.4.0
*
* @param int $comment_id The Comment ID
* @param int $post_id The Post ID
*//**
* Event: sce.comment.save
*
* Event triggered after a comment is saved
*
* @since 1.4.0
*
* @param int $comment_id The Comment ID
* @param int $post_id The Post ID
*//**
* Event: sce.timer.loaded
*
* Event triggered after a commen's timer has been loaded
*
* @since 1.3.0
*
* @param jQuery Element of the comment
*/This hook is useful for third-party plugins who post comments via Ajax.
/**
* Event: sce.comment.loaded
*
* Event triggered after SCE has loaded a comment.
*
* @since 1.5.0
*
* @param object Comment Object
*/JS hooks are using WP-JS-Hooks: https://github.com/carldanley/WP-JS-Hooks
Please use handle wp-hooks when enqueueing for consistency and to prevent conflicts.
Used to modify POST object before being sent via Ajax. This is useful for adding extra fields.
/**
* JSFilter: sce.comment.save.data
*
* Event triggered before a comment is saved
*
* @since 1.4.0
*
* @param object $ajax_save_params
*/Used to modify timer output.
/**
* JSFilter: sce.comment.timer.text
*
* Filter triggered before a timer is returned
*
* @since 1.4.0
*
* @param string Timer text
* @param string Minutes text (internationalized)
* @param string Seconds text (internationalized)
* @param int minutes
* @param int seconds
*/Example placed in functions.php:
add_action( 'wp_footer', function() {
?>
<script type="text/javascript">
jQuery( document ).ready( function( $ ) {
/* Will give you format of minutes:seconds (e.g., 2:58) */
if (typeof wp.hooks != 'undefined') {
wp.hooks.addFilter( 'sce.comment.timer.text', function( timer_text, minutes_text, seconds_text, minutes, seconds ) {
timer_text = ' ' + minutes;
timer_text += ":";
if (seconds >= 0) {
if( seconds < 10 ) {
timer_text += '' + '0' + seconds;
} else {
timer_text += seconds;
}
}
return timer_text;
} );
}
} );
</script>
<?php
} );The plugin doesn't come with any styles. We leave it up to you to style the interface. It doesn't look horribly ugly on most themes, but we leave the advanced customization up to you.
The overall editing interface has been wrapped in a div with class sce-edit-comment.
.sce-edit-comment { /* styles here */ }The edit button and timer have been wrapped in a div with class sce-edit-button.
.sce-edit-button { /* styles here */ }
.sce-edit-button a { /* styles here */ }
.sce-edit-button .sce-timer { /* styles here */ }The loading icon has been wrapped in a div with class sce-loading.
.sce-loading { /* styles here */ }
.sce-loading img { /* styles here */ }The textarea interface has been wrapped in a div with class sce-textarea.
The actual textarea has been wrapped in a div with class sce-comment-textarea.
The save/cancel buttons have been wrapped in a div with class sce-comment-edit-buttons.
.sce-textarea { /* styles here */ }
.sce-textarea .sce-comment-textarea textarea { /* styles here */ }
.sce-comment-edit-buttons { /* styles here */ }
.sce-comment-edit-buttons .sce-comment-save { /* styles here */ }
.sce-comment-edit-buttons .sce-comment-cancel { /* styles here */ }For an inline WP ULike-style action row, style the existing wrapper instead of
moving controls outside it. SCE's JavaScript expects .sce-edit-comment to
contain .sce-textarea, .sce-comment-text, and
.sce-comment-edit-buttons.
.sce-edit-comment .sce-comment-edit-buttons {
display: inline-flex;
align-items: center;
gap: 0.5rem;
}
.sce-edit-comment .sce-comment-edit-buttons-group {
display: inline-flex;
gap: 0.25rem;
}This keeps Save, Cancel, Delete, and the timer inside their required hierarchy
and preserves their native button behavior. Do not replace the buttons with
links to admin-ajax.php or move them into arbitrary theme markup.
The status message has been wrapped in a div with class sce-status.
Here's some sample styles that mimic how error messages are displayed in the WordPress admin area:
.sce-status {
border-left: 4px solid #FFF;
-webkit-box-shadow: 0 1px 1px 0 rgba( 0, 0, 0, 0.1 );
box-shadow: 0 1px 1px 0 rgba( 0, 0, 0, 0.1 );
background: #fff;
color: #333;
padding: 10px;
margin-top: 10px;
}
.sce-status.error {
border-color: #dd3d36;
}
.sce-status.updated {
border-color: #7ad03a;
}Since most of the interface is hidden, it's a little hard to style. Just place this into your stylesheet, and remove when you're done.
/* todo - remove me when done styling */
.sce-edit-button,
.sce-loading,
.sce-textarea {
display: block !important;
}Have fun leaving lots of test comments :) - Recommended is to use the filter (in the FAQ section) to temporarily increase the comment editing time. Make sure you leave the test comments when you're not logged in.
This project was created and is maintained with aidevops.sh.