Add Stimulus (#65)
This commit is contained in:
parent
5885dbd5fd
commit
f5e0188c1f
@ -418,7 +418,6 @@ Fires right after the `<main>` container is closed in the `single-fcn_chapter.ph
|
|||||||
* $next_index (int|boolean) – Index of next chapter or false if outside bounds.
|
* $next_index (int|boolean) – Index of next chapter or false if outside bounds.
|
||||||
|
|
||||||
**Hooked Actions:**
|
**Hooked Actions:**
|
||||||
* `fictioneer_chapter_micro_menu( $args )` – Add the HTML for the chapter micro menu. Priority 10.
|
|
||||||
* `fictioneer_chapter_paragraph_tools()` – Add the HTML for the chapter paragraph tools. Priority 10.
|
* `fictioneer_chapter_paragraph_tools()` – Add the HTML for the chapter paragraph tools. Priority 10.
|
||||||
* `fictioneer_chapter_suggestion_tools()` – Add the HTML for the chapter suggestion tools. Priority 10.
|
* `fictioneer_chapter_suggestion_tools()` – Add the HTML for the chapter suggestion tools. Priority 10.
|
||||||
|
|
||||||
@ -482,6 +481,7 @@ List page template hook. Fires right after the content section in the `chapters.
|
|||||||
**Hooked Actions:**
|
**Hooked Actions:**
|
||||||
* `fictioneer_sort_order_filter_interface( $args )` – Interface to sort, order, and filter. Priority 20.
|
* `fictioneer_sort_order_filter_interface( $args )` – Interface to sort, order, and filter. Priority 20.
|
||||||
* `fictioneer_chapters_list( $args )` – Paginated card list of all visible chapters. Priority 30.
|
* `fictioneer_chapters_list( $args )` – Paginated card list of all visible chapters. Priority 30.
|
||||||
|
* `fictioneer_chapter_micro_menu( $args )` – Add the HTML for the chapter micro menu. Priority 99.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -129,7 +129,9 @@ font-size: clamp(1.35em, 1vw + 18.4px, 1.75em); // CSS
|
|||||||
|
|
||||||
## JavaScript
|
## JavaScript
|
||||||
|
|
||||||
Fictioneer is built on [Vanilla JS](http://vanilla-js.com/) without hard dependencies, *especially* not jQuery which is to be avoided like the plague. Bad enough that WordPress and most plugins insist on the performance hog. If you need something from an external library, just copy the functions and credit the source. Avoid additional overhead. There is also an argument for refactoring the JS into classes and modules. But since everything is already working, this would be a labor of passion without immediate benefit.
|
~~Fictioneer is built on [Vanilla JS](http://vanilla-js.com/) without hard dependencies, *especially* not jQuery which is to be avoided like the plague. Bad enough that WordPress and most plugins insist on the performance hog. If you need something from an external library, just copy the functions and credit the source. Avoid additional overhead. There is also an argument for refactoring the JS into classes and modules. But since everything is already working, this would be a labor of passion without immediate benefit.~~
|
||||||
|
|
||||||
|
As of 5.27.0, the theme uses [Stimulus](https://stimulus.hotwired.dev/). This section will be updated in the future.
|
||||||
|
|
||||||
### Libraries
|
### Libraries
|
||||||
|
|
||||||
@ -145,7 +147,6 @@ Fictioneer is built on [Vanilla JS](http://vanilla-js.com/) without hard depende
|
|||||||
|
|
||||||
* **scroll.rAF:** Window scroll event bound to [requestAnimationFrame](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame).
|
* **scroll.rAF:** Window scroll event bound to [requestAnimationFrame](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame).
|
||||||
* **resize.rAF:** Window resize event bound to [requestAnimationFrame](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame).
|
* **resize.rAF:** Window resize event bound to [requestAnimationFrame](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame).
|
||||||
* **fcnAuthReady:** Fires when the user has been successfully authenticated via AJAX.
|
|
||||||
* **fcnUserDataReady:** Fires when the user data has been successfully fetched via AJAX.
|
* **fcnUserDataReady:** Fires when the user data has been successfully fetched via AJAX.
|
||||||
* **fcnUserDataFailed:** Fires when the user data could not be fetched via AJAX.
|
* **fcnUserDataFailed:** Fires when the user data could not be fetched via AJAX.
|
||||||
* **fcnUserDataError:** Fires when there was an error while fetching the user data via AJAX.
|
* **fcnUserDataError:** Fires when there was an error while fetching the user data via AJAX.
|
||||||
@ -155,10 +156,10 @@ Fictioneer is built on [Vanilla JS](http://vanilla-js.com/) without hard depende
|
|||||||
AJAX requests can be made with the theme’s [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch) helper functions, returning an object parsed from a JSON response. For that to work, the server must always respond with a JSON (which can contain an HTML node, of course). You can use [wp_send_json_success()](https://developer.wordpress.org/reference/functions/wp_send_json_success/) and [wp_send_json_error()](https://developer.wordpress.org/reference/functions/wp_send_json_error/) for this, making it easier to evaluate the result client-side.
|
AJAX requests can be made with the theme’s [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch) helper functions, returning an object parsed from a JSON response. For that to work, the server must always respond with a JSON (which can contain an HTML node, of course). You can use [wp_send_json_success()](https://developer.wordpress.org/reference/functions/wp_send_json_success/) and [wp_send_json_error()](https://developer.wordpress.org/reference/functions/wp_send_json_error/) for this, making it easier to evaluate the result client-side.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
fcn_ajaxGet(
|
FcnUtils.aGet(
|
||||||
{
|
{
|
||||||
'action': 'fictioneer_ajax_your_function',
|
'action': 'fictioneer_ajax_your_function',
|
||||||
'nonce': fcn_getNonce(), // Optional
|
'nonce': FcnUtils.nonce(), // Optional
|
||||||
'payload': 'foobar'
|
'payload': 'foobar'
|
||||||
},
|
},
|
||||||
null, // Optional AJAX URL
|
null, // Optional AJAX URL
|
||||||
@ -173,10 +174,10 @@ fcn_ajaxGet(
|
|||||||
```
|
```
|
||||||
|
|
||||||
```js
|
```js
|
||||||
fcn_ajaxPost(
|
FcnUtils.aPost(
|
||||||
{
|
{
|
||||||
'action': 'fictioneer_ajax_your_function',
|
'action': 'fictioneer_ajax_your_function',
|
||||||
'nonce': fcn_getNonce(), // Optional
|
'nonce': FcnUtils.nonce(), // Optional
|
||||||
'payload': 'foobar'
|
'payload': 'foobar'
|
||||||
},
|
},
|
||||||
null, // Optional AJAX URL
|
null, // Optional AJAX URL
|
||||||
@ -310,14 +311,14 @@ Fictioneer customizes WordPress by using as many standard action and filter hook
|
|||||||
| `trashed_post` | `fictioneer_refresh_post_caches` (20), `fictioneer_track_chapter_and_story_updates` (10), `fictioneer_update_modified_date_on_story_for_chapter` (10), `fictioneer_purge_transients_after_update` (10), `fictioneer_remove_chapter_from_story` (10)
|
| `trashed_post` | `fictioneer_refresh_post_caches` (20), `fictioneer_track_chapter_and_story_updates` (10), `fictioneer_update_modified_date_on_story_for_chapter` (10), `fictioneer_purge_transients_after_update` (10), `fictioneer_remove_chapter_from_story` (10)
|
||||||
| `untrash_post` | `fictioneer_refresh_post_caches` (20), `fictioneer_track_chapter_and_story_updates` (10), `fictioneer_update_modified_date_on_story_for_chapter` (10), `fictioneer_purge_transients_after_update` (10)
|
| `untrash_post` | `fictioneer_refresh_post_caches` (20), `fictioneer_track_chapter_and_story_updates` (10), `fictioneer_update_modified_date_on_story_for_chapter` (10), `fictioneer_purge_transients_after_update` (10)
|
||||||
| `update_option_*` | `fictioneer_update_option_disable_extended_chapter_list_meta_queries` (10), `fictioneer_update_option_disable_extended_story_list_meta_queries` (10)
|
| `update_option_*` | `fictioneer_update_option_disable_extended_chapter_list_meta_queries` (10), `fictioneer_update_option_disable_extended_story_list_meta_queries` (10)
|
||||||
| `wp_ajax_*` | `fictioneer_ajax_clear_my_checkmarks` (10), `fictioneer_ajax_clear_my_comments` (10), `fictioneer_ajax_clear_my_comment_subscriptions` (10), `fictioneer_ajax_clear_my_follows` (10), `fictioneer_ajax_clear_my_reminders` (10), `fictioneer_ajax_delete_epub` (10), `fictioneer_ajax_delete_my_account` (10), `fictioneer_ajax_delete_my_comment` (10), `fictioneer_ajax_edit_comment` (10), `fictioneer_ajax_get_avatar` (10), `fictioneer_ajax_get_comment_form` (10), `fictioneer_ajax_get_comment_section` (10), `fictioneer_ajax_get_finished_checkmarks_list` (10), `fictioneer_ajax_get_follows_list` (10), `fictioneer_ajax_get_follows_notifications` (10), `fictioneer_ajax_get_reminders_list` (10), `fictioneer_ajax_mark_follows_read` (10), `fictioneer_ajax_moderate_comment` (10), `fictioneer_ajax_report_comment` (10), `fictioneer_ajax_save_bookmarks` (10), `fictioneer_ajax_set_checkmark` (10), `fictioneer_ajax_submit_comment` (10), `fictioneer_ajax_toggle_follow` (10), `fictioneer_ajax_toggle_reminder` (10), `fictioneer_ajax_unset_my_oauth` (10), `fictioneer_ajax_get_user_data` (10), `fictioneer_ajax_get_auth` (10), `fictioneer_ajax_purge_schema` (10), `fictioneer_ajax_purge_all_schemas` (10), `fictioneer_ajax_reset_theme_colors` (10), `fictioneer_ajax_search_posts_to_unlock` (10), `fictioneer_ajax_get_chapter_group_options` (10)
|
| `wp_ajax_*` | `fictioneer_ajax_clear_my_checkmarks` (10), `fictioneer_ajax_clear_my_comments` (10), `fictioneer_ajax_clear_my_comment_subscriptions` (10), `fictioneer_ajax_clear_my_follows` (10), `fictioneer_ajax_clear_my_reminders` (10), `fictioneer_ajax_delete_epub` (10), `fictioneer_ajax_delete_my_account` (10), `fictioneer_ajax_delete_my_comment` (10), `fictioneer_ajax_edit_comment` (10), `fictioneer_ajax_get_comment_form` (10), `fictioneer_ajax_get_comment_section` (10), `fictioneer_ajax_get_finished_checkmarks_list` (10), `fictioneer_ajax_get_follows_list` (10), `fictioneer_ajax_get_follows_notifications` (10), `fictioneer_ajax_get_reminders_list` (10), `fictioneer_ajax_mark_follows_read` (10), `fictioneer_ajax_moderate_comment` (10), `fictioneer_ajax_report_comment` (10), `fictioneer_ajax_save_bookmarks` (10), `fictioneer_ajax_set_checkmark` (10), `fictioneer_ajax_submit_comment` (10), `fictioneer_ajax_toggle_follow` (10), `fictioneer_ajax_toggle_reminder` (10), `fictioneer_ajax_unset_my_oauth` (10), `fictioneer_ajax_get_user_data` (10), `fictioneer_ajax_purge_schema` (10), `fictioneer_ajax_purge_all_schemas` (10), `fictioneer_ajax_reset_theme_colors` (10), `fictioneer_ajax_search_posts_to_unlock` (10), `fictioneer_ajax_get_chapter_group_options` (10), `fictioneer_ajax_clear_cookies` (10)
|
||||||
| `wp_ajax_nopriv_*` | `fictioneer_ajax_get_comment_form` (10), `fictioneer_ajax_get_comment_section` (10), `fictioneer_ajax_submit_comment` (10), `fictioneer_ajax_get_auth` (10)
|
| `wp_ajax_nopriv_*` | `fictioneer_ajax_get_comment_form` (10), `fictioneer_ajax_get_comment_section` (10), `fictioneer_ajax_submit_comment` (10), `fictioneer_ajax_get_user_data` (10)
|
||||||
| `wp_before_admin_bar_render` | `fictioneer_remove_admin_bar_links` (10), `fictioneer_remove_dashboard_from_admin_bar` (10), `fictioneer_remove_comments_from_admin_bar` (10)
|
| `wp_before_admin_bar_render` | `fictioneer_remove_admin_bar_links` (10), `fictioneer_remove_dashboard_from_admin_bar` (10), `fictioneer_remove_comments_from_admin_bar` (10)
|
||||||
| `wp_dashboard_setup` | `fictioneer_remove_dashboard_widgets` (10)
|
| `wp_dashboard_setup` | `fictioneer_remove_dashboard_widgets` (10)
|
||||||
| `wp_default_scripts` | `fictioneer_remove_jquery_migrate` (10)
|
| `wp_default_scripts` | `fictioneer_remove_jquery_migrate` (10)
|
||||||
| `wp_enqueue_scripts` | `fictioneer_add_custom_scripts` (10), `fictioneer_style_queue` (10), `fictioneer_output_customize_css` (9999), `fictioneer_output_customize_preview_css` (9999), `fictioneer_elementor_override_styles` (9999)
|
| `wp_enqueue_scripts` | `fictioneer_add_custom_scripts` (10), `fictioneer_style_queue` (10), `fictioneer_output_customize_css` (9999), `fictioneer_output_customize_preview_css` (9999), `fictioneer_elementor_override_styles` (9999)
|
||||||
| `wp_footer` | `fictioneer_render_category_submenu` (10), `fictioneer_render_tag_submenu` (10), `fictioneer_render_genre_submenu` (10), `fictioneer_render_fandom_submenu` (10), `fictioneer_render_character_submenu` (10), `fictioneer_render_warning_submenu` (10)
|
| `wp_footer` | `fictioneer_render_category_submenu` (10), `fictioneer_render_tag_submenu` (10), `fictioneer_render_genre_submenu` (10), `fictioneer_render_fandom_submenu` (10), `fictioneer_render_character_submenu` (10), `fictioneer_render_warning_submenu` (10)
|
||||||
| `wp_head` | `fictioneer_output_head_seo` (5), `fictioneer_output_rss` (10), `fictioneer_output_schemas` (10), `fictioneer_add_fiction_css` (10), `fictioneer_output_head_fonts` (5), `fictioneer_output_head_translations` (10), `fictioneer_remove_mu_registration_styles` (1), `fictioneer_output_mu_registration_style` (10), `fictioneer_output_head_meta` (1), `fictioneer_output_head_critical_scripts` (9999). `fictioneer_output_head_anti_flicker` (10), `fictioneer_cleanup_discord_meta` (10), `fictioneer_output_critical_skin_scripts` (9999)
|
| `wp_head` | `fictioneer_output_head_seo` (5), `fictioneer_output_rss` (10), `fictioneer_output_schemas` (10), `fictioneer_add_fiction_css` (10), `fictioneer_output_head_fonts` (5), `fictioneer_output_head_translations` (10), `fictioneer_remove_mu_registration_styles` (1), `fictioneer_output_mu_registration_style` (10), `fictioneer_output_head_meta` (1), `fictioneer_output_head_critical_scripts` (9999). `fictioneer_output_head_anti_flicker` (10), `fictioneer_cleanup_discord_meta` (10), `fictioneer_output_critical_skin_scripts` (9999), `fictioneer_output_stimulus` (5)
|
||||||
| `wp_insert_comment` | `fictioneer_delete_cached_story_card_by_comment` (10), `fictioneer_increment_story_comment_count` (10)
|
| `wp_insert_comment` | `fictioneer_delete_cached_story_card_by_comment` (10), `fictioneer_increment_story_comment_count` (10)
|
||||||
| `wp_logout` | `fictioneer_remove_logged_in_cookie` (10)
|
| `wp_logout` | `fictioneer_remove_logged_in_cookie` (10)
|
||||||
| `wp_update_nav_menu` | `fictioneer_purge_nav_menu_transients` (10)
|
| `wp_update_nav_menu` | `fictioneer_purge_nav_menu_transients` (10)
|
||||||
|
@ -47,6 +47,12 @@ Filters the data to be returned as JSON by the `fictioneer_ajax_get_user_data()`
|
|||||||
* $checkmarks (array|false) – The user’s Checkmarks data or false if disabled.
|
* $checkmarks (array|false) – The user’s Checkmarks data or false if disabled.
|
||||||
* $bookmarks (string) – The user’s Bookmarks JSON as string. `'{}'` if disabled.
|
* $bookmarks (string) – The user’s Bookmarks JSON as string. `'{}'` if disabled.
|
||||||
* $fingerprint (string) – The user’s unique hash.
|
* $fingerprint (string) – The user’s unique hash.
|
||||||
|
* 'isAdmin' (bool) - Whether the user is an admin.
|
||||||
|
* 'isModerator' (bool) - Whether the user is a moderator.
|
||||||
|
* 'isAuthor' (bool) - Whether the user is an author.
|
||||||
|
* 'isEditor' (bool) - Whether the user is an editor.
|
||||||
|
* 'nonce' (string) - The `'fictioneer_nonce'` nonce.
|
||||||
|
* 'nonceHtml' (string) - Nonce HTMl ready to be appended to the DOM.
|
||||||
|
|
||||||
**Parameters:**
|
**Parameters:**
|
||||||
* $user (WP_User) – The user object.
|
* $user (WP_User) – The user object.
|
||||||
|
@ -1531,7 +1531,6 @@ define( 'CONSTANT_NAME', value );
|
|||||||
| FICTIONEER_DEFAULT_SITE_WIDTH | integer | Default site width. Default `960`.
|
| FICTIONEER_DEFAULT_SITE_WIDTH | integer | Default site width. Default `960`.
|
||||||
| FICTIONEER_COMMENTCODE_TTL | integer | How long guests can see their private/unapproved comments in _seconds_. Default `600`.
|
| FICTIONEER_COMMENTCODE_TTL | integer | How long guests can see their private/unapproved comments in _seconds_. Default `600`.
|
||||||
| FICTIONEER_AJAX_TTL | integer | How long to cache certain AJAX requests locally in _milliseconds_. Default `60000`.
|
| FICTIONEER_AJAX_TTL | integer | How long to cache certain AJAX requests locally in _milliseconds_. Default `60000`.
|
||||||
| FICTIONEER_AJAX_LOGIN_TTL | integer | How long to cache AJAX authentications locally in _milliseconds_. Default `15000`.
|
|
||||||
| FICTIONEER_AJAX_POST_DEBOUNCE_RATE | integer | How long to debounce AJAX requests of the same type in _milliseconds_. Default `700`.
|
| FICTIONEER_AJAX_POST_DEBOUNCE_RATE | integer | How long to debounce AJAX requests of the same type in _milliseconds_. Default `700`.
|
||||||
| FICTIONEER_AUTHOR_KEYWORD_SEARCH_LIMIT | integer | Maximum number of authors in the advanced search suggestions. Default `100`.
|
| FICTIONEER_AUTHOR_KEYWORD_SEARCH_LIMIT | integer | Maximum number of authors in the advanced search suggestions. Default `100`.
|
||||||
| FICTIONEER_UPDATE_CHECK_TIMEOUT | integer | Timeout between checks for theme updates in _seconds_. Default `43200`.
|
| FICTIONEER_UPDATE_CHECK_TIMEOUT | integer | Timeout between checks for theme updates in _seconds_. Default `43200`.
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<p align="center"><img src="./repo/assets/fictioneer_logo.svg?raw=true" alt="Fictioneer"></p>
|
<p align="center"><img src="./repo/assets/fictioneer_logo.svg?raw=true" alt="Fictioneer"></p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://github.com/Tetrakern/fictioneer"><img alt="Theme: 5.26" src="https://img.shields.io/badge/theme-5.26-blue?style=flat" /></a>
|
<a href="https://github.com/Tetrakern/fictioneer"><img alt="Theme: 5.27" src="https://img.shields.io/badge/theme-5.27-blue?style=flat" /></a>
|
||||||
<a href="LICENSE.md"><img alt="License: GPL v3" src="https://img.shields.io/badge/license-GPL%20v3-blue?style=flat" /></a>
|
<a href="LICENSE.md"><img alt="License: GPL v3" src="https://img.shields.io/badge/license-GPL%20v3-blue?style=flat" /></a>
|
||||||
<a href="https://wordpress.org/download/"><img alt="WordPress 6.1+" src="https://img.shields.io/badge/WordPress-%3E%3D6.1-blue?style=flat" /></a>
|
<a href="https://wordpress.org/download/"><img alt="WordPress 6.1+" src="https://img.shields.io/badge/WordPress-%3E%3D6.1-blue?style=flat" /></a>
|
||||||
<a href="https://www.php.net/"><img alt="PHP: 7.4+" src="https://img.shields.io/badge/php-%3E%3D7.4-blue?logoColor=white&style=flat" /></a>
|
<a href="https://www.php.net/"><img alt="PHP: 7.4+" src="https://img.shields.io/badge/php-%3E%3D7.4-blue?logoColor=white&style=flat" /></a>
|
||||||
|
24
comments.php
24
comments.php
@ -26,6 +26,14 @@ $logout_url = fictioneer_get_logout_url( get_permalink() );
|
|||||||
$order_link = add_query_arg( 'corder', $order === 'desc' ? 'asc' : 'desc', home_url( $wp->request ) ) . '#comments';
|
$order_link = add_query_arg( 'corder', $order === 'desc' ? 'asc' : 'desc', home_url( $wp->request ) ) . '#comments';
|
||||||
$is_ajax_comments = get_option( 'fictioneer_enable_ajax_comments' );
|
$is_ajax_comments = get_option( 'fictioneer_enable_ajax_comments' );
|
||||||
|
|
||||||
|
// Edit template
|
||||||
|
if (
|
||||||
|
get_option( 'fictioneer_enable_user_comment_editing' ) &&
|
||||||
|
! fictioneer_is_commenting_disabled()
|
||||||
|
) {
|
||||||
|
get_template_part( 'partials/_template_comment_edit' );
|
||||||
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<div id="comments" class="fictioneer-comments scroll-margin-top" data-post-id="<?php echo $post_id; ?>" data-order="<?php echo $order; ?>" data-logout-url="<?php echo esc_url( $logout_url ); ?>" <?php echo $is_ajax_comments ? 'data-ajax-comments' : ''; ?>><?php
|
<div id="comments" class="fictioneer-comments scroll-margin-top" data-post-id="<?php echo $post_id; ?>" data-order="<?php echo $order; ?>" data-logout-url="<?php echo esc_url( $logout_url ); ?>" <?php echo $is_ajax_comments ? 'data-ajax-comments' : ''; ?>><?php
|
||||||
@ -62,7 +70,11 @@ $is_ajax_comments = get_option( 'fictioneer_enable_ajax_comments' );
|
|||||||
if ( get_option( 'fictioneer_enable_ajax_comment_form' ) ) {
|
if ( get_option( 'fictioneer_enable_ajax_comment_form' ) ) {
|
||||||
fictioneer_comments_ajax_form_skeleton();
|
fictioneer_comments_ajax_form_skeleton();
|
||||||
} else {
|
} else {
|
||||||
|
if ( get_option( 'fictioneer_disable_comment_form' ) ) {
|
||||||
comment_form();
|
comment_form();
|
||||||
|
} else {
|
||||||
|
fictioneer_comment_form();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
echo '<div class="fictioneer-comments__disabled">' . __( 'Commenting is disabled.', 'fictioneer' ) . '</div>';
|
echo '<div class="fictioneer-comments__disabled">' . __( 'Commenting is disabled.', 'fictioneer' ) . '</div>';
|
||||||
@ -81,6 +93,9 @@ $is_ajax_comments = get_option( 'fictioneer_enable_ajax_comments' );
|
|||||||
// Count all comments regardless of status
|
// Count all comments regardless of status
|
||||||
$count = count( $comments );
|
$count = count( $comments );
|
||||||
|
|
||||||
|
// Moderation menu template
|
||||||
|
fictioneer_comment_moderation_template();
|
||||||
|
|
||||||
// Comment list
|
// Comment list
|
||||||
if (
|
if (
|
||||||
have_comments() ||
|
have_comments() ||
|
||||||
@ -104,13 +119,4 @@ $is_ajax_comments = get_option( 'fictioneer_enable_ajax_comments' );
|
|||||||
the_comments_pagination( $pag_args );
|
the_comments_pagination( $pag_args );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Edit template
|
|
||||||
if (
|
|
||||||
get_option( 'fictioneer_enable_user_comment_editing' ) &&
|
|
||||||
! fictioneer_is_commenting_disabled()
|
|
||||||
) {
|
|
||||||
get_template_part( 'partials/_template_comment_edit' );
|
|
||||||
}
|
|
||||||
|
|
||||||
?></div>
|
?></div>
|
||||||
|
526
config.codekit3
526
config.codekit3
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -5,9 +5,9 @@
|
|||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
// Version
|
// Version
|
||||||
define( 'FICTIONEER_VERSION', '5.26.1' );
|
define( 'FICTIONEER_VERSION', '5.27.0-beta2' );
|
||||||
define( 'FICTIONEER_MAJOR_VERSION', '5' );
|
define( 'FICTIONEER_MAJOR_VERSION', '5' );
|
||||||
define( 'FICTIONEER_RELEASE_TAG', 'v5.26.1' );
|
define( 'FICTIONEER_RELEASE_TAG', 'v5.27.0-beta2' );
|
||||||
|
|
||||||
if ( ! defined( 'CHILD_VERSION' ) ) {
|
if ( ! defined( 'CHILD_VERSION' ) ) {
|
||||||
define( 'CHILD_VERSION', null );
|
define( 'CHILD_VERSION', null );
|
||||||
@ -221,11 +221,6 @@ if ( ! defined( 'FICTIONEER_AJAX_TTL' ) ) {
|
|||||||
define( 'FICTIONEER_AJAX_TTL', 60000 );
|
define( 'FICTIONEER_AJAX_TTL', 60000 );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Integer: AJAX login cache TTL in milliseconds
|
|
||||||
if ( ! defined( 'FICTIONEER_AJAX_LOGIN_TTL' ) ) {
|
|
||||||
define( 'FICTIONEER_AJAX_LOGIN_TTL', 15000 );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Integer: AJAX POST debounce rate in milliseconds
|
// Integer: AJAX POST debounce rate in milliseconds
|
||||||
if ( ! defined( 'FICTIONEER_AJAX_POST_DEBOUNCE_RATE' ) ) {
|
if ( ! defined( 'FICTIONEER_AJAX_POST_DEBOUNCE_RATE' ) ) {
|
||||||
define( 'FICTIONEER_AJAX_POST_DEBOUNCE_RATE', 700 );
|
define( 'FICTIONEER_AJAX_POST_DEBOUNCE_RATE', 700 );
|
||||||
@ -273,7 +268,7 @@ if ( ! defined( 'FICTIONEER_STORY_COMMENT_COUNT_TIMEOUT' ) ) {
|
|||||||
|
|
||||||
// Integer: Requests per minute
|
// Integer: Requests per minute
|
||||||
if ( ! defined( 'FICTIONEER_REQUESTS_PER_MINUTE' ) ) {
|
if ( ! defined( 'FICTIONEER_REQUESTS_PER_MINUTE' ) ) {
|
||||||
define( 'FICTIONEER_REQUESTS_PER_MINUTE', 5 );
|
define( 'FICTIONEER_REQUESTS_PER_MINUTE', 10 );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Integer: Maximum number of IDs in 'post__in' and 'post__not_in' query arguments
|
// Integer: Maximum number of IDs in 'post__in' and 'post__not_in' query arguments
|
||||||
@ -630,15 +625,6 @@ if ( get_option( 'fictioneer_enable_checkmarks' ) ) {
|
|||||||
require_once __DIR__ . '/includes/functions/users/_checkmarks.php';
|
require_once __DIR__ . '/includes/functions/users/_checkmarks.php';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Add the bookmarks feature.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ( get_option( 'fictioneer_enable_bookmarks' ) && is_admin() ) {
|
|
||||||
// Only used for AJAX
|
|
||||||
require_once __DIR__ . '/includes/functions/users/_bookmarks.php';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add the skins feature.
|
* Add the skins feature.
|
||||||
*/
|
*/
|
||||||
|
20
header.php
20
header.php
@ -91,9 +91,27 @@ $action_args = array(
|
|||||||
|
|
||||||
// Body attributes
|
// Body attributes
|
||||||
$body_attributes = array(
|
$body_attributes = array(
|
||||||
'data-post-id' => ( $post_id ?: -1 )
|
'data-post-id' => ( $post_id ?: -1 ),
|
||||||
|
'data-controller' => 'fictioneer-last-click fictioneer-mobile-menu',
|
||||||
|
'data-action' => 'click->fictioneer-last-click#removeAll keydown.esc->fictioneer-last-click#removeAll click->fictioneer#bodyClick'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if ( get_option( 'fictioneer_enable_bookmarks' ) ) {
|
||||||
|
$body_attributes['data-controller'] .= ' fictioneer-bookmarks';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( get_option( 'fictioneer_enable_follows' ) ) {
|
||||||
|
$body_attributes['data-controller'] .= ' fictioneer-follows';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( get_option( 'fictioneer_enable_reminders' ) ) {
|
||||||
|
$body_attributes['data-controller'] .= ' fictioneer-reminders';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( get_option( 'fictioneer_enable_checkmarks' ) ) {
|
||||||
|
$body_attributes['data-controller'] .= ' fictioneer-checkmarks';
|
||||||
|
}
|
||||||
|
|
||||||
if ( $story_id ) {
|
if ( $story_id ) {
|
||||||
$body_attributes['data-story-id'] = $story_id;
|
$body_attributes['data-story-id'] = $story_id;
|
||||||
}
|
}
|
||||||
|
@ -608,7 +608,7 @@ if ( ! function_exists( 'fictioneer_get_story_page_cover' ) ) {
|
|||||||
|
|
||||||
// Build, filter, and return
|
// Build, filter, and return
|
||||||
$html = sprintf(
|
$html = sprintf(
|
||||||
'<figure class="story__thumbnail ' . $classes . '"><a href="%s" %s>%s<div id="ribbon-read" class="story__thumbnail-ribbon hidden"><div class="ribbon">%s</div></div></a></figure>',
|
'<figure class="story__thumbnail ' . $classes . '"><a href="%s" %s>%s<div id="ribbon-read" class="story__thumbnail-ribbon hidden" data-fictioneer-checkmarks-target="ribbon"><div class="ribbon">%s</div></div></a></figure>',
|
||||||
get_the_post_thumbnail_url( $story['id'], 'full' ),
|
get_the_post_thumbnail_url( $story['id'], 'full' ),
|
||||||
fictioneer_get_lightbox_attribute(),
|
fictioneer_get_lightbox_attribute(),
|
||||||
get_the_post_thumbnail( $story['id'], array( 200, 300 ), array(
|
get_the_post_thumbnail( $story['id'], array( 200, 300 ), array(
|
||||||
@ -1057,7 +1057,7 @@ if ( ! function_exists( 'fictioneer_get_story_buttons' ) ) {
|
|||||||
// Subscribe
|
// Subscribe
|
||||||
if ( ! empty( $subscribe_buttons ) ) {
|
if ( ! empty( $subscribe_buttons ) ) {
|
||||||
$output['subscribe'] = sprintf(
|
$output['subscribe'] = sprintf(
|
||||||
'<div class="toggle-last-clicked subscribe-menu-toggle button _secondary popup-menu-toggle _popup-right-if-last" tabindex="0" role="button" aria-label="%s"><div><i class="fa-solid fa-bell"></i> %s</div><div class="popup-menu _bottom _center">%s</div></div>',
|
'<div class="subscribe-menu-toggle button _secondary popup-menu-toggle _popup-right-if-last" tabindex="0" role="button" aria-label="%s" data-fictioneer-last-click-target="toggle" data-action="click->fictioneer-last-click#toggle"><div><i class="fa-solid fa-bell"></i> %s</div><div class="popup-menu _bottom _center">%s</div></div>',
|
||||||
fcntr( 'subscribe', true ),
|
fcntr( 'subscribe', true ),
|
||||||
fcntr( 'subscribe' ),
|
fcntr( 'subscribe' ),
|
||||||
$subscribe_buttons
|
$subscribe_buttons
|
||||||
@ -1067,7 +1067,7 @@ if ( ! function_exists( 'fictioneer_get_story_buttons' ) ) {
|
|||||||
// File download
|
// File download
|
||||||
if ( $show_epub_download && ! $ebook_upload ) {
|
if ( $show_epub_download && ! $ebook_upload ) {
|
||||||
$output['epub'] = sprintf(
|
$output['epub'] = sprintf(
|
||||||
'<a href="%s" class="button _secondary" rel="noreferrer noopener nofollow" data-action="download-epub" data-story-id="%d" aria-label="%s" download><i class="fa-solid fa-cloud-download-alt"></i><span class="span-epub hide-below-640">%s</span></a>',
|
'<a href="%s" class="button _secondary" rel="noreferrer noopener nofollow" data-action="click->fictioneer-story#startEpubDownload" data-story-id="%d" aria-label="%s" download><i class="fa-solid fa-cloud-download-alt"></i><span class="span-epub hide-below-640">%s</span></a>',
|
||||||
esc_url( home_url( 'download-epub/' . $args['story_id'] ) ),
|
esc_url( home_url( 'download-epub/' . $args['story_id'] ) ),
|
||||||
$args['story_id'],
|
$args['story_id'],
|
||||||
esc_attr__( 'Download ePUB', 'fictioneer' ),
|
esc_attr__( 'Download ePUB', 'fictioneer' ),
|
||||||
@ -1085,14 +1085,14 @@ if ( ! function_exists( 'fictioneer_get_story_buttons' ) ) {
|
|||||||
// Reminder
|
// Reminder
|
||||||
if ( get_option( 'fictioneer_enable_reminders' ) ) {
|
if ( get_option( 'fictioneer_enable_reminders' ) ) {
|
||||||
$output['reminder'] = sprintf(
|
$output['reminder'] = sprintf(
|
||||||
'<button class="button _secondary button-read-later hide-if-logged-out" data-story-id="%d"><i class="fa-solid fa-clock"></i><span class="span-follow hide-below-480">%s</span></button>',
|
'<button class="button _secondary button-read-later hide-if-logged-out" data-story-id="%1$d" data-fictioneer-reminders-target="toggleButton" data-action="click->fictioneer-reminders#toggleReminder" data-fictioneer-reminders-id-param="%1$d"><i class="fa-solid fa-clock"></i><span class="span-follow hide-below-480">%2$s</span></button>',
|
||||||
$story_id,
|
$story_id,
|
||||||
fcntr( 'read_later' )
|
fcntr( 'read_later' )
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( $show_login ) {
|
if ( $show_login ) {
|
||||||
$output['reminder'] .= sprintf(
|
$output['reminder'] .= sprintf(
|
||||||
'<label for="modal-login-toggle" class="button _secondary button-read-later-notice hide-if-logged-in tooltipped" tabindex="0" data-tooltip="%s"><i class="fa-solid fa-clock"></i><span class="span-follow hide-below-480">%s</span></label>',
|
'<button class="button _secondary button-read-later-notice hide-if-logged-in tooltipped" data-tooltip="%s" data-action="click->fictioneer#toggleModal" data-fictioneer-id-param="login-modal"><i class="fa-solid fa-clock"></i><span class="span-follow hide-below-480">%s</span></button>',
|
||||||
esc_attr__( 'Log in to set Reminders', 'fictioneer' ),
|
esc_attr__( 'Log in to set Reminders', 'fictioneer' ),
|
||||||
fcntr( 'read_later' )
|
fcntr( 'read_later' )
|
||||||
);
|
);
|
||||||
@ -1102,14 +1102,14 @@ if ( ! function_exists( 'fictioneer_get_story_buttons' ) ) {
|
|||||||
// Follow
|
// Follow
|
||||||
if ( get_option( 'fictioneer_enable_follows' ) ) {
|
if ( get_option( 'fictioneer_enable_follows' ) ) {
|
||||||
$output['follow'] = sprintf(
|
$output['follow'] = sprintf(
|
||||||
'<button class="button _secondary button-follow-story hide-if-logged-out" data-story-id="%d"><i class="fa-solid fa-star"></i><span class="span-follow hide-below-400">%s</span></button>',
|
'<button class="button _secondary button-follow-story hide-if-logged-out" data-story-id="%1$d" data-fictioneer-follows-target="toggleButton" data-action="click->fictioneer-follows#toggleFollow" data-fictioneer-follows-id-param="%1$d"><i class="fa-solid fa-star"></i><span class="span-follow hide-below-400">%2$s</span></button>',
|
||||||
$story_id,
|
$story_id,
|
||||||
fcntr( 'follow' )
|
fcntr( 'follow' )
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( $show_login ) {
|
if ( $show_login ) {
|
||||||
$output['follow'] .= sprintf(
|
$output['follow'] .= sprintf(
|
||||||
'<label for="modal-login-toggle" class="button _secondary button-follow-login-notice hide-if-logged-in tooltipped" tabindex="0" data-tooltip="%s"><i class="fa-regular fa-star off"></i><span class="span-follow hide-below-400">%s</span></label>',
|
'<button class="button _secondary button-follow-login-notice hide-if-logged-in tooltipped" data-tooltip="%s" data-action="click->fictioneer#toggleModal" data-fictioneer-id-param="login-modal"><i class="fa-regular fa-star off"></i><span class="span-follow hide-below-400">%s</span></button>',
|
||||||
esc_attr__( 'Log in to Follow', 'fictioneer' ),
|
esc_attr__( 'Log in to Follow', 'fictioneer' ),
|
||||||
fcntr( 'follow' )
|
fcntr( 'follow' )
|
||||||
);
|
);
|
||||||
@ -1153,7 +1153,7 @@ function fictioneer_get_media_buttons( $args = [] ) {
|
|||||||
|
|
||||||
// Share modal button
|
// Share modal button
|
||||||
if ( $args['share'] ?? 1 ) {
|
if ( $args['share'] ?? 1 ) {
|
||||||
$output['share'] = '<label for="modal-sharing-toggle" class="tooltipped media-buttons__item" data-tooltip="' . esc_attr__( 'Share', 'fictioneer' ) . '" tabindex="0"><i class="fa-solid fa-share-nodes"></i></label>';
|
$output['share'] = '<button class="tooltipped media-buttons__item" data-tooltip="' . esc_attr__( 'Share', 'fictioneer' ) . '" data-action="click->fictioneer#toggleModal" data-fictioneer-id-param="sharing-modal"><i class="fa-solid fa-share-nodes"></i></button>';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Feed buttons
|
// Feed buttons
|
||||||
@ -1224,27 +1224,27 @@ if ( ! function_exists( 'fictioneer_get_chapter_micro_menu' ) ) {
|
|||||||
|
|
||||||
// Open formatting modal
|
// Open formatting modal
|
||||||
$micro_menu['formatting'] = sprintf(
|
$micro_menu['formatting'] = sprintf(
|
||||||
'<label for="modal-formatting-toggle" class="micro-menu__item micro-menu__modal-formatting" tabindex="-1">%s</label>',
|
'<button class="micro-menu__item micro-menu__modal-formatting" tabindex="-1" data-action="click->fictioneer#toggleModal" data-fictioneer-id-param="formatting-modal">%s</button>',
|
||||||
fictioneer_get_icon( 'font-settings' )
|
fictioneer_get_icon( 'font-settings' )
|
||||||
);
|
);
|
||||||
|
|
||||||
// Open fullscreen
|
// Open fullscreen
|
||||||
$micro_menu['open_fullscreen'] = sprintf(
|
$micro_menu['open_fullscreen'] = sprintf(
|
||||||
'<button type="button" title="%s" class="micro-menu__item micro-menu__enter-fullscreen open-fullscreen hide-on-iOS hide-on-fullscreen" tabindex="-1">%s</button>',
|
'<button type="button" title="%s" class="micro-menu__item micro-menu__enter-fullscreen open-fullscreen hide-on-iOS hide-on-fullscreen" tabindex="-1" data-action="click->fictioneer-chapter#openFullscreen">%s</button>',
|
||||||
esc_attr__( 'Enter fullscreen', 'fictioneer' ),
|
esc_attr__( 'Enter fullscreen', 'fictioneer' ),
|
||||||
fictioneer_get_icon( 'expand' )
|
fictioneer_get_icon( 'expand' )
|
||||||
);
|
);
|
||||||
|
|
||||||
// Close fullscreen
|
// Close fullscreen
|
||||||
$micro_menu['close_fullscreen'] = sprintf(
|
$micro_menu['close_fullscreen'] = sprintf(
|
||||||
'<button type="button" title="%s" class="micro-menu__item micro-menu__close-fullscreen close-fullscreen hide-on-iOS show-on-fullscreen hidden" tabindex="-1">%s</button>',
|
'<button type="button" title="%s" class="micro-menu__item micro-menu__close-fullscreen close-fullscreen hide-on-iOS show-on-fullscreen hidden" tabindex="-1" data-action="click->fictioneer-chapter#closeFullscreen">%s</button>',
|
||||||
esc_attr__( 'Exit fullscreen', 'fictioneer' ),
|
esc_attr__( 'Exit fullscreen', 'fictioneer' ),
|
||||||
fictioneer_get_icon( 'collapse' )
|
fictioneer_get_icon( 'collapse' )
|
||||||
);
|
);
|
||||||
|
|
||||||
// Scroll to bookmark
|
// Scroll to bookmark
|
||||||
$micro_menu['bookmark_jump'] = sprintf(
|
$micro_menu['bookmark_jump'] = sprintf(
|
||||||
'<button type="button" title="%s" class="micro-menu__item micro-menu__bookmark button--bookmark hidden" tabindex="-1"><i class="fa-solid fa-bookmark"></i></button>',
|
'<button type="button" title="%s" class="micro-menu__item micro-menu__bookmark button--bookmark" tabindex="-1" data-action="click->fictioneer-chapter#scrollToBookmark" data-fictioneer-chapter-target="bookmarkScroll" data-fictioneer-bookmarks-target="bookmarkScroll" hidden><i class="fa-solid fa-bookmark"></i></button>',
|
||||||
fcntr( 'jump_to_bookmark', true )
|
fcntr( 'jump_to_bookmark', true )
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1397,11 +1397,11 @@ function fictioneer_get_chapter_index_html( $story_id ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Compile HTML
|
// Compile HTML
|
||||||
$toggle = '<button type="button" data-click-action="toggle-chapter-index-order" class="chapter-index__order list-button" aria-label="' . esc_attr__( 'Toggle between ascending and descending order', 'fictioneer' ) . '"><i class="fa-solid fa-arrow-down-1-9 off"></i><i class="fa-solid fa-arrow-down-9-1 on"></i></button>';
|
$toggle = '<button type="button" data-action="click->fictioneer-chapter#toggleIndexOrder" class="chapter-index__order list-button" aria-label="' . esc_attr__( 'Toggle between ascending and descending order', 'fictioneer' ) . '"><i class="fa-solid fa-arrow-down-1-9 off"></i><i class="fa-solid fa-arrow-down-9-1 on"></i></button>';
|
||||||
|
|
||||||
$back_link = '<a href="' . esc_url( $story_link ) . '" class="chapter-index__back-link"><i class="fa-solid fa-caret-left"></i> <span>' . __( 'Back to Story', 'fictioneer' ) . '</span></a>';
|
$back_link = '<a href="' . esc_url( $story_link ) . '" class="chapter-index__back-link"><i class="fa-solid fa-caret-left"></i> <span>' . __( 'Back to Story', 'fictioneer' ) . '</span></a>';
|
||||||
|
|
||||||
$html = '<div class="chapter-index" data-order="asc" data-story-id="' . $story_id . '"><div class="chapter-index__control">' . $back_link . '<div class="chapter-index__sof">' . $toggle . '</div></div><ul id="chapter-index-list" class="chapter-index__list">' . implode( '', $items ) . '</ul></div>';
|
$html = '<div class="chapter-index" data-fictioneer-chapter-target="index" data-order="asc"><div class="chapter-index__control">' . $back_link . '<div class="chapter-index__sof">' . $toggle . '</div></div><ul id="chapter-index-list" class="chapter-index__list">' . implode( '', $items ) . '</ul></div>';
|
||||||
|
|
||||||
$html = apply_filters( 'fictioneer_filter_chapter_index_html', $html, $items, $story_id, $story_link );
|
$html = apply_filters( 'fictioneer_filter_chapter_index_html', $html, $items, $story_id, $story_link );
|
||||||
|
|
||||||
@ -1641,7 +1641,7 @@ if ( ! function_exists( 'fictioneer_user_menu_items' ) ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Site settings
|
// Site settings
|
||||||
$output['site_settings'] = '<li class="menu-item"><label for="modal-site-settings-toggle" tabindex="0">' . fcntr( 'site_settings' ) . '</label></li>';
|
$output['site_settings'] = '<li class="menu-item"><button data-action="click->fictioneer#toggleModal" data-fictioneer-id-param="site-settings-modal">' . fcntr( 'site_settings' ) . '</button></li>';
|
||||||
|
|
||||||
// Discord link
|
// Discord link
|
||||||
if ( ! empty( $discord_link ) ) {
|
if ( ! empty( $discord_link ) ) {
|
||||||
@ -1668,7 +1668,7 @@ if ( ! function_exists( 'fictioneer_user_menu_items' ) ) {
|
|||||||
|
|
||||||
// Logout
|
// Logout
|
||||||
if ( fictioneer_show_auth_content() ) {
|
if ( fictioneer_show_auth_content() ) {
|
||||||
$output['logout'] = '<li class="menu-item hide-if-logged-out"><a href="' . fictioneer_get_logout_url() . '" data-click="logout" rel="noopener noreferrer nofollow">' . fcntr( 'logout' ) . '</a></li>';
|
$output['logout'] = '<li class="menu-item hide-if-logged-out"><a href="' . fictioneer_get_logout_url() . '" data-action="click->fictioneer#logout" rel="noopener noreferrer nofollow">' . fcntr( 'logout' ) . '</a></li>';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply filters
|
// Apply filters
|
||||||
@ -1817,9 +1817,8 @@ if ( ! function_exists( 'fictioneer_get_card_controls' ) ) {
|
|||||||
// Follows menu item
|
// Follows menu item
|
||||||
if ( $can_follows ) {
|
if ( $can_follows ) {
|
||||||
$menu['follow'] = sprintf(
|
$menu['follow'] = sprintf(
|
||||||
'<button class="popup-action-follow" data-click="card-toggle-follow" data-story-id="%1$s">%2$s</button>' .
|
'<button class="popup-action-follow" data-action="click->fictioneer-large-card#toggleFollow">%1$s</button>' .
|
||||||
'<button class="popup-action-unfollow" data-click="card-toggle-follow" data-story-id="%1$s">%3$s</button>',
|
'<button class="popup-action-unfollow" data-action="click->fictioneer-large-card#toggleFollow">%2$s</button>',
|
||||||
$story_id,
|
|
||||||
fcntr( 'follow' ),
|
fcntr( 'follow' ),
|
||||||
fcntr( 'unfollow' )
|
fcntr( 'unfollow' )
|
||||||
);
|
);
|
||||||
@ -1828,9 +1827,8 @@ if ( ! function_exists( 'fictioneer_get_card_controls' ) ) {
|
|||||||
// Reminders menu item
|
// Reminders menu item
|
||||||
if ( $can_reminders ) {
|
if ( $can_reminders ) {
|
||||||
$menu['reminder'] = sprintf(
|
$menu['reminder'] = sprintf(
|
||||||
'<button class="popup-action-reminder" data-click="card-toggle-reminder" data-story-id="%1$s">%2$s</button>' .
|
'<button class="popup-action-reminder" data-action="click->fictioneer-large-card#toggleReminder">%1$s</button>' .
|
||||||
'<button class="popup-action-forget" data-click="card-toggle-reminder" data-story-id="%1$s">%3$s</button>',
|
'<button class="popup-action-forget" data-action="click->fictioneer-large-card#toggleReminder">%2$s</button>',
|
||||||
$story_id,
|
|
||||||
fcntr( 'read_later' ),
|
fcntr( 'read_later' ),
|
||||||
fcntr( 'forget' )
|
fcntr( 'forget' )
|
||||||
);
|
);
|
||||||
@ -1839,11 +1837,9 @@ if ( ! function_exists( 'fictioneer_get_card_controls' ) ) {
|
|||||||
// Checkmark menu item
|
// Checkmark menu item
|
||||||
if ( $can_checkmarks ) {
|
if ( $can_checkmarks ) {
|
||||||
$menu['checkmark'] = sprintf(
|
$menu['checkmark'] = sprintf(
|
||||||
'<button class="popup-action-mark-read" data-click="card-toggle-checkmarks" data-story-id="%1$s" data-type="%2$s" data-chapter-id="%3$s" data-mode="set">%4$s</button>' .
|
'<button class="popup-action-mark-read" data-action="click->fictioneer-large-card#setCheckmarks" data-fictioneer-large-card-type-param="%1$s">%2$s</button>' .
|
||||||
'<button class="popup-action-mark-unread" data-click="card-toggle-checkmarks" data-story-id="%1$s" data-type="%2$s" data-chapter-id="%3$s" data-mode="unset">%5$s</button>',
|
'<button class="popup-action-mark-unread" data-action="click->fictioneer-large-card#unsetCheckmarks" data-fictioneer-large-card-type-param="%1$s">%3$s</button>',
|
||||||
$story_id,
|
|
||||||
$type,
|
$type,
|
||||||
$chapter_id ?: 'null',
|
|
||||||
fcntr( 'mark_read' ),
|
fcntr( 'mark_read' ),
|
||||||
fcntr( 'mark_unread' )
|
fcntr( 'mark_unread' )
|
||||||
);
|
);
|
||||||
@ -1852,26 +1848,29 @@ if ( ! function_exists( 'fictioneer_get_card_controls' ) ) {
|
|||||||
// Apply filters
|
// Apply filters
|
||||||
$icons = apply_filters( 'fictioneer_filter_card_control_icons', $icons, $story_id, $chapter_id );
|
$icons = apply_filters( 'fictioneer_filter_card_control_icons', $icons, $story_id, $chapter_id );
|
||||||
$menu = apply_filters( 'fictioneer_filter_card_control_menu', $menu, $story_id, $chapter_id );
|
$menu = apply_filters( 'fictioneer_filter_card_control_menu', $menu, $story_id, $chapter_id );
|
||||||
|
$menu_count = count( $menu );
|
||||||
|
|
||||||
// Abort if...
|
// Abort if...
|
||||||
if ( count( $icons ) < 1 || count( $menu ) < 1 ) {
|
if ( count( $icons ) < 1 || $menu_count < 1 ) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build menu
|
// Build menu
|
||||||
$menu_html = '';
|
$menu_html = '';
|
||||||
|
|
||||||
if ( count( $menu ) > 0 ) {
|
if ( $menu_count > 0 ) {
|
||||||
$menu_html = sprintf(
|
$menu_html = sprintf(
|
||||||
'<i class="fa-solid fa-ellipsis-vertical card__popup-menu-toggle" tabindex="0"></i>' .
|
'<i class="fa-solid fa-ellipsis-vertical card__popup-menu-toggle" tabindex="0"></i>' .
|
||||||
'<div class="popup-menu _fixed-position _bottom">%s</div>',
|
'<div class="popup-menu _fixed-position _bottom" data-fictioneer-large-card-target="menu">%s</div>',
|
||||||
implode( '', $menu )
|
implode( '', $menu )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$output = sprintf(
|
$output = sprintf(
|
||||||
'<div class="card__controls %s">%s%s</div>',
|
'<div class="card__controls %s" %s data-fictioneer-large-card-target="controls" data-action="click->fictioneer-large-card#toggleMenu %s">%s%s</div>',
|
||||||
count( $menu ) > 0 ? 'popup-menu-toggle toggle-last-clicked' : '',
|
$menu_count > 0 ? 'popup-menu-toggle' : '',
|
||||||
|
$menu_count > 0 ? 'data-fictioneer-last-click-target="toggle"' : '',
|
||||||
|
$menu_count > 0 ? 'click->fictioneer-last-click#toggle' : '',
|
||||||
implode( '', $icons ),
|
implode( '', $icons ),
|
||||||
$menu_html
|
$menu_html
|
||||||
);
|
);
|
||||||
@ -2361,7 +2360,7 @@ function fictioneer_render_icon_menu( $args ) {
|
|||||||
// Build items
|
// Build items
|
||||||
if ( fictioneer_show_login() ) {
|
if ( fictioneer_show_login() ) {
|
||||||
$output['login'] = sprintf(
|
$output['login'] = sprintf(
|
||||||
'<div class="menu-item menu-item-icon subscriber-login hide-if-logged-in"><label for="modal-login-toggle" title="%1$s" tabindex="0" aria-label="%2$s">%3$s</label></div>',
|
'<div class="menu-item menu-item-icon subscriber-login hide-if-logged-in"><button title="%1$s" aria-label="%2$s" data-action="click->fictioneer#toggleModal" data-fictioneer-id-param="login-modal">%3$s</button></div>',
|
||||||
esc_attr__( 'Login', 'fictioneer' ),
|
esc_attr__( 'Login', 'fictioneer' ),
|
||||||
esc_attr__( 'Open login modal', 'fictioneer' ),
|
esc_attr__( 'Open login modal', 'fictioneer' ),
|
||||||
fictioneer_get_icon( 'fa-login' )
|
fictioneer_get_icon( 'fa-login' )
|
||||||
@ -2370,7 +2369,7 @@ function fictioneer_render_icon_menu( $args ) {
|
|||||||
|
|
||||||
if ( fictioneer_show_auth_content() ) {
|
if ( fictioneer_show_auth_content() ) {
|
||||||
$output['profile'] = sprintf(
|
$output['profile'] = sprintf(
|
||||||
'<div class="menu-item menu-item-icon menu-item-has-children hide-if-logged-out"><a href="%1$s" title="%2$s" class="subscriber-profile" rel="noopener noreferrer nofollow" aria-label="%3$s"><i class="fa-solid fa-circle-user user-icon"></i></a><ul class="sub-menu">%4$s</ul></div>',
|
'<div class="menu-item menu-item-icon menu-item-has-children hide-if-logged-out"><a href="%1$s" title="%2$s" class="subscriber-profile" data-fictioneer-target="avatarWrapper" rel="noopener noreferrer nofollow" aria-label="%3$s"><i class="fa-solid fa-circle-user user-icon"></i></a><ul class="sub-menu">%4$s</ul></div>',
|
||||||
esc_url( $profile_link ),
|
esc_url( $profile_link ),
|
||||||
esc_attr__( 'User Profile', 'fictioneer' ),
|
esc_attr__( 'User Profile', 'fictioneer' ),
|
||||||
esc_attr__( 'Link to user profile', 'fictioneer' ),
|
esc_attr__( 'Link to user profile', 'fictioneer' ),
|
||||||
@ -2380,7 +2379,7 @@ function fictioneer_render_icon_menu( $args ) {
|
|||||||
|
|
||||||
if ( ! empty( $bookmarks_link ) ) {
|
if ( ! empty( $bookmarks_link ) ) {
|
||||||
$output['bookmarks'] = sprintf(
|
$output['bookmarks'] = sprintf(
|
||||||
'<div class="menu-item menu-item-icon icon-menu-bookmarks hidden hide-if-logged-in"><a href="%1$s" title="%2$s" rel="noopener noreferrer nofollow" aria-label="%3$s"><i class="fa-solid fa-bookmark"></i></a></div>',
|
'<div class="menu-item menu-item-icon icon-menu-bookmarks hidden hide-if-logged-in" data-fictioneer-bookmarks-target="overviewPageIconLink"><a href="%1$s" title="%2$s" rel="noopener noreferrer nofollow" aria-label="%3$s"><i class="fa-solid fa-bookmark"></i></a></div>',
|
||||||
esc_url( $bookmarks_link ),
|
esc_url( $bookmarks_link ),
|
||||||
esc_attr__( 'Bookmarks Page', 'fictioneer' ),
|
esc_attr__( 'Bookmarks Page', 'fictioneer' ),
|
||||||
esc_attr__( 'Link to bookmarks page', 'fictioneer' )
|
esc_attr__( 'Link to bookmarks page', 'fictioneer' )
|
||||||
@ -2402,7 +2401,7 @@ function fictioneer_render_icon_menu( $args ) {
|
|||||||
fictioneer_show_auth_content()
|
fictioneer_show_auth_content()
|
||||||
) {
|
) {
|
||||||
$output['follows'] = sprintf(
|
$output['follows'] = sprintf(
|
||||||
'<div class="menu-item menu-item-icon menu-item-has-children hide-if-logged-out"><button id="follow-menu-button" class="icon-menu__item _with-submenu follow-menu-item follows-alert-number mark-follows-read" aria-label="%1$s">%2$s<i class="fa-solid fa-spinner fa-spin" style="--fa-animation-duration: .8s;"></i><span class="follow-menu-item__read">%3$s</span></button><div class="follow-notifications sub-menu"><div id="follow-menu-scroll" class="follow-notifications__scroll"><div class="follow-item"><div class="follow-wrapper"><div class="follow-placeholder truncate _1-1">%4$s</div></div></div></div></div></div>',
|
'<div class="menu-item menu-item-icon menu-item-has-children hide-if-logged-out"><button id="follow-menu-button" class="icon-menu__item _with-submenu follow-menu-item follows-alert-number mark-follows-read" aria-label="%1$s" data-fictioneer-follows-target="newDisplay" data-action="mouseover->fictioneer-follows#loadFollowsHtml:once focus->fictioneer-follows#loadFollowsHtml:once click->fictioneer-follows#markRead">%2$s<i class="fa-solid fa-spinner fa-spin" style="--fa-animation-duration: .8s;"></i><span class="follow-menu-item__read">%3$s</span></button><div class="follow-notifications sub-menu"><div id="follow-menu-scroll" class="follow-notifications__scroll" data-fictioneer-follows-target="scrollList"><div class="follow-item"><div class="follow-wrapper"><div class="follow-placeholder truncate _1-1">%4$s</div></div></div></div></div></div>',
|
||||||
esc_attr__( 'Mark follows as read', 'fictioneer' ),
|
esc_attr__( 'Mark follows as read', 'fictioneer' ),
|
||||||
fictioneer_get_icon( 'fa-bell' ),
|
fictioneer_get_icon( 'fa-bell' ),
|
||||||
_x( 'Read', 'Mark as read button.', 'fictioneer' ),
|
_x( 'Read', 'Mark as read button.', 'fictioneer' ),
|
||||||
@ -2427,7 +2426,7 @@ function fictioneer_render_icon_menu( $args ) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
$output['settings'] = sprintf(
|
$output['settings'] = sprintf(
|
||||||
'<div class="menu-item menu-item-icon site-setting"><label for="modal-site-settings-toggle" title="%1$s" tabindex="0" aria-label="%2$s">%3$s</label></div>',
|
'<div class="menu-item menu-item-icon site-setting"><button title="%1$s" aria-label="%2$s" data-action="click->fictioneer#toggleModal" data-fictioneer-id-param="site-settings-modal">%3$s</button></div>',
|
||||||
esc_attr__( 'Site Settings', 'fictioneer' ),
|
esc_attr__( 'Site Settings', 'fictioneer' ),
|
||||||
esc_attr__( 'Open site settings modal', 'fictioneer' ),
|
esc_attr__( 'Open site settings modal', 'fictioneer' ),
|
||||||
fictioneer_get_icon( 'fa-tools' )
|
fictioneer_get_icon( 'fa-tools' )
|
||||||
@ -2445,7 +2444,7 @@ function fictioneer_render_icon_menu( $args ) {
|
|||||||
|
|
||||||
if ( $location === 'in-mobile-menu' && fictioneer_show_auth_content() ) {
|
if ( $location === 'in-mobile-menu' && fictioneer_show_auth_content() ) {
|
||||||
$output['logout'] = sprintf(
|
$output['logout'] = sprintf(
|
||||||
'<div class="menu-item menu-item-icon hide-if-logged-out"><a href="%1$s" title="%2$s" data-click="logout" rel="noopener noreferrer nofollow" aria-label="%3$s">%4$s</a></div>',
|
'<div class="menu-item menu-item-icon hide-if-logged-out"><a href="%1$s" title="%2$s" data-action="click->fictioneer#logout" rel="noopener noreferrer nofollow" aria-label="%3$s">%4$s</a></div>',
|
||||||
fictioneer_get_logout_url(),
|
fictioneer_get_logout_url(),
|
||||||
esc_attr__( 'Logout', 'fictioneer' ),
|
esc_attr__( 'Logout', 'fictioneer' ),
|
||||||
esc_attr__( 'Click to log out', 'fictioneer' ),
|
esc_attr__( 'Click to log out', 'fictioneer' ),
|
||||||
|
@ -8,8 +8,6 @@
|
|||||||
* Submit contact form via AJAX
|
* Submit contact form via AJAX
|
||||||
*
|
*
|
||||||
* @since 5.0.0
|
* @since 5.0.0
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_error/
|
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_success/
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function fictioneer_ajax_submit_contact_form() {
|
function fictioneer_ajax_submit_contact_form() {
|
||||||
|
@ -95,9 +95,6 @@ function fictioneer_frequency_node( $content ) {
|
|||||||
* Get <url> node helper
|
* Get <url> node helper
|
||||||
*
|
*
|
||||||
* @since 4.0.0
|
* @since 4.0.0
|
||||||
* @see fictioneer_loc_node()
|
|
||||||
* @see fictioneer_lastmod_node()
|
|
||||||
* @see fictioneer_frequency_node()
|
|
||||||
*
|
*
|
||||||
* @param string $loc URL.
|
* @param string $loc URL.
|
||||||
* @param string $lastmod Optional. Last modified timestamp.
|
* @param string $lastmod Optional. Last modified timestamp.
|
||||||
|
@ -949,7 +949,6 @@ function fictioneer_get_cache_salt() {
|
|||||||
* Get static HTML of cached template partial
|
* Get static HTML of cached template partial
|
||||||
*
|
*
|
||||||
* @since 5.18.3
|
* @since 5.18.3
|
||||||
* @see get_template_directory()
|
|
||||||
*
|
*
|
||||||
* @param string|null $dir Optional. Directory path to override the default.
|
* @param string|null $dir Optional. Directory path to override the default.
|
||||||
*
|
*
|
||||||
@ -999,7 +998,6 @@ function fictioneer_create_html_cache_directory( $dir = null ) {
|
|||||||
* Get static HTML of cached template partial
|
* Get static HTML of cached template partial
|
||||||
*
|
*
|
||||||
* @since 5.18.1
|
* @since 5.18.1
|
||||||
* @see get_template_part()
|
|
||||||
*
|
*
|
||||||
* @param string $slug The slug name for the generic template.
|
* @param string $slug The slug name for the generic template.
|
||||||
* @param string $identifier Optional. Additional identifier string for the file. Default empty string.
|
* @param string $identifier Optional. Additional identifier string for the file. Default empty string.
|
||||||
|
@ -52,8 +52,6 @@ fictioneer_add_stud_post_actions( 'fictioneer_update_modified_date_on_story_for_
|
|||||||
* @since 3.0.0
|
* @since 3.0.0
|
||||||
* @since 5.23.0 - Account for non-Latin scripts.
|
* @since 5.23.0 - Account for non-Latin scripts.
|
||||||
* @since 5.25.0 - Split into action and utility function.
|
* @since 5.25.0 - Split into action and utility function.
|
||||||
* @see fictioneer_count_words()
|
|
||||||
* @see update_post_meta()
|
|
||||||
*
|
*
|
||||||
* @param int $post_id Post ID.
|
* @param int $post_id Post ID.
|
||||||
*/
|
*/
|
||||||
@ -79,7 +77,6 @@ if ( ! get_option( 'fictioneer_count_characters_as_words' ) ) {
|
|||||||
* Store character count of posts as word count
|
* Store character count of posts as word count
|
||||||
*
|
*
|
||||||
* @since 5.9.4
|
* @since 5.9.4
|
||||||
* @see update_post_meta()
|
|
||||||
*
|
*
|
||||||
* @param int $post_id Post ID.
|
* @param int $post_id Post ID.
|
||||||
*/
|
*/
|
||||||
|
@ -1059,8 +1059,8 @@ function fictioneer_shortcode_cookie_buttons( $attr ) {
|
|||||||
|
|
||||||
// Start HTML ---> ?>
|
// Start HTML ---> ?>
|
||||||
<div class="cookies spacing-top spacing-bottom ">
|
<div class="cookies spacing-top spacing-bottom ">
|
||||||
<button type="button" data-click="reset-consent" class="button"><?php _e( 'Reset Consent', 'fictioneer' ); ?></button>
|
<button type="button" data-action="click->fictioneer#clearConsent" class="button"><?php _e( 'Reset Consent', 'fictioneer' ); ?></button>
|
||||||
<button type="button" data-click="clear-cookies" data-message="<?php _e( 'Cookies and local storage have been cleared. To keep it that way, you should leave the site.', 'fictioneer' ); ?>" class="button"><?php _e( 'Clear Cookies', 'fictioneer' ); ?></button>
|
<button type="button" data-action="click->fictioneer#clearCookies" data-message="<?php _e( 'Cookies and local storage have been cleared. To keep it that way, you should leave the site.', 'fictioneer' ); ?>" class="button"><?php _e( 'Clear Cookies', 'fictioneer' ); ?></button>
|
||||||
</div>
|
</div>
|
||||||
<?php // <--- End HTML
|
<?php // <--- End HTML
|
||||||
|
|
||||||
@ -1076,7 +1076,6 @@ add_shortcode( 'fictioneer_cookie_buttons', 'fictioneer_shortcode_cookie_buttons
|
|||||||
* Returns empty chapter list
|
* Returns empty chapter list
|
||||||
*
|
*
|
||||||
* @since 5.9.4
|
* @since 5.9.4
|
||||||
* @see fictioneer_shortcode_chapter_list()
|
|
||||||
*
|
*
|
||||||
* @param string|null $attr['heading'] Optional. Show <h5> heading above list.
|
* @param string|null $attr['heading'] Optional. Show <h5> heading above list.
|
||||||
*
|
*
|
||||||
@ -1089,7 +1088,7 @@ function fictioneer_shortcode_chapter_list_empty( $attr ) {
|
|||||||
// Start HTML ---> ?>
|
// Start HTML ---> ?>
|
||||||
<div class="chapter-group chapter-list _standalone _empty">
|
<div class="chapter-group chapter-list _standalone _empty">
|
||||||
<?php if ( ! empty( $attr['heading'] ) ) : ?>
|
<?php if ( ! empty( $attr['heading'] ) ) : ?>
|
||||||
<button class="chapter-group__name" aria-label="<?php echo esc_attr( sprintf( __( 'Toggle chapter group: %s', 'fictioneer' ), $attr['heading'] ) ); ?>" tabindex="0">
|
<button class="chapter-group__name" data-action="click->fictioneer#toggleChapterGroup" aria-label="<?php echo esc_attr( sprintf( __( 'Toggle chapter group: %s', 'fictioneer' ), $attr['heading'] ) ); ?>" tabindex="0">
|
||||||
<i class="fa-solid fa-chevron-down chapter-group__heading-icon"></i>
|
<i class="fa-solid fa-chevron-down chapter-group__heading-icon"></i>
|
||||||
<span><?php echo $attr['heading']; ?></span>
|
<span><?php echo $attr['heading']; ?></span>
|
||||||
</button>
|
</button>
|
||||||
@ -1107,8 +1106,6 @@ function fictioneer_shortcode_chapter_list_empty( $attr ) {
|
|||||||
* Shortcode to show chapter list outside of story pages
|
* Shortcode to show chapter list outside of story pages
|
||||||
*
|
*
|
||||||
* @since 5.0.0
|
* @since 5.0.0
|
||||||
* @see fictioneer_validate_id()
|
|
||||||
* @see fictioneer_get_story_data()
|
|
||||||
*
|
*
|
||||||
* @param string $attr['story_id'] Either/Or. The ID of the story the chapters belong to.
|
* @param string $attr['story_id'] Either/Or. The ID of the story the chapters belong to.
|
||||||
* @param string|null $attr['chapter_ids'] Either/Or. Comma-separated list of chapter IDs.
|
* @param string|null $attr['chapter_ids'] Either/Or. Comma-separated list of chapter IDs.
|
||||||
@ -1221,7 +1218,7 @@ function fictioneer_shortcode_chapter_list( $attr ) {
|
|||||||
// Start HTML ---> ?>
|
// Start HTML ---> ?>
|
||||||
<div class="chapter-group chapter-list _standalone <?php echo esc_attr( $classes ); ?>">
|
<div class="chapter-group chapter-list _standalone <?php echo esc_attr( $classes ); ?>">
|
||||||
<?php if ( $heading ) : ?>
|
<?php if ( $heading ) : ?>
|
||||||
<button class="chapter-group__name" aria-label="<?php echo esc_attr( sprintf( __( 'Toggle chapter group: %s', 'fictioneer' ), $heading ) ); ?>" tabindex="0">
|
<button class="chapter-group__name" data-action="click->fictioneer#toggleChapterGroup" aria-label="<?php echo esc_attr( sprintf( __( 'Toggle chapter group: %s', 'fictioneer' ), $heading ) ); ?>" tabindex="0">
|
||||||
<i class="fa-solid fa-chevron-down chapter-group__heading-icon"></i>
|
<i class="fa-solid fa-chevron-down chapter-group__heading-icon"></i>
|
||||||
<span><?php echo $heading; ?></span>
|
<span><?php echo $heading; ?></span>
|
||||||
</button>
|
</button>
|
||||||
@ -1328,10 +1325,11 @@ function fictioneer_shortcode_chapter_list( $attr ) {
|
|||||||
|
|
||||||
<?php if ( $can_checkmarks && ! empty( $chapter_story_id ) && get_post_status( $chapter_story_id ) === 'publish' ) : ?>
|
<?php if ( $can_checkmarks && ! empty( $chapter_story_id ) && get_post_status( $chapter_story_id ) === 'publish' ) : ?>
|
||||||
<button
|
<button
|
||||||
class="checkmark chapter-group__list-item-checkmark"
|
class="checkmark chapter-group__list-item-checkmark only-logged-in"
|
||||||
data-type="chapter"
|
data-fictioneer-checkmarks-target="chapterCheck"
|
||||||
data-story-id="<?php echo $chapter_story_id; ?>"
|
data-fictioneer-checkmarks-story-param="<?php echo $chapter_story_id; ?>"
|
||||||
data-id="<?php echo $chapter_id; ?>"
|
data-fictioneer-checkmarks-chapter-param="<?php echo $chapter_id; ?>"
|
||||||
|
data-action="click->fictioneer-checkmarks#toggleChapter"
|
||||||
role="checkbox"
|
role="checkbox"
|
||||||
aria-checked="false"
|
aria-checked="false"
|
||||||
aria-label="<?php
|
aria-label="<?php
|
||||||
@ -2111,7 +2109,7 @@ function fictioneer_shortcode_subscribe_button( $attr ) {
|
|||||||
// Build and return button
|
// Build and return button
|
||||||
if ( ! empty( $subscribe_buttons ) ) {
|
if ( ! empty( $subscribe_buttons ) ) {
|
||||||
return sprintf(
|
return sprintf(
|
||||||
'<div class="toggle-last-clicked subscribe-menu-toggle button _secondary popup-menu-toggle _popup-right-if-last ' . esc_attr( $classes ) . '" tabindex="0" role="button" aria-label="%s"><div><i class="fa-solid fa-bell"></i> %s</div><div class="popup-menu _bottom _center">%s</div></div>',
|
'<div class="subscribe-menu-toggle button _secondary popup-menu-toggle _popup-right-if-last ' . esc_attr( $classes ) . '" tabindex="0" role="button" aria-label="%s" data-fictioneer-last-click-target="toggle" data-action="click->fictioneer-last-click#toggle"><div><i class="fa-solid fa-bell"></i> %s</div><div class="popup-menu _bottom _center">%s</div></div>',
|
||||||
fcntr( 'subscribe', true ),
|
fcntr( 'subscribe', true ),
|
||||||
fcntr( 'subscribe' ),
|
fcntr( 'subscribe' ),
|
||||||
$subscribe_buttons
|
$subscribe_buttons
|
||||||
|
@ -705,6 +705,9 @@ function fictioneer_root_attributes() {
|
|||||||
$classes[] = 'no-page-shadow';
|
$classes[] = 'no-page-shadow';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Stimulus
|
||||||
|
$output['data-controller'] = 'fictioneer';
|
||||||
|
|
||||||
// Prepare
|
// Prepare
|
||||||
$output['class'] = implode( ' ', $classes );
|
$output['class'] = implode( ' ', $classes );
|
||||||
$output['data-mode-default'] = get_option( 'fictioneer_dark_mode_as_default', false ) ? 'dark' : 'light';
|
$output['data-mode-default'] = get_option( 'fictioneer_dark_mode_as_default', false ) ? 'dark' : 'light';
|
||||||
@ -738,26 +741,30 @@ function fictioneer_root_attributes() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$conditions = array(
|
$conditions = array(
|
||||||
'data-age-confirmation' => get_option( 'fictioneer_enable_site_age_confirmation' ),
|
'age-confirmation' => get_option( 'fictioneer_enable_site_age_confirmation' ),
|
||||||
'data-caching-active' => fictioneer_caching_active( 'root_attribute' ),
|
'caching-active' => fictioneer_caching_active( 'root_attribute' ),
|
||||||
'data-ajax-submit' => get_option( 'fictioneer_enable_ajax_comment_submit', false ),
|
'ajax-submit' => get_option( 'fictioneer_enable_ajax_comment_submit', false ),
|
||||||
'data-force-child-theme' => ! FICTIONEER_THEME_SWITCH,
|
'force-child-theme' => ! FICTIONEER_THEME_SWITCH,
|
||||||
'data-public-caching' => get_option( 'fictioneer_enable_public_cache_compatibility', false ),
|
'public-caching' => get_option( 'fictioneer_enable_public_cache_compatibility', false ),
|
||||||
'data-ajax-auth' => get_option( 'fictioneer_enable_ajax_authentication', false ),
|
'ajax-auth' => get_option( 'fictioneer_enable_ajax_authentication', false ),
|
||||||
'data-edit-time' => get_option( 'fictioneer_enable_user_comment_editing', false ) ?
|
'edit-time' => get_option( 'fictioneer_enable_user_comment_editing', false ) ?
|
||||||
get_option( 'fictioneer_user_comment_edit_time', 15 ) : false,
|
get_option( 'fictioneer_user_comment_edit_time', 15 ) : false,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Iterate conditions and add the truthy to the output
|
// Iterate conditions and add the truthy to the output
|
||||||
foreach ( $conditions as $key => $condition ) {
|
foreach ( $conditions as $key => $condition ) {
|
||||||
if ( $condition ) {
|
if ( $condition ) {
|
||||||
$output[ $key ] = is_bool( $condition ) ? '1' : $condition;
|
$value = is_bool( $condition ) ? '1' : $condition;
|
||||||
|
|
||||||
|
$output["data-{$key}"] = $value;
|
||||||
|
$output["data-fictioneer-{$key}-value"] = $value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fingerprint
|
// Fingerprint
|
||||||
if ( $post_author_id ) {
|
if ( $post_author_id ) {
|
||||||
$output['data-author-fingerprint'] = fictioneer_get_user_fingerprint( $post_author_id );
|
$output['data-author-fingerprint'] = fictioneer_get_user_fingerprint( $post_author_id );
|
||||||
|
$output['data-fictioneer-fingerprint-value'] = $output['data-author-fingerprint'];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter output
|
// Filter output
|
||||||
@ -1250,7 +1257,6 @@ function fictioneer_build_dynamic_scripts() {
|
|||||||
'ajax_url' => admin_url( 'admin-ajax.php' ),
|
'ajax_url' => admin_url( 'admin-ajax.php' ),
|
||||||
'rest_url' => get_rest_url( null, 'fictioneer/v1/' ),
|
'rest_url' => get_rest_url( null, 'fictioneer/v1/' ),
|
||||||
'ttl' => FICTIONEER_AJAX_TTL,
|
'ttl' => FICTIONEER_AJAX_TTL,
|
||||||
'login_ttl' => FICTIONEER_AJAX_LOGIN_TTL,
|
|
||||||
'post_debounce_rate' => FICTIONEER_AJAX_POST_DEBOUNCE_RATE
|
'post_debounce_rate' => FICTIONEER_AJAX_POST_DEBOUNCE_RATE
|
||||||
)) . ";";
|
)) . ";";
|
||||||
|
|
||||||
@ -1319,17 +1325,9 @@ function fictioneer_add_custom_scripts() {
|
|||||||
// Application
|
// Application
|
||||||
wp_register_script( 'fictioneer-application-scripts', get_template_directory_uri() . '/js/application.min.js', [ 'fictioneer-utility-scripts', 'fictioneer-dynamic-scripts'], $cache_bust, $strategy );
|
wp_register_script( 'fictioneer-application-scripts', get_template_directory_uri() . '/js/application.min.js', [ 'fictioneer-utility-scripts', 'fictioneer-dynamic-scripts'], $cache_bust, $strategy );
|
||||||
|
|
||||||
// Lightbox
|
|
||||||
if ( get_option( 'fictioneer_enable_lightbox' ) ) {
|
|
||||||
wp_enqueue_script( 'fictioneer-lightbox', get_template_directory_uri() . '/js/lightbox.min.js', ['fictioneer-application-scripts'], $cache_bust, $strategy );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mobile menu
|
// Mobile menu
|
||||||
wp_register_script( 'fictioneer-mobile-menu-scripts', get_template_directory_uri() . '/js/mobile-menu.min.js', [ 'fictioneer-application-scripts'], $cache_bust, $strategy );
|
wp_register_script( 'fictioneer-mobile-menu-scripts', get_template_directory_uri() . '/js/mobile-menu.min.js', [ 'fictioneer-application-scripts'], $cache_bust, $strategy );
|
||||||
|
|
||||||
// Consent
|
|
||||||
wp_register_script( 'fictioneer-consent-scripts', get_template_directory_uri() . '/js/laws.min.js', [ 'fictioneer-application-scripts'], $cache_bust, $strategy );
|
|
||||||
|
|
||||||
// Chapter
|
// Chapter
|
||||||
wp_register_script( 'fictioneer-chapter-scripts', get_template_directory_uri() . '/js/chapter.min.js', [ 'fictioneer-application-scripts'], $cache_bust, $strategy );
|
wp_register_script( 'fictioneer-chapter-scripts', get_template_directory_uri() . '/js/chapter.min.js', [ 'fictioneer-application-scripts'], $cache_bust, $strategy );
|
||||||
|
|
||||||
@ -1345,26 +1343,23 @@ function fictioneer_add_custom_scripts() {
|
|||||||
// Story
|
// Story
|
||||||
wp_register_script( 'fictioneer-story-scripts', get_template_directory_uri() . '/js/story.min.js', [ 'fictioneer-application-scripts'], $cache_bust, $strategy );
|
wp_register_script( 'fictioneer-story-scripts', get_template_directory_uri() . '/js/story.min.js', [ 'fictioneer-application-scripts'], $cache_bust, $strategy );
|
||||||
|
|
||||||
// User
|
|
||||||
wp_register_script( 'fictioneer-user-scripts', get_template_directory_uri() . '/js/user.min.js', [ 'fictioneer-application-scripts'], $cache_bust, $strategy );
|
|
||||||
|
|
||||||
// User Profile
|
// User Profile
|
||||||
wp_register_script( 'fictioneer-user-profile-scripts', get_template_directory_uri() . '/js/user-profile.min.js', [ 'fictioneer-application-scripts', 'fictioneer-user-scripts'], $cache_bust, $strategy );
|
wp_register_script( 'fictioneer-user-profile-scripts', get_template_directory_uri() . '/js/user-profile.min.js', [ 'fictioneer-application-scripts'], $cache_bust, $strategy );
|
||||||
|
|
||||||
// CSS Skins
|
// CSS Skins
|
||||||
wp_register_script( 'fictioneer-css-skins-scripts', get_template_directory_uri() . '/js/css-skins.min.js', [ 'fictioneer-application-scripts', 'fictioneer-user-scripts'], $cache_bust, $strategy );
|
wp_register_script( 'fictioneer-css-skins-scripts', get_template_directory_uri() . '/js/css-skins.min.js', [ 'fictioneer-application-scripts'], $cache_bust, $strategy );
|
||||||
|
|
||||||
// Bookmarks
|
// Bookmarks
|
||||||
wp_register_script( 'fictioneer-bookmarks-scripts', get_template_directory_uri() . '/js/bookmarks.min.js', [ 'fictioneer-application-scripts', 'fictioneer-user-scripts'], $cache_bust, $strategy );
|
wp_register_script( 'fictioneer-bookmarks-scripts', get_template_directory_uri() . '/js/bookmarks.min.js', [ 'fictioneer-application-scripts'], $cache_bust, $strategy );
|
||||||
|
|
||||||
// Follows
|
// Follows
|
||||||
wp_register_script( 'fictioneer-follows-scripts', get_template_directory_uri() . '/js/follows.min.js', [ 'fictioneer-application-scripts', 'fictioneer-user-scripts'], $cache_bust, $strategy );
|
wp_register_script( 'fictioneer-follows-scripts', get_template_directory_uri() . '/js/follows.min.js', [ 'fictioneer-application-scripts'], $cache_bust, $strategy );
|
||||||
|
|
||||||
// Checkmarks
|
// Checkmarks
|
||||||
wp_register_script( 'fictioneer-checkmarks-scripts', get_template_directory_uri() . '/js/checkmarks.min.js', [ 'fictioneer-application-scripts', 'fictioneer-user-scripts'], $cache_bust, $strategy );
|
wp_register_script( 'fictioneer-checkmarks-scripts', get_template_directory_uri() . '/js/checkmarks.min.js', [ 'fictioneer-application-scripts'], $cache_bust, $strategy );
|
||||||
|
|
||||||
// Reminders
|
// Reminders
|
||||||
wp_register_script( 'fictioneer-reminders-scripts', get_template_directory_uri() . '/js/reminders.min.js', [ 'fictioneer-application-scripts', 'fictioneer-user-scripts'], $cache_bust, $strategy );
|
wp_register_script( 'fictioneer-reminders-scripts', get_template_directory_uri() . '/js/reminders.min.js', [ 'fictioneer-application-scripts'], $cache_bust, $strategy );
|
||||||
|
|
||||||
// Comments
|
// Comments
|
||||||
wp_register_script( 'fictioneer-comments-scripts', get_template_directory_uri() . '/js/comments.min.js', [ 'fictioneer-application-scripts'], $cache_bust, $strategy );
|
wp_register_script( 'fictioneer-comments-scripts', get_template_directory_uri() . '/js/comments.min.js', [ 'fictioneer-application-scripts'], $cache_bust, $strategy );
|
||||||
@ -1384,11 +1379,6 @@ function fictioneer_add_custom_scripts() {
|
|||||||
// Enqueue mobile menu
|
// Enqueue mobile menu
|
||||||
wp_enqueue_script( 'fictioneer-mobile-menu-scripts' );
|
wp_enqueue_script( 'fictioneer-mobile-menu-scripts' );
|
||||||
|
|
||||||
// Enqueue consent
|
|
||||||
if ( get_option( 'fictioneer_cookie_banner' ) ) {
|
|
||||||
wp_enqueue_script( 'fictioneer-consent-scripts' );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enqueue chapter
|
// Enqueue chapter
|
||||||
if ( $post_type == 'fcn_chapter' && ! is_archive() && ! is_search() ) {
|
if ( $post_type == 'fcn_chapter' && ! is_archive() && ! is_search() ) {
|
||||||
wp_enqueue_script( 'fictioneer-chapter-scripts' );
|
wp_enqueue_script( 'fictioneer-chapter-scripts' );
|
||||||
@ -1424,10 +1414,8 @@ function fictioneer_add_custom_scripts() {
|
|||||||
wp_enqueue_script( 'fictioneer-story-scripts' );
|
wp_enqueue_script( 'fictioneer-story-scripts' );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enqueue users + user profile + follows + checkmarks + reminders
|
// Enqueue user profile + follows + checkmarks + reminders
|
||||||
if ( is_user_logged_in() || get_option( 'fictioneer_enable_ajax_authentication' ) ) {
|
if ( is_user_logged_in() || get_option( 'fictioneer_enable_ajax_authentication' ) ) {
|
||||||
wp_enqueue_script( 'fictioneer-user-scripts' );
|
|
||||||
|
|
||||||
if ( get_option( 'fictioneer_enable_checkmarks' ) ) {
|
if ( get_option( 'fictioneer_enable_checkmarks' ) ) {
|
||||||
wp_enqueue_script( 'fictioneer-checkmarks-scripts' );
|
wp_enqueue_script( 'fictioneer-checkmarks-scripts' );
|
||||||
}
|
}
|
||||||
@ -1603,7 +1591,7 @@ add_filter( 'customize_refresh_nonces', 'fictioneer_add_customizer_refresh_nonce
|
|||||||
function fictioneer_wp_login_scripts() {
|
function fictioneer_wp_login_scripts() {
|
||||||
// Clear web storage in preparation of login
|
// Clear web storage in preparation of login
|
||||||
wp_print_inline_script_tag(
|
wp_print_inline_script_tag(
|
||||||
'localStorage.removeItem("fcnUserData"); localStorage.removeItem("fcnAuth");',
|
'localStorage.removeItem("fcnUserData");',
|
||||||
array(
|
array(
|
||||||
'id' => 'fictioneer-login-scripts',
|
'id' => 'fictioneer-login-scripts',
|
||||||
'type' => 'text/javascript',
|
'type' => 'text/javascript',
|
||||||
@ -1679,7 +1667,7 @@ add_filter( 'autoptimize_filter_css_exclude', 'fictioneer_ao_exclude_css' );
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function fictioneer_ao_exclude_js( $exclude ) {
|
function fictioneer_ao_exclude_js( $exclude ) {
|
||||||
return $exclude . ', fictioneer/js/splide.min.js';
|
return $exclude . ', fictioneer/js/splide.min.js, fictioneer/js/stimulus.umd.min.js';
|
||||||
}
|
}
|
||||||
add_filter( 'autoptimize_filter_js_exclude', 'fictioneer_ao_exclude_js' );
|
add_filter( 'autoptimize_filter_js_exclude', 'fictioneer_ao_exclude_js' );
|
||||||
|
|
||||||
@ -1898,6 +1886,26 @@ if ( get_option( 'fictioneer_enable_css_skins' ) ) {
|
|||||||
add_action( 'wp_head', 'fictioneer_output_critical_skin_scripts', 9999 );
|
add_action( 'wp_head', 'fictioneer_output_critical_skin_scripts', 9999 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// STIMULUS
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Outputs Stimulus in <head>
|
||||||
|
*
|
||||||
|
* @since 5.27.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
function fictioneer_output_stimulus() {
|
||||||
|
$link = get_template_directory_uri() . '/js/stimulus.umd.min.js?bust=' . fictioneer_get_cache_bust();
|
||||||
|
|
||||||
|
// Start HTML ---> ?>
|
||||||
|
<script id="fictioneer-stimulus-umd" src="<?php echo esc_url( $link ); ?>" type="text/javascript" data-jetpack-boost="ignore" data-no-optimize="1" data-no-defer="1" data-no-minify="1"></script>
|
||||||
|
<script id="fictioneer-stimulus-setup" type="text/javascript" data-jetpack-boost="ignore" data-no-optimize="1" data-no-defer="1" data-no-minify="1">const application = Stimulus.Application.start();</script>
|
||||||
|
<?php // <--- End HTML
|
||||||
|
}
|
||||||
|
add_action( 'wp_head', 'fictioneer_output_stimulus', 5 );
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// ADD EXCERPTS TO PAGES
|
// ADD EXCERPTS TO PAGES
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
@ -2009,9 +2017,6 @@ function fictioneer_get_js_translations() {
|
|||||||
'enterPageNumber' => _x( 'Enter page number:', 'Pagination jump prompt.', 'fictioneer' ),
|
'enterPageNumber' => _x( 'Enter page number:', 'Pagination jump prompt.', 'fictioneer' ),
|
||||||
'slowDown' => _x( 'Slow down.', 'Rate limit reached notification.', 'fictioneer' ),
|
'slowDown' => _x( 'Slow down.', 'Rate limit reached notification.', 'fictioneer' ),
|
||||||
'error' => _x( 'Error', 'Generic error notification.', 'fictioneer' ),
|
'error' => _x( 'Error', 'Generic error notification.', 'fictioneer' ),
|
||||||
'checkmarksResynchronized' => __( 'Checkmarks re-synchronized.', 'fictioneer' ),
|
|
||||||
'remindersResynchronized' => __( 'Reminders re-synchronized.', 'fictioneer' ),
|
|
||||||
'followsResynchronized' => __( 'Follows re-synchronized.', 'fictioneer' ),
|
|
||||||
'suggestionAppendedToComment' => __( 'Suggestion appended to comment!<br><a style="font-weight: 700;" href="#comments">Go to comment section.</a>', 'fictioneer' ),
|
'suggestionAppendedToComment' => __( 'Suggestion appended to comment!<br><a style="font-weight: 700;" href="#comments">Go to comment section.</a>', 'fictioneer' ),
|
||||||
'quoteAppendedToComment' => __( 'Quote appended to comment!<br><a style="font-weight: 700;" href="#comments">Go to comment section.</a>', 'fictioneer' ),
|
'quoteAppendedToComment' => __( 'Quote appended to comment!<br><a style="font-weight: 700;" href="#comments">Go to comment section.</a>', 'fictioneer' ),
|
||||||
'linkCopiedToClipboard' => __( 'Link copied to clipboard!', 'fictioneer' ),
|
'linkCopiedToClipboard' => __( 'Link copied to clipboard!', 'fictioneer' ),
|
||||||
|
@ -261,7 +261,7 @@ if ( ! function_exists( 'fictioneer_get_logout_url' ) ) {
|
|||||||
|
|
||||||
function fictioneer_after_logout_cleanup() {
|
function fictioneer_after_logout_cleanup() {
|
||||||
wp_print_inline_script_tag(
|
wp_print_inline_script_tag(
|
||||||
'localStorage.removeItem("fcnProfileAvatar"); localStorage.removeItem("fcnUserData"); localStorage.removeItem("fcnAuth"); localStorage.removeItem("fcnBookshelfContent"); localStorage.removeItem("fcnChapterBookmarks");',
|
'localStorage.removeItem("fcnUserData"); localStorage.removeItem("fcnBookshelfContent"); localStorage.removeItem("fcnChapterBookmarks");',
|
||||||
array(
|
array(
|
||||||
'id' => 'fictioneer-logout-cleanup',
|
'id' => 'fictioneer-logout-cleanup',
|
||||||
'type' => 'text/javascript',
|
'type' => 'text/javascript',
|
||||||
@ -1533,11 +1533,10 @@ function fictioneer_fast_ajax() {
|
|||||||
'fictioneer_ajax_clear_my_checkmarks',
|
'fictioneer_ajax_clear_my_checkmarks',
|
||||||
'fictioneer_ajax_get_finished_checkmarks_list',
|
'fictioneer_ajax_get_finished_checkmarks_list',
|
||||||
// User
|
// User
|
||||||
'fictioneer_ajax_get_auth',
|
|
||||||
'fictioneer_ajax_get_user_data',
|
'fictioneer_ajax_get_user_data',
|
||||||
'fictioneer_ajax_get_avatar',
|
|
||||||
'fictioneer_ajax_save_skins',
|
'fictioneer_ajax_save_skins',
|
||||||
'fictioneer_ajax_get_skins',
|
'fictioneer_ajax_get_skins',
|
||||||
|
'fictioneer_ajax_clear_cookies',
|
||||||
// Admin
|
// Admin
|
||||||
'fictioneer_ajax_query_relationship_posts',
|
'fictioneer_ajax_query_relationship_posts',
|
||||||
'fictioneer_ajax_search_posts_to_unlock'
|
'fictioneer_ajax_search_posts_to_unlock'
|
||||||
|
@ -2121,7 +2121,7 @@ function fcntr( $key, $escape = false ) {
|
|||||||
'bbcode_ins' => _x( '<code>[ins]</code><ins>Insert</ins><code>[/ins]</code> more bad puns!', 'BBCode example.', 'fictioneer' ),
|
'bbcode_ins' => _x( '<code>[ins]</code><ins>Insert</ins><code>[/ins]</code> more bad puns!', 'BBCode example.', 'fictioneer' ),
|
||||||
'bbcode_del' => _x( '<code>[del]</code><del>Delete</del><code>[/del]</code> your browser history!', 'BBCode example.', 'fictioneer' ),
|
'bbcode_del' => _x( '<code>[del]</code><del>Delete</del><code>[/del]</code> your browser history!', 'BBCode example.', 'fictioneer' ),
|
||||||
'log_in_with' => _x( 'Enter your details or log in with:', 'Comment form login note.', 'fictioneer' ),
|
'log_in_with' => _x( 'Enter your details or log in with:', 'Comment form login note.', 'fictioneer' ),
|
||||||
'logged_in_as' => _x( '<span>Logged in as <strong><a href="%1$s">%2$s</a></strong>. <a class="logout-link" href="%3$s" data-click="logout">Log out?</a></span>', 'Comment form logged-in note.', 'fictioneer' ),
|
'logged_in_as' => _x( '<span>Logged in as <strong><a href="%1$s">%2$s</a></strong>. <a class="logout-link" href="%3$s" data-action="click->fictioneer#logout">Log out?</a></span>', 'Comment form logged-in note.', 'fictioneer' ),
|
||||||
'accept_privacy_policy' => _x( 'I accept the <b><a class="link" href="%s" target="_blank">privacy policy</a></b>.', 'Comment form privacy checkbox.', 'fictioneer' ),
|
'accept_privacy_policy' => _x( 'I accept the <b><a class="link" href="%s" target="_blank">privacy policy</a></b>.', 'Comment form privacy checkbox.', 'fictioneer' ),
|
||||||
'save_in_cookie' => _x( 'Save in cookie for next time.', 'Comment form cookie checkbox.', 'fictioneer' ),
|
'save_in_cookie' => _x( 'Save in cookie for next time.', 'Comment form cookie checkbox.', 'fictioneer' ),
|
||||||
'future_prefix' => _x( 'Scheduled:', 'Chapter list status prefix.', 'fictioneer' ),
|
'future_prefix' => _x( 'Scheduled:', 'Chapter list status prefix.', 'fictioneer' ),
|
||||||
@ -2266,7 +2266,6 @@ if ( ! function_exists( 'fictioneer_check_comment_disallowed_list' ) ) {
|
|||||||
* returns the offenders within the comment content
|
* returns the offenders within the comment content
|
||||||
*
|
*
|
||||||
* @since 5.0.0
|
* @since 5.0.0
|
||||||
* @see wp_check_comment_disallowed_list()
|
|
||||||
*
|
*
|
||||||
* @param string $author The author of the comment.
|
* @param string $author The author of the comment.
|
||||||
* @param string $email The email of the comment.
|
* @param string $email The email of the comment.
|
||||||
@ -3850,52 +3849,3 @@ function fictioneer_get_wp_debug_log() {
|
|||||||
// Return HTML
|
// Return HTML
|
||||||
return '<ul class="fictioneer-log _wp-debug-log">' . $output . '</ul>';
|
return '<ul class="fictioneer-log _wp-debug-log">' . $output . '</ul>';
|
||||||
}
|
}
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
// AJAX REQUESTS
|
|
||||||
// > Return early if no AJAX functions are required.
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
if ( ! wp_doing_ajax() ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
// AJAX AUTHENTICATION
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* AJAX: Send user authentication status
|
|
||||||
*
|
|
||||||
* @since 5.7.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
function fictioneer_ajax_get_auth() {
|
|
||||||
// Enabled?
|
|
||||||
if ( ! get_option( 'fictioneer_enable_ajax_authentication' ) ) {
|
|
||||||
wp_send_json_error( null, 403 );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup
|
|
||||||
$user = wp_get_current_user();
|
|
||||||
$nonce = wp_create_nonce( 'fictioneer_nonce' );
|
|
||||||
$nonce_html = '<input id="fictioneer-ajax-nonce" name="fictioneer-ajax-nonce" type="hidden" value="' . $nonce . '">';
|
|
||||||
|
|
||||||
// Response
|
|
||||||
wp_send_json_success(
|
|
||||||
array(
|
|
||||||
'loggedIn' => is_user_logged_in(),
|
|
||||||
'isAdmin' => fictioneer_is_admin( $user->ID ),
|
|
||||||
'isModerator' => fictioneer_is_moderator( $user->ID ),
|
|
||||||
'isAuthor' => fictioneer_is_author( $user->ID ),
|
|
||||||
'isEditor' => fictioneer_is_editor( $user->ID ),
|
|
||||||
'nonce' => $nonce,
|
|
||||||
'nonceHtml' => $nonce_html
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( get_option( 'fictioneer_enable_ajax_authentication' ) ) {
|
|
||||||
add_action( 'wp_ajax_fictioneer_ajax_get_auth', 'fictioneer_ajax_get_auth' );
|
|
||||||
add_action( 'wp_ajax_nopriv_fictioneer_ajax_get_auth', 'fictioneer_ajax_get_auth' );
|
|
||||||
}
|
|
||||||
|
@ -8,8 +8,6 @@
|
|||||||
* Sends the comment form HTML via AJAX
|
* Sends the comment form HTML via AJAX
|
||||||
*
|
*
|
||||||
* @since 5.0.0
|
* @since 5.0.0
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_error/
|
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_success/
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function fictioneer_ajax_get_comment_form() {
|
function fictioneer_ajax_get_comment_form() {
|
||||||
@ -38,7 +36,7 @@ function fictioneer_ajax_get_comment_form() {
|
|||||||
if ( get_option( 'fictioneer_disable_comment_form' ) ) {
|
if ( get_option( 'fictioneer_disable_comment_form' ) ) {
|
||||||
comment_form( [], $post_id );
|
comment_form( [], $post_id );
|
||||||
} else {
|
} else {
|
||||||
comment_form( fictioneer_comment_form_args( [], $post_id ), $post_id );
|
fictioneer_comment_form( fictioneer_comment_form_args( [], $post_id ), $post_id );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get buffer
|
// Get buffer
|
||||||
@ -63,8 +61,6 @@ if ( get_option( 'fictioneer_enable_ajax_comment_form' ) ) {
|
|||||||
* Sends the comment section HTML via AJAX
|
* Sends the comment section HTML via AJAX
|
||||||
*
|
*
|
||||||
* @since 5.0.0
|
* @since 5.0.0
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_error/
|
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_success/
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function fictioneer_ajax_get_comment_section() {
|
function fictioneer_ajax_get_comment_section() {
|
||||||
@ -138,7 +134,7 @@ function fictioneer_ajax_get_comment_section() {
|
|||||||
if ( get_option( 'fictioneer_disable_comment_form' ) ) {
|
if ( get_option( 'fictioneer_disable_comment_form' ) ) {
|
||||||
comment_form( [], $post_id );
|
comment_form( [], $post_id );
|
||||||
} else {
|
} else {
|
||||||
comment_form( fictioneer_comment_form_args( [], $post_id ), $post_id );
|
fictioneer_comment_form( fictioneer_comment_form_args( [], $post_id ), $post_id );
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
echo '<div class="fictioneer-comments__disabled">' . __( 'Commenting is disabled.', 'fictioneer' ) . '</div>';
|
echo '<div class="fictioneer-comments__disabled">' . __( 'Commenting is disabled.', 'fictioneer' ) . '</div>';
|
||||||
@ -209,8 +205,6 @@ if ( get_option( 'fictioneer_enable_ajax_comments' ) ) {
|
|||||||
*
|
*
|
||||||
* @since 5.0.0
|
* @since 5.0.0
|
||||||
* @since 5.20.3 - Use form field names as keys.
|
* @since 5.20.3 - Use form field names as keys.
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_error/
|
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_success/
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function fictioneer_ajax_submit_comment() {
|
function fictioneer_ajax_submit_comment() {
|
||||||
@ -429,8 +423,6 @@ if ( get_option( 'fictioneer_enable_ajax_comment_submit' ) ) {
|
|||||||
* Edit comment via AJAX
|
* Edit comment via AJAX
|
||||||
*
|
*
|
||||||
* @since 5.0.0
|
* @since 5.0.0
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_error/
|
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_success/
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function fictioneer_ajax_edit_comment() {
|
function fictioneer_ajax_edit_comment() {
|
||||||
@ -567,8 +559,6 @@ if ( get_option( 'fictioneer_enable_user_comment_editing' ) ) {
|
|||||||
* Delete a user's comment on AJAX request
|
* Delete a user's comment on AJAX request
|
||||||
*
|
*
|
||||||
* @since 5.0.0
|
* @since 5.0.0
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_error/
|
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_success/
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function fictioneer_ajax_delete_my_comment() {
|
function fictioneer_ajax_delete_my_comment() {
|
||||||
|
@ -301,8 +301,6 @@ if ( ! get_option( 'fictioneer_disable_comment_form' ) ) {
|
|||||||
* @since 4.7.0
|
* @since 4.7.0
|
||||||
* @link https://developer.wordpress.org/reference/hooks/comment_post/
|
* @link https://developer.wordpress.org/reference/hooks/comment_post/
|
||||||
* @link https://github.com/WordPress/WordPress/blob/master/wp-includes/comment.php
|
* @link https://github.com/WordPress/WordPress/blob/master/wp-includes/comment.php
|
||||||
* @see add_comment_meta()
|
|
||||||
* @see filter_var()
|
|
||||||
*
|
*
|
||||||
* @param int $comment_id The comment ID.
|
* @param int $comment_id The comment ID.
|
||||||
* @param int|string $comment_approved 1 if the comment is approved, 0 if not, 'spam' if spam.
|
* @param int|string $comment_approved 1 if the comment is approved, 0 if not, 'spam' if spam.
|
||||||
|
@ -1,5 +1,26 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// COMMENT FORM HELPER
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
if ( ! function_exists( 'fictioneer_comment_form' ) ) {
|
||||||
|
/**
|
||||||
|
* Renders comment form with injected custom HTML
|
||||||
|
*
|
||||||
|
* @since 5.27.0
|
||||||
|
*
|
||||||
|
* @param array $args Default arguments and form fields to override.
|
||||||
|
* @param int|WP_Post $post Post ID or WP_Post object to generate the form for. Default current post.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function fictioneer_comment_form( $args = array(), $post = \null ) {
|
||||||
|
ob_start();
|
||||||
|
comment_form( $args, $post );
|
||||||
|
echo str_replace( '<form', '<form data-controller="fictioneer-comment-form" ', ob_get_clean() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// COMMENT TOOLBAR
|
// COMMENT TOOLBAR
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
@ -22,7 +43,7 @@ if ( ! function_exists( 'fictioneer_get_comment_toolbar' ) ) {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
return '<div class="fictioneer-comment-toolbar"><span class="fictioneer-comment-toolbar-bold" data-bbcode="b"><i class="fa-solid fa-bold"></i></span><span class="fictioneer-comment-toolbar-italic" data-bbcode="i"><i class="fa-solid fa-italic"></i></span><span class="fictioneer-comment-toolbar-strike" data-bbcode="s"><i class="fa-solid fa-strikethrough"></i></span><span class="fictioneer-comment-toolbar-image" data-bbcode="img"><i class="fa-solid fa-image"></i></span><span class="fictioneer-comment-toolbar-link" data-bbcode="link"><i class="fa-solid fa-link"></i></span><span class="fictioneer-comment-toolbar-quote" data-bbcode="quote"><i class="fa-solid fa-quote-left"></i></span><span class="fictioneer-comment-toolbar-spoiler" data-bbcode="spoiler"><i class="fa-solid fa-eye-low-vision"></i></span><label class="fictioneer-comment-toolbar-help" for="modal-bbcodes-toggle"><i class="fa-solid fa-circle-question"></i></label></div>';
|
return '<div class="fictioneer-comment-toolbar" data-action="click->fictioneer-comment-form#toolbarButtons"><span class="fictioneer-comment-toolbar-bold" data-bbcode="b"><i class="fa-solid fa-bold"></i></span><span class="fictioneer-comment-toolbar-italic" data-bbcode="i"><i class="fa-solid fa-italic"></i></span><span class="fictioneer-comment-toolbar-strike" data-bbcode="s"><i class="fa-solid fa-strikethrough"></i></span><span class="fictioneer-comment-toolbar-image" data-bbcode="img"><i class="fa-solid fa-image"></i></span><span class="fictioneer-comment-toolbar-link" data-bbcode="link"><i class="fa-solid fa-link"></i></span><span class="fictioneer-comment-toolbar-quote" data-bbcode="quote"><i class="fa-solid fa-quote-left"></i></span><span class="fictioneer-comment-toolbar-spoiler" data-bbcode="spoiler"><i class="fa-solid fa-eye-low-vision"></i></span><span class="fictioneer-comment-toolbar-help" data-action="click->fictioneer#toggleModal" data-fictioneer-id-param="bbcodes-modal"><i class="fa-solid fa-circle-question"></i></span></div>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,22 +76,22 @@ function fictioneer_change_comment_fields( $fields ) {
|
|||||||
$hidden = FICTIONEER_COLLAPSE_COMMENT_FORM ? 'hidden' : '';
|
$hidden = FICTIONEER_COLLAPSE_COMMENT_FORM ? 'hidden' : '';
|
||||||
|
|
||||||
// Rebuild author field
|
// Rebuild author field
|
||||||
$fields['author'] = '<div class="comment-form-author"><input type="text" name="author" data-lpignore="true" value="' . esc_attr( $commenter['comment_author'] ) . '"' . $required_attribute . ' maxlength="245" placeholder="' . $name_placeholder . '"></div>';
|
$fields['author'] = '<div class="comment-form-author"><input type="text" name="author" data-lpignore="true" value="' . esc_attr( $commenter['comment_author'] ) . '"' . $required_attribute . ' maxlength="245" placeholder="' . $name_placeholder . '" data-fictioneer-comment-form-target="author"></div>';
|
||||||
|
|
||||||
// Rebuild email field
|
// Rebuild email field
|
||||||
$fields['email'] = '<div class="comment-form-email"><input type="text" name="email" data-lpignore="true" value="' . esc_attr( $commenter['comment_author_email'] ) . '" maxlength="100" aria-describedby="email-notes" placeholder="' . $email_placeholder . '"' . $required_attribute . '></div>';
|
$fields['email'] = '<div class="comment-form-email"><input type="email" name="email" data-lpignore="true" value="' . esc_attr( $commenter['comment_author_email'] ) . '" maxlength="100" aria-describedby="email-notes" placeholder="' . $email_placeholder . '"' . $required_attribute . ' data-fictioneer-comment-form-target="email"></div>';
|
||||||
|
|
||||||
// Open .fictioneer-respond__checkboxes wrapper
|
// Open .fictioneer-respond__checkboxes wrapper
|
||||||
$fields['checkboxes'] = '<div class="fictioneer-respond__form-checkboxes fictioneer-respond__form-bottom-block">';
|
$fields['checkboxes'] = '<div class="fictioneer-respond__form-checkboxes fictioneer-respond__form-bottom-block">';
|
||||||
|
|
||||||
// Rebuild cookies field (ignores 'show_comments_cookies_opt_in' and is always enabled)
|
// Rebuild cookies field (ignores 'show_comments_cookies_opt_in' and is always enabled)
|
||||||
$fields['cookies'] = '<label class="comment-form-cookies-consent fictioneer-respond__checkbox-label-pair"><input name="wp-comment-cookies-consent" type="checkbox" value="yes"' . $cookie_checked_attribute . '><span>' . fcntr( 'save_in_cookie' ) . '</span></label>';
|
$fields['cookies'] = '<label class="comment-form-cookies-consent fictioneer-respond__checkbox-label-pair"><input name="wp-comment-cookies-consent" type="checkbox" value="yes"' . $cookie_checked_attribute . ' data-fictioneer-comment-form-target="cookies"><span>' . fcntr( 'save_in_cookie' ) . '</span></label>';
|
||||||
|
|
||||||
// Build new privacy policy field
|
// Build new privacy policy field
|
||||||
$privacy_policy = '';
|
$privacy_policy = '';
|
||||||
|
|
||||||
if ( $privacy_policy_link ) {
|
if ( $privacy_policy_link ) {
|
||||||
$privacy_policy = '<label class="comment-form-privacy-policy-consent fictioneer-respond__checkbox-label-pair"><input name="fictioneer-privacy-policy-consent" type="checkbox" value="1" required' . $cookie_checked_attribute . '><span>' . sprintf( fcntr( 'accept_privacy_policy' ), $privacy_policy_link ) . '</span></label>';
|
$privacy_policy = '<label class="comment-form-privacy-policy-consent fictioneer-respond__checkbox-label-pair"><input name="fictioneer-privacy-policy-consent" type="checkbox" value="1" required' . $cookie_checked_attribute . ' data-fictioneer-comment-form-target="privacyPolicy"><span>' . sprintf( fcntr( 'accept_privacy_policy' ), $privacy_policy_link ) . '</span></label>';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append checkboxes and close .fictioneer-respond__checkboxes wrapper
|
// Append checkboxes and close .fictioneer-respond__checkboxes wrapper
|
||||||
@ -131,7 +152,7 @@ function fictioneer_change_submit_field( $submit_field, $args ) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
$submit_button = sprintf(
|
$submit_button = sprintf(
|
||||||
'<input name="%1$s" type="submit" id="%2$s" class="%3$s" value="%4$s" data-enabled="%4$s" data-disabled="Posting…">',
|
'<input name="%1$s" type="submit" id="%2$s" class="%3$s" value="%4$s" data-enabled="%4$s" data-disabled="Posting…" data-fictioneer-comment-form-target="submit" data-action="click->fictioneer-comment-form#ajaxSubmit">',
|
||||||
esc_attr( $args['name_submit'] ),
|
esc_attr( $args['name_submit'] ),
|
||||||
esc_attr( $args['id_submit'] ),
|
esc_attr( $args['id_submit'] ),
|
||||||
esc_attr( $args['class_submit'] ) . ' button fictioneer-respond__form-submit',
|
esc_attr( $args['class_submit'] ) . ' button fictioneer-respond__form-submit',
|
||||||
@ -143,7 +164,7 @@ function fictioneer_change_submit_field( $submit_field, $args ) {
|
|||||||
|
|
||||||
if ( get_option( 'fictioneer_enable_private_commenting' ) ) {
|
if ( get_option( 'fictioneer_enable_private_commenting' ) ) {
|
||||||
$hint = esc_attr_x( 'Toggle to mark as private. Hides the comment from uninvolved viewers.', 'Comment form private toggle.', 'fictioneer' );
|
$hint = esc_attr_x( 'Toggle to mark as private. Hides the comment from uninvolved viewers.', 'Comment form private toggle.', 'fictioneer' );
|
||||||
$private_toggle = '<div class="fictioneer-private-comment-toggle fictioneer-respond__form-toggle"><label class="comment-respond-option-toggle" tabindex="0" role="checkbox" aria-checked="false" aria-label="' . $hint . '"><input name="fictioneer-private-comment-toggle" type="checkbox" tabindex="-1" hidden><span class="tooltipped _mobile-tooltip" data-tooltip="' . $hint . '"><i class="fa-solid fa-eye off"></i><i class="fa-solid fa-eye-slash on"></i></span></label></div>';
|
$private_toggle = '<div class="fictioneer-private-comment-toggle fictioneer-respond__form-toggle"><label class="comment-respond-option-toggle" tabindex="0" role="checkbox" aria-checked="false" aria-label="' . $hint . '"><input name="fictioneer-private-comment-toggle" type="checkbox" tabindex="-1" data-fictioneer-comment-form-target="privateToggle" data-action="change->fictioneer-comment-form#togglePrivate" hidden><span class="tooltipped _mobile-tooltip" data-tooltip="' . $hint . '"><i class="fa-solid fa-eye off"></i><i class="fa-solid fa-eye-slash on"></i></span></label></div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Email subscriptions toggle
|
// Email subscriptions toggle
|
||||||
@ -155,7 +176,7 @@ function fictioneer_change_submit_field( $submit_field, $args ) {
|
|||||||
if ( get_option( 'fictioneer_enable_comment_notifications' ) && ! $notifications_blocked ) {
|
if ( get_option( 'fictioneer_enable_comment_notifications' ) && ! $notifications_blocked ) {
|
||||||
$hint = esc_attr_x( 'Toggle to get email notifications about direct replies.', 'Comment form email notification toggle.', 'fictioneer' );
|
$hint = esc_attr_x( 'Toggle to get email notifications about direct replies.', 'Comment form email notification toggle.', 'fictioneer' );
|
||||||
$aria_checked = $notification_checked ? 'true' : 'false';
|
$aria_checked = $notification_checked ? 'true' : 'false';
|
||||||
$notification_toggle = '<div class="fictioneer-comment-notification-toggle fictioneer-respond__form-toggle"><label class="comment-respond-option-toggle" tabindex="0" role="checkbox" aria-checked="' . $aria_checked . '" aria-label="' . $hint . '"><input name="fictioneer-comment-notification-toggle" type="checkbox" ' . checked( 1, $notification_checked, false ) . ' tabindex="-1" hidden><span class="tooltipped _mobile-tooltip" data-tooltip="' . $hint . '"><i class="fa-solid fa-bell on"></i><i class="fa-solid fa-bell-slash off"></i></span></label></div>';
|
$notification_toggle = '<div class="fictioneer-comment-notification-toggle fictioneer-respond__form-toggle"><label class="comment-respond-option-toggle" tabindex="0" role="checkbox" aria-checked="' . $aria_checked . '" aria-label="' . $hint . '"><input name="fictioneer-comment-notification-toggle" type="checkbox" ' . checked( 1, $notification_checked, false ) . ' tabindex="-1" data-fictioneer-comment-form-target="emailNotificationToggle" hidden><span class="tooltipped _mobile-tooltip" data-tooltip="' . $hint . '"><i class="fa-solid fa-bell on"></i><i class="fa-solid fa-bell-slash off"></i></span></label></div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hidden parent_comment field
|
// Hidden parent_comment field
|
||||||
@ -189,7 +210,7 @@ function fictioneer_change_submit_field( $submit_field, $args ) {
|
|||||||
$close_bottom_container . '<div class="form-submit fictioneer-respond__form-actions ' . $hidden . '"><div class="fictioneer-respond__form-actions-wrapper">' . $private_toggle . $notification_toggle . '%1$s %2$s</div>%3$s</div><div class="fictioneer-respond__notices">' . $private_notice . '</div>',
|
$close_bottom_container . '<div class="form-submit fictioneer-respond__form-actions ' . $hidden . '"><div class="fictioneer-respond__form-actions-wrapper">' . $private_toggle . $notification_toggle . '%1$s %2$s</div>%3$s</div><div class="fictioneer-respond__notices">' . $private_notice . '</div>',
|
||||||
$submit_button,
|
$submit_button,
|
||||||
( $post_id ? get_comment_id_fields( $post_id ) : ( $parent_field . $comment_post_id ) ) . $order_field,
|
( $post_id ? get_comment_id_fields( $post_id ) : ( $parent_field . $comment_post_id ) ) . $order_field,
|
||||||
preg_replace( '/<a/', '<a class="button _secondary"', get_cancel_comment_reply_link( 'Cancel' ) )
|
preg_replace( '/<a/', '<a data-fictioneer-comment-form-target="cancel" class="button _secondary"', get_cancel_comment_reply_link( 'Cancel' ) )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -245,7 +266,7 @@ function fictioneer_comment_form_args( $defaults = [], $post_id = null ) {
|
|||||||
fictioneer_get_logout_url( get_permalink( $post_id ) )
|
fictioneer_get_logout_url( get_permalink( $post_id ) )
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
$comment_field = "<div class='comment-form-comment fictioneer-respond__form-comment'><textarea id='comment' class='adaptive-textarea' aria-label='{$aria_label_textarea}' name='comment' maxlength='65525' required></textarea>{$toolbar}</div>";
|
$comment_field = "<div class='comment-form-comment fictioneer-respond__form-comment'><textarea id='comment' class='adaptive-textarea' aria-label='{$aria_label_textarea}' name='comment' maxlength='65525' data-fictioneer-comment-form-target='textarea' data-action='keydown->fictioneer-comment-form#keyComboCodes input->fictioneer-comment-form#adjustTextarea focus->fictioneer-comment-form#revealFormInputs:once' required></textarea>{$toolbar}</div>";
|
||||||
|
|
||||||
// Prepare arguments
|
// Prepare arguments
|
||||||
$args = array(
|
$args = array(
|
||||||
@ -274,7 +295,7 @@ function fictioneer_comment_form_args( $defaults = [], $post_id = null ) {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
$args['must_log_in'] = '<div class="fictioneer-respond__must-login">' . __( 'You must be <label for="modal-login-toggle">logged in</label> to comment.', 'fictioneer' ) . '</div>';
|
$args['must_log_in'] = '<div class="fictioneer-respond__must-login">' . __( 'You must be <button data-action="click->fictioneer#toggleModal" data-fictioneer-id-param="login-modal">logged in</button> to comment.', 'fictioneer' ) . '</div>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -371,132 +371,64 @@ function fictioneer_track_comment_edit( $data, $comment ) {
|
|||||||
}
|
}
|
||||||
add_filter( 'wp_update_comment_data', 'fictioneer_track_comment_edit', 10, 2 );
|
add_filter( 'wp_update_comment_data', 'fictioneer_track_comment_edit', 10, 2 );
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
// GET COMMENT ACTION LINK
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
if ( ! function_exists( 'fictioneer_get_comment_action_link' ) ) {
|
|
||||||
/**
|
|
||||||
* Returns a link to an admin comment moderation action or false
|
|
||||||
*
|
|
||||||
* @since 4.7.0
|
|
||||||
* @link https://github.com/WordPress/WordPress/blob/master/wp-admin/comment.php
|
|
||||||
*
|
|
||||||
* @param int $comment_id The ID of the comment.
|
|
||||||
* @param string $action Optional. The action to perform. Default 'edit'.
|
|
||||||
* @param string|boolean $redirect_to Optional. Return URL after action. Default false.
|
|
||||||
*
|
|
||||||
* @return string|boolean The link or false if an invalid call.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function fictioneer_get_comment_action_link( $comment_id, $action = 'edit', $redirect_to = false ) {
|
|
||||||
// Setup
|
|
||||||
$comment_id = fictioneer_validate_id( $comment_id );
|
|
||||||
|
|
||||||
// Validation
|
|
||||||
if ( ! $comment_id ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Data
|
|
||||||
$template = '<a class="comment-' . $action . '-link" href="%1$s">%2$s</a>';
|
|
||||||
$admin_url = admin_url( 'comment.php?c=' . $comment_id . '&action=' );
|
|
||||||
$redirect_to = $redirect_to ? '&redirect_to=' . $redirect_to : '';
|
|
||||||
$output = false;
|
|
||||||
|
|
||||||
switch ( $action ) {
|
|
||||||
case 'edit':
|
|
||||||
$output = sprintf( $template, $admin_url . 'editcomment', __( 'Edit' ) );
|
|
||||||
break;
|
|
||||||
case 'spam':
|
|
||||||
$nonce_url = esc_url( wp_nonce_url( $admin_url . 'spamcomment', 'delete-comment_' . $comment_id ) );
|
|
||||||
$output = sprintf( $template, $nonce_url . $redirect_to, __( 'Spam' ) );
|
|
||||||
break;
|
|
||||||
case 'trash':
|
|
||||||
$nonce_url = esc_url( wp_nonce_url( $admin_url . 'trashcomment', 'delete-comment_' . $comment_id ) );
|
|
||||||
$output = sprintf( $template, $nonce_url . $redirect_to, __( 'Trash' ) );
|
|
||||||
break;
|
|
||||||
case 'approve':
|
|
||||||
$nonce_url = esc_url( wp_nonce_url( $admin_url . 'approvecomment', 'approve-comment_' . $comment_id ) );
|
|
||||||
$output = sprintf( $template, $nonce_url . $redirect_to, __( 'Approve' ) );
|
|
||||||
break;
|
|
||||||
case 'unapprove':
|
|
||||||
$nonce_url = esc_url( wp_nonce_url( $admin_url . 'unapprovecomment', 'approve-comment_' . $comment_id ) );
|
|
||||||
$output = sprintf( $template, $nonce_url . $redirect_to, __( 'Unapprove' ) );
|
|
||||||
break;
|
|
||||||
case 'delete':
|
|
||||||
$nonce_url = esc_url( wp_nonce_url( $admin_url . 'deletecomment', 'delete-comment_' . $comment_id ) );
|
|
||||||
$output = sprintf( $template, $nonce_url . $redirect_to, __( 'Delete' ) );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $output;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// RENDER COMMENT MODERATION MENU
|
// RENDER COMMENT MODERATION MENU
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
if ( ! function_exists( 'fictioneer_comment_mod_menu' ) ) {
|
function fictioneer_comment_moderation_template() {
|
||||||
|
// Abort if...
|
||||||
|
if ( ! get_option( 'fictioneer_enable_ajax_comment_moderation' ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start HTML ---> ?>
|
||||||
|
<template id="template-comment-frontend-moderation-menu">
|
||||||
|
<button data-action="click->fictioneer-comment#trash"><?php _e( 'Trash', 'fictioneer' ); ?></button>
|
||||||
|
<button data-action="click->fictioneer-comment#spam"><?php _e( 'Spam', 'fictioneer' ); ?></button>
|
||||||
|
<button data-action="click->fictioneer-comment#offensive"><?php _e( 'Offensive', 'fictioneer' ); ?></button>
|
||||||
|
<button data-action="click->fictioneer-comment#unoffensive"><?php _e( 'Unoffensive', 'fictioneer' ); ?></button>
|
||||||
|
<button data-action="click->fictioneer-comment#unapprove"><?php _e( 'Unapprove', 'fictioneer' ); ?></button>
|
||||||
|
<button data-action="click->fictioneer-comment#approve"><?php _e( 'Approve', 'fictioneer' ); ?></button>
|
||||||
|
<button data-action="click->fictioneer-comment#close"><?php _e( 'Close', 'fictioneer' ); ?></button>
|
||||||
|
<button data-action="click->fictioneer-comment#open"><?php _e( 'Open', 'fictioneer' ); ?></button>
|
||||||
|
|
||||||
|
<?php if ( get_option( 'fictioneer_enable_sticky_comments' ) ) : ?>
|
||||||
|
<button data-action="click->fictioneer-comment#sticky"><?php _e( 'Sticky', 'fictioneer' ); ?></button>
|
||||||
|
<button data-action="click->fictioneer-comment#unsticky"><?php _e( 'Unsticky', 'fictioneer' ); ?></button>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<a class="comment-edit-link" data-fictioneer-comment-target="editLink"><?php _e( 'Edit' ); ?></a>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
<?php // <--- End HTML
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! function_exists( 'fictioneer_comment_moderation' ) ) {
|
||||||
/**
|
/**
|
||||||
* Renders HTML for the moderation menu
|
* Renders icon and frame for the frontend comment moderation
|
||||||
*
|
*
|
||||||
* @since 4.7.0
|
* @since 4.7.0
|
||||||
*
|
*
|
||||||
* @param WP_Comment $comment Comment object.
|
* @param WP_Comment $comment Comment object.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function fictioneer_comment_mod_menu( $comment ) {
|
function fictioneer_comment_moderation( $comment ) {
|
||||||
// Setup
|
|
||||||
$comment_id = $comment->comment_ID;
|
|
||||||
$user_can_moderate = fictioneer_user_can_moderate( $comment );
|
|
||||||
|
|
||||||
// Abort conditions...
|
// Abort conditions...
|
||||||
if (
|
if (
|
||||||
! current_user_can( 'moderate_comments' ) &&
|
! current_user_can( 'moderate_comments' ) &&
|
||||||
! $user_can_moderate &&
|
! fictioneer_user_can_moderate( $comment ) &&
|
||||||
! get_option( 'fictioneer_enable_public_cache_compatibility' )
|
! get_option( 'fictioneer_enable_public_cache_compatibility' )
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start HTML ---> ?>
|
// Setup
|
||||||
<div class="popup-menu-toggle comment-quick-button toggle-last-clicked hide-if-logged-out only-moderators hide-on-ajax" tabindex="0">
|
$edit_link = admin_url( 'comment.php?c=' . $comment->comment_ID . '&action=editcomment' );
|
||||||
<i class="fa-solid fa-gear mod-menu-toggle-icon"></i>
|
|
||||||
<div class="popup-menu hide-if-logged-out only-moderators _top _justify-right _fixed-position">
|
|
||||||
<?php if ( get_option( 'fictioneer_enable_ajax_comment_moderation' ) ) : ?>
|
|
||||||
<button data-id="<?php echo $comment_id; ?>" data-click="ajax-mod-action" data-action="trash"><?php _e( 'Trash', 'fictioneer' ); ?></button>
|
|
||||||
<button data-id="<?php echo $comment_id; ?>" data-click="ajax-mod-action" data-action="spam"><?php _e( 'Spam', 'fictioneer' ); ?></button>
|
|
||||||
<button data-id="<?php echo $comment_id; ?>" data-click="ajax-mod-action" data-action="offensive"><?php _e( 'Offensive', 'fictioneer' ); ?></button>
|
|
||||||
<button data-id="<?php echo $comment_id; ?>" data-click="ajax-mod-action" data-action="unoffensive"><?php _e( 'Unoffensive', 'fictioneer' ); ?></button>
|
|
||||||
<button data-id="<?php echo $comment_id; ?>" data-click="ajax-mod-action" data-action="unapprove"><?php _e( 'Unapprove', 'fictioneer' ); ?></button>
|
|
||||||
<button data-id="<?php echo $comment_id; ?>" data-click="ajax-mod-action" data-action="approve"><?php _e( 'Approve', 'fictioneer' ); ?></button>
|
|
||||||
<button data-id="<?php echo $comment_id; ?>" data-click="ajax-mod-action" data-action="close"><?php _e( 'Close', 'fictioneer' ); ?></button>
|
|
||||||
<button data-id="<?php echo $comment_id; ?>" data-click="ajax-mod-action" data-action="open"><?php _e( 'Open', 'fictioneer' ); ?></button>
|
|
||||||
<?php else : ?>
|
|
||||||
<?php
|
|
||||||
echo fictioneer_get_comment_action_link( $comment_id, 'trash', '#comments' );
|
|
||||||
echo fictioneer_get_comment_action_link( $comment_id, 'spam', '#comments' );
|
|
||||||
|
|
||||||
if ( $comment->comment_approved == '0' ) {
|
// Start HTML ---> ?>
|
||||||
echo fictioneer_get_comment_action_link( $comment_id, 'approve', get_comment_link( $comment_id ) );
|
<div class="popup-menu-toggle comment-quick-button hide-if-logged-out only-moderators hide-on-ajax" tabindex="0" data-fictioneer-last-click-target="toggle" data-fictioneer-comment-target="modMenuToggle" data-action="click->fictioneer-comment#toggleMenu click->fictioneer-last-click#toggle">
|
||||||
} else {
|
<i class="fa-solid fa-gear mod-menu-toggle-icon" data-fictioneer-comment-target="modIcon"></i>
|
||||||
echo fictioneer_get_comment_action_link( $comment_id, 'unapprove', get_comment_link( $comment_id ) );
|
<div data-fictioneer-comment-target="modMenu" data-edit-link="<?php echo esc_attr( $edit_link ); ?>" class="popup-menu _top _justify-right _fixed-position"></div>
|
||||||
}
|
|
||||||
?>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php
|
|
||||||
if (
|
|
||||||
get_option( 'fictioneer_enable_sticky_comments' ) &&
|
|
||||||
get_option( 'fictioneer_enable_ajax_comment_moderation' )
|
|
||||||
) :
|
|
||||||
?>
|
|
||||||
<button data-click="ajax-mod-action" data-id="<?php echo $comment_id; ?>" data-action="sticky"><?php _e( 'Sticky', 'fictioneer' ); ?></button>
|
|
||||||
<button data-click="ajax-mod-action" data-id="<?php echo $comment_id; ?>" data-action="unsticky"><?php _e( 'Unsticky', 'fictioneer' ); ?></button>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php echo fictioneer_get_comment_action_link( $comment_id, 'edit' ); ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<?php // <--- End HTML
|
<?php // <--- End HTML
|
||||||
}
|
}
|
||||||
@ -510,8 +442,6 @@ if ( ! function_exists( 'fictioneer_comment_mod_menu' ) ) {
|
|||||||
* Performs comment moderation action via AJAX
|
* Performs comment moderation action via AJAX
|
||||||
*
|
*
|
||||||
* @since 4.7.0
|
* @since 4.7.0
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_success/
|
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_error/
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function fictioneer_ajax_moderate_comment() {
|
function fictioneer_ajax_moderate_comment() {
|
||||||
|
@ -25,7 +25,7 @@ function fictioneer_comment_login_to_reply( $link, $args, $comment, $post ) {
|
|||||||
|
|
||||||
// Reply link or login modal toggle
|
// Reply link or login modal toggle
|
||||||
if ( get_option( 'comment_registration' ) && ! is_user_logged_in() ) {
|
if ( get_option( 'comment_registration' ) && ! is_user_logged_in() ) {
|
||||||
return $args['before'] . '<label for="modal-login-toggle" class="fictioneer-comment__login-to-reply">' . $args['login_text'] . '</label>' . $args['after'];
|
return $args['before'] . '<button class="fictioneer-comment__login-to-reply" data-action="click->fictioneer#toggleModal" data-fictioneer-id-param="login-modal">' . $args['login_text'] . '</button>' . $args['after'];
|
||||||
} else {
|
} else {
|
||||||
return $link;
|
return $link;
|
||||||
}
|
}
|
||||||
@ -226,6 +226,9 @@ if ( ! function_exists( 'fictioneer_ajax_list_comments' ) ) {
|
|||||||
<i class="fa-solid fa-arrow-up-short-wide _off"></i><i class="fa-solid fa-arrow-down-wide-short _on"></i>
|
<i class="fa-solid fa-arrow-up-short-wide _off"></i><i class="fa-solid fa-arrow-down-wide-short _on"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<?php fictioneer_comment_moderation_template(); ?>
|
||||||
|
|
||||||
<ol class="fictioneer-comments__list commentlist">
|
<ol class="fictioneer-comments__list commentlist">
|
||||||
<?php wp_list_comments( $list_args, $comments ); ?>
|
<?php wp_list_comments( $list_args, $comments ); ?>
|
||||||
</ol>
|
</ol>
|
||||||
@ -339,14 +342,14 @@ function fictioneer_get_comment_delete_button( $hidden = true ) {
|
|||||||
static $html_start = null;
|
static $html_start = null;
|
||||||
|
|
||||||
if ( is_null( $html_start ) ) {
|
if ( is_null( $html_start ) ) {
|
||||||
$html_start = '<button class="fictioneer-comment__delete comment-quick-button hide-on-edit tooltipped hide-if-logged-out hide-on-ajax" type="button" data-dialog-message="' .
|
$html_start = '<button class="fictioneer-comment__delete comment-quick-button hide-on-edit tooltipped hide-if-logged-out hide-on-ajax" type="button" data-fictioneer-comment-target="deleteButton" data-action="click->fictioneer-comment#selfDelete" data-dialog-message="' .
|
||||||
sprintf(
|
sprintf(
|
||||||
__( 'Are you sure you want to delete your comment? Enter %s to confirm.', 'fictioneer' ),
|
__( 'Are you sure you want to delete your comment? Enter %s to confirm.', 'fictioneer' ),
|
||||||
mb_strtoupper( _x( 'delete', 'Prompt confirm deletion string.', 'fictioneer' ) )
|
mb_strtoupper( _x( 'delete', 'Prompt confirm deletion string.', 'fictioneer' ) )
|
||||||
) .
|
) .
|
||||||
'" data-dialog-confirm="' . esc_attr_x( 'delete', 'Prompt confirm deletion string.', 'fictioneer' ) .
|
'" data-dialog-confirm="' . esc_attr_x( 'delete', 'Prompt confirm deletion string.', 'fictioneer' ) .
|
||||||
'" data-tooltip="' . esc_attr_x( 'Delete', 'Delete comment inline.', 'fictioneer' ) .
|
'" data-tooltip="' . esc_attr_x( 'Delete', 'Delete comment inline.', 'fictioneer' ) .
|
||||||
'" data-click="delete-my-comment" %s><i class="fa-solid fa-eraser"></i></button>';
|
'" %s><i class="fa-solid fa-eraser"></i></button>';
|
||||||
}
|
}
|
||||||
|
|
||||||
return sprintf(
|
return sprintf(
|
||||||
@ -369,7 +372,7 @@ function fictioneer_get_comment_edit_button( $hidden = true ) {
|
|||||||
static $html_start = null;
|
static $html_start = null;
|
||||||
|
|
||||||
if ( is_null( $html_start ) ) {
|
if ( is_null( $html_start ) ) {
|
||||||
$html_start = '<button class="fictioneer-comment__edit-toggle comment-quick-button hide-on-edit tooltipped hide-if-logged-out hide-on-ajax" type="button" data-tooltip="' . esc_attr_x( 'Edit', 'Edit comment inline.', 'fictioneer' ) . '" data-click="trigger-inline-comment-edit" %s><i class="fa-solid fa-pen"></i></button>';
|
$html_start = '<button class="fictioneer-comment__edit-toggle comment-quick-button hide-on-edit tooltipped hide-if-logged-out hide-on-ajax" type="button" data-fictioneer-comment-target="editButton" data-action="click->fictioneer-comment#startEditInline" data-tooltip="' . esc_attr_x( 'Edit', 'Edit comment inline.', 'fictioneer' ) . '" %s><i class="fa-solid fa-pen"></i></button>';
|
||||||
}
|
}
|
||||||
|
|
||||||
return sprintf(
|
return sprintf(
|
||||||
@ -551,14 +554,14 @@ if ( ! function_exists( 'fictioneer_theme_comment' ) ) {
|
|||||||
|
|
||||||
// Build HTML (tag closed by WordPress!)
|
// Build HTML (tag closed by WordPress!)
|
||||||
$comment_class = comment_class( $classes, $comment, $comment->comment_post_ID, false );
|
$comment_class = comment_class( $classes, $comment, $comment->comment_post_ID, false );
|
||||||
$fingerprint_data = empty( $fingerprint ) ? '' : "data-fingerprint=\"$fingerprint\"";
|
$fingerprint_data = empty( $fingerprint ) ? '' : "data-fictioneer-comment-fingerprint-value=\"$fingerprint\"";
|
||||||
|
|
||||||
if ( $is_new ) {
|
if ( $is_new ) {
|
||||||
$comment_class = str_replace( 'depth-1', "depth-$depth", $comment_class );
|
$comment_class = str_replace( 'depth-1', "depth-$depth", $comment_class );
|
||||||
}
|
}
|
||||||
|
|
||||||
$open = "<{$tag} id=\"comment-{$comment->comment_ID}\" {$comment_class} data-id=\"{$comment->comment_ID}\" data-depth=\"{$depth}\" data-timestamp=\"" . ( $timestamp * 1000 ) . "\" {$fingerprint_data}>";
|
$open = "<{$tag} id=\"comment-{$comment->comment_ID}\" {$comment_class} data-id=\"{$comment->comment_ID}\" data-depth=\"{$depth}\">";
|
||||||
$open .= "<div id=\"div-comment-{$comment->comment_ID}\" class=\"fictioneer-comment__container\">";
|
$open .= "<div id=\"div-comment-{$comment->comment_ID}\" class=\"fictioneer-comment__container\" data-controller=\"fictioneer-comment\" data-action=\"click->fictioneer-comment#commentClick mouseleave->fictioneer-comment#mouseLeave:stop\" data-fictioneer-comment-id-value=\"{$comment->comment_ID}\" data-fictioneer-comment-timestamp-value=\"" . ( $timestamp * 1000 ) . "\" {$fingerprint_data}>";
|
||||||
|
|
||||||
if ( $is_sticky ) {
|
if ( $is_sticky ) {
|
||||||
$open .= '<i class="fa-solid fa-thumbtack sticky-pin"></i>';
|
$open .= '<i class="fa-solid fa-thumbtack sticky-pin"></i>';
|
||||||
@ -613,7 +616,7 @@ if ( ! function_exists( 'fictioneer_theme_comment' ) ) {
|
|||||||
<?php _e( 'Comment has been deleted by user.', 'fictioneer' ); ?>
|
<?php _e( 'Comment has been deleted by user.', 'fictioneer' ); ?>
|
||||||
</div>
|
</div>
|
||||||
<div class="fictioneer-comment__footer-right hide-unless-hover-on-desktop">
|
<div class="fictioneer-comment__footer-right hide-unless-hover-on-desktop">
|
||||||
<?php fictioneer_comment_mod_menu( $comment ); ?>
|
<?php fictioneer_comment_moderation( $comment ); ?>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -677,15 +680,19 @@ if ( ! function_exists( 'fictioneer_theme_comment' ) ) {
|
|||||||
// COMMENT CONTENT
|
// COMMENT CONTENT
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
?>
|
?>
|
||||||
<div class="fictioneer-comment__content"><?php comment_text( $comment ); ?></div>
|
<div class="fictioneer-comment__content" data-fictioneer-comment-target="content"><?php
|
||||||
|
comment_text( $comment );
|
||||||
|
?></div>
|
||||||
<?php
|
<?php
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// COMMENT EDIT
|
// COMMENT EDIT
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
?>
|
?>
|
||||||
<?php if ( ( $can_edit && $is_editable ) || ( $cache_plugin_active && ! $is_deleted_by_owner) ) : ?>
|
<?php if ( ( $can_edit && $is_editable ) || ( $cache_plugin_active && ! $is_deleted_by_owner) ) : ?>
|
||||||
<div class="fictioneer-comment__edit" hidden>
|
<div class="fictioneer-comment__edit" data-fictioneer-comment-target="inlineEditWrapper" hidden>
|
||||||
<textarea class="comment-inline-edit-content"><?php echo $comment->comment_content; ?></textarea>
|
<textarea class="comment-inline-edit-content" data-fictioneer-comment-target="inlineEditTextarea" data-action="keydown->fictioneer-comment#keyComboCodes"><?php
|
||||||
|
echo $comment->comment_content;
|
||||||
|
?></textarea>
|
||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<?php
|
<?php
|
||||||
@ -694,7 +701,7 @@ if ( ! function_exists( 'fictioneer_theme_comment' ) ) {
|
|||||||
// =============================================================================
|
// =============================================================================
|
||||||
?>
|
?>
|
||||||
<?php if ( ! empty( $edit_stack ) && ! $is_deleted_by_owner ) : ?>
|
<?php if ( ! empty( $edit_stack ) && ! $is_deleted_by_owner ) : ?>
|
||||||
<div class="fictioneer-comment__edit-note"><?php
|
<div class="fictioneer-comment__edit-note" data-fictioneer-comment-target="editNote"><?php
|
||||||
$edit_data = $edit_stack[count( $edit_stack ) - 1];
|
$edit_data = $edit_stack[count( $edit_stack ) - 1];
|
||||||
$edit_user = isset( $edit_data['user_id'] ) && $comment->user_id != $edit_data['user_id'] ?
|
$edit_user = isset( $edit_data['user_id'] ) && $comment->user_id != $edit_data['user_id'] ?
|
||||||
get_user_by( 'id', $edit_data['user_id'] ) : false;
|
get_user_by( 'id', $edit_data['user_id'] ) : false;
|
||||||
@ -832,7 +839,8 @@ if ( ! function_exists( 'fictioneer_theme_comment' ) ) {
|
|||||||
<?php if ( fictioneer_show_auth_content() && $is_reportable ) : ?>
|
<?php if ( fictioneer_show_auth_content() && $is_reportable ) : ?>
|
||||||
<button
|
<button
|
||||||
class="fictioneer-report-comment-button comment-quick-button hide-if-logged-out tooltipped <?php echo $flag_classes ?> <?php echo $is_flagged_by_current_user ? 'on' : ''; ?> hide-on-ajax"
|
class="fictioneer-report-comment-button comment-quick-button hide-if-logged-out tooltipped <?php echo $flag_classes ?> <?php echo $is_flagged_by_current_user ? 'on' : ''; ?> hide-on-ajax"
|
||||||
data-click="flag-comment"
|
data-fictioneer-comment-target="flagButton"
|
||||||
|
data-action="click->fictioneer-comment#flag"
|
||||||
data-tooltip="<?php echo esc_attr_x( 'Report', 'Report this comment.', 'fictioneer' ); ?>"
|
data-tooltip="<?php echo esc_attr_x( 'Report', 'Report this comment.', 'fictioneer' ); ?>"
|
||||||
><i class="fa-solid fa-flag"></i></button>
|
><i class="fa-solid fa-flag"></i></button>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
@ -841,7 +849,7 @@ if ( ! function_exists( 'fictioneer_theme_comment' ) ) {
|
|||||||
// FRONTEND MODERATION
|
// FRONTEND MODERATION
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
?>
|
?>
|
||||||
<?php fictioneer_comment_mod_menu( $comment ); ?>
|
<?php fictioneer_comment_moderation( $comment ); ?>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -269,7 +269,7 @@ function fictioneer_rest_get_story_comments( WP_REST_Request $request ) {
|
|||||||
|
|
||||||
// Start HTML ---> ?>
|
// Start HTML ---> ?>
|
||||||
<li class="load-more-list-item">
|
<li class="load-more-list-item">
|
||||||
<button class="load-more-comments-button" data-story-id="<?php echo $story_id; ?>"><?php
|
<button class="load-more-comments-button" data-action="click->fictioneer-story#loadComments"><?php
|
||||||
printf(
|
printf(
|
||||||
_n(
|
_n(
|
||||||
'Load next comment (may contain spoilers)',
|
'Load next comment (may contain spoilers)',
|
||||||
@ -281,7 +281,7 @@ function fictioneer_rest_get_story_comments( WP_REST_Request $request ) {
|
|||||||
);
|
);
|
||||||
?></button>
|
?></button>
|
||||||
</li>
|
</li>
|
||||||
<div class="comments-loading-placeholder hidden"><i class="fas fa-spinner spinner"></i></div>
|
<div class="comments-loading-placeholder hidden" data-fictioneer-story-target="commentsPlaceholder"><i class="fas fa-spinner spinner"></i></div>
|
||||||
<?php // <--- End HTML
|
<?php // <--- End HTML
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -359,10 +359,10 @@ add_action( 'fictioneer_chapter_actions_bottom_right', 'fictioneer_chapter_nav_b
|
|||||||
|
|
||||||
function fictioneer_chapter_formatting_button() {
|
function fictioneer_chapter_formatting_button() {
|
||||||
// Start HTML ---> ?>
|
// Start HTML ---> ?>
|
||||||
<label class="button _secondary open" for="modal-formatting-toggle" tabindex="0" role="button" aria-label="<?php esc_attr_e( 'Open chapter formatting modal', 'fictioneer' ); ?>">
|
<button class="button _secondary open" data-action="click->fictioneer#toggleModal" data-fictioneer-id-param="formatting-modal" aria-label="<?php esc_attr_e( 'Open chapter formatting modal', 'fictioneer' ); ?>">
|
||||||
<?php fictioneer_icon( 'font-settings' ); ?>
|
<?php fictioneer_icon( 'font-settings' ); ?>
|
||||||
<span class="hide-below-tablet"><?php echo fcntr( 'formatting' ); ?></span>
|
<span class="hide-below-tablet"><?php echo fcntr( 'formatting' ); ?></span>
|
||||||
</label>
|
</button>
|
||||||
<?php // <--- End HTML
|
<?php // <--- End HTML
|
||||||
}
|
}
|
||||||
add_action( 'fictioneer_chapter_actions_top_center', 'fictioneer_chapter_formatting_button', 10 );
|
add_action( 'fictioneer_chapter_actions_top_center', 'fictioneer_chapter_formatting_button', 10 );
|
||||||
@ -390,7 +390,7 @@ function fictioneer_chapter_subscribe_button() {
|
|||||||
|
|
||||||
if ( ! empty( $subscribe_buttons ) ) {
|
if ( ! empty( $subscribe_buttons ) ) {
|
||||||
// Start HTML ---> ?>
|
// Start HTML ---> ?>
|
||||||
<div class="toggle-last-clicked button _secondary popup-menu-toggle" tabindex="0" role="button" aria-label="<?php echo fcntr( 'subscribe', true ); ?>">
|
<div class="button _secondary popup-menu-toggle" tabindex="0" role="button" aria-label="<?php echo fcntr( 'subscribe', true ); ?>" data-fictioneer-last-click-target="toggle" data-action="click->fictioneer-last-click#toggle">
|
||||||
<i class="fa-solid fa-bell"></i> <span class="hide-below-tablet"><?php echo fcntr( 'subscribe' ); ?></span>
|
<i class="fa-solid fa-bell"></i> <span class="hide-below-tablet"><?php echo fcntr( 'subscribe' ); ?></span>
|
||||||
<div class="popup-menu _top _center"><?php echo $subscribe_buttons; ?></div>
|
<div class="popup-menu _top _center"><?php echo $subscribe_buttons; ?></div>
|
||||||
</div>
|
</div>
|
||||||
@ -415,10 +415,10 @@ function fictioneer_chapter_fullscreen_buttons() {
|
|||||||
$close = esc_attr__( 'Exit fullscreen', 'fictioneer' );
|
$close = esc_attr__( 'Exit fullscreen', 'fictioneer' );
|
||||||
|
|
||||||
// Start HTML ---> ?>
|
// Start HTML ---> ?>
|
||||||
<button type="button" class="open-fullscreen button _secondary button--fullscreen hide-on-fullscreen hide-on-iOS tooltipped" data-tooltip="<?php echo $open; ?>" aria-label="<?php echo $open; ?>">
|
<button type="button" class="open-fullscreen button _secondary button--fullscreen hide-on-fullscreen hide-on-iOS tooltipped" data-tooltip="<?php echo $open; ?>" aria-label="<?php echo $open; ?>" data-action="click->fictioneer-chapter#openFullscreen">
|
||||||
<?php fictioneer_icon( 'expand' ); ?>
|
<?php fictioneer_icon( 'expand' ); ?>
|
||||||
</button>
|
</button>
|
||||||
<button type="button" class="close-fullscreen button _secondary button--fullscreen show-on-fullscreen hide-on-iOS hidden tooltipped" data-tooltip="<?php echo $close; ?>" aria-label="<?php echo $close; ?>">
|
<button type="button" class="close-fullscreen button _secondary button--fullscreen show-on-fullscreen hide-on-iOS hidden tooltipped" data-tooltip="<?php echo $close; ?>" aria-label="<?php echo $close; ?>" data-action="click->fictioneer-chapter#closeFullscreen">
|
||||||
<?php fictioneer_icon( 'collapse' ); ?>
|
<?php fictioneer_icon( 'collapse' ); ?>
|
||||||
</button>
|
</button>
|
||||||
<?php // <--- End HTML
|
<?php // <--- End HTML
|
||||||
@ -494,7 +494,7 @@ function fictioneer_chapter_bookmark_jump_button() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Start HTML ---> ?>
|
// Start HTML ---> ?>
|
||||||
<button type="button" class="button _secondary button--bookmark hidden">
|
<button type="button" class="button _secondary button--bookmark" data-fictioneer-chapter-target="bookmarkScroll" data-fictioneer-bookmarks-target="bookmarkScroll" data-action="click->fictioneer-chapter#scrollToBookmark" hidden>
|
||||||
<i class="fa-solid fa-bookmark"></i>
|
<i class="fa-solid fa-bookmark"></i>
|
||||||
<span class="hide-below-tablet"><?php echo fcntr( 'bookmark' ); ?></span>
|
<span class="hide-below-tablet"><?php echo fcntr( 'bookmark' ); ?></span>
|
||||||
</button>
|
</button>
|
||||||
@ -693,7 +693,7 @@ add_action( 'fictioneer_chapter_after_content', 'fictioneer_chapter_support_link
|
|||||||
function fictioneer_chapter_micro_menu( $args ) {
|
function fictioneer_chapter_micro_menu( $args ) {
|
||||||
echo fictioneer_get_chapter_micro_menu( $args );
|
echo fictioneer_get_chapter_micro_menu( $args );
|
||||||
}
|
}
|
||||||
add_action( 'fictioneer_chapter_after_main', 'fictioneer_chapter_micro_menu', 10 );
|
add_action( 'fictioneer_chapter_after_content', 'fictioneer_chapter_micro_menu', 99 );
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// CHAPTER PARAGRAPH TOOLS
|
// CHAPTER PARAGRAPH TOOLS
|
||||||
@ -711,10 +711,10 @@ function fictioneer_chapter_paragraph_tools() {
|
|||||||
$hide_if_logged_out = get_option( 'comment_registration' ) ? 'hide-if-logged-out' : ''; // Safer for cached site
|
$hide_if_logged_out = get_option( 'comment_registration' ) ? 'hide-if-logged-out' : ''; // Safer for cached site
|
||||||
|
|
||||||
// Start HTML ---> ?>
|
// Start HTML ---> ?>
|
||||||
<div id="paragraph-tools" class="paragraph-tools" data-nosnippet>
|
<div id="paragraph-tools" class="paragraph-tools" data-fictioneer-chapter-target="tools" data-nosnippet>
|
||||||
<div class="paragraph-tools__actions">
|
<div class="paragraph-tools__actions">
|
||||||
<?php if ( get_option( 'fictioneer_enable_bookmarks' ) ) : ?>
|
<?php if ( get_option( 'fictioneer_enable_bookmarks' ) ) : ?>
|
||||||
<button id="button-set-bookmark" type="button" class="button">
|
<button id="button-set-bookmark" type="button" class="button" data-action="click->fictioneer-chapter#toggleBookmark">
|
||||||
<i class="fa-solid fa-bookmark"></i>
|
<i class="fa-solid fa-bookmark"></i>
|
||||||
<span><?php _ex( 'Bookmark', 'Paragraph tools bookmark button', 'fictioneer' ); ?></span>
|
<span><?php _ex( 'Bookmark', 'Paragraph tools bookmark button', 'fictioneer' ); ?></span>
|
||||||
<div class="paragraph-tools__bookmark-colors">
|
<div class="paragraph-tools__bookmark-colors">
|
||||||
@ -726,13 +726,13 @@ function fictioneer_chapter_paragraph_tools() {
|
|||||||
</button>
|
</button>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<?php if ( $can_comment ) : ?>
|
<?php if ( $can_comment ) : ?>
|
||||||
<button id="button-comment-stack" type="button" class="button <?php echo $hide_if_logged_out ?>">
|
<button id="button-comment-stack" type="button" class="button <?php echo $hide_if_logged_out ?>" data-action="click->fictioneer-chapter#quote">
|
||||||
<i class="fa-solid fa-quote-right"></i>
|
<i class="fa-solid fa-quote-right"></i>
|
||||||
<span><?php _ex( 'Quote', 'Paragraph tools quote button', 'fictioneer' ); ?></span>
|
<span><?php _ex( 'Quote', 'Paragraph tools quote button', 'fictioneer' ); ?></span>
|
||||||
</button>
|
</button>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<?php if ( $can_comment && get_option( 'fictioneer_enable_suggestions' ) ) : ?>
|
<?php if ( $can_comment && get_option( 'fictioneer_enable_suggestions' ) ) : ?>
|
||||||
<button id="button-tools-add-suggestion" type="button" class="button <?php echo $hide_if_logged_out ?>">
|
<button id="button-tools-add-suggestion" type="button" class="button <?php echo $hide_if_logged_out ?>" data-action="click->fictioneer-suggestion#toggleModalViaParagraph">
|
||||||
<i class="fa-solid fa-highlighter"></i>
|
<i class="fa-solid fa-highlighter"></i>
|
||||||
<span class="hide-below-480"><?php _ex( 'Suggestion', 'Paragraph tools suggestion button', 'fictioneer' ); ?></span>
|
<span class="hide-below-480"><?php _ex( 'Suggestion', 'Paragraph tools suggestion button', 'fictioneer' ); ?></span>
|
||||||
</button>
|
</button>
|
||||||
@ -743,11 +743,11 @@ function fictioneer_chapter_paragraph_tools() {
|
|||||||
<span class="hide-below-480"><?php _ex( 'TTS', 'Paragraph tools text-to-speech button', 'fictioneer' ); ?></span>
|
<span class="hide-below-480"><?php _ex( 'TTS', 'Paragraph tools text-to-speech button', 'fictioneer' ); ?></span>
|
||||||
</button>
|
</button>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<button id="button-get-link" type="button" class="button">
|
<button id="button-get-link" type="button" class="button" data-action="click->fictioneer-chapter#copyLink">
|
||||||
<i class="fa-solid fa-link"></i>
|
<i class="fa-solid fa-link"></i>
|
||||||
<span class="hide-below-480"><?php _ex( 'Link', 'Paragraph tools copy link button', 'fictioneer' ); ?></span>
|
<span class="hide-below-480"><?php _ex( 'Link', 'Paragraph tools copy link button', 'fictioneer' ); ?></span>
|
||||||
</button>
|
</button>
|
||||||
<button id="button-close-paragraph-tools" type="button" class="button">
|
<button id="button-close-paragraph-tools" type="button" class="button" data-action="click->fictioneer-chapter#closeTools">
|
||||||
<i class="fa-solid fa-times"></i>
|
<i class="fa-solid fa-times"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -137,10 +137,7 @@ function fictioneer_output_modals( $args ) {
|
|||||||
|
|
||||||
// Formatting and suggestions
|
// Formatting and suggestions
|
||||||
if ( ! $is_archive && $args['post_type'] == 'fcn_chapter' ) {
|
if ( ! $is_archive && $args['post_type'] == 'fcn_chapter' ) {
|
||||||
?><input id="modal-formatting-toggle" data-target="formatting-modal" type="checkbox" tabindex="-1" class="modal-toggle" autocomplete="off" hidden><?php
|
|
||||||
fictioneer_get_cached_partial( 'partials/_modal-formatting' );
|
fictioneer_get_cached_partial( 'partials/_modal-formatting' );
|
||||||
|
|
||||||
?><input id="modal-tts-settings-toggle" data-target="tts-settings-modal" type="checkbox" tabindex="-1" class="modal-toggle" autocomplete="off" hidden><?php
|
|
||||||
fictioneer_get_cached_partial( 'partials/_modal-tts-settings' );
|
fictioneer_get_cached_partial( 'partials/_modal-tts-settings' );
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@ -148,23 +145,19 @@ function fictioneer_output_modals( $args ) {
|
|||||||
! fictioneer_is_commenting_disabled( get_the_ID() ) &&
|
! fictioneer_is_commenting_disabled( get_the_ID() ) &&
|
||||||
comments_open()
|
comments_open()
|
||||||
) {
|
) {
|
||||||
?><input id="suggestions-modal-toggle" data-target="suggestions-modal" type="checkbox" tabindex="-1" class="modal-toggle" autocomplete="off" hidden><?php
|
|
||||||
fictioneer_get_cached_partial( 'partials/_modal-suggestions' );
|
fictioneer_get_cached_partial( 'partials/_modal-suggestions' );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Login
|
// Login
|
||||||
if ( fictioneer_show_login() ) {
|
if ( fictioneer_show_login() ) {
|
||||||
?><input id="modal-login-toggle" data-target="login-modal" type="checkbox" tabindex="-1" class="modal-toggle" autocomplete="off" hidden><?php
|
|
||||||
get_template_part( 'partials/_modal-login' );
|
get_template_part( 'partials/_modal-login' );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Social sharing
|
// Social sharing
|
||||||
?><input id="modal-sharing-toggle" data-target="sharing-modal" type="checkbox" tabindex="-1" class="modal-toggle" autocomplete="off" hidden><?php
|
|
||||||
get_template_part( 'partials/_modal-sharing' );
|
get_template_part( 'partials/_modal-sharing' );
|
||||||
|
|
||||||
// Site settings
|
// Site settings
|
||||||
?><input id="modal-site-settings-toggle" data-target="site-settings-modal" type="checkbox" tabindex="-1" class="modal-toggle" autocomplete="off" hidden><?php
|
|
||||||
fictioneer_get_cached_partial( 'partials/_modal-site-settings' );
|
fictioneer_get_cached_partial( 'partials/_modal-site-settings' );
|
||||||
|
|
||||||
// BBCodes tutorial
|
// BBCodes tutorial
|
||||||
@ -174,7 +167,6 @@ function fictioneer_output_modals( $args ) {
|
|||||||
comments_open() &&
|
comments_open() &&
|
||||||
! fictioneer_is_commenting_disabled( $args['post_id'] )
|
! fictioneer_is_commenting_disabled( $args['post_id'] )
|
||||||
) {
|
) {
|
||||||
?><input id="modal-bbcodes-toggle" data-target="bbcodes-modal" type="checkbox" tabindex="-1" class="modal-toggle" autocomplete="off" hidden><?php
|
|
||||||
fictioneer_get_cached_partial( 'partials/_modal-bbcodes' );
|
fictioneer_get_cached_partial( 'partials/_modal-bbcodes' );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,7 +177,6 @@ function fictioneer_output_modals( $args ) {
|
|||||||
FICTIONEER_ENABLE_STORY_CHANGELOG &&
|
FICTIONEER_ENABLE_STORY_CHANGELOG &&
|
||||||
get_option( 'fictioneer_show_story_changelog' )
|
get_option( 'fictioneer_show_story_changelog' )
|
||||||
) {
|
) {
|
||||||
?><input id="modal-chapter-changelog-toggle" data-target="chapter-changelog-modal" type="checkbox" tabindex="-1" class="modal-toggle" autocomplete="off" hidden><?php
|
|
||||||
get_template_part( 'partials/_modal-chapter-changelog' );
|
get_template_part( 'partials/_modal-chapter-changelog' );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -725,7 +716,7 @@ function fictioneer_sort_order_filter_interface( $args ) {
|
|||||||
<div id="sof" class="sort-order-filter">
|
<div id="sof" class="sort-order-filter">
|
||||||
|
|
||||||
<?php if ( is_archive() && ! empty( $post_type_menu ) ) : ?>
|
<?php if ( is_archive() && ! empty( $post_type_menu ) ) : ?>
|
||||||
<div class="list-button _text popup-menu-toggle toggle-last-clicked" tabindex="0" role="button"><?php
|
<div class="list-button _text popup-menu-toggle" tabindex="0" role="button" data-fictioneer-last-click-target="toggle" data-action="click->fictioneer-last-click#toggle"><?php
|
||||||
echo $post_type_menu[ $post_type ?? 'any' ]['label'] ?? __( 'Unknown', 'fictioneer' );
|
echo $post_type_menu[ $post_type ?? 'any' ]['label'] ?? __( 'Unknown', 'fictioneer' );
|
||||||
echo '<div class="popup-menu _bottom _center _fixed-position">';
|
echo '<div class="popup-menu _bottom _center _fixed-position">';
|
||||||
echo '<div class="popup-heading">' . __( 'Post Type', 'fictioneer' ) . '</div>';
|
echo '<div class="popup-heading">' . __( 'Post Type', 'fictioneer' ) . '</div>';
|
||||||
@ -740,7 +731,7 @@ function fictioneer_sort_order_filter_interface( $args ) {
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php if ( ! empty( $orderby_menu ) ) : ?>
|
<?php if ( ! empty( $orderby_menu ) ) : ?>
|
||||||
<div class="list-button _text popup-menu-toggle toggle-last-clicked" tabindex="0" role="button"><?php
|
<div class="list-button _text popup-menu-toggle" tabindex="0" role="button" data-fictioneer-last-click-target="toggle" data-action="click->fictioneer-last-click#toggle"><?php
|
||||||
echo $orderby_menu[ $args['orderby'] ]['label'] ?? __( 'Custom', 'fictioneer' );
|
echo $orderby_menu[ $args['orderby'] ]['label'] ?? __( 'Custom', 'fictioneer' );
|
||||||
echo '<div class="popup-menu _bottom _center _fixed-position">';
|
echo '<div class="popup-menu _bottom _center _fixed-position">';
|
||||||
echo '<div class="popup-heading">' . __( 'Order By', 'fictioneer' ) . '</div>';
|
echo '<div class="popup-heading">' . __( 'Order By', 'fictioneer' ) . '</div>';
|
||||||
@ -755,7 +746,7 @@ function fictioneer_sort_order_filter_interface( $args ) {
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php if ( ! empty( $date_menu ) ) : ?>
|
<?php if ( ! empty( $date_menu ) ) : ?>
|
||||||
<div class="list-button _text popup-menu-toggle toggle-last-clicked" tabindex="0" role="button"><?php
|
<div class="list-button _text popup-menu-toggle" tabindex="0" role="button" data-fictioneer-last-click-target="toggle" data-action="click->fictioneer-last-click#toggle"><?php
|
||||||
$key = str_replace( ' ', '_', $args['ago'] ?? '' );
|
$key = str_replace( ' ', '_', $args['ago'] ?? '' );
|
||||||
|
|
||||||
if ( empty( $date_menu[ $key ]['label'] ) ) {
|
if ( empty( $date_menu[ $key ]['label'] ) ) {
|
||||||
|
@ -33,11 +33,10 @@ function fictioneer_output_mobile_menu( $args ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Start HTML ---> ?>
|
// Start HTML ---> ?>
|
||||||
<input id="mobile-menu-toggle" type="checkbox" autocomplete="off" tabindex="-1" hidden>
|
<div class="mobile-menu <?php echo implode( ' ', $classes ); ?>" data-action="fictioneer:bodyClick@window->fictioneer-mobile-menu#clickOutside">
|
||||||
<div class="mobile-menu <?php echo implode( ' ', $classes ); ?>">
|
|
||||||
<div class="mobile-menu__top"><?php do_action( 'fictioneer_mobile_menu_top' ); ?></div>
|
<div class="mobile-menu__top"><?php do_action( 'fictioneer_mobile_menu_top' ); ?></div>
|
||||||
<div class="mobile-menu__center">
|
<div class="mobile-menu__center">
|
||||||
<div class="mobile-menu__frame _active" data-frame="main"><?php
|
<div id="mobile-frame-main" class="mobile-menu__frame _active" data-fictioneer-mobile-menu-target="frame"><?php
|
||||||
do_action( 'fictioneer_mobile_menu_main_frame_panels' );
|
do_action( 'fictioneer_mobile_menu_main_frame_panels' );
|
||||||
?></div>
|
?></div>
|
||||||
<?php do_action( 'fictioneer_mobile_menu_center' ); ?>
|
<?php do_action( 'fictioneer_mobile_menu_center' ); ?>
|
||||||
@ -88,12 +87,12 @@ function fictioneer_mobile_quick_buttons() {
|
|||||||
|
|
||||||
if ( $post_type === 'fcn_chapter' && ! is_search() ) {
|
if ( $post_type === 'fcn_chapter' && ! is_search() ) {
|
||||||
$output['darken'] = sprintf(
|
$output['darken'] = sprintf(
|
||||||
'<button class="button _quick button-change-lightness" value="-0.2">%s</button>',
|
'<button class="button _quick" data-action="click->fictioneer-mobile-menu#changeLightness" value="-0.2">%s</button>',
|
||||||
__( 'Darken', 'fictioneer' )
|
__( 'Darken', 'fictioneer' )
|
||||||
);
|
);
|
||||||
|
|
||||||
$output['brighten'] = sprintf(
|
$output['brighten'] = sprintf(
|
||||||
'<button class="button _quick button-change-lightness" value="0.2">%s</button>',
|
'<button class="button _quick" data-action="click->fictioneer-mobile-menu#changeLightness" value="0.2">%s</button>',
|
||||||
__( 'Brighten', 'fictioneer' )
|
__( 'Brighten', 'fictioneer' )
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -108,7 +107,7 @@ function fictioneer_mobile_quick_buttons() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
$output['formatting'] = sprintf(
|
$output['formatting'] = sprintf(
|
||||||
'<label for="modal-formatting-toggle" class="button _quick"><span>%s</span></label>',
|
'<button class="button _quick" data-action="click->fictioneer#toggleModal" data-fictioneer-id-param="formatting-modal"><span>%s</span></button>',
|
||||||
fcntr( 'formatting' )
|
fcntr( 'formatting' )
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -158,17 +157,17 @@ add_action( 'fictioneer_mobile_menu_bottom', 'fictioneer_mobile_quick_buttons',
|
|||||||
|
|
||||||
function fictioneer_mobile_follows_frame() {
|
function fictioneer_mobile_follows_frame() {
|
||||||
// Start HTML ---> ?>
|
// Start HTML ---> ?>
|
||||||
<div class="mobile-menu__frame" data-frame="follows">
|
<div id="mobile-frame-follows" class="mobile-menu__frame" data-fictioneer-mobile-menu-target="frame">
|
||||||
<div class="mobile-menu__panel mobile-menu__follows-panel">
|
<div class="mobile-menu__panel mobile-menu__follows-panel">
|
||||||
<div class="mobile-menu__panel-header">
|
<div class="mobile-menu__panel-header">
|
||||||
<button class="mobile-menu__back-button">
|
<button class="mobile-menu__back-button" data-action="click->fictioneer-mobile-menu#back">
|
||||||
<i class="fa-solid fa-caret-left mobile-menu__item-icon"></i> <?php _e( 'Back', 'fictioneer' ); ?>
|
<i class="fa-solid fa-caret-left mobile-menu__item-icon"></i> <?php _e( 'Back', 'fictioneer' ); ?>
|
||||||
</button>
|
</button>
|
||||||
<button class="mark-follows-read mobile-menu__panel-action-button">
|
<button class="mark-follows-read mobile-menu__panel-action-button hidden" data-fictioneer-follows-target="mobileMarkRead" data-action="click->fictioneer-follows#markRead">
|
||||||
<i class="fa-solid fa-check"></i>
|
<i class="fa-solid fa-check"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div id="mobile-menu-follows-list" class="mobile-menu__list mobile-follow-notifications">
|
<div id="mobile-menu-follows-list" class="mobile-menu__list mobile-follow-notifications" data-fictioneer-follows-target="mobileScrollList">
|
||||||
<div class="mobile-content-is-loading">
|
<div class="mobile-content-is-loading">
|
||||||
<i class="fa-solid fa-spinner fa-spin" style="--fa-animation-duration: .8s;"></i>
|
<i class="fa-solid fa-spinner fa-spin" style="--fa-animation-duration: .8s;"></i>
|
||||||
</div>
|
</div>
|
||||||
@ -196,17 +195,17 @@ function fictioneer_mobile_bookmarks_frame() {
|
|||||||
fictioneer_get_cached_partial( 'partials/_template_mobile_bookmark' );
|
fictioneer_get_cached_partial( 'partials/_template_mobile_bookmark' );
|
||||||
|
|
||||||
// Start HTML ---> ?>
|
// Start HTML ---> ?>
|
||||||
<div class="mobile-menu__frame" data-frame="bookmarks">
|
<div id="mobile-frame-bookmarks" class="mobile-menu__frame" data-fictioneer-mobile-menu-target="frame">
|
||||||
<div class="mobile-menu__panel mobile-menu__bookmarks-panel" data-editing="false">
|
<div class="mobile-menu__panel mobile-menu__bookmarks-panel" data-editing="false" data-fictioneer-mobile-menu-target="panelBookmarks">
|
||||||
<div class="mobile-menu__panel-header">
|
<div class="mobile-menu__panel-header">
|
||||||
<button class="mobile-menu__back-button">
|
<button class="mobile-menu__back-button" data-action="click->fictioneer-mobile-menu#back">
|
||||||
<i class="fa-solid fa-caret-left mobile-menu__item-icon"></i> <?php _e( 'Back', 'fictioneer' ); ?>
|
<i class="fa-solid fa-caret-left mobile-menu__item-icon"></i> <?php _e( 'Back', 'fictioneer' ); ?>
|
||||||
</button>
|
</button>
|
||||||
<button id="button-mobile-menu-toggle-bookmarks-edit" class="mobile-menu__panel-action-button">
|
<button id="button-mobile-menu-toggle-bookmarks-edit" class="mobile-menu__panel-action-button" data-action="click->fictioneer-mobile-menu#toggleBookmarksEdit">
|
||||||
<i class="fa-solid fa-pen off"></i><i class="fa-solid fa-check on"></i>
|
<i class="fa-solid fa-pen off"></i><i class="fa-solid fa-check on"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<ul class="mobile-menu__list mobile-menu__bookmark-list" data-empty="<?php echo fcntr( 'no_bookmarks', true ); ?>"></ul>
|
<ul class="mobile-menu__list mobile-menu__bookmark-list" data-empty="<?php echo fcntr( 'no_bookmarks', true ); ?>" data-fictioneer-mobile-menu-target="bookmarks"></ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<?php // <--- End HTML
|
<?php // <--- End HTML
|
||||||
@ -295,7 +294,7 @@ function fictioneer_mobile_lists_panel() {
|
|||||||
// Bookmarks?
|
// Bookmarks?
|
||||||
if ( get_option( 'fictioneer_enable_bookmarks' ) ) {
|
if ( get_option( 'fictioneer_enable_bookmarks' ) ) {
|
||||||
$output['bookmarks'] = sprintf(
|
$output['bookmarks'] = sprintf(
|
||||||
'<button class="mobile-menu__frame-button" data-frame-target="bookmarks"><i class="fa-solid fa-caret-right mobile-menu__item-icon"></i> %s</button>',
|
'<button class="mobile-menu__frame-button" data-action="click->fictioneer-mobile-menu#openFrame click->fictioneer-mobile-menu#setMobileBookmarks" data-fictioneer-mobile-menu-frame-param="bookmarks"><i class="fa-solid fa-caret-right mobile-menu__item-icon"></i> %s</button>',
|
||||||
fcntr( 'bookmarks' )
|
fcntr( 'bookmarks' )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -303,7 +302,7 @@ function fictioneer_mobile_lists_panel() {
|
|||||||
// Follows?
|
// Follows?
|
||||||
if ( get_option( 'fictioneer_enable_follows' ) ) {
|
if ( get_option( 'fictioneer_enable_follows' ) ) {
|
||||||
$output['follows'] = sprintf(
|
$output['follows'] = sprintf(
|
||||||
'<button class="mobile-menu__frame-button hide-if-logged-out follows-alert-number" data-frame-target="follows"><i class="fa-solid fa-caret-right mobile-menu__item-icon"></i> %s</button>',
|
'<button class="mobile-menu__frame-button hide-if-logged-out follows-alert-number" data-fictioneer-follows-target="newDisplay" data-frame-target="follows" data-action="click->fictioneer-follows#loadFollowsHtml:once click->fictioneer-mobile-menu#openFrame" data-fictioneer-mobile-menu-frame-param="follows"><i class="fa-solid fa-caret-right mobile-menu__item-icon"></i> %s</button>',
|
||||||
fcntr( 'follows' )
|
fcntr( 'follows' )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -359,7 +358,7 @@ function fictioneer_mobile_user_menu() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$output['site_settings'] = sprintf(
|
$output['site_settings'] = sprintf(
|
||||||
'<label for="modal-site-settings-toggle"><i class="fa-solid fa-tools mobile-menu__item-icon"></i> %s</label>',
|
'<button data-action="click->fictioneer#toggleModal" data-fictioneer-id-param="site-settings-modal"><i class="fa-solid fa-tools mobile-menu__item-icon"></i> %s</button>',
|
||||||
fcntr( 'site_settings' )
|
fcntr( 'site_settings' )
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -397,7 +396,7 @@ function fictioneer_mobile_user_menu() {
|
|||||||
|
|
||||||
if ( $post_type === 'fcn_chapter' && ! is_search() ) {
|
if ( $post_type === 'fcn_chapter' && ! is_search() ) {
|
||||||
$output['formatting'] = sprintf(
|
$output['formatting'] = sprintf(
|
||||||
'<label for="modal-formatting-toggle">%s %s</label>',
|
'<button data-action="click->fictioneer#toggleModal" data-fictioneer-id-param="formatting-modal">%s %s</button>',
|
||||||
fictioneer_get_icon( 'font-settings', 'mobile-menu__item-icon' ),
|
fictioneer_get_icon( 'font-settings', 'mobile-menu__item-icon' ),
|
||||||
fcntr( 'formatting' )
|
fcntr( 'formatting' )
|
||||||
);
|
);
|
||||||
@ -411,7 +410,7 @@ function fictioneer_mobile_user_menu() {
|
|||||||
! $password_required
|
! $password_required
|
||||||
) {
|
) {
|
||||||
$output['comment_jump'] = sprintf(
|
$output['comment_jump'] = sprintf(
|
||||||
'<a id="mobile-menu-comment-jump" class="comments-toggle" rel="noopener noreferrer nofollow"><i class="fa-solid fa-comments mobile-menu__item-icon"></i> %s</a>',
|
'<a id="mobile-menu-comment-jump" class="comments-toggle" data-action="click->fictioneer-mobile-menu#scrollToComments"><i class="fa-solid fa-comments mobile-menu__item-icon"></i> %s</a>',
|
||||||
fcntr( 'jump_to_comments' )
|
fcntr( 'jump_to_comments' )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -423,14 +422,14 @@ function fictioneer_mobile_user_menu() {
|
|||||||
! $password_required
|
! $password_required
|
||||||
) {
|
) {
|
||||||
$output['bookmark_jump'] = sprintf(
|
$output['bookmark_jump'] = sprintf(
|
||||||
'<a id="mobile-menu-bookmark-jump" rel="noopener noreferrer nofollow" hidden><i class="fa-solid fa-bookmark mobile-menu__item-icon"></i> %s</a>',
|
'<a id="mobile-menu-bookmark-jump" data-fictioneer-bookmarks-target="bookmarkScroll" data-action="click->fictioneer-mobile-menu#scrollToBookmark" hidden><i class="fa-solid fa-bookmark mobile-menu__item-icon"></i> %s</a>',
|
||||||
fcntr( 'jump_to_bookmark' )
|
fcntr( 'jump_to_bookmark' )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( fictioneer_show_auth_content() ) {
|
if ( fictioneer_show_auth_content() ) {
|
||||||
$output['logout'] = sprintf(
|
$output['logout'] = sprintf(
|
||||||
'<a href="%s" data-click="logout" rel="noopener noreferrer nofollow" class="hide-if-logged-out">%s %s</a>',
|
'<a href="%s" data-action="click->fictioneer#logout" rel="noopener noreferrer nofollow" class="hide-if-logged-out">%s %s</a>',
|
||||||
fictioneer_get_logout_url(),
|
fictioneer_get_logout_url(),
|
||||||
fictioneer_get_icon( 'fa-logout', 'mobile-menu__item-icon', '', 'style="transform: translateY(-1px);"' ),
|
fictioneer_get_icon( 'fa-logout', 'mobile-menu__item-icon', '', 'style="transform: translateY(-1px);"' ),
|
||||||
fcntr( 'logout' )
|
fcntr( 'logout' )
|
||||||
@ -439,7 +438,7 @@ function fictioneer_mobile_user_menu() {
|
|||||||
|
|
||||||
if ( fictioneer_show_login() ) {
|
if ( fictioneer_show_login() ) {
|
||||||
$output['login'] = sprintf(
|
$output['login'] = sprintf(
|
||||||
'<label for="modal-login-toggle" class="hide-if-logged-in subscriber-login">%s %s</label>',
|
'<button class="hide-if-logged-in subscriber-login" data-action="click->fictioneer#toggleModal" data-fictioneer-id-param="login-modal">%s %s</button>',
|
||||||
fictioneer_get_icon( 'fa-login', 'mobile-menu__item-icon' ),
|
fictioneer_get_icon( 'fa-login', 'mobile-menu__item-icon' ),
|
||||||
fcntr( 'login' )
|
fcntr( 'login' )
|
||||||
);
|
);
|
||||||
|
@ -172,7 +172,7 @@ function fictioneer_post_subscribe_button( $post_id, $args ) {
|
|||||||
|
|
||||||
if ( ! empty( $subscribe_buttons ) ) {
|
if ( ! empty( $subscribe_buttons ) ) {
|
||||||
// Start HTML ---> ?>
|
// Start HTML ---> ?>
|
||||||
<div class="toggle-last-clicked button _secondary popup-menu-toggle" tabindex="0" role="button" aria-label="<?php echo fcntr( 'subscribe', true ); ?>">
|
<div class="button _secondary popup-menu-toggle" tabindex="0" role="button" aria-label="<?php echo fcntr( 'subscribe', true ); ?>" data-fictioneer-last-click-target="toggle" data-action="click->fictioneer-last-click#toggle">
|
||||||
<i class="fa-solid fa-bell"></i> <span><?php echo fcntr( 'subscribe' ); ?></span>
|
<i class="fa-solid fa-bell"></i> <span><?php echo fcntr( 'subscribe' ); ?></span>
|
||||||
<div class="popup-menu _top _justify-right"><?php echo $subscribe_buttons; ?></div>
|
<div class="popup-menu _top _justify-right"><?php echo $subscribe_buttons; ?></div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -300,7 +300,7 @@ function fictioneer_story_tabs( $args ) {
|
|||||||
<section id="tabs-<?php echo $story_id; ?>" class="story__tabs tabs-wrapper" data-current="chapters" data-order="asc" data-view="list">
|
<section id="tabs-<?php echo $story_id; ?>" class="story__tabs tabs-wrapper" data-current="chapters" data-order="asc" data-view="list">
|
||||||
|
|
||||||
<div class="tabs">
|
<div class="tabs">
|
||||||
<button class="tabs__item _current" data-target="chapters" tabindex="0"><?php
|
<button class="tabs__item _current" data-fictioneer-story-target="tab" data-fictioneer-story-tab-name-param="chapters" data-action="click->fictioneer-story#toggleTab" data-target="chapters" tabindex="0"><?php
|
||||||
if ( $story['status'] === 'Oneshot' ) {
|
if ( $story['status'] === 'Oneshot' ) {
|
||||||
_e( 'Oneshot', 'fictioneer' );
|
_e( 'Oneshot', 'fictioneer' );
|
||||||
} else {
|
} else {
|
||||||
@ -313,7 +313,7 @@ function fictioneer_story_tabs( $args ) {
|
|||||||
?></button>
|
?></button>
|
||||||
|
|
||||||
<?php if ( $blog_posts->have_posts() ) : ?>
|
<?php if ( $blog_posts->have_posts() ) : ?>
|
||||||
<button class="tabs__item" data-target="blog" tabindex="0"><?php echo fcntr( 'story_blog' ); ?></button>
|
<button class="tabs__item" data-fictioneer-story-target="tab" data-fictioneer-story-tab-name-param="blog" data-action="click->fictioneer-story#toggleTab" data-target="blog" tabindex="0"><?php echo fcntr( 'story_blog' ); ?></button>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
@ -325,7 +325,7 @@ function fictioneer_story_tabs( $args ) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
echo "<button class='tabs__item' data-target='tab-page-{$index}' tabindex='0'>{$page[1]}</button>";
|
echo "<button class='tabs__item' data-fictioneer-story-target='tab' data-fictioneer-story-tab-name-param='tab-page-{$index}' data-action='click->fictioneer-story#toggleTab' data-target='tab-page-{$index}' tabindex='0'>{$page[1]}</button>";
|
||||||
|
|
||||||
$index++;
|
$index++;
|
||||||
|
|
||||||
@ -339,11 +339,11 @@ function fictioneer_story_tabs( $args ) {
|
|||||||
|
|
||||||
<?php if ( $story['status'] !== 'Oneshot' || $story['chapter_count'] > 1 ) : ?>
|
<?php if ( $story['status'] !== 'Oneshot' || $story['chapter_count'] > 1 ) : ?>
|
||||||
<div class="story__chapter-list-toggles">
|
<div class="story__chapter-list-toggles">
|
||||||
<button data-click-action="toggle-chapter-view" class="list-button story__toggle _view" data-view="list" tabindex="0" aria-label="<?php esc_attr_e( 'Toggle between list and grid view', 'fictioneer' ); ?>">
|
<button data-action="click->fictioneer-story#toggleChapterView" class="list-button story__toggle _view" data-view="list" tabindex="0" aria-label="<?php esc_attr_e( 'Toggle between list and grid view', 'fictioneer' ); ?>">
|
||||||
<?php fictioneer_icon( 'grid-2x2', 'on' ); ?>
|
<?php fictioneer_icon( 'grid-2x2', 'on' ); ?>
|
||||||
<i class="fa-solid fa-list off"></i>
|
<i class="fa-solid fa-list off"></i>
|
||||||
</button>
|
</button>
|
||||||
<button data-click-action="toggle-chapter-order" class="list-button story__toggle _order" data-order="asc" tabindex="0" aria-label="<?php esc_attr_e( 'Toggle between ascending and descending order', 'fictioneer' ); ?>">
|
<button data-action="click->fictioneer-story#toggleChapterOrder" class="list-button story__toggle _order" data-order="asc" tabindex="0" aria-label="<?php esc_attr_e( 'Toggle between ascending and descending order', 'fictioneer' ); ?>">
|
||||||
<i class="fa-solid fa-arrow-down-1-9 off"></i>
|
<i class="fa-solid fa-arrow-down-1-9 off"></i>
|
||||||
<i class="fa-solid fa-arrow-down-9-1 on"></i>
|
<i class="fa-solid fa-arrow-down-9-1 on"></i>
|
||||||
</button>
|
</button>
|
||||||
@ -401,7 +401,7 @@ function fictioneer_story_scheduled_chapter( $args ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Start HTML ---> ?>
|
// Start HTML ---> ?>
|
||||||
<section class="story__tab-target story__scheduled-chapter _current" data-finder="chapters">
|
<section class="story__tab-target story__scheduled-chapter _current" data-fictioneer-story-target="tabContent" data-tab-name="chapters">
|
||||||
<i class="fa-solid fa-calendar-days"></i>
|
<i class="fa-solid fa-calendar-days"></i>
|
||||||
<span><?php
|
<span><?php
|
||||||
printf(
|
printf(
|
||||||
@ -458,7 +458,7 @@ function fictioneer_story_pages( $args ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Start HTML ---> ?>
|
// Start HTML ---> ?>
|
||||||
<section class="story__tab-target content-section background-texture" data-finder="tab-page-<?php echo $index; ?>">
|
<section class="story__tab-target content-section background-texture" data-fictioneer-story-target="tabContent" data-tab-name="tab-page-<?php echo $index; ?>">
|
||||||
<div class="story__custom-page"><?php echo apply_filters( 'the_content', $page[2] ); ?></div>
|
<div class="story__custom-page"><?php echo apply_filters( 'the_content', $page[2] ); ?></div>
|
||||||
</section>
|
</section>
|
||||||
<?php // <--- End HTML
|
<?php // <--- End HTML
|
||||||
@ -518,7 +518,7 @@ function fictioneer_story_chapters( $args ) {
|
|||||||
ob_start();
|
ob_start();
|
||||||
|
|
||||||
// Start HTML ---> ?>
|
// Start HTML ---> ?>
|
||||||
<section class="story__tab-target _current story__chapters" data-finder="chapters" data-order="asc" data-view="list">
|
<section class="story__tab-target _current story__chapters" data-fictioneer-story-target="tabContent" data-tab-name="chapters" data-order="asc" data-view="list">
|
||||||
<?php
|
<?php
|
||||||
$chapters = fictioneer_get_story_chapter_posts( $story_id );
|
$chapters = fictioneer_get_story_chapter_posts( $story_id );
|
||||||
$chapter_groups = fictioneer_prepare_chapter_groups( $story_id, $chapters );
|
$chapter_groups = fictioneer_prepare_chapter_groups( $story_id, $chapters );
|
||||||
@ -561,6 +561,7 @@ function fictioneer_story_chapters( $args ) {
|
|||||||
aria-label="<?php echo esc_attr( sprintf( $aria_label, $group['group'] ) ); ?>"
|
aria-label="<?php echo esc_attr( sprintf( $aria_label, $group['group'] ) ); ?>"
|
||||||
data-item-count="<?php echo esc_attr( $group_item_count ); ?>"
|
data-item-count="<?php echo esc_attr( $group_item_count ); ?>"
|
||||||
data-group-index="<?php echo esc_attr( $group_index ); ?>"
|
data-group-index="<?php echo esc_attr( $group_index ); ?>"
|
||||||
|
data-action="click->fictioneer#toggleChapterGroup"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
>
|
>
|
||||||
<i class="<?php echo $group['toggle_icon']; ?> chapter-group__heading-icon"></i>
|
<i class="<?php echo $group['toggle_icon']; ?> chapter-group__heading-icon"></i>
|
||||||
@ -591,7 +592,7 @@ function fictioneer_story_chapters( $args ) {
|
|||||||
|
|
||||||
<?php if ( $chapter_folding && $index == FICTIONEER_CHAPTER_FOLDING_THRESHOLD + 1 ) : ?>
|
<?php if ( $chapter_folding && $index == FICTIONEER_CHAPTER_FOLDING_THRESHOLD + 1 ) : ?>
|
||||||
<li class="chapter-group__list-item _folding-toggle" style="order: <?php echo $reverse_order - $index; ?>">
|
<li class="chapter-group__list-item _folding-toggle" style="order: <?php echo $reverse_order - $index; ?>">
|
||||||
<button class="chapter-group__folding-toggle" tabindex="0">
|
<button class="chapter-group__folding-toggle" data-action="click->fictioneer-story#unfoldChapters" tabindex="0">
|
||||||
<?php
|
<?php
|
||||||
printf(
|
printf(
|
||||||
__( 'Show %s more', 'fictioneer' ),
|
__( 'Show %s more', 'fictioneer' ),
|
||||||
@ -665,10 +666,11 @@ function fictioneer_story_chapters( $args ) {
|
|||||||
|
|
||||||
<?php if ( get_option( 'fictioneer_enable_checkmarks' ) ) : ?>
|
<?php if ( get_option( 'fictioneer_enable_checkmarks' ) ) : ?>
|
||||||
<button
|
<button
|
||||||
class="checkmark chapter-group__list-item-checkmark"
|
class="checkmark chapter-group__list-item-checkmark only-logged-in"
|
||||||
data-type="chapter"
|
data-fictioneer-checkmarks-target="chapterCheck"
|
||||||
data-story-id="<?php echo $story_id; ?>"
|
data-fictioneer-checkmarks-story-param="<?php echo $story_id; ?>"
|
||||||
data-id="<?php echo $chapter['id']; ?>"
|
data-fictioneer-checkmarks-chapter-param="<?php echo $chapter['id']; ?>"
|
||||||
|
data-action="click->fictioneer-checkmarks#toggleChapter"
|
||||||
role="checkbox"
|
role="checkbox"
|
||||||
aria-checked="false"
|
aria-checked="false"
|
||||||
aria-label="<?php
|
aria-label="<?php
|
||||||
@ -743,7 +745,7 @@ function fictioneer_story_blog( $args ) {
|
|||||||
$blog_posts = fictioneer_get_story_blog_posts( $story_id );
|
$blog_posts = fictioneer_get_story_blog_posts( $story_id );
|
||||||
|
|
||||||
// Start HTML ---> ?>
|
// Start HTML ---> ?>
|
||||||
<section class="story__blog story__tab-target" data-finder="blog">
|
<section class="story__blog story__tab-target" data-fictioneer-story-target="tabContent" data-tab-name="blog">
|
||||||
<ol class="story__blog-list">
|
<ol class="story__blog-list">
|
||||||
<?php
|
<?php
|
||||||
if ( $blog_posts->have_posts() ) {
|
if ( $blog_posts->have_posts() ) {
|
||||||
@ -815,10 +817,10 @@ function fictioneer_story_comments( $args ) {
|
|||||||
?></h2>
|
?></h2>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<?php do_action( 'fictioneer_story_before_comments_list', $args ); ?>
|
<?php do_action( 'fictioneer_story_before_comments_list', $args ); ?>
|
||||||
<div class="fictioneer-comments__list">
|
<div class="fictioneer-comments__list" data-fictioneer-story-target="commentsWrapper">
|
||||||
<ul>
|
<ul>
|
||||||
<li class="load-more-list-item">
|
<li class="load-more-list-item" data-fictioneer-story-target="commentsList">
|
||||||
<button class="load-more-comments-button" data-story-id="<?php echo $args['story_id']; ?>"><?php
|
<button class="load-more-comments-button" data-action="click->fictioneer-story#loadComments"><?php
|
||||||
$load_n = $story['comment_count'] < get_option( 'comments_per_page' ) ?
|
$load_n = $story['comment_count'] < get_option( 'comments_per_page' ) ?
|
||||||
$story['comment_count'] : get_option( 'comments_per_page' );
|
$story['comment_count'] : get_option( 'comments_per_page' );
|
||||||
|
|
||||||
@ -833,7 +835,7 @@ function fictioneer_story_comments( $args ) {
|
|||||||
);
|
);
|
||||||
?></button>
|
?></button>
|
||||||
</li>
|
</li>
|
||||||
<div class="comments-loading-placeholder hidden"><i class="fa-solid fa-spinner spinner"></i></div>
|
<div class="comments-loading-placeholder hidden" data-fictioneer-story-target="commentsPlaceholder"><i class="fa-solid fa-spinner spinner"></i></div>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
@ -1308,7 +1308,6 @@ function fictioneer_register_settings() {
|
|||||||
* Sanitizes the 'words per minute' setting with fallback
|
* Sanitizes the 'words per minute' setting with fallback
|
||||||
*
|
*
|
||||||
* @since 4.0.0
|
* @since 4.0.0
|
||||||
* @see fictioneer_sanitize_integer()
|
|
||||||
*
|
*
|
||||||
* @param mixed $input The input value to sanitize.
|
* @param mixed $input The input value to sanitize.
|
||||||
*
|
*
|
||||||
@ -1323,7 +1322,6 @@ function fictioneer_sanitize_words_per_minute( $input ) {
|
|||||||
* Sanitizes integer to be 1 or more
|
* Sanitizes integer to be 1 or more
|
||||||
*
|
*
|
||||||
* @since 4.6.0
|
* @since 4.6.0
|
||||||
* @see fictioneer_sanitize_integer()
|
|
||||||
*
|
*
|
||||||
* @param mixed $input The input value to sanitize.
|
* @param mixed $input The input value to sanitize.
|
||||||
*
|
*
|
||||||
@ -1374,7 +1372,6 @@ function fictioneer_sanitize_absint_or_empty_string( $input ) {
|
|||||||
* problematic HTML.
|
* problematic HTML.
|
||||||
*
|
*
|
||||||
* @since 4.6.0
|
* @since 4.6.0
|
||||||
* @see wp_kses_post()
|
|
||||||
*
|
*
|
||||||
* @param mixed $input The content for the cookie consent banner.
|
* @param mixed $input The content for the cookie consent banner.
|
||||||
*
|
*
|
||||||
|
@ -1396,7 +1396,6 @@ add_action( 'admin_post_fictioneer_tools_add_chapter_hidden_fields', 'fictioneer
|
|||||||
* Append chapters to a story by ID
|
* Append chapters to a story by ID
|
||||||
*
|
*
|
||||||
* @since 5.8.6
|
* @since 5.8.6
|
||||||
* @see fictioneer_append_chapter_to_story()
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function fictioneer_tools_append_chapters() {
|
function fictioneer_tools_append_chapters() {
|
||||||
|
@ -466,7 +466,6 @@ add_action( 'untrashed_post', function( $post_id ) {
|
|||||||
* Helper to log published posts
|
* Helper to log published posts
|
||||||
*
|
*
|
||||||
* @since 5.0.0
|
* @since 5.0.0
|
||||||
* @see fictioneer_log_post_update()
|
|
||||||
*
|
*
|
||||||
* @param int $post_id The post ID.
|
* @param int $post_id The post ID.
|
||||||
*/
|
*/
|
||||||
@ -502,7 +501,6 @@ add_action( 'publish_fcn_recommendation', 'fictioneer_log_published_posts' );
|
|||||||
* Helper to log pending posts
|
* Helper to log pending posts
|
||||||
*
|
*
|
||||||
* @since 5.0.0
|
* @since 5.0.0
|
||||||
* @see fictioneer_log_post_update()
|
|
||||||
*
|
*
|
||||||
* @param int $post_id The post ID.
|
* @param int $post_id The post ID.
|
||||||
*/
|
*/
|
||||||
@ -532,7 +530,6 @@ add_action( 'pending_fcn_recommendation', 'fictioneer_log_published_posts' );
|
|||||||
* Helper to log deleted posts
|
* Helper to log deleted posts
|
||||||
*
|
*
|
||||||
* @since 5.0.0
|
* @since 5.0.0
|
||||||
* @see fictioneer_log_post_update()
|
|
||||||
*
|
*
|
||||||
* @param int $post_id The post ID.
|
* @param int $post_id The post ID.
|
||||||
*/
|
*/
|
||||||
|
@ -1459,6 +1459,7 @@ function fictioneer_admin_profile_fields_data_nodes( $profile_user ) {
|
|||||||
data-confirm-dialog
|
data-confirm-dialog
|
||||||
data-dialog-message="<?php echo esc_attr( $confirmation_message ); ?>"
|
data-dialog-message="<?php echo esc_attr( $confirmation_message ); ?>"
|
||||||
data-dialog-confirm="<?php echo esc_attr( $confirmation_string ); ?>"
|
data-dialog-confirm="<?php echo esc_attr( $confirmation_string ); ?>"
|
||||||
|
data-action="click->fictioneer-admin-profile#purgeLocalUserData"
|
||||||
>
|
>
|
||||||
<?php echo $node[1]; ?>
|
<?php echo $node[1]; ?>
|
||||||
<span><?php
|
<span><?php
|
||||||
|
@ -1,67 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
// SAVE BOOKMARKS FOR USERS - AJAX
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Save bookmarks JSON for user via AJAX
|
|
||||||
*
|
|
||||||
* Note: Bookmarks are not evaluated server-side, only stored as JSON string.
|
|
||||||
* Everything else happens client-side.
|
|
||||||
*
|
|
||||||
* @since 4.0.0
|
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_success/
|
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_error/
|
|
||||||
* @see fictioneer_get_validated_ajax_user()
|
|
||||||
*/
|
|
||||||
|
|
||||||
function fictioneer_ajax_save_bookmarks() {
|
|
||||||
// Enabled?
|
|
||||||
if ( ! get_option( 'fictioneer_enable_bookmarks' ) ) {
|
|
||||||
wp_send_json_error( null, 403 );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup and validations
|
|
||||||
$user = fictioneer_get_validated_ajax_user();
|
|
||||||
|
|
||||||
if ( ! $user ) {
|
|
||||||
wp_send_json_error( array( 'error' => 'Request did not pass validation.' ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( empty( $_POST['bookmarks'] ) ) {
|
|
||||||
wp_send_json_error( array( 'error' => 'Missing arguments.' ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Valid?
|
|
||||||
$bookmarks = sanitize_text_field( $_POST['bookmarks'] );
|
|
||||||
|
|
||||||
if ( $bookmarks && fictioneer_is_valid_json( wp_unslash( $bookmarks ) ) ) {
|
|
||||||
// Inspect
|
|
||||||
$decoded = json_decode( wp_unslash( $bookmarks ), true );
|
|
||||||
|
|
||||||
if ( ! $decoded || ! isset( $decoded['data'] ) ) {
|
|
||||||
wp_send_json_error( array( 'error' => 'Invalid JSON.' ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update and response (uses wp_slash/wp_unslash internally)
|
|
||||||
$old_bookmarks = get_user_meta( $user->ID, 'fictioneer_bookmarks', true );
|
|
||||||
|
|
||||||
if ( wp_unslash( $bookmarks ) === $old_bookmarks ) {
|
|
||||||
wp_send_json_success(); // Nothing to update
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( update_user_meta( $user->ID, 'fictioneer_bookmarks', $bookmarks ) ) {
|
|
||||||
wp_send_json_success();
|
|
||||||
} else {
|
|
||||||
wp_send_json_error( array( 'error' => 'Bookmarks could not be updated.' ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Something went wrong if we end up here...
|
|
||||||
wp_send_json_error( array( 'error' => 'An unknown error occurred.' ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( get_option( 'fictioneer_enable_bookmarks' ) ) {
|
|
||||||
add_action( 'wp_ajax_fictioneer_ajax_save_bookmarks', 'fictioneer_ajax_save_bookmarks' );
|
|
||||||
}
|
|
@ -120,12 +120,6 @@ if ( ! wp_doing_ajax() ) {
|
|||||||
* Set Checkmarks for a story via AJAX
|
* Set Checkmarks for a story via AJAX
|
||||||
*
|
*
|
||||||
* @since 4.0.0
|
* @since 4.0.0
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_success/
|
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_error/
|
|
||||||
* @see fictioneer_get_validated_ajax_user()
|
|
||||||
* @see fictioneer_validate_id()
|
|
||||||
* @see fictioneer_get_story_data()
|
|
||||||
* @see fictioneer_load_checkmarks()
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function fictioneer_ajax_set_checkmark() {
|
function fictioneer_ajax_set_checkmark() {
|
||||||
@ -152,23 +146,17 @@ function fictioneer_ajax_set_checkmark() {
|
|||||||
$story_data = fictioneer_get_story_data( $story_id, false ); // Does not refresh comment count!
|
$story_data = fictioneer_get_story_data( $story_id, false ); // Does not refresh comment count!
|
||||||
|
|
||||||
// Prepare update
|
// Prepare update
|
||||||
$update = isset( $_POST['update'] ) ? explode( ' ', sanitize_text_field( $_POST['update'] ) ) : [];
|
$update = isset( $_POST['update'] ) ? array_map( 'absint', explode( ' ', sanitize_text_field( $_POST['update'] ) ) ) : [];
|
||||||
$update_ids = [];
|
$update_ids = [];
|
||||||
|
|
||||||
// Check update...
|
// Prepare story chapter IDs
|
||||||
if ( in_array( $story_id, $update ) ) {
|
$chapter_ids = array_map( 'absint', $story_data['chapter_ids'] );
|
||||||
// If story ID in update, add all chapters and mark story as read
|
|
||||||
$update_ids = array_map( function ( $a ) { return absint( $a ); }, $story_data['chapter_ids'] );
|
|
||||||
$update_ids[] = absint( $story_id );
|
|
||||||
} else {
|
|
||||||
// Check if chapter IDs are part of the story
|
|
||||||
foreach ( $update as $chapter_id ) {
|
|
||||||
$chapter_id = absint( $chapter_id );
|
|
||||||
|
|
||||||
if ( in_array( $chapter_id, $story_data['chapter_ids'] ) ) {
|
// Prepare valid update IDs
|
||||||
$update_ids[] = $chapter_id;
|
if ( in_array( $story_id, $update, true ) ) {
|
||||||
}
|
$update_ids = array_merge( $chapter_ids, [ $story_id ] );
|
||||||
}
|
} else {
|
||||||
|
$update_ids = array_intersect( $update, $chapter_ids );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare Checkmarks
|
// Prepare Checkmarks
|
||||||
@ -198,9 +186,6 @@ if ( get_option( 'fictioneer_enable_checkmarks' ) ) {
|
|||||||
* Clears Checkmarks for a story via AJAX
|
* Clears Checkmarks for a story via AJAX
|
||||||
*
|
*
|
||||||
* @since 5.0.0
|
* @since 5.0.0
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_success/
|
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_error/
|
|
||||||
* @see fictioneer_get_validated_ajax_user()
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function fictioneer_ajax_clear_my_checkmarks() {
|
function fictioneer_ajax_clear_my_checkmarks() {
|
||||||
|
@ -119,10 +119,6 @@ if ( ! wp_doing_ajax() ) {
|
|||||||
* Toggle Follow for a story via AJAX
|
* Toggle Follow for a story via AJAX
|
||||||
*
|
*
|
||||||
* @since 4.3.0
|
* @since 4.3.0
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_success/
|
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_error/
|
|
||||||
* @see fictioneer_get_validated_ajax_user()
|
|
||||||
* @see fictioneer_load_follows()
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function fictioneer_ajax_toggle_follow() {
|
function fictioneer_ajax_toggle_follow() {
|
||||||
@ -190,9 +186,6 @@ if ( get_option( 'fictioneer_enable_follows' ) ) {
|
|||||||
* Clears an user's Follows via AJAX
|
* Clears an user's Follows via AJAX
|
||||||
*
|
*
|
||||||
* @since 5.0.0
|
* @since 5.0.0
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_success/
|
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_error/
|
|
||||||
* @see fictioneer_get_validated_ajax_user()
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function fictioneer_ajax_clear_my_follows() {
|
function fictioneer_ajax_clear_my_follows() {
|
||||||
@ -231,9 +224,6 @@ if ( get_option( 'fictioneer_enable_follows' ) ) {
|
|||||||
* of them as read, you cannot mark single items in the list as read.
|
* of them as read, you cannot mark single items in the list as read.
|
||||||
*
|
*
|
||||||
* @since 4.3.0
|
* @since 4.3.0
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_success/
|
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_error/
|
|
||||||
* @see fictioneer_get_validated_ajax_user()
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function fictioneer_ajax_mark_follows_read() {
|
function fictioneer_ajax_mark_follows_read() {
|
||||||
@ -280,8 +270,6 @@ if ( get_option( 'fictioneer_enable_follows' ) ) {
|
|||||||
* Sends the HTML for Follows notifications via AJAX
|
* Sends the HTML for Follows notifications via AJAX
|
||||||
*
|
*
|
||||||
* @since 4.3.0
|
* @since 4.3.0
|
||||||
* @see fictioneer_check_rate_limit()
|
|
||||||
* @see fictioneer_get_validated_ajax_user()
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function fictioneer_ajax_get_follows_notifications() {
|
function fictioneer_ajax_get_follows_notifications() {
|
||||||
|
@ -57,9 +57,6 @@ if ( ! wp_doing_ajax() ) {
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @since 5.0.0
|
* @since 5.0.0
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_success/
|
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_error/
|
|
||||||
* @see fictioneer_get_validated_ajax_user()
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function fictioneer_ajax_toggle_reminder() {
|
function fictioneer_ajax_toggle_reminder() {
|
||||||
@ -125,9 +122,6 @@ if ( get_option( 'fictioneer_enable_reminders' ) ) {
|
|||||||
* Clears an user's Reminders via AJAX
|
* Clears an user's Reminders via AJAX
|
||||||
*
|
*
|
||||||
* @since 5.0.0
|
* @since 5.0.0
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_success/
|
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_error/
|
|
||||||
* @see fictioneer_get_validated_ajax_user()
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function fictioneer_ajax_clear_my_reminders() {
|
function fictioneer_ajax_clear_my_reminders() {
|
||||||
|
@ -14,28 +14,44 @@ function fictioneer_ajax_get_user_data() {
|
|||||||
// Rate limit
|
// Rate limit
|
||||||
fictioneer_check_rate_limit( 'fictioneer_ajax_get_user_data', 30 );
|
fictioneer_check_rate_limit( 'fictioneer_ajax_get_user_data', 30 );
|
||||||
|
|
||||||
// Validations
|
|
||||||
$user = fictioneer_get_validated_ajax_user();
|
|
||||||
|
|
||||||
if ( ! $user ) {
|
|
||||||
wp_send_json_error( array( 'error' => 'Request did not pass validation.' ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup
|
// Setup
|
||||||
|
$logged_in = is_user_logged_in();
|
||||||
|
$user = wp_get_current_user();
|
||||||
|
$nonce = wp_create_nonce( 'fictioneer_nonce' );
|
||||||
$data = array(
|
$data = array(
|
||||||
'user_id' => $user->ID,
|
'user_id' => $user->ID,
|
||||||
'timestamp' => time() * 1000, // Compatible with Date.now() in JavaScript
|
'timestamp' => time() * 1000, // Compatible with Date.now() in JavaScript
|
||||||
'loggedIn' => true,
|
'loggedIn' => $logged_in,
|
||||||
'follows' => false,
|
'follows' => false,
|
||||||
'reminders' => false,
|
'reminders' => false,
|
||||||
'checkmarks' => false,
|
'checkmarks' => false,
|
||||||
'bookmarks' => '{}',
|
'bookmarks' => '{}',
|
||||||
'fingerprint' => fictioneer_get_user_fingerprint( $user->ID )
|
'fingerprint' => fictioneer_get_user_fingerprint( $user->ID ),
|
||||||
|
'avatarUrl' => '',
|
||||||
|
'isAdmin' => false,
|
||||||
|
'isModerator' => false,
|
||||||
|
'isAuthor' => false,
|
||||||
|
'isEditor' => false,
|
||||||
|
'nonce' => $nonce,
|
||||||
|
'nonceHtml' => '<input id="fictioneer-ajax-nonce" name="fictioneer-ajax-nonce" type="hidden" value="' . $nonce . '">'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if ( $logged_in ) {
|
||||||
|
$data = array_merge(
|
||||||
|
$data,
|
||||||
|
array(
|
||||||
|
'isAdmin' => fictioneer_is_admin( $user->ID ),
|
||||||
|
'isModerator' => fictioneer_is_moderator( $user->ID ),
|
||||||
|
'isAuthor' => fictioneer_is_author( $user->ID ),
|
||||||
|
'isEditor' => fictioneer_is_editor( $user->ID ),
|
||||||
|
'avatarUrl' => get_avatar_url( $user->ID )
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// --- FOLLOWS ---------------------------------------------------------------
|
// --- FOLLOWS ---------------------------------------------------------------
|
||||||
|
|
||||||
if ( get_option( 'fictioneer_enable_follows' ) ) {
|
if ( $logged_in && get_option( 'fictioneer_enable_follows' ) ) {
|
||||||
$follows = fictioneer_load_follows( $user );
|
$follows = fictioneer_load_follows( $user );
|
||||||
$follows['new'] = false;
|
$follows['new'] = false;
|
||||||
$latest = 0;
|
$latest = 0;
|
||||||
@ -57,19 +73,19 @@ function fictioneer_ajax_get_user_data() {
|
|||||||
|
|
||||||
// --- REMINDERS -------------------------------------------------------------
|
// --- REMINDERS -------------------------------------------------------------
|
||||||
|
|
||||||
if ( get_option( 'fictioneer_enable_reminders' ) ) {
|
if ( $logged_in && get_option( 'fictioneer_enable_reminders' ) ) {
|
||||||
$data['reminders'] = fictioneer_load_reminders( $user );
|
$data['reminders'] = fictioneer_load_reminders( $user );
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- CHECKMARKS ------------------------------------------------------------
|
// --- CHECKMARKS ------------------------------------------------------------
|
||||||
|
|
||||||
if ( get_option( 'fictioneer_enable_checkmarks' ) ) {
|
if ( $logged_in && get_option( 'fictioneer_enable_checkmarks' ) ) {
|
||||||
$data['checkmarks'] = fictioneer_load_checkmarks( $user );
|
$data['checkmarks'] = fictioneer_load_checkmarks( $user );
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- BOOKMARKS -------------------------------------------------------------
|
// --- BOOKMARKS -------------------------------------------------------------
|
||||||
|
|
||||||
if ( get_option( 'fictioneer_enable_bookmarks' ) ) {
|
if ( $logged_in && get_option( 'fictioneer_enable_bookmarks' ) ) {
|
||||||
$bookmarks = get_user_meta( $user->ID, 'fictioneer_bookmarks', true );
|
$bookmarks = get_user_meta( $user->ID, 'fictioneer_bookmarks', true );
|
||||||
$data['bookmarks'] = $bookmarks ? $bookmarks : '{}';
|
$data['bookmarks'] = $bookmarks ? $bookmarks : '{}';
|
||||||
}
|
}
|
||||||
@ -84,6 +100,7 @@ function fictioneer_ajax_get_user_data() {
|
|||||||
wp_send_json_success( $data );
|
wp_send_json_success( $data );
|
||||||
}
|
}
|
||||||
add_action( 'wp_ajax_fictioneer_ajax_get_user_data', 'fictioneer_ajax_get_user_data' );
|
add_action( 'wp_ajax_fictioneer_ajax_get_user_data', 'fictioneer_ajax_get_user_data' );
|
||||||
|
add_action( 'wp_ajax_nopriv_fictioneer_ajax_get_user_data', 'fictioneer_ajax_get_user_data' );
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// SELF-DELETE USER - AJAX
|
// SELF-DELETE USER - AJAX
|
||||||
@ -93,10 +110,6 @@ add_action( 'wp_ajax_fictioneer_ajax_get_user_data', 'fictioneer_ajax_get_user_d
|
|||||||
* Delete an user's account via AJAX
|
* Delete an user's account via AJAX
|
||||||
*
|
*
|
||||||
* @since 4.5.0
|
* @since 4.5.0
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_success/
|
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_error/
|
|
||||||
* @see fictioneer_validate_id()
|
|
||||||
* @see fictioneer_get_validated_ajax_user()
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function fictioneer_ajax_delete_my_account() {
|
function fictioneer_ajax_delete_my_account() {
|
||||||
@ -119,7 +132,6 @@ function fictioneer_ajax_delete_my_account() {
|
|||||||
'button' => __( 'Denied', 'fictioneer' )
|
'button' => __( 'Denied', 'fictioneer' )
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
die(); // Just to be sure
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete user
|
// Delete user
|
||||||
@ -151,9 +163,6 @@ if ( current_user_can( 'fcn_allow_self_delete' ) ) {
|
|||||||
* and updating all comments.
|
* and updating all comments.
|
||||||
*
|
*
|
||||||
* @since 5.0.0
|
* @since 5.0.0
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_success/
|
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_error/
|
|
||||||
* @see fictioneer_get_validated_ajax_user()
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function fictioneer_ajax_clear_my_comment_subscriptions() {
|
function fictioneer_ajax_clear_my_comment_subscriptions() {
|
||||||
@ -184,9 +193,6 @@ add_action( 'wp_ajax_fictioneer_ajax_clear_my_comment_subscriptions', 'fictionee
|
|||||||
* garbage, preserving the comment thread integrity.
|
* garbage, preserving the comment thread integrity.
|
||||||
*
|
*
|
||||||
* @since 5.0.0
|
* @since 5.0.0
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_success/
|
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_error/
|
|
||||||
* @see fictioneer_get_validated_ajax_user()
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function fictioneer_ajax_clear_my_comments() {
|
function fictioneer_ajax_clear_my_comments() {
|
||||||
@ -248,8 +254,6 @@ add_action( 'wp_ajax_fictioneer_ajax_clear_my_comments', 'fictioneer_ajax_clear_
|
|||||||
* Unset one of the user's OAuth bindings via AJAX
|
* Unset one of the user's OAuth bindings via AJAX
|
||||||
*
|
*
|
||||||
* @since 4.0.0
|
* @since 4.0.0
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_success/
|
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_error/
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function fictioneer_ajax_unset_my_oauth() {
|
function fictioneer_ajax_unset_my_oauth() {
|
||||||
@ -294,19 +298,73 @@ function fictioneer_ajax_unset_my_oauth() {
|
|||||||
add_action( 'wp_ajax_fictioneer_ajax_unset_my_oauth', 'fictioneer_ajax_unset_my_oauth' );
|
add_action( 'wp_ajax_fictioneer_ajax_unset_my_oauth', 'fictioneer_ajax_unset_my_oauth' );
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// GET USER AVATAR URL - AJAX
|
// AJAX: CLEAR COOKIES
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get user avatar URL via AJAX
|
* Clear all cookies and log out.
|
||||||
*
|
*
|
||||||
* @since 4.0.0
|
* @since 5.27.0
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_success/
|
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_error/
|
|
||||||
* @see fictioneer_get_validated_ajax_user()
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function fictioneer_ajax_get_avatar() {
|
function fictioneer_ajax_clear_cookies() {
|
||||||
|
// Setup and validations
|
||||||
|
$user = fictioneer_get_validated_ajax_user();
|
||||||
|
|
||||||
|
if ( ! $user ) {
|
||||||
|
wp_send_json_error(
|
||||||
|
array(
|
||||||
|
'error' => 'Request did not pass validation.',
|
||||||
|
'failure' => __( 'There has been an error. Try again later and if the problem persists, contact an administrator.', 'fictioneer' )
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Logout
|
||||||
|
wp_logout();
|
||||||
|
|
||||||
|
// Clear remaining cookies
|
||||||
|
if ( isset( $_SERVER['HTTP_COOKIE'] ) ) {
|
||||||
|
$cookies = explode( ';', $_SERVER['HTTP_COOKIE'] );
|
||||||
|
|
||||||
|
foreach ($cookies as $cookie) {
|
||||||
|
$parts = explode( '=', $cookie );
|
||||||
|
$name = trim( $parts[0] );
|
||||||
|
|
||||||
|
setcookie( $name, '', time() - 3600, '/' );
|
||||||
|
|
||||||
|
unset( $_COOKIE[ $name ] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Response
|
||||||
|
wp_send_json_success(
|
||||||
|
array(
|
||||||
|
'success' => __( 'Cookies and local storage have been cleared. To keep it that way, you should leave the site.', 'fictioneer' )
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
add_action( 'wp_ajax_fictioneer_ajax_clear_cookies', 'fictioneer_ajax_clear_cookies' );
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// SAVE BOOKMARKS FOR USERS - AJAX
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save bookmarks JSON for user via AJAX
|
||||||
|
*
|
||||||
|
* Note: Bookmarks are not evaluated server-side, only stored as JSON string.
|
||||||
|
* Everything else happens client-side.
|
||||||
|
*
|
||||||
|
* @since 4.0.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
function fictioneer_ajax_save_bookmarks() {
|
||||||
|
// Enabled?
|
||||||
|
if ( ! get_option( 'fictioneer_enable_bookmarks' ) ) {
|
||||||
|
wp_send_json_error( null, 403 );
|
||||||
|
}
|
||||||
|
|
||||||
// Setup and validations
|
// Setup and validations
|
||||||
$user = fictioneer_get_validated_ajax_user();
|
$user = fictioneer_get_validated_ajax_user();
|
||||||
|
|
||||||
@ -314,7 +372,39 @@ function fictioneer_ajax_get_avatar() {
|
|||||||
wp_send_json_error( array( 'error' => 'Request did not pass validation.' ) );
|
wp_send_json_error( array( 'error' => 'Request did not pass validation.' ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Response
|
if ( empty( $_POST['bookmarks'] ) ) {
|
||||||
wp_send_json_success( array( 'url' => get_avatar_url( $user->ID ) ) );
|
wp_send_json_error( array( 'error' => 'Missing arguments.' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valid?
|
||||||
|
$bookmarks = sanitize_text_field( $_POST['bookmarks'] );
|
||||||
|
|
||||||
|
if ( $bookmarks && fictioneer_is_valid_json( wp_unslash( $bookmarks ) ) ) {
|
||||||
|
// Inspect
|
||||||
|
$decoded = json_decode( wp_unslash( $bookmarks ), true );
|
||||||
|
|
||||||
|
if ( ! $decoded || ! isset( $decoded['data'] ) ) {
|
||||||
|
wp_send_json_error( array( 'error' => 'Invalid JSON.' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update and response (uses wp_slash/wp_unslash internally)
|
||||||
|
$old_bookmarks = get_user_meta( $user->ID, 'fictioneer_bookmarks', true );
|
||||||
|
|
||||||
|
if ( wp_unslash( $bookmarks ) === $old_bookmarks ) {
|
||||||
|
wp_send_json_success(); // Nothing to update
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( update_user_meta( $user->ID, 'fictioneer_bookmarks', $bookmarks ) ) {
|
||||||
|
wp_send_json_success();
|
||||||
|
} else {
|
||||||
|
wp_send_json_error( array( 'error' => 'Bookmarks could not be updated.' ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Something went wrong if we end up here...
|
||||||
|
wp_send_json_error( array( 'error' => 'An unknown error occurred.' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( get_option( 'fictioneer_enable_bookmarks' ) ) {
|
||||||
|
add_action( 'wp_ajax_fictioneer_ajax_save_bookmarks', 'fictioneer_ajax_save_bookmarks' );
|
||||||
}
|
}
|
||||||
add_action( 'wp_ajax_fictioneer_ajax_get_avatar', 'fictioneer_ajax_get_avatar' );
|
|
||||||
|
2
js/admin.min.js
vendored
2
js/admin.min.js
vendored
File diff suppressed because one or more lines are too long
2
js/ajax-bookshelf.min.js
vendored
2
js/ajax-bookshelf.min.js
vendored
@ -1 +1 @@
|
|||||||
const fcn_bookshelfTarget=_$$$("ajax-bookshelf-target");function fcn_getBookshelfContent(){return fcn_parseJSON(localStorage.getItem("fcnBookshelfContent"))??{html:{},count:{}}}function fcn_updateBookshelfView(e=null,t=null,o=null,n=!1){let a=fcn_getBookshelfContent();const s=(e=e??fcn_bookshelfTarget.dataset.action)+(t=t??fcn_bookshelfTarget.dataset.page)+(o=o??fcn_bookshelfTarget.dataset.order);if(!a.timestamp||a.timestamp+6e4<Date.now())return localStorage.removeItem("fcnBookshelfContent"),a={html:{},count:{}},void fcn_fetchBookshelfPart(e,t,o,n);a.html&&a.html[s]?(fcn_bookshelfTarget.innerHTML=a.html[s],fcn_bookshelfTarget.classList.remove("ajax-in-progress"),fcn_bookshelfTarget.dataset.page=t,_$(".item-number").innerHTML=`(${a.count[e]})`,n&&_$$$("main").scrollIntoView({behavior:"smooth"})):fcn_fetchBookshelfPart(e,t,o,n)}function fcn_browseBookshelfPage(e){fcn_bookshelfTarget.classList.add("ajax-in-progress"),fcn_updateBookshelfView(null,e,null,!0),history.pushState({},"",fcn_buildUrl({tab:fcn_bookshelfTarget.dataset.tab,pg:e,order:fcn_bookshelfTarget.dataset.order}).href)}function fcn_fetchBookshelfPart(e,t,o,n=!1){const a=e+t+o,s=fcn_getBookshelfContent();fcn_ajaxGet({action:e,fcn_fast_ajax:1,page:t,order:o}).then((o=>{o.success?(s.timestamp=Date.now(),s.html[a]=o.data.html,s.count[e]=o.data.count,localStorage.setItem("fcnBookshelfContent",JSON.stringify(s)),fcn_bookshelfTarget.innerHTML=o.data.html,fcn_bookshelfTarget.dataset.page=t,_$(".item-number").innerHTML=`(${o.data.count})`):(fcn_bookshelfTarget.innerHTML="",fcn_bookshelfTarget.appendChild(fcn_buildErrorNotice(o.data.error)))})).catch((e=>{_$(".item-number").innerHTML="",fcn_bookshelfTarget.innerHTML="",fcn_bookshelfTarget.appendChild(fcn_buildErrorNotice(`${e.status}: ${e.statusText}`))})).then((()=>{fcn_bookshelfTarget.classList.remove("ajax-in-progress"),n&&_$$$("main").scrollIntoView({behavior:"smooth"})}))}fcn_bookshelfTarget&&(fcn_theRoot.dataset.ajaxAuth?document.addEventListener("fcnAuthReady",(()=>{fcn_updateBookshelfView()})):fcn_updateBookshelfView()),_$(".bookshelf__list")?.addEventListener("click",(e=>{const t=e.target.closest(".page-numbers[data-page]");t&&fcn_browseBookshelfPage(t.dataset.page)}));
|
const fcn_bookshelfTarget=_$$$("ajax-bookshelf-target");function fcn_getBookshelfContent(){return FcnUtils.parseJSON(localStorage.getItem("fcnBookshelfContent"))??{html:{},count:{}}}function fcn_updateBookshelfView(e=null,t=null,o=null,n=!1){let a=fcn_getBookshelfContent();const s=(e=e??fcn_bookshelfTarget.dataset.action)+(t=t??fcn_bookshelfTarget.dataset.page)+(o=o??fcn_bookshelfTarget.dataset.order);if(!a.timestamp||a.timestamp+6e4<Date.now())return localStorage.removeItem("fcnBookshelfContent"),a={html:{},count:{}},void fcn_fetchBookshelfPart(e,t,o,n);a.html&&a.html[s]?(fcn_bookshelfTarget.innerHTML=a.html[s],fcn_bookshelfTarget.classList.remove("ajax-in-progress"),fcn_bookshelfTarget.dataset.page=t,_$(".item-number").innerHTML=`(${a.count[e]})`,n&&_$$$("main").scrollIntoView({behavior:"smooth"})):fcn_fetchBookshelfPart(e,t,o,n)}function fcn_browseBookshelfPage(e){fcn_bookshelfTarget.classList.add("ajax-in-progress"),fcn_updateBookshelfView(null,e,null,!0),history.pushState({},"",FcnUtils.buildUrl({tab:fcn_bookshelfTarget.dataset.tab,pg:e,order:fcn_bookshelfTarget.dataset.order}).href)}function fcn_fetchBookshelfPart(e,t,o,n=!1){const a=e+t+o,s=fcn_getBookshelfContent();FcnUtils.aGet({action:e,fcn_fast_ajax:1,page:t,order:o}).then((o=>{o.success?(s.timestamp=Date.now(),s.html[a]=o.data.html,s.count[e]=o.data.count,localStorage.setItem("fcnBookshelfContent",JSON.stringify(s)),fcn_bookshelfTarget.innerHTML=o.data.html,fcn_bookshelfTarget.dataset.page=t,_$(".item-number").innerHTML=`(${o.data.count})`):(fcn_bookshelfTarget.innerHTML="",fcn_bookshelfTarget.appendChild(FcnUtils.buildErrorNotice(o.data.error)))})).catch((e=>{_$(".item-number").innerHTML="",fcn_bookshelfTarget.innerHTML="",fcn_bookshelfTarget.appendChild(FcnUtils.buildErrorNotice(`${e.status}: ${e.statusText}`))})).then((()=>{fcn_bookshelfTarget.classList.remove("ajax-in-progress"),n&&_$$$("main").scrollIntoView({behavior:"smooth"})}))}fcn_bookshelfTarget&&document.addEventListener("fcnUserDataReady",(()=>{fcn_updateBookshelfView()})),_$(".bookshelf__list")?.addEventListener("click",(e=>{const t=e.target.closest(".page-numbers[data-page]");t&&fcn_browseBookshelfPage(t.dataset.page)}));
|
2
js/ajax-comments.min.js
vendored
2
js/ajax-comments.min.js
vendored
@ -1 +1 @@
|
|||||||
const fcn_commentSection=_$("#comments[data-ajax-comments]");function fcn_getCommentSection(e=null,t=null,n=null,o=!1){if(!fcn_commentSection)return;let c,a="",m=_$(fictioneer_comments.form_selector??"#comment");if(m&&(a=m.value),fcn_commentSection.classList.contains("ajax-in-progress"))return;if(fcn_commentSection.classList.add("ajax-in-progress"),t||(t=fcn_urlParams.pg??1),n||(n=n??fcn_commentSection.dataset.order??"desc"),!fcn_commentSection)return;const r={action:"fictioneer_ajax_get_comment_section",post_id:e??fcn_commentSection.dataset.postId,page:parseInt(t),corder:n,fcn_fast_comment_ajax:1};fcn_urlParams.commentcode&&(r.commentcode=fcn_urlParams.commentcode),fcn_ajaxGet(r).then((e=>{if(e.success){t=e.data.page,fcn_commentSection.dataset.page=t;const c=document.createElement("div");if(c.innerHTML=e.data.html,c.querySelector("#comment_post_ID")){c.querySelector("#comment_post_ID").value=e.data.postId,c.querySelector("#cancel-comment-reply-link").href="#respond";const t=c.querySelector(".logout-link");t&&(t.href=fcn_commentSection.dataset.logoutUrl)}fcn_commentSection.innerHTML=c.innerHTML,c.remove(),m=_$(fictioneer_comments.form_selector??"#comment"),m&&!e.data.disabled&&(m.value=a,fcn_applyCommentStack(m)),fcn_addCommentMouseleaveEvents(),fcn_addCommentFormEvents(),fcn_bindAJAXCommentSubmit(),fcn_addJSTrap(),fcn_revealEditButton(),fcn_revealDeleteButton();const r=location.hash.includes("#comment")?location.hash:".respond",s=document.querySelector(r)??_$$$("respond");o&&s.scrollIntoView({behavior:"smooth"});const i=window.location.protocol+"//"+window.location.host+window.location.pathname;(t>1||fcn_urlParams.pg)&&(fcn_urlParams.pg=t),("desc"!=n||fcn_urlParams.corder)&&(fcn_urlParams.corder=n);let l=Object.entries(fcn_urlParams).map((([e,t])=>`${e}=${t}`)).join("&");""!==l&&(l=`?${l}`),window.history.pushState({path:i},"",i+l+location.hash)}else c=fcn_buildErrorNotice(e.data.error)})).catch((e=>{c=fcn_buildErrorNotice(e)})).then((()=>{fcn_commentSection.classList.remove("ajax-in-progress"),c&&(fcn_commentSection.innerHTML="",fcn_commentSection.appendChild(c))}))}function fcn_reloadCommentsPage(e=null){fcn_getCommentSection(null,e,null,!0)}function fcn_jumpToCommentPage(){const e=parseInt(window.prompt(fictioneer_tl.notification.enterPageNumber));e>0&&fcn_reloadCommentsPage(e)}var fct_commentSectionObserver;function fcn_setupCommentSectionObserver(){fct_commentSectionObserver=new IntersectionObserver((([e])=>{e.isIntersecting&&(fcn_getCommentSection(),fct_commentSectionObserver.disconnect())}),{rootMargin:"450px",threshold:1}),fcn_commentSection&&fct_commentSectionObserver.observe(fcn_commentSection)}function fcn_loadCommentEarly(){fcn_commentSection&&location.hash.includes("#comment")&&(_$(fictioneer_comments.form_selector??"#comment")||(fct_commentSectionObserver.disconnect(),fcn_reloadCommentsPage()))}function fcn_toggleCommentOrder(e){const t=e.closest(".fictioneer-comments"),n="desc"==t.dataset.order;t.dataset.order=n?"asc":"desc",e.classList.toggle("_on",!n),e.classList.toggle("_off",n),fcn_reloadCommentsPage(t.dataset.page)}fcn_theRoot.dataset.ajaxAuth?document.addEventListener("fcnAuthReady",(()=>{fcn_setupCommentSectionObserver()})):fcn_setupCommentSectionObserver(),fcn_theRoot.dataset.ajaxAuth?document.addEventListener("fcnAuthReady",(()=>{fcn_loadCommentEarly()})):fcn_loadCommentEarly(),_$(".fictioneer-comments")?.addEventListener("click",(e=>{if(e.target.closest("button[data-page-jump]"))return void fcn_jumpToCommentPage();const t=e.target.closest("button[data-page]");if(t)return void fcn_reloadCommentsPage(t.dataset.page);const n=e.target.closest("button[data-toggle-order]");n&&fcn_toggleCommentOrder(n)}));
|
const fcn_commentSection=_$("#comments[data-ajax-comments]");function fcn_getCommentSection(e=null,t=null,n=null,o=!1){if(!fcn_commentSection)return;let c,a="",r=_$(FcnGlobals.commentFormSelector);if(r&&(a=r.value),fcn_commentSection.classList.contains("ajax-in-progress"))return;if(fcn_commentSection.classList.add("ajax-in-progress"),t||(t=FcnGlobals.urlParams.pg??1),n||(n=n??fcn_commentSection.dataset.order??"desc"),!fcn_commentSection)return;const m={action:"fictioneer_ajax_get_comment_section",post_id:e??fcn_commentSection.dataset.postId,page:parseInt(t),corder:n,fcn_fast_comment_ajax:1};FcnGlobals.urlParams.commentcode&&(m.commentcode=FcnGlobals.urlParams.commentcode),FcnUtils.aGet(m).then((e=>{if(e.success){t=e.data.page,fcn_commentSection.dataset.page=t;const c=document.createElement("div");if(c.innerHTML=e.data.html,c.querySelector("#comment_post_ID")){c.querySelector("#comment_post_ID").value=e.data.postId,c.querySelector("#cancel-comment-reply-link").href="#respond";const t=c.querySelector(".logout-link");t&&(t.href=fcn_commentSection.dataset.logoutUrl)}fcn_commentSection.innerHTML=c.innerHTML,c.remove(),r=_$(FcnGlobals.commentFormSelector),r&&!e.data.disabled&&(r.value=a,fcn_applyCommentStack(r));const m=location.hash.includes("#comment")?location.hash:".respond",s=document.querySelector(m)??_$$$("respond");o&&s.scrollIntoView({behavior:"smooth"});const l=window.location.protocol+"//"+window.location.host+window.location.pathname;(t>1||FcnGlobals.urlParams.pg)&&(FcnGlobals.urlParams.pg=t),("desc"!=n||FcnGlobals.urlParams.corder)&&(FcnGlobals.urlParams.corder=n);let i=Object.entries(FcnGlobals.urlParams).map((([e,t])=>`${e}=${t}`)).join("&");""!==i&&(i=`?${i}`),window.history.pushState({path:l},"",l+i+location.hash)}else c=FcnUtils.buildErrorNotice(e.data.error)})).catch((e=>{c=FcnUtils.buildErrorNotice(e)})).then((()=>{fcn_commentSection.classList.remove("ajax-in-progress"),c&&(fcn_commentSection.innerHTML="",fcn_commentSection.appendChild(c))}))}function fcn_reloadCommentsPage(e=null){fcn_getCommentSection(null,e,null,!0)}function fcn_jumpToCommentPage(){const e=parseInt(window.prompt(fictioneer_tl.notification.enterPageNumber));e>0&&fcn_reloadCommentsPage(e)}var fct_commentSectionObserver;function fcn_setupCommentSectionObserver(){fct_commentSectionObserver=new IntersectionObserver((([e])=>{e.isIntersecting&&(fcn_getCommentSection(),fct_commentSectionObserver.disconnect())}),{rootMargin:"450px",threshold:1}),fcn_commentSection&&fct_commentSectionObserver.observe(fcn_commentSection)}function fcn_loadCommentEarly(){fcn_commentSection&&location.hash.includes("#comment")&&(_$(FcnGlobals.commentFormSelector)||(fct_commentSectionObserver.disconnect(),fcn_reloadCommentsPage()))}function fcn_toggleCommentOrder(e){const t=e.closest(".fictioneer-comments"),n="desc"==t.dataset.order;t.dataset.order=n?"asc":"desc",e.classList.toggle("_on",!n),e.classList.toggle("_off",n),fcn_reloadCommentsPage(t.dataset.page)}document.addEventListener("fcnUserDataReady",(()=>{fcn_setupCommentSectionObserver()})),document.addEventListener("fcnUserDataReady",(()=>{fcn_loadCommentEarly()})),_$(".fictioneer-comments")?.addEventListener("click",(e=>{if(e.target.closest("button[data-page-jump]"))return void fcn_jumpToCommentPage();const t=e.target.closest("button[data-page]");if(t)return void fcn_reloadCommentsPage(t.dataset.page);const n=e.target.closest("button[data-toggle-order]");n&&fcn_toggleCommentOrder(n)}));
|
4
js/application.min.js
vendored
4
js/application.min.js
vendored
File diff suppressed because one or more lines are too long
2
js/bookmarks.min.js
vendored
2
js/bookmarks.min.js
vendored
File diff suppressed because one or more lines are too long
2
js/chapter.min.js
vendored
2
js/chapter.min.js
vendored
File diff suppressed because one or more lines are too long
2
js/checkmarks.min.js
vendored
2
js/checkmarks.min.js
vendored
@ -1 +1 @@
|
|||||||
var fcn_checkmarks,fcn_userCheckmarksTimeout;function fcn_initializeCheckmarks(a){const e=a.detail.data.checkmarks;!1!==e&&(Array.isArray(e.data)&&0===e.data.length&&(e.data={}),fcn_checkmarks=e,fcn_updateCheckmarksView(),localStorage.removeItem("fcnBookshelfContent"),_$$("button.checkmark").forEach((a=>{a.addEventListener("click",(a=>{fcn_clickCheckmark(a.currentTarget)}))})))}function fcn_toggleCheckmark(a,e,t=null,c=null,s="toggle"){const r=fcn_getUserData();if(fcn_checkmarks&&r.checkmarks){if(localStorage.removeItem("fcnBookshelfContent"),"toggle"===s&&JSON.stringify(fcn_checkmarks.data[a])!==JSON.stringify(r.checkmarks.data[a]))return fcn_checkmarks=r.checkmarks,fcn_showNotification(fictioneer_tl.notification.checkmarksResynchronized),void fcn_updateCheckmarksView();if(fcn_checkmarks.data[a]||(fcn_checkmarks.data[a]=[]),r.checkmarks.data[a]||(r.checkmarks.data[a]=[]),t&&"progress"===e&&!fcn_checkmarks.data[a].includes(t)&&fcn_checkmarks.data[a].push(t),t&&"chapter"===e)if(!fcn_checkmarks.data[a].includes(t)&&"unset"!==s||"set"===s)fcn_checkmarks.data[a].push(t),c&&(c.classList.add("marked"),c.setAttribute("aria-checked",!0));else{fcn_removeItemOnce(fcn_checkmarks.data[a],t),c&&(c.classList.remove("marked"),c.setAttribute("aria-checked",!1)),fcn_removeItemOnce(fcn_checkmarks.data[a],a);const e=_$('button[data-type="story"]');e&&(e.classList.remove("marked"),e.setAttribute("aria-checked",!1))}if("story"===e){const e=(fcn_checkmarks.data[a].includes(a)||"unset"===s)&&"set"!==s;fcn_checkmarks.data[a]=[],e||(_$$("button.checkmark").forEach((e=>{fcn_checkmarks.data[a].push(parseInt(e.dataset.id))})),fcn_checkmarks.data[a].includes(a)||fcn_checkmarks.data[a].push(a))}fcn_checkmarks.data[a]=fcn_checkmarks.data[a].filter(((a,e,t)=>t.indexOf(a)==e)),r.checkmarks.data[a]=fcn_checkmarks.data[a],r.lastLoaded=0,fcn_setUserData(r),fcn_updateCheckmarksView(),clearTimeout(fcn_userCheckmarksTimeout),fcn_userCheckmarksTimeout=setTimeout((()=>{fcn_updateCheckmarks(a,fcn_checkmarks.data[a])}),fictioneer_ajax.post_debounce_rate)}}function fcn_clickCheckmark(a){fcn_toggleCheckmark(parseInt(a.dataset.storyId),a.dataset.type,parseInt(a.dataset.id),a)}function fcn_updateCheckmarks(a,e=null){e=e||fcn_getUserData().checkmarks.data[a],fcn_ajaxPost({action:"fictioneer_ajax_set_checkmark",fcn_fast_ajax:1,story_id:a,update:e.join(" ")}).then((a=>{a.success||(fcn_showNotification(a.data.failure??a.data.error??fictioneer_tl.notification.error,3,"warning"),(a.data.error||a.data.failure)&&console.error("Error:",a.data.error??a.data.failure))})).catch((a=>{a.status&&a.statusText&&fcn_showNotification(`${a.status}: ${a.statusText}`,5,"warning"),console.error(a)}))}function fcn_updateCheckmarksView(){const a=fcn_getUserData(),e=a.checkmarks;if(!e)return;const t=parseInt(fcn_theBody.dataset.storyId);if(t){const c=e.data[t]&&e.data[t].includes(t);if(c){let c=!1;_$$("button.checkmark").forEach((a=>{const s=parseInt(a.dataset.id);e.data[t].includes(s)||(e.data[t].push(s),c=!0)})),c&&(a.checkmarks=e,fcn_setUserData(a),fcn_updateCheckmarks(t,e.data[t]))}_$$$("ribbon-read")?.classList.toggle("hidden",!c)}_$$("button.checkmark").forEach((a=>{const t=parseInt(a.dataset.storyId);if(e.data[t]){const c=e.data[t].includes(parseInt(a.dataset.id));a.classList.toggle("marked",c),a.setAttribute("aria-checked",c)}})),_$$(".card").forEach((a=>{const t=parseInt(a.dataset.storyId),c=e.data[t]&&(e.data[t].includes(parseInt(a.dataset.checkId))||e.data[t].includes(t));a.classList.toggle("has-checkmark",1==c)}))}document.addEventListener("fcnUserDataReady",(a=>{fcn_initializeCheckmarks(a)}));
|
function fcn_toggleCheckmark(e,t=null,a=null){const r=window.FictioneerApp.Controllers.fictioneerCheckmarks;if(!r)return void fcn_showNotification("Error: Checkmarks Controller not connected.",3,"warning");const s=FcnUtils.userData();let i="story";if((e=parseInt(e??0))<1)return void fcn_showNotification("Error: Invalid story ID.",3,"warning");if(null!==t){if((t=parseInt(t))<1)return void fcn_showNotification("Error: Invalid chapter ID.",3,"warning");i="chapter"}s.checkmarks.data[e]||(s.checkmarks.data[e]=[]),null===a&&(a="chapter"===i?!s.checkmarks.data[e]?.includes(t):!s.checkmarks.data[e]?.includes(e));const c="chapter"===i?t:e;a?s.checkmarks.data[e].push(c):(FcnUtils.removeArrayItemOnce(s.checkmarks.data[e],c),"chapter"===i&&FcnUtils.removeArrayItemOnce(s.checkmarks.data[e],e)),s.checkmarks.data[e]=s.checkmarks.data[e].filter(((e,t,a)=>a.indexOf(e)==t)),s.lastLoaded=0,FcnUtils.setUserData(s),r.refreshView(),clearTimeout(r.timeout),r.timeout=setTimeout((()=>{FcnUtils.remoteAction("fictioneer_ajax_set_checkmark",{payload:{update:s.checkmarks.data[e].join(" "),story_id:e}})}),FcnGlobals.debounceRate)}application.register("fictioneer-checkmarks",class extends Stimulus.Controller{static get targets(){return["chapterCheck","storyCheck","ribbon"]}timeout=0;initialize(){fcn()?.userReady?this.#e=!0:document.addEventListener("fcnUserDataReady",(()=>{this.refreshView(),this.#e=!0,this.#t()}))}connect(){window.FictioneerApp.Controllers.fictioneerCheckmarks=this,this.#e&&(this.refreshView(),this.#t())}data(){return this.checkmarksCachedData=FcnUtils.userData().checkmarks?.data,Array.isArray(this.checkmarksCachedData)&&0===this.checkmarksCachedData.length&&(this.checkmarksCachedData={}),this.checkmarksCachedData}toggleChapter({params:{chapter:e,story:t}}){fcn_toggleCheckmark(t,e)}toggleStory({params:{story:e}}){fcn_toggleCheckmark(e)}clear(){const e=FcnUtils.userData();e.checkmarks={data:{},updated:Date.now()},fcn().setUserData(e),this.refreshView()}refreshView(){const e=this.data();!e||Object.keys(e).length<1?this.uncheckAll():Object.entries(e).forEach((([e,t])=>{e=parseInt(e);const a=t?.includes(e);this.hasChapterCheckTarget&&(a?this.chapterCheckTargets.forEach((e=>{e.classList.toggle("marked",!0),e.setAttribute("aria-checked",!0)})):this.chapterCheckTargets.forEach((a=>{const r=parseInt(a.dataset.fictioneerCheckmarksChapterParam);if(parseInt(a.dataset.fictioneerCheckmarksStoryParam)===e){const e=t?.includes(r);a.classList.toggle("marked",e),a.setAttribute("aria-checked",e)}}))),this.hasStoryCheckTarget&&(this.storyCheckTarget.classList.toggle("marked",a),this.storyCheckTarget.setAttribute("aria-checked",a)),this.hasRibbonTarget&&this.ribbonTarget.classList.toggle("hidden",!a)}))}uncheckAll(){this.hasChapterCheckTarget&&this.chapterCheckTargets.forEach((e=>{e.classList.toggle("marked",!1),e.setAttribute("aria-checked",!1)})),this.hasStoryCheckTarget&&(this.storyCheckTarget.classList.toggle("marked",!1),this.storyCheckTarget.setAttribute("aria-checked",!1))}#e=!1;#a=!1;#r(){const e=FcnUtils.loggedIn();return e||(this.#s(),this.#a=!0),e}#i(){return this.#r()&&JSON.stringify(this.checkmarksCachedData??0)!==JSON.stringify(this.data())}#c(){this.refreshInterval||(this.refreshInterval=setInterval((()=>{!this.#a&&this.#i()&&this.refreshView()}),3e4+1e3*Math.random()))}#t(){this.#c(),this.visibilityStateCheck=()=>{this.#r()&&("visible"===document.visibilityState?(this.#a=!1,this.refreshView(),this.#c()):(this.#a=!0,clearInterval(this.refreshInterval),this.refreshInterval=null))},document.addEventListener("visibilitychange",this.visibilityStateCheck)}#s(){clearInterval(this.refreshInterval),document.removeEventListener("visibilitychange",this.visibilityStateCheck)}});
|
4
js/comments.min.js
vendored
4
js/comments.min.js
vendored
File diff suppressed because one or more lines are too long
10
js/complete.min.js
vendored
10
js/complete.min.js
vendored
File diff suppressed because one or more lines are too long
2
js/critical-skin-script.min.js
vendored
2
js/critical-skin-script.min.js
vendored
@ -1 +1 @@
|
|||||||
!function(){const e="fcnLoggedIn=",t=document.cookie.split(";");let n=null;for(var c=0;c<t.length;c++){const i=t[c].trim();if(0==i.indexOf(e)){n=decodeURIComponent(i.substring(12,i.length));break}}if(!n)return;const i=JSON.parse(localStorage.getItem("fcnSkins"))??{data:{},active:null,fingerprint:n};if(i?.data?.[i.active]?.css&&n===i?.fingerprint){const e=document.createElement("style");e.textContent=i.data[i.active].css,e.id="fictioneer-active-custom-skin",document.querySelector("head").appendChild(e)}}();
|
!function(){const t="fcnLoggedIn=",e=document.cookie.split(";");let n=null;for(var c=0;c<e.length;c++){const i=e[c].trim();if(0==i.indexOf(t)){n=decodeURIComponent(i.substring(12,i.length));break}}if(!n)return;const i=FcnUtils.parseJSON(localStorage.getItem("fcnSkins"))??{data:{},active:null,fingerprint:n};if(i?.data?.[i.active]?.css&&n===i?.fingerprint){const t=document.createElement("style");t.textContent=i.data[i.active].css,t.id="fictioneer-active-custom-skin",document.querySelector("head").appendChild(t)}}();
|
2
js/css-skins.min.js
vendored
2
js/css-skins.min.js
vendored
File diff suppressed because one or more lines are too long
2
js/dev-tools.min.js
vendored
2
js/dev-tools.min.js
vendored
@ -1 +1 @@
|
|||||||
async function fcn_benchmarkAjax(e=1,n={},o=null,t={},r="get"){let a=0;console.log(`Starting benchmark with ${e} AJAX requests...`);for(let c=0;c<e;c++){const e=performance.now();try{"get"===r?await fcn_ajaxGet(n,o,t):await fcn_ajaxPost(n,o,t),a+=performance.now()-e}catch(e){console.error("Error during AJAX request:",e)}}const c=a/e;return console.log(`Finished benchmarking. Average AJAX response time over ${e} requests: ${c.toFixed(2)} ms`),c}function fcn_printAjaxResponse(e,n="get"){"get"===n?fcn_ajaxGet(e).then((e=>{console.log(e)})):fcn_ajaxPost(e).then((e=>{console.log(e)}))}
|
async function fcn_benchmarkAjax(e=1,n={},t=null,o={},r="get"){let s=0;console.log(`Starting benchmark with ${e} AJAX requests...`);for(let c=0;c<e;c++){const e=performance.now();try{"get"===r?await FcnUtils.aGet(n,t,o):await FcnUtils.aPost(n,t,o),s+=performance.now()-e}catch(e){console.error("Error during AJAX request:",e)}}const c=s/e;return console.log(`Finished benchmarking. Average AJAX response time over ${e} requests: ${c.toFixed(2)} ms`),c}function fcn_printAjaxResponse(e,n="get"){"get"===n?FcnUtils.aGet(e).then((e=>{console.log(e)})):FcnUtils.aPost(e).then((e=>{console.log(e)}))}
|
2
js/follows.min.js
vendored
2
js/follows.min.js
vendored
@ -1 +1 @@
|
|||||||
const fcn_followsMenuItem=_$$$("follow-menu-button");var fcn_userFollowsTimeout,fcn_follows;function fcn_initializeFollows(o){const t=o.detail.data.follows;!1!==t&&(Array.isArray(t.data)&&0===t.data.length&&(t.data={}),fcn_follows=t,fcn_updateFollowsView(),localStorage.removeItem("fcnBookshelfContent"))}function fcn_toggleFollow(o){const t=fcn_getUserData();if(fcn_follows&&t.follows){if(localStorage.removeItem("fcnBookshelfContent"),JSON.stringify(fcn_follows.data[o])!==JSON.stringify(t.follows.data[o]))return fcn_follows=t.follows,fcn_showNotification(fictioneer_tl.notification.followsResynchronized),void fcn_updateFollowsView();fcn_follows.data[o]?delete fcn_follows.data[o]:fcn_follows.data[o]={story_id:parseInt(o),timestamp:Date.now()},t.follows.data[o]=fcn_follows.data[o],t.lastLoaded=0,fcn_setUserData(t),fcn_updateFollowsView(),clearTimeout(fcn_userFollowsTimeout),fcn_userFollowsTimeout=setTimeout((()=>{fcn_ajaxPost({action:"fictioneer_ajax_toggle_follow",fcn_fast_ajax:1,story_id:o,set:!!fcn_follows.data[o]}).then((o=>{o.success||(fcn_showNotification(o.data.failure??o.data.error??fictioneer_tl.notification.error,5,"warning"),(o.data.error||o.data.failure)&&console.error("Error:",o.data.error??o.data.failure))})).catch((o=>{429===o.status?fcn_showNotification(fictioneer_tl.notification.slowDown,3,"warning"):o.status&&o.statusText&&fcn_showNotification(`${o.status}: ${o.statusText}`,5,"warning"),console.error(o)}))}),fictioneer_ajax.post_debounce_rate)}}function fcn_updateFollowsView(){const o=fcn_getUserData();if(!fcn_follows||!o.follows)return;_$$(".button-follow-story").forEach((o=>{o.classList.toggle("_followed",!!fcn_follows?.data[o.dataset.storyId])})),_$$(".card").forEach((o=>{o.classList.toggle("has-follow",!!fcn_follows?.data[o.dataset.storyId])}));const t=parseInt(fcn_follows.new)>0;_$$(".mark-follows-read, .follows-alert-number, .mobile-menu-button").forEach((o=>{o.classList.toggle("_new",t),t>0&&(o.dataset.newCount=fcn_follows.new)}))}function fcn_setupFollowsHTML(){fcn_followsMenuItem.classList.contains("_loaded")||fcn_ajaxGet({action:"fictioneer_ajax_get_follows_notifications",fcn_fast_ajax:1}).then((o=>{if(o.data.html){const t=_$$$("follow-menu-scroll");t&&(t.innerHTML=o.data.html);const e=_$$$("mobile-menu-follows-list");e&&(e.innerHTML=o.data.html),!1===fcn_getUserData().loggedIn&&(fcn_prepareLogin(),fcn_fetchUserData())}})).catch((o=>{429===o.status?fcn_showNotification(fictioneer_tl.notification.slowDown,3,"warning"):o.status&&o.statusText&&fcn_showNotification(`${o.status}: ${o.statusText}`,5,"warning"),_$$$("follow-menu-scroll")?.remove(),_$$$("mobile-menu-follows-list")?.remove()})).then((()=>{fcn_followsMenuItem.classList.add("_loaded")}))}function fcn_markFollowsRead(){if(!fcn_followsMenuItem.classList.contains("_new")||!fcn_followsMenuItem.classList.contains("_loaded"))return;_$$(".mark-follows-read, .follows-alert-number, .follow-item, .mobile-menu-button").forEach((o=>{o.classList.remove("_new")}));const o=fcn_getUserData();o.new=0,o.lastLoaded=0,fcn_setUserData(o),fcn_ajaxPost({action:"fictioneer_ajax_mark_follows_read",fcn_fast_ajax:1}).catch((o=>{o.status&&o.statusText&&fcn_showNotification(`${o.status}: ${o.statusText}`,5,"warning")}))}document.addEventListener("fcnUserDataReady",(o=>{fcn_initializeFollows(o)})),fcn_followsMenuItem?.addEventListener("mouseover",(()=>{fcn_setupFollowsHTML()}),{once:!0}),fcn_followsMenuItem?.addEventListener("focus",(()=>{fcn_setupFollowsHTML()}),{once:!0}),_$('.mobile-menu__frame-button[data-frame-target="follows"]')?.addEventListener("click",(()=>{fcn_setupFollowsHTML()}),{once:!0}),_$$(".button-follow-story").forEach((o=>{o.addEventListener("click",(o=>{fcn_toggleFollow(o.currentTarget.dataset.storyId)}))})),_$$(".mark-follows-read").forEach((o=>{o.addEventListener("click",(()=>{fcn_markFollowsRead()}))}));
|
function fcn_toggleFollow(t,e=null){const s=window.FictioneerApp.Controllers.fictioneerFollows;if(!s)return void fcn_showNotification("Error: Follows Controller not connected.",3,"warning");const a=FcnUtils.userData();(e=e??!a.follows.data[t])?a.follows.data[t]={story_id:parseInt(t),timestamp:Date.now()}:delete a.follows.data[t],a.lastLoaded=0,FcnUtils.setUserData(a),s.refreshView(),clearTimeout(s.timeout),s.timeout=setTimeout((()=>{FcnUtils.remoteAction("fictioneer_ajax_toggle_follow",{payload:{set:e,story_id:t}})}),FcnGlobals.debounceRate)}application.register("fictioneer-follows",class extends Stimulus.Controller{static get targets(){return["toggleButton","newDisplay","scrollList","mobileScrollList","mobileMarkRead"]}followsLoaded=!1;markedRead=!1;timeout=0;initialize(){fcn()?.userReady?this.#t=!0:document.addEventListener("fcnUserDataReady",(()=>{this.refreshView(),this.#t=!0,this.#e()}))}connect(){window.FictioneerApp.Controllers.fictioneerFollows=this,this.#t&&(this.refreshView(),this.#e())}data(){return this.followsCachedData=FcnUtils.userData().follows?.data,Array.isArray(this.followsCachedData)&&0===this.followsCachedData.length&&(this.followsCachedData={}),this.followsCachedData}isFollowed(t){return!(!FcnUtils.loggedIn()||!this.data()?.[t])}unreadCount(){return parseInt(FcnUtils.userData()?.follows?.new??0)}toggleFollow({params:{id:t}}){this.#s()&&(fcn_toggleFollow(t,!this.isFollowed(t)),this.refreshView())}clear(){const t=FcnUtils.userData();t.follows={data:{}},fcn().setUserData(t),this.refreshView()}refreshView(){this.toggleButtonTargets.forEach((t=>{const e=t.dataset.storyId;t.classList.toggle("_followed",this.isFollowed(e))}));const t=this.unreadCount();this.newDisplayTargets.forEach((e=>{e.classList.toggle("_new",t>0),t>0&&(e.dataset.newCount=t,this.hasMobileMarkReadTarget&&this.mobileMarkReadTarget.classList.remove("hidden"))}))}loadFollowsHtml(){this.followsLoaded||FcnUtils.aGet({action:"fictioneer_ajax_get_follows_notifications",fcn_fast_ajax:1}).then((t=>{t.data.html&&(this.hasScrollListTarget&&(this.scrollListTarget.innerHTML=t.data.html),this.hasMobileScrollListTarget&&(this.mobileScrollListTarget.innerHTML=t.data.html),!1===FcnUtils.userData().loggedIn&&(fcn().removeUserData(),fcn().fetchUserData()))})).catch((t=>{429===t.status?fcn_showNotification(fictioneer_tl.notification.slowDown,3,"warning"):t.status&&t.statusText&&fcn_showNotification(`${t.status}: ${t.statusText}`,5,"warning"),this.hasScrollListTarget&&this.scrollListTarget.remove(),this.hasMobileScrollListTarget&&this.mobileScrollListTarget.remove()})).then((()=>{this.followsLoaded=!0,this.hasNewDisplayTarget&&this.newDisplayTargets.forEach((t=>{t.classList.add("_loaded")}))}))}markRead(){if(!this.followsLoaded&&this.unreadCount()>0||this.markedRead)return;this.markedRead=!0,this.newDisplayTargets.forEach((t=>{t.classList.remove("_new")})),this.hasMobileMarkReadTarget&&this.mobileMarkReadTarget.classList.add("hidden");const t=FcnUtils.userData();t.new=0,t.lastLoaded=0,FcnUtils.setUserData(t),FcnUtils.aPost({action:"fictioneer_ajax_mark_follows_read",fcn_fast_ajax:1}).catch((t=>{t.status&&t.statusText&&fcn_showNotification(`${t.status}: ${t.statusText}`,5,"warning")}))}#t=!1;#a=!1;#s(){const t=FcnUtils.loggedIn();return t||(this.#i(),this.#a=!0),t}#o(){return this.#s()&&JSON.stringify(this.followsCachedData??0)!==JSON.stringify(this.data())}#l(){this.refreshInterval||(this.refreshInterval=setInterval((()=>{!this.#a&&this.#o()&&this.refreshView()}),3e4+1e3*Math.random()))}#e(){this.#l(),this.visibilityStateCheck=()=>{this.#s()&&("visible"===document.visibilityState?(this.#a=!1,this.refreshView(),this.#l()):(this.#a=!0,clearInterval(this.refreshInterval),this.refreshInterval=null))},document.addEventListener("visibilitychange",this.visibilityStateCheck)}#i(){clearInterval(this.refreshInterval),document.removeEventListener("visibilitychange",this.visibilityStateCheck)}});
|
1
js/laws.min.js
vendored
1
js/laws.min.js
vendored
@ -1 +0,0 @@
|
|||||||
const fcn_consentBanner=_$$$("consent-banner");function fcn_loadConsentBanner(){fcn_consentBanner.classList.remove("hidden"),fcn_consentBanner.hidden=!1,_$$$("consent-accept-button")?.addEventListener("click",(()=>{fcn_setCookie("fcn_cookie_consent","full"),fcn_consentBanner.classList.add("hidden"),fcn_consentBanner.hidden=!0})),_$$$("consent-reject-button")?.addEventListener("click",(()=>{fcn_setCookie("fcn_cookie_consent","necessary"),fcn_consentBanner.classList.add("hidden"),fcn_consentBanner.hidden=!0}))}fcn_consentBanner&&""===(fcn_getCookie("fcn_cookie_consent")??"")&&!fcn_isSearchEngineCrawler()?setTimeout((()=>{fcn_loadConsentBanner()}),4e3):fcn_consentBanner.remove();
|
|
1
js/lightbox.min.js
vendored
1
js/lightbox.min.js
vendored
@ -1 +0,0 @@
|
|||||||
function fcn_showLightbox(t){const e=_$$$("fictioneer-lightbox"),o=_$(".lightbox__content");let l=!1,i=null;if(o.innerHTML="",t.classList.add("lightbox-last-trigger"),"IMG"==t.tagName?(i=t.cloneNode(),l=!0):t.href&&(i=document.createElement("img"),i.src=t.href,l=!0),l&&i){["class","style","height","width"].forEach((t=>i.removeAttribute(t))),o.appendChild(i),e.classList.add("show");const t=e.querySelector(".lightbox__close");t?.focus(),t?.blur()}}fcn_theBody.addEventListener("click",(t=>{const e=t.target.closest("[data-lightbox]:not(.no-auto-lightbox)");e&&(t.preventDefault(),fcn_showLightbox(e))})),fcn_theBody.addEventListener("keydown",(t=>{const e=t.target.closest("[data-lightbox]:not(.no-auto-lightbox)");e&&(32!=t.keyCode&&13!=t.keyCode||(t.preventDefault(),fcn_showLightbox(e)))})),document.querySelectorAll(".lightbox__close, .lightbox").forEach((t=>{t.addEventListener("click",(t=>{if("IMG"!=t.target.tagName){_$$$("fictioneer-lightbox").classList.remove("show");const t=_$(".lightbox-last-trigger");t?.focus(),t?.blur(),t?.classList.remove("lightbox-last-trigger")}}))}));
|
|
2
js/mobile-menu.min.js
vendored
2
js/mobile-menu.min.js
vendored
@ -1 +1 @@
|
|||||||
function fcn_toggleMobileMenu(e){_$(".mobile-menu._advanced-mobile-menu")?fcn_toggleAdvancedMobileMenu(e):fcn_toggleSimpleMobileMenu(e)}function fcn_toggleSimpleMobileMenu(e){e?(fcn_theBody.classList.add("mobile-menu-open","scrolling-down"),fcn_theBody.classList.remove("scrolling-up")):(fcn_theBody.classList.remove("mobile-menu-open"),fcn_closeMobileFrames(),fcn_openMobileFrame("main"),_$$$("mobile-menu-toggle").checked=!1)}function fcn_toggleAdvancedMobileMenu(e){const o=_$$$("wpadminbar")?.offsetHeight??0,n=window.scrollY,t=fcn_theSite.scrollTop;e?(fcn_theBody.classList.add("mobile-menu-open","scrolling-down","scrolled-to-top"),fcn_theBody.classList.remove("scrolling-up"),fcn_theSite.classList.add("transformed-scroll","transformed-site"),fcn_theSite.scrollTop=n-o,fcn_updateThemeColor()):(fcn_theSite.classList.remove("transformed-site","transformed-scroll"),fcn_theBody.classList.remove("mobile-menu-open"),fcn_updateThemeColor(),fcn_closeMobileFrames(),fcn_openMobileFrame("main"),fcn_theRoot.style.scrollBehavior="auto",window.scroll(0,t+o),fcn_theRoot.style.scrollBehavior="",_$$$("mobile-menu-toggle").checked=!1,"function"==typeof fcn_trackProgress&&fcn_trackProgress())}function fcn_setupMobileJumpButton(e,o){const n=_$(e);n&&n.addEventListener("click",(()=>{fcn_toggleMobileMenu(!1),setTimeout((()=>{const e=o();e&&fcn_scrollTo(e)}),200)}))}function fcn_openMobileFrame(e){fcn_closeMobileFrames(),_$(`.mobile-menu__frame[data-frame="${e}"]`)?.classList.add("_active")}function fcn_closeMobileFrames(){_$$(".mobile-menu__frame._active").forEach((e=>{e.classList.remove("_active")}));const e=_$(".mobile-menu__bookmarks-panel");e&&(e.dataset.editing="false")}_$$$("mobile-menu-toggle")?.addEventListener("change",(e=>{fcn_toggleMobileMenu(e.currentTarget.checked)})),fcn_theSite.addEventListener("click",(e=>{fcn_theBody.classList.contains("mobile-menu-open")&&(e.preventDefault(),fcn_toggleMobileMenu(!1))})),fcn_setupMobileJumpButton("#mobile-menu-comment-jump",(()=>_$$$("comments"))),fcn_setupMobileJumpButton("#mobile-menu-bookmark-jump",(()=>_$(`[data-paragraph-id="${fcn_bookmarks.data[_$("article").id]["paragraph-id"]}"]`))),_$$(".button-change-lightness").forEach((e=>{e.addEventListener("click",(e=>{fcn_updateDarken(fcn_siteSettings.darken+parseFloat(e.currentTarget.value))}))})),_$$(".mobile-menu__frame-button").forEach((e=>{e.addEventListener("click",(e=>{fcn_openMobileFrame(e.currentTarget.dataset.frameTarget)}))})),_$$(".mobile-menu__back-button").forEach((e=>{e.addEventListener("click",(()=>{fcn_openMobileFrame("main")}))})),_$$$("button-mobile-menu-toggle-bookmarks-edit")?.addEventListener("click",(e=>{const o=e.currentTarget.closest(".mobile-menu__bookmarks-panel");o.dataset.editing="false"==o.dataset.editing?"true":"false"})),_$('.mobile-menu__frame-button[data-frame-target="bookmarks"]')?.addEventListener("click",(()=>{fcn_setMobileMenuBookmarks()}),{once:!0});
|
application.register("fictioneer-mobile-menu",class extends Stimulus.Controller{static get targets(){return["frame","bookmarks","panelBookmarks"]}advanced=!!_$(".mobile-menu._advanced-mobile-menu");open=!1;editingBookmarks=!1;currentFrame=null;bookmarkTemplate=_$$$("mobile-bookmark-template");chapterId=_$("article")?.id;connect(){window.FictioneerApp.Controllers.fictioneerMobileMenu=this}toggle(e=null){this.open=e??!this.open,this.advanced?this.#e(this.open):this.#o(this.open)}clickOutside({detail:{target:e}}){this.open&&"site"===e?.id&&this.toggle(!1)}openFrame({params:{frame:e}}){const o=`mobile-frame-${e}`;this.editingBookmarks=!1,this.panelBookmarksTarget.dataset.editing=!1,this.hasFrameTarget&&this.frameTargets.forEach((e=>{e.classList.toggle("_active",e.id===o),e.id===o&&(this.currentFrame=e)}))}back(){this.openFrame({params:{frame:"main"}})}setMobileBookmarks(){const e=window.FictioneerApp.Controllers.fictioneerBookmarks;if(e&&this.hasBookmarksTarget){const o=Object.entries(e.data());if(this.bookmarksTarget.innerHTML="",!o||o.length<1){const e=document.createElement("li");return e.classList.add("no-bookmarks"),e.textContent=this.bookmarksTarget.dataset.empty,void this.bookmarksTarget.appendChild(e)}const t=document.createDocumentFragment();o.forEach((([e,{color:o,progress:r,link:s,chapter:a,"paragraph-id":i}])=>{const n=this.bookmarkTemplate.content.cloneNode(!0),l=n.querySelector(".mobile-menu__bookmark");l.classList.add(`bookmark-${e}`),l.dataset.color=o,n.querySelector(".mobile-menu__bookmark-progress > div > div").style.width=`${r.toFixed(1)}%`,n.querySelector(".mobile-menu__bookmark a").href=`${s}#paragraph-${i}`,n.querySelector(".mobile-menu__bookmark a span").innerText=a,n.querySelector(".mobile-menu-bookmark-delete-button").setAttribute("data-fictioneer-mobile-menu-id-param",e),t.appendChild(n)})),this.bookmarksTarget.appendChild(t)}}deleteBookmark({params:{id:e}}){const o=window.FictioneerApp.Controllers.fictioneerBookmarks;o?(o.remove({params:{id:e}}),this.setMobileBookmarks()):fcn_showNotification("Error: Bookmarks Controller not connected.",3,"warning")}toggleBookmarksEdit(){this.editingBookmarks=!this.editingBookmarks,this.panelBookmarksTarget.dataset.editing=this.editingBookmarks}scrollToComments(){this.#t(_$$$("comments"))}scrollToBookmark(){const e=window.FictioneerApp.Controllers.fictioneerBookmarks;if(!e)return void fcn_showNotification("Error: Bookmarks Controller not connected.",3,"warning");const o=e.data()?.[this.chapterId]?.["paragraph-id"],t=_$(`[data-paragraph-id="${o}"]`);this.#t(t)}changeLightness({currentTarget:e}){fcn_updateDarken(fcn_siteSettings.darken+parseFloat(e.value))}#t(e){this.toggle(!1),e&&setTimeout((()=>{FcnUtils.scrollTo(e)}),200)}#o(e){this.back(),e?(document.body.classList.add("mobile-menu-open","scrolling-down"),document.body.classList.remove("scrolling-up")):document.body.classList.remove("mobile-menu-open")}#e(e){const o=_$$$("wpadminbar")?.offsetHeight??0,t=window.scrollY,r=FcnGlobals.eSite.scrollTop;this.back(),e?(document.body.classList.add("mobile-menu-open","scrolling-down","scrolled-to-top"),document.body.classList.remove("scrolling-up"),FcnGlobals.eSite.classList.add("transformed-scroll","transformed-site"),FcnGlobals.eSite.scrollTop=t-o):(FcnGlobals.eSite.classList.remove("transformed-site","transformed-scroll"),document.body.classList.remove("mobile-menu-open"),document.documentElement.style.scrollBehavior="auto",window.scroll(0,r+o),document.documentElement.style.scrollBehavior="")}});
|
2
js/reminders.min.js
vendored
2
js/reminders.min.js
vendored
@ -1 +1 @@
|
|||||||
var fcn_userRemindersTimeout,fcn_reminders;function fcn_initializeReminders(e){const t=e.detail.data.reminders;!1!==t&&(Array.isArray(t.data)&&0===t.data.length&&(t.data={}),fcn_reminders=t,fcn_updateRemindersView(),localStorage.removeItem("fcnBookshelfContent"))}function fcn_toggleReminder(e){const t=fcn_getUserData();if(fcn_reminders&&t.reminders){if(localStorage.removeItem("fcnBookshelfContent"),JSON.stringify(fcn_reminders.data[e])!==JSON.stringify(t.reminders.data[e]))return fcn_reminders=t.reminders,fcn_showNotification(fictioneer_tl.notification.remindersResynchronized),void fcn_updateRemindersView();fcn_reminders.data[e]?delete fcn_reminders.data[e]:fcn_reminders.data[e]={story_id:parseInt(e),timestamp:Date.now()},t.reminders.data[e]=fcn_reminders.data[e],t.lastLoaded=0,fcn_setUserData(t),fcn_updateRemindersView(),clearTimeout(fcn_userRemindersTimeout),fcn_userRemindersTimeout=setTimeout((()=>{fcn_ajaxPost({action:"fictioneer_ajax_toggle_reminder",fcn_fast_ajax:1,story_id:e,set:!!fcn_reminders.data[e]}).then((e=>{e.success||(fcn_showNotification(e.data.failure??e.data.error??fictioneer_tl.notification.error,5,"warning"),(e.data.error||e.data.failure)&&console.error("Error:",e.data.error??e.data.failure))})).catch((e=>{429===e.status?fcn_showNotification(fictioneer_tl.notification.slowDown,3,"warning"):e.status&&e.statusText&&fcn_showNotification(`${e.status}: ${e.statusText}`,5,"warning"),console.error(e)}))}),fictioneer_ajax.post_debounce_rate)}}function fcn_updateRemindersView(){const e=fcn_getUserData();fcn_reminders&&e.reminders&&(_$$(".button-read-later").forEach((e=>{e.classList.toggle("_remembered",!!fcn_reminders.data[e.dataset.storyId])})),_$$(".card").forEach((e=>{e.classList.toggle("has-reminder",!!fcn_reminders.data[e.dataset.storyId])})))}document.addEventListener("fcnUserDataReady",(e=>{fcn_initializeReminders(e)})),_$$(".button-read-later").forEach((e=>{e.addEventListener("click",(e=>{fcn_toggleReminder(e.currentTarget.dataset.storyId)}))}));
|
function fcn_toggleReminder(e,t=null){const i=window.FictioneerApp.Controllers.fictioneerReminders;if(!i)return void fcn_showNotification("Error: Reminders Controller not connected.",3,"warning");const r=FcnUtils.userData();(t=t??!r.reminders.data[e])?r.reminders.data[e]={story_id:parseInt(e),timestamp:Date.now()}:delete r.reminders.data[e],r.lastLoaded=0,FcnUtils.setUserData(r),i.refreshView(),clearTimeout(i.timeout),i.timeout=setTimeout((()=>{FcnUtils.remoteAction("fictioneer_ajax_toggle_reminder",{payload:{set:t,story_id:e}})}),FcnGlobals.debounceRate)}application.register("fictioneer-reminders",class extends Stimulus.Controller{static get targets(){return["toggleButton"]}remindersLoaded=!1;timeout=0;initialize(){fcn()?.userReady?this.#e=!0:document.addEventListener("fcnUserDataReady",(()=>{this.refreshView(),this.#e=!0,this.#t()}))}connect(){window.FictioneerApp.Controllers.fictioneerReminders=this,this.#e&&(this.refreshView(),this.#t())}data(){return this.remindersCachedData=FcnUtils.userData().reminders?.data,Array.isArray(this.remindersCachedData)&&0===this.remindersCachedData.length&&(this.remindersCachedData={}),this.remindersCachedData}isRemembered(e){return!(!FcnUtils.loggedIn()||!this.data()?.[e])}toggleReminder({params:{id:e}}){this.#i()&&(fcn_toggleReminder(e,!this.isRemembered(e)),this.refreshView())}clear(){const e=FcnUtils.userData();e.reminders={data:{}},fcn().setUserData(e),this.refreshView()}refreshView(){this.toggleButtonTargets.forEach((e=>{const t=e.dataset.storyId;e.classList.toggle("_remembered",this.isRemembered(t))}))}#e=!1;#r=!1;#i(){const e=FcnUtils.loggedIn();return e||(this.#s(),this.#r=!0),e}#a(){return this.#i()&&JSON.stringify(this.remindersCachedData??0)!==JSON.stringify(this.data())}#n(){this.refreshInterval||(this.refreshInterval=setInterval((()=>{!this.#r&&this.#a()&&this.refreshView()}),3e4+1e3*Math.random()))}#t(){this.#n(),this.visibilityStateCheck=()=>{this.#i()&&("visible"===document.visibilityState?(this.#r=!1,this.refreshView(),this.#n()):(this.#r=!0,clearInterval(this.refreshInterval),this.refreshInterval=null))},document.addEventListener("visibilitychange",this.visibilityStateCheck)}#s(){clearInterval(this.refreshInterval),document.removeEventListener("visibilitychange",this.visibilityStateCheck)}});
|
2
js/stimulus.umd.min.js
vendored
Normal file
2
js/stimulus.umd.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
2
js/story.min.js
vendored
2
js/story.min.js
vendored
@ -1 +1 @@
|
|||||||
var fcn_storyCommentPage=1,fcn_storySettings=fcn_getStorySettings();function fcn_cleanUpActions(){_$$(".story__actions > *").forEach((t=>{const e=window.getComputedStyle(t);"none"!==e.display&&"hidden"!==e.visibility||t.remove()}))}function fcn_getStorySettings(){let t=fcn_parseJSON(localStorage.getItem("fcnStorySettings"))??fcn_defaultStorySettings();return t.timestamp<1674770712849&&(t=fcn_defaultStorySettings(),t.timestamp=Date.now()),fcn_setStorySettings(t),t}function fcn_defaultStorySettings(){return{view:"list",order:"asc",timestamp:1674770712849}}function fcn_setStorySettings(t){"object"==typeof t&&(fcn_storySettings=t,localStorage.setItem("fcnStorySettings",JSON.stringify(t)))}function fcn_applyStorySettings(){"object"==typeof fcn_storySettings&&(_$$("[data-view]").forEach((t=>{t.dataset.view="grid"==fcn_storySettings.view?"grid":"list"})),_$$("[data-order]").forEach((t=>{t.dataset.order="desc"==fcn_storySettings.order?"desc":"asc"})))}fcn_theRoot.dataset.ajaxAuth?document.addEventListener("fcnAuthReady",(()=>{fcn_cleanUpActions()})):document.addEventListener("DOMContentLoaded",(()=>{fcn_cleanUpActions()})),fcn_applyStorySettings();var fcn_isToggling=!1;function fcn_toggleStoryTab(t){const e=t.closest(".story");e.querySelectorAll(".story__tab-target._current, .story__tabs ._current").forEach((t=>{t.classList.remove("_current")})),e.querySelectorAll(`[data-finder="${t.dataset.target}"]`).forEach((t=>{t.classList.add("_current")})),e.querySelector(".story__tabs").dataset.current=t.dataset.target,t.classList.add("_current")}function fcn_loadStoryComments(t){let e;_$(".load-more-list-item").remove(),_$(".comments-loading-placeholder").classList.remove("hidden"),fcn_ajaxGet({post_id:t.dataset.storyId??fcn_theBody.dataset.postId,page:fcn_storyCommentPage},"get_story_comments").then((t=>{t.success?(_$(".fictioneer-comments__list > ul").innerHTML+=t.data.html,fcn_storyCommentPage++):t.data?.error&&(e=fcn_buildErrorNotice(t.data.error))})).catch((t=>{e=fcn_buildErrorNotice(t)})).then((()=>{_$(".comments-loading-placeholder").remove(),e&&_$(".fictioneer-comments__list > ul").appendChild(e)}))}function fcn_startEpubDownload(t,e=0){e>3?t.classList.remove("ajax-in-progress"):fcn_ajaxGet({action:"fictioneer_ajax_download_epub",story_id:t.dataset.storyId}).then((n=>{n.success?(window.location.href=t.href,setTimeout((()=>{t.classList.remove("ajax-in-progress")}),2e3)):setTimeout((()=>{fcn_startEpubDownload(t,e+1)}),2e3)})).catch((e=>{t.classList.remove("ajax-in-progress"),e.status&&e.statusText&&fcn_showNotification(`${e.status}: ${e.statusText}`,5,"warning")}))}_$$('[data-click-action*="toggle-chapter-order"]').forEach((t=>{t.addEventListener("click",(t=>{fcn_isToggling||(fcn_isToggling=!0,setTimeout((()=>fcn_isToggling=!1),50),fcn_storySettings.order="asc"===t.currentTarget.dataset.order?"desc":"asc",fcn_setStorySettings(fcn_storySettings),fcn_applyStorySettings())}))})),_$$('[data-click-action*="toggle-chapter-view"]').forEach((t=>{t.addEventListener("click",(t=>{fcn_isToggling||(fcn_isToggling=!0,setTimeout((()=>fcn_isToggling=!1),50),fcn_storySettings.view="list"===t.currentTarget.dataset.view?"grid":"list",fcn_setStorySettings(fcn_storySettings),fcn_applyStorySettings())}))})),_$$(".chapter-group__folding-toggle").forEach((t=>{t.addEventListener("click",(t=>{const e=t.currentTarget.closest(".chapter-group[data-folded]");e&&(e.dataset.folded="true"==e.dataset.folded?"false":"true")}))})),_$$(".tabs__item").forEach((t=>{t.addEventListener("click",(t=>{fcn_toggleStoryTab(t.currentTarget)}))})),_$(".comment-section")?.addEventListener("click",(t=>{t.target?.classList.contains("load-more-comments-button")&&fcn_loadStoryComments(t.target)})),_$$('[data-action="download-epub"]').forEach((t=>{t.addEventListener("click",(t=>{t.preventDefault(),t.currentTarget.classList.contains("ajax-in-progress")||(t.currentTarget.classList.add("ajax-in-progress"),fcn_startEpubDownload(t.currentTarget))}))}));
|
function fcn_cleanUpActions(){_$$(".story__actions > *").forEach((t=>{const e=window.getComputedStyle(t);"none"!==e.display&&"hidden"!==e.visibility||t.remove()}))}application.register("fictioneer-story",class extends Stimulus.Controller{static get targets(){return["tab","tabContent","commentsPlaceholder","commentsWrapper","commentsList"]}static values={id:Number};commentPage=1;connect(){window.FictioneerApp.Controllers.fictioneerStory=this,this.#t()}toggleChapterOrder(){const t=this.#e();t.order="asc"===t.order?"desc":"asc",this.#s(t),this.#t()}toggleChapterView(){const t=this.#e();t.view="list"===t.view?"grid":"list",this.#s(t),this.#t()}unfoldChapters(t){const e=t.currentTarget.closest(".chapter-group[data-folded]");e&&(e.dataset.folded="true"==e.dataset.folded?"false":"true")}toggleTab(t){const e=t.currentTarget;this.tabTargets.forEach((t=>{t.classList.remove("_current")})),this.tabContentTargets.forEach((e=>{e.dataset.tabName===t.params.tabName?e.classList.add("_current"):e.classList.remove("_current")})),e.classList.add("_current")}loadComments(t){this.hasIdValue&&this.hasCommentsListTarget&&(t.currentTarget.remove(),this.hasCommentsPlaceholderTarget&&this.commentsPlaceholderTarget.classList.remove("hidden"),FcnUtils.aGet({post_id:this.idValue,page:this.commentPage},"get_story_comments").then((t=>{this.hasCommentsPlaceholderTarget&&this.commentsPlaceholderTarget.remove(),t.success?(this.commentsListTarget.innerHTML+=t.data.html,this.commentPage++):t.data?.error&&this.commentsListTarget.appendChild(FcnUtils.buildErrorNotice(t.data.error))})).catch((t=>{this.hasCommentsPlaceholderTarget&&this.commentsPlaceholderTarget.remove(),this.commentsListTarget.appendChild(FcnUtils.buildErrorNotice(t))})))}startEpubDownload(t){t.preventDefault(),this.#a(t.currentTarget,0)}#e(){let t=FcnUtils.parseJSON(localStorage.getItem("fcnStorySettings"))??this.#i();return t.timestamp<1674770712849&&(t=this.#i(),t.timestamp=Date.now()),this.#s(t),t}#i(){return{view:"list",order:"asc",timestamp:1674770712849}}#s(t){"object"==typeof t&&localStorage.setItem("fcnStorySettings",JSON.stringify(t))}#t(){const t=this.#e();"object"==typeof t&&(_$$("[data-view]").forEach((e=>{e.dataset.view=t.view})),_$$("[data-order]").forEach((e=>{e.dataset.order=t.order})))}#a(t,e=0){!t.classList.contains("ajax-in-progress")&&this.hasIdValue&&(e>3?t.classList.remove("ajax-in-progress"):(t.classList.add("ajax-in-progress"),FcnUtils.aGet({action:"fictioneer_ajax_download_epub",story_id:this.idValue}).then((s=>{s.success?(window.location.href=t.href,setTimeout((()=>{t.classList.remove("ajax-in-progress")}),2e3)):setTimeout((()=>{fcn_startEpubDownload(t,e+1)}),2e3)})).catch((e=>{t.classList.remove("ajax-in-progress"),e.status&&e.statusText&&fcn_showNotification(`${e.status}: ${e.statusText}`,5,"warning")}))))}}),document.addEventListener("fcnUserDataReady",(()=>{fcn_cleanUpActions()}));
|
2
js/suggestion.min.js
vendored
2
js/suggestion.min.js
vendored
@ -1 +1 @@
|
|||||||
diff_match_patch.prototype.fcn_prettyHtml=function(t){for(var e=[],n=/&/g,i=/</g,o=/>/g,s=/\n/g,l=0;l<t.length;l++){var a=t[l][0],r=t[l][1].replace(n,"&").replace(i,"<").replace(o,">").replace(s,"¶<br>");switch(a){case 1:e[l]=`<ins>${r}</ins>`;break;case-1:e[l]=`<del>${r}</del>`;break;case 0:e[l]=`${r}`}}return e.join("")};class FCN_Suggestion{constructor(){this.toggle=_$$$("suggestions-modal-toggle"),this.tools=_$$$("selection-tools"),this.button=_$$$("button-add-suggestion"),this.toolsButton=_$$$("button-tools-add-suggestion"),this.reset=_$$$("button-suggestion-reset"),this.submit=_$$$("button-suggestion-submit"),this.current=_$$$("suggestions-modal-original"),this.input=_$$$("suggestions-modal-input"),this.output=_$$$("suggestions-modal-diff"),this.chapter=_$(".chapter__article"),this.text="",this.original="",this.latest="",this.paragraph=null,this.dmp=new diff_match_patch,this.bindEvents()}getCaretCoordinates(){let t=0,e=0;if(void 0!==window.getSelection){const n=window.getSelection();if(0!==n.rangeCount){let i=n.getRangeAt(0).cloneRange().getClientRects();i=i[i.length-1],i&&(t=i.right+window.scrollX,e=i.bottom+window.scrollY)}}return{x:t,y:e}}getClosestParagraph(){const t=window.getSelection();return t.rangeCount?t.getRangeAt(0).startContainer.parentNode.closest("p"):null}showTools(t,e){const n=document.documentElement.offsetWidth/2+this.tools.offsetWidth,i=_$$$("wpadminbar")?_$$$("wpadminbar").offsetHeight:0;this.tools.style.transform=e>n?"translate(-100%)":"translate(0)",this.tools.style.top=t+4-i+"px",this.tools.style.left=`${e}px`,this.tools.classList.remove("invisible")}hideTools(){this.tools.style.top="0",this.tools.style.left="-1000px",this.tools.classList.add("invisible")}textSelection(){return fcn_cleanTextSelectionFromButtons(window.getSelection().toString())}clearSelection(){window.getSelection?window.getSelection().empty?window.getSelection().empty():window.getSelection().removeAllRanges&&window.getSelection().removeAllRanges():document.selection&&document.selection.empty()}getDiff(t,e){const n=this.dmp.diff_main(t,e);return this.dmp.diff_cleanupEfficiency(n),this.dmp.fcn_prettyHtml(n)}toggleTools(t){fcn_theSite.classList.contains("transformed-site")||window.getSelection().rangeCount<1||!window.getSelection().getRangeAt(0).startContainer.parentNode.closest(".content-section")||setTimeout((()=>{if(t.text=t.textSelection().replaceAll("\n\n","\n"),""!==t.text){const e=t.getCaretCoordinates();t.showTools(e.y,e.x)}else t.hideTools()}),10)}toggleViaParagraphTools(t){fcn_theSite.classList.contains("transformed-site")||(t.text=_$(".selected-paragraph").querySelector(".paragraph-inner").innerText,t.showModal(t))}resizeInput(){this.input.style.height="auto",this.input.style.height=`${fcn_clamp(32,108,this.input.scrollHeight+4)}px`}showModal(t){fcn_lastSelectedParagraphId&&fcn_toggleParagraphTools(!1),t.original=t.text,t.current.innerHTML=t.text.replaceAll("\n","<br>"),t.input.value=t.text,t.output.innerHTML=t.getDiff(t.original,t.text),t.paragraph=t.getClosestParagraph(),t.toggle.click(),t.toggle.checked=!0,t.clearSelection(),t.hideTools(),t.resizeInput(),t.input.focus()}editSuggestion(t){t.resizeInput(),t.output.innerHTML=t.getDiff(t.original,t.input.value)}resetSuggestion(t){t.input.value=t.original,t.resizeInput(),t.output.innerHTML=t.getDiff(t.original,t.original)}submitSuggestion(t){const e=_$(fictioneer_comments.form_selector??"#comment"),n=t.paragraph?.id??null;let i=t.output.innerHTML;[["¶","¶\n"],["<br>","\n"],["<ins>","[ins]"],["</ins>","[/ins]"],["<del>","[del]"],["</del>","[/del]"]].forEach((([t,e])=>{i=i.replaceAll(t,e)})),t.latest=n?`\n[quote]${i} [anchor]${n}[/anchor][/quote]\n`:`\n[quote]${i}[/quote]\n`,e?"TEXTAREA"==e.tagName?(e.value+=t.latest,fcn_textareaAdjust(_$("textarea#comment"))):"DIV"==e.tagName&&(e.innerHTML+=t.latest):fcn_commentStack?.push(t.latest),t.toggle.click(),t.toggle.checked=!1,fcn_showNotification(fictioneer_tl.notification.suggestionAppendedToComment)}bindEvents(){this.chapter?.addEventListener("mouseup",this.toggleTools.bind(null,this)),this.button?.addEventListener("click",this.showModal.bind(null,this)),this.toolsButton?.addEventListener("click",this.toggleViaParagraphTools.bind(null,this)),this.input?.addEventListener("input",this.editSuggestion.bind(null,this)),this.reset?.addEventListener("click",this.resetSuggestion.bind(null,this)),this.submit?.addEventListener("click",this.submitSuggestion.bind(null,this))}}const fcn_suggestions=_$(".chapter__article")&&_$(".comment-section")&&_$$$("selection-tools")?new FCN_Suggestion:null;fcn_suggestions&&document.addEventListener("click",(function(t){t.target.closest(".content-section")||fcn_suggestions.hideTools()}));
|
diff_match_patch.prototype.fcn_prettyHtml=function(t){for(var e=[],i=/&/g,n=/</g,o=/>/g,s=/\n/g,l=0;l<t.length;l++){var a=t[l][0],r=t[l][1].replace(i,"&").replace(n,"<").replace(o,">").replace(s,"¶<br>");switch(a){case 1:e[l]=`<ins>${r}</ins>`;break;case-1:e[l]=`<del>${r}</del>`;break;case 0:e[l]=`${r}`}}return e.join("")},application.register("fictioneer-suggestion",class extends Stimulus.Controller{modal=_$$$("suggestions-modal");floatingButton=_$$$("selection-tools");input=_$$$("suggestions-modal-input");current=_$$$("suggestions-modal-original");diff=_$$$("suggestions-modal-diff");reset=_$$$("button-suggestion-reset");submit=_$$$("button-suggestion-submit");original="";text="";open=!1;paragraph=null;dmp=new diff_match_patch;initialize(){this.floatingButton&&this.floatingButton.addEventListener("click",(t=>{this.toggleModalViaSelection(t.currentTarget)})),this.input.addEventListener("input",(()=>this.#t())),this.reset.addEventListener("click",(()=>this.#e())),this.submit.addEventListener("click",(()=>this.#i()))}connect(){window.FictioneerApp.Controllers.fictioneerSuggestion=this}clickOutside(){this.open&&this.#n()}toggleModalViaSelection(t){this.paragraph=this.#o(),this.toggleModalVisibility(t)}toggleModalViaParagraph(t){this.paragraph=_$(".selected-paragraph"),this.text=FcnUtils.extractTextNodes(this.paragraph),this.toggleModalVisibility(t.currentTarget)}toggleModalVisibility(t){const e=fcn(),i=window.FictioneerApp.Controllers.fictioneerChapter;e?i?(e.toggleModalVisibility(t,"suggestions-modal"),i.closeTools(),this.#s(),this.original=this.text,this.current.innerText=this.text,this.diff.innerText=this.text,this.input.value=this.text,this.input.focus()):fcn_showNotification("Error: Chapter Controller not connected.",3,"warning"):fcn_showNotification("Error: Fictioneer Controller not connected.",3,"warning")}toggleFloatingButton(){FcnGlobals.eSite.classList.contains("transformed-site")||window.getSelection().rangeCount<1||!window.getSelection().getRangeAt(0).startContainer.parentNode.closest(".content-section")||setTimeout((()=>{if(this.text=window.getSelection().toString().replaceAll("\n\n","\n").trim(),""!==this.text){const t=this.#l();this.#a(t.x,t.y)}else this.#n()}),10)}closeModal(){this.open=!1,this.original="",this.text="",this.paragraph=null,fcn().closeModals()}#a(t,e){this.open=!0;const i=document.documentElement.offsetWidth/2+this.floatingButton.offsetWidth,n=_$$$("wpadminbar")?.offsetHeight??0;this.floatingButton.style.transform=t>i?"translate(-100%)":"translate(0)",this.floatingButton.style.top=e+4-n+"px",this.floatingButton.style.left=`${t}px`,this.floatingButton.classList.remove("invisible")}#n(){this.open=!1,this.floatingButton.style.top="0",this.floatingButton.style.left="-1000px",this.floatingButton.classList.add("invisible")}#o(){const t=window.getSelection();return t.rangeCount?t.getRangeAt(0).startContainer.parentNode.closest("p"):null}#l(){let t=0,e=0;if(void 0!==window.getSelection){const i=window.getSelection();if(0!==i.rangeCount){let n=i.getRangeAt(0).cloneRange().getClientRects();n=n[n.length-1],n&&(t=n.right+window.scrollX,e=n.bottom+window.scrollY)}}return{x:t,y:e}}#s(){window.getSelection&&(window.getSelection().empty?window.getSelection().empty():window.getSelection().removeAllRanges&&window.getSelection().removeAllRanges())}#t(){this.diff.innerHTML=this.#r(this.original,this.input.value)}#e(){this.input.value=this.original,this.diff.innerText=this.original}#r(t,e){const i=this.dmp.diff_main(t,e);return this.dmp.diff_cleanupEfficiency(i),this.dmp.fcn_prettyHtml(i)}#i(){const t=this.paragraph?.id??null;let e=this.diff.innerHTML;[["¶","¶\n"],["<br>","\n"],["<ins>","[ins]"],["</ins>","[/ins]"],["<del>","[del]"],["</del>","[/del]"]].forEach((([t,i])=>{e=e.replaceAll(t,i)})),t&&(e=`${e} [anchor]${t}[/anchor]`),FcnUtils.appendToComment(`\n[quote]${e}[/quote]\n`),this.closeModal(),fcn_showNotification(fictioneer_tl.notification.suggestionAppendedToComment)}});
|
2
js/tts.min.js
vendored
2
js/tts.min.js
vendored
File diff suppressed because one or more lines are too long
2
js/user-profile.min.js
vendored
2
js/user-profile.min.js
vendored
@ -1 +1 @@
|
|||||||
function fcn_unsetOauth(t){const e=prompt(t.dataset.warning);if(!e||e.toLowerCase()!=t.dataset.confirm.toLowerCase())return;const a=_$$$(`oauth-${t.dataset.channel}`);a.classList.add("ajax-in-progress"),fcn_ajaxPost(payload={action:"fictioneer_ajax_unset_my_oauth",nonce:t.dataset.nonce,channel:t.dataset.channel,id:t.dataset.id}).then((t=>{t.success?(a.classList.remove("_connected"),a.classList.add("_disconnected"),a.querySelector("button").remove(),fcn_showNotification(a.dataset.unset)):(a.style.background="var(--notice-warning-background)",fcn_showNotification(t.data.failure??t.data.error??fictioneer_tl.notification.error,5,"warning"),(t.data.error||t.data.failure)&&console.error("Error:",t.data.error??t.data.failure))})).catch((t=>{t.status&&t.statusText&&(a.style.background="var(--notice-warning-background)",fcn_showNotification(`${t.status}: ${t.statusText}`,5,"warning")),console.error(t)})).then((()=>{a.classList.remove("ajax-in-progress")}))}function fcn_deleteMyAccount(t){if(_$$$("button-delete-my-account").hasAttribute("disabled"))return;const e=prompt(t.dataset.warning);e&&e.toLowerCase()==t.dataset.confirm.toLowerCase()&&(_$$$("button-delete-my-account").setAttribute("disabled",!0),fcn_ajaxPost({action:"fictioneer_ajax_delete_my_account",nonce:t.dataset.nonce,id:t.dataset.id}).then((t=>{t.success?(localStorage.removeItem("fcnAuth"),localStorage.removeItem("fcnProfileAvatar"),location.reload()):(_$$$("button-delete-my-account").innerHTML=t.data.button,fcn_showNotification(t.data.failure??t.data.error??fictioneer_tl.notification.error,5,"warning"),(t.data.error||t.data.failure)&&console.error("Error:",t.data.error??t.data.failure))})).catch((t=>{t.status&&t.statusText&&(fcn_showNotification(`${t.status}: ${t.statusText}`,5,"warning"),_$$$("button-delete-my-account").innerHTML=response.data.button),console.error(t)})))}_$$(".button-unset-oauth").forEach((t=>{t.addEventListener("click",(t=>{fcn_unsetOauth(t.currentTarget)}))})),_$$$("button-delete-my-account")?.addEventListener("click",(t=>{fcn_deleteMyAccount(t.currentTarget)}));const fcn_profileDataTranslations=_$$$("profile-data-translations")?.dataset;function fcn_dataDeletionPrompt(t){const e=prompt(t.dataset.warning);return!(!e||e.toLowerCase()!=t.dataset.confirm.toLowerCase())}function fcn_clearData(t,e){const a=t.closest(".card");localStorage.removeItem("fcnBookshelfContent"),a.classList.add("ajax-in-progress"),t.remove(),fcn_ajaxPost({action:e,fcn_fast_ajax:1,nonce:t.dataset.nonce}).then((t=>{t.success?a.querySelector(".card__content").innerHTML=t.data.success:(fcn_showNotification(t.data.failure??t.data.error??fictioneer_tl.notification.error,10,"warning"),(t.data.error||t.data.failure)&&console.error("Error:",t.data.error??t.data.failure))})).catch((t=>{t.status&&t.statusText&&fcn_showNotification(`${t.status}: ${t.statusText}`,10,"warning"),console.error(t)})).then((()=>{a.classList.remove("ajax-in-progress")}))}_$(".button-clear-comments")?.addEventListener("click",(t=>{fcn_dataDeletionPrompt(t.currentTarget)&&fcn_clearData(t.currentTarget,"fictioneer_ajax_clear_my_comments")})),_$(".button-clear-comment-subscriptions")?.addEventListener("click",(t=>{fcn_dataDeletionPrompt(t.currentTarget)&&fcn_clearData(t.currentTarget,"fictioneer_ajax_clear_my_comment_subscriptions")})),_$(".button-clear-checkmarks")?.addEventListener("click",(t=>{if(!fcn_dataDeletionPrompt(t.currentTarget))return;const e=fcn_getUserData();e.checkmarks={data:{},updated:Date.now()},fcn_setUserData(e),fcn_updateCheckmarksView(),fcn_clearData(t.currentTarget,"fictioneer_ajax_clear_my_checkmarks",!0)})),_$(".button-clear-reminders")?.addEventListener("click",(t=>{if(!fcn_dataDeletionPrompt(t.currentTarget))return;const e=fcn_getUserData();e.reminders={data:{}},fcn_setUserData(e),fcn_updateRemindersView(),fcn_clearData(t.currentTarget,"fictioneer_ajax_clear_my_reminders",!0)})),_$(".button-clear-follows")?.addEventListener("click",(t=>{if(!fcn_dataDeletionPrompt(t.currentTarget))return;const e=fcn_getUserData();e.follows={data:{}},fcn_setUserData(e),fcn_updateFollowsView(),fcn_clearData(t.currentTarget,"fictioneer_ajax_clear_my_follows",!0)})),_$(".button-clear-bookmarks")?.addEventListener("click",(t=>{if(!fcn_dataDeletionPrompt(t.currentTarget))return;const e=fcn_getUserData();e.bookmarks="{}",fcn_setUserData(e),fcn_bookmarks.data={},t.currentTarget.closest(".card").querySelector(".card__content").innerHTML=fcn_profileDataTranslations.clearedSuccess,fcn_setBookmarks(fcn_bookmarks)}));
|
function fcn_unsetOauth(e){const t=prompt(e.dataset.warning);t&&t.toLowerCase()==e.dataset.confirm.toLowerCase()&&FcnUtils.remoteAction("fictioneer_ajax_unset_my_oauth",{nonce:e.dataset.nonce,element:_$$$(`oauth-${e.dataset.channel}`),payload:{channel:e.dataset.channel,id:e.dataset.id},callback:(e,t)=>{e.success?(t.classList.remove("_connected"),t.classList.add("_disconnected"),t.querySelector("button").remove(),fcn_showNotification(t.dataset.unset)):t.style.background="var(--notice-warning-background)"},errorCallback:(e,t)=>{t.style.background="var(--notice-warning-background)"}})}function fcn_deleteMyAccount(e){const t=prompt(e.dataset.warning);t&&t.toLowerCase()==e.dataset.confirm.toLowerCase()&&(e.disabled=!0,FcnUtils.remoteAction("fictioneer_ajax_delete_my_account",{nonce:e.dataset.nonce,element:e,payload:{id:e.dataset.id},callback:(e,t)=>{e.success?location.reload():t.innerHTML=e.data.button},errorCallback:(e,t)=>{t.innerHTML=e.status??fictioneer_tl.notification.error}}))}function fcn_dataDeletionPrompt(e){const t=prompt(e.dataset.warning);return!(!t||t.toLowerCase()!=e.dataset.confirm.toLowerCase())}function fcn_clearData(e,t){const n=e.closest(".card");localStorage.removeItem("fcnBookshelfContent"),e.remove(),FcnUtils.remoteAction(t,{nonce:e.dataset.nonce,element:n,callback:(e,t)=>{e.success&&t&&(t.querySelector(".card__content").innerHTML=e.data.success)}})}_$$(".button-unset-oauth").forEach((e=>{e.addEventListener("click",(e=>{fcn_unsetOauth(e.currentTarget)}))})),_$$$("button-delete-my-account")?.addEventListener("click",(e=>{fcn_deleteMyAccount(e.currentTarget)})),_$(".button-clear-comments")?.addEventListener("click",(e=>{fcn_dataDeletionPrompt(e.currentTarget)&&fcn_clearData(e.currentTarget,"fictioneer_ajax_clear_my_comments")})),_$(".button-clear-comment-subscriptions")?.addEventListener("click",(e=>{fcn_dataDeletionPrompt(e.currentTarget)&&fcn_clearData(e.currentTarget,"fictioneer_ajax_clear_my_comment_subscriptions")})),_$(".button-clear-checkmarks")?.addEventListener("click",(e=>{if(fcn_dataDeletionPrompt(e.currentTarget)){const t=window.FictioneerApp.Controllers.fictioneerCheckmarks;if(!t)return void fcn_showNotification("Error: Checkmarks Controller not connected.",3,"warning");t.clear(),fcn_clearData(e.currentTarget,"fictioneer_ajax_clear_my_checkmarks",!0)}})),_$(".button-clear-reminders")?.addEventListener("click",(e=>{if(fcn_dataDeletionPrompt(e.currentTarget)){const t=window.FictioneerApp.Controllers.fictioneerReminders;if(!t)return void fcn_showNotification("Error: Reminders Controller not connected.",3,"warning");t.clear(),fcn_clearData(e.currentTarget,"fictioneer_ajax_clear_my_reminders",!0)}})),_$(".button-clear-follows")?.addEventListener("click",(e=>{if(fcn_dataDeletionPrompt(e.currentTarget)){const t=window.FictioneerApp.Controllers.fictioneerFollows;if(!t)return void fcn_showNotification("Error: Follows Controller not connected.",3,"warning");t.clear(),fcn_clearData(e.currentTarget,"fictioneer_ajax_clear_my_follows",!0)}})),_$(".button-clear-bookmarks")?.addEventListener("click",(e=>{if(fcn_dataDeletionPrompt(e.currentTarget)){const t=window.FictioneerApp.Controllers.fictioneerBookmarks,n=_$$$("profile-data-translations")?.dataset;if(!t)return void fcn_showNotification("Error: Bookmarks Controller not connected.",3,"warning");t.clear(),e.currentTarget.closest(".card").querySelector(".card__content").innerHTML=n.clearedSuccess}}));
|
1
js/user.min.js
vendored
1
js/user.min.js
vendored
@ -1 +0,0 @@
|
|||||||
function fcn_replaceProfileImage(e,t){const a=e.querySelector(".user-icon");if(a){const n=document.createElement("img");n.classList.add("user-profile-image"),n.src=t,a.remove(),e.appendChild(n)}}function fcn_setProfileImage(e,t=!0){e&&fcn_isValidUrl(e)&&(t&&localStorage.setItem("fcnProfileAvatar",e),_$$("a.subscriber-profile")?.forEach((t=>{fcn_replaceProfileImage(t,e)})),!1===fcn_getUserData().loggedIn&&fcn_prepareLogin())}function fcn_getProfileImage(){let e=localStorage.getItem("fcnProfileAvatar");fcn_isLoggedIn?(fcn_isValidUrl(e)||(e=!1),e?fcn_setProfileImage(e):fcn_getUserAvatar()):localStorage.removeItem("fcnProfileAvatar")}function fcn_getUserAvatar(){fcn_ajaxGet({action:"fictioneer_ajax_get_avatar",fcn_fast_ajax:1}).then((e=>{e.success&&fcn_setProfileImage(e.data.url)})).catch((()=>{fcn_theRoot.dataset.defaultAvatar&&fcn_setProfileImage(fcn_theRoot.dataset.defaultAvatar,!1)}))}function fcn_getUserData(){return fcn_parseJSON(localStorage.getItem("fcnUserData"))??{lastLoaded:0,timestamp:0,loggedIn:"pending",follows:!1,reminders:!1,checkmarks:!1,bookmarks:{},fingerprint:!1}}function fcn_setUserData(e){localStorage.setItem("fcnUserData",JSON.stringify(e))}function fcn_fetchUserData(){let e=fcn_getUserData();if(fcn_isLoggedIn&&!1===e.loggedIn&&(fcn_prepareLogin(),e=fcn_getUserData()),fcn_ajaxLimitThreshold<e.lastLoaded||!1===e.loggedIn)if(e.loggedIn){const t=new CustomEvent("fcnUserDataReady",{detail:{data:e,time:new Date},bubbles:!1,cancelable:!0});document.dispatchEvent(t)}else{const t=new CustomEvent("fcnUserDataFailed",{detail:{response:e,time:new Date},bubbles:!0,cancelable:!1});document.dispatchEvent(t)}else fcn_ajaxGet({action:"fictioneer_ajax_get_user_data",fcn_fast_ajax:1}).then((e=>{if(e.success){let t=fcn_getUserData();t=e.data,t.lastLoaded=Date.now(),fcn_setUserData(t);const a=new CustomEvent("fcnUserDataReady",{detail:{data:e.data,time:new Date},bubbles:!0,cancelable:!1});document.dispatchEvent(a)}else{const t=fcn_getUserData();t.lastLoaded=Date.now(),t.loggedIn=!1,fcn_setUserData(t);const a=new CustomEvent("fcnUserDataFailed",{detail:{response:e,time:new Date},bubbles:!0,cancelable:!1});document.dispatchEvent(a)}})).catch((e=>{localStorage.removeItem("fcnUserData");const t=new CustomEvent("fcnUserDataError",{detail:{error:e,time:new Date},bubbles:!0,cancelable:!1});document.dispatchEvent(t)}))}document.addEventListener("DOMContentLoaded",(()=>{fcn_isLoggedIn&&!fcn_theRoot.dataset.ajaxAuth&&fcn_getProfileImage()})),fcn_theRoot.dataset.ajaxAuth&&document.addEventListener("fcnAuthReady",(()=>{fcn_getProfileImage()})),fcn_theRoot.dataset.ajaxAuth?document.addEventListener("fcnAuthReady",(()=>{fcn_fetchUserData()})):document.addEventListener("DOMContentLoaded",(()=>{fcn_isLoggedIn&&fcn_fetchUserData()}));
|
|
2
js/utility.min.js
vendored
2
js/utility.min.js
vendored
File diff suppressed because one or more lines are too long
@ -26,9 +26,9 @@ fictioneer_get_cached_partial( 'partials/_template_bookmark', '', null, null, $a
|
|||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<section class="small-card-block bookmarks-block <?php echo $show_empty ? '' : 'hidden' ?>" data-count="<?php echo $count; ?>">
|
<section class="small-card-block bookmarks-block <?php echo $show_empty ? '' : 'hidden' ?>" data-count="<?php echo $count; ?>" data-fictioneer-bookmarks-target="shortcodeBlock">
|
||||||
<?php if ( $show_empty ) : ?>
|
<?php if ( $show_empty ) : ?>
|
||||||
<div class="bookmarks-block__no-bookmarks no-results"><?php echo fcntr( 'no_bookmarks' ); ?></div>
|
<div class="bookmarks-block__no-bookmarks no-results" data-fictioneer-bookmarks-target="noBookmarksNote"><?php echo fcntr( 'no_bookmarks' ); ?></div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<ul class="grid-columns"></ul>
|
<ul class="grid-columns"></ul>
|
||||||
</section>
|
</section>
|
||||||
|
@ -93,9 +93,12 @@ $thumbnail_args = array(
|
|||||||
<li
|
<li
|
||||||
id="chapter-card-<?php echo $post_id; ?>"
|
id="chapter-card-<?php echo $post_id; ?>"
|
||||||
class="post-<?php echo $post_id; ?> card _large _chapter <?php echo implode( ' ', $card_classes ); ?>"
|
class="post-<?php echo $post_id; ?> card _large _chapter <?php echo implode( ' ', $card_classes ); ?>"
|
||||||
data-story-id="<?php echo $story_id; ?>"
|
|
||||||
data-check-id="<?php echo $post_id; ?>"
|
|
||||||
data-unavailable="<?php esc_attr_e( 'Unavailable', 'fictioneer' ); ?>"
|
data-unavailable="<?php esc_attr_e( 'Unavailable', 'fictioneer' ); ?>"
|
||||||
|
data-controller="fictioneer-large-card"
|
||||||
|
data-fictioneer-large-card-post-id-value="<?php echo $post_id; ?>"
|
||||||
|
data-fictioneer-large-card-story-id-value="<?php echo $story_id; ?>"
|
||||||
|
data-fictioneer-large-card-chapter-id-value="<?php echo $post_id; ?>"
|
||||||
|
data-action="click->fictioneer-large-card#cardClick"
|
||||||
<?php echo $card_attributes; ?>
|
<?php echo $card_attributes; ?>
|
||||||
>
|
>
|
||||||
<div class="card__body polygon">
|
<div class="card__body polygon">
|
||||||
|
@ -104,8 +104,10 @@ if ( $card_cache_active ) {
|
|||||||
<li
|
<li
|
||||||
id="story-card-<?php echo $post_id; ?>"
|
id="story-card-<?php echo $post_id; ?>"
|
||||||
class="post-<?php echo $post_id; ?> card _large _story <?php echo implode( ' ', $card_classes ); ?>"
|
class="post-<?php echo $post_id; ?> card _large _story <?php echo implode( ' ', $card_classes ); ?>"
|
||||||
data-story-id="<?php echo $post_id; ?>"
|
data-controller="fictioneer-large-card"
|
||||||
data-check-id="<?php echo $post_id; ?>"
|
data-fictioneer-large-card-post-id-value="<?php echo $post_id; ?>"
|
||||||
|
data-fictioneer-large-card-story-id-value="<?php echo $post_id; ?>"
|
||||||
|
data-action="click->fictioneer-large-card#cardClick"
|
||||||
<?php echo $card_attributes; ?>
|
<?php echo $card_attributes; ?>
|
||||||
>
|
>
|
||||||
<div class="card__body polygon">
|
<div class="card__body polygon">
|
||||||
|
@ -221,7 +221,7 @@ if ( $splide ) {
|
|||||||
<div class="card__body polygon">
|
<div class="card__body polygon">
|
||||||
|
|
||||||
<?php if ( $words > 0 && $args['infobox'] ) : ?>
|
<?php if ( $words > 0 && $args['infobox'] ) : ?>
|
||||||
<button class="card__info-toggle toggle-last-clicked" aria-label="<?php esc_attr_e( 'Open info box', 'fictioneer' ); ?>"><i class="fa-solid fa-chevron-down"></i></button>
|
<button class="card__info-toggle" aria-label="<?php esc_attr_e( 'Open info box', 'fictioneer' ); ?>" data-fictioneer-last-click-target="toggle" data-action="click->fictioneer-last-click#toggle"><i class="fa-solid fa-chevron-down"></i></button>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<div class="card__main <?php echo $grid_or_vertical; ?> _small">
|
<div class="card__main <?php echo $grid_or_vertical; ?> _small">
|
||||||
|
@ -282,7 +282,7 @@ if ( $splide ) {
|
|||||||
?></a></h3>
|
?></a></h3>
|
||||||
|
|
||||||
<div class="card__content _small cell-desc">
|
<div class="card__content _small cell-desc">
|
||||||
<div class="truncate <?php echo $truncate_factor; ?> <?php if ( ! $args['spoiler'] ) echo '_obfuscated'; ?>" data-obfuscation-target>
|
<div class="truncate <?php echo $truncate_factor; ?> <?php if ( ! $args['spoiler'] ) echo '_obfuscated'; ?>" data-fictioneer-target="obfuscated">
|
||||||
<?php if ( get_option( 'fictioneer_show_authors' ) && $args['source'] && $args['footer_author'] ) : ?>
|
<?php if ( get_option( 'fictioneer_show_authors' ) && $args['source'] && $args['footer_author'] ) : ?>
|
||||||
<span class="card__by-author"><?php
|
<span class="card__by-author"><?php
|
||||||
printf( _x( 'by %s', 'Small card: by {Author}.', 'fictioneer' ), fictioneer_get_author_node() );
|
printf( _x( 'by %s', 'Small card: by {Author}.', 'fictioneer' ), fictioneer_get_author_node() );
|
||||||
@ -308,7 +308,7 @@ if ( $splide ) {
|
|||||||
?>
|
?>
|
||||||
<?php if ( mb_strlen( str_replace( '…', '', $excerpt ) ) > 2 ) : ?>
|
<?php if ( mb_strlen( str_replace( '…', '', $excerpt ) ) > 2 ) : ?>
|
||||||
<?php if ( ! $args['spoiler'] ) : ?>
|
<?php if ( ! $args['spoiler'] ) : ?>
|
||||||
<span data-click="toggle-obfuscation" tabindex="0">
|
<span data-action="click->fictioneer#toggleObfuscation" tabindex="0">
|
||||||
<span class="obfuscated"> <?php echo $spoiler_note; ?></span>
|
<span class="obfuscated"> <?php echo $spoiler_note; ?></span>
|
||||||
<span class="clean"><?php
|
<span class="clean"><?php
|
||||||
echo $args['source'] ? '— ' : '';
|
echo $args['source'] ? '— ' : '';
|
||||||
|
@ -191,7 +191,7 @@ if ( $splide ) {
|
|||||||
<div class="card__body polygon">
|
<div class="card__body polygon">
|
||||||
|
|
||||||
<?php if ( $show_terms && $args['infobox'] ) : ?>
|
<?php if ( $show_terms && $args['infobox'] ) : ?>
|
||||||
<button class="card__info-toggle toggle-last-clicked" aria-label="<?php esc_attr_e( 'Open info box', 'fictioneer' ); ?>"><i class="fa-solid fa-chevron-down"></i></button>
|
<button class="card__info-toggle" aria-label="<?php esc_attr_e( 'Open info box', 'fictioneer' ); ?>" data-fictioneer-last-click-target="toggle" data-action="click->fictioneer-last-click#toggle"><i class="fa-solid fa-chevron-down"></i></button>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<div class="card__main <?php echo $grid_or_vertical; ?> _small">
|
<div class="card__main <?php echo $grid_or_vertical; ?> _small">
|
||||||
|
@ -255,7 +255,7 @@ if ( $splide ) {
|
|||||||
<div class="card__body polygon">
|
<div class="card__body polygon">
|
||||||
|
|
||||||
<?php if ( $args['infobox'] ) : ?>
|
<?php if ( $args['infobox'] ) : ?>
|
||||||
<button class="card__info-toggle toggle-last-clicked" aria-label="<?php esc_attr_e( 'Open info box', 'fictioneer' ); ?>"><i class="fa-solid fa-chevron-down"></i></button>
|
<button class="card__info-toggle" aria-label="<?php esc_attr_e( 'Open info box', 'fictioneer' ); ?>" data-fictioneer-last-click-target="toggle" data-action="click->fictioneer-last-click#toggle"><i class="fa-solid fa-chevron-down"></i></button>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<div class="card__main <?php echo $grid_or_vertical; ?> _small">
|
<div class="card__main <?php echo $grid_or_vertical; ?> _small">
|
||||||
|
@ -269,7 +269,7 @@ if ( $splide ) {
|
|||||||
<div class="card__body polygon">
|
<div class="card__body polygon">
|
||||||
|
|
||||||
<?php if ( $show_excerpt && $args['infobox'] ) : ?>
|
<?php if ( $show_excerpt && $args['infobox'] ) : ?>
|
||||||
<button class="card__info-toggle toggle-last-clicked" aria-label="<?php esc_attr_e( 'Open info box', 'fictioneer' ); ?>"><i class="fa-solid fa-chevron-down"></i></button>
|
<button class="card__info-toggle" aria-label="<?php esc_attr_e( 'Open info box', 'fictioneer' ); ?>" data-fictioneer-last-click-target="toggle" data-action="click->fictioneer-last-click#toggle"><i class="fa-solid fa-chevron-down"></i></button>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<div class="card__main <?php echo $grid_or_vertical; ?> _small">
|
<div class="card__main <?php echo $grid_or_vertical; ?> _small">
|
||||||
|
@ -26,7 +26,7 @@ if ( empty( $redirect_url ) ) {
|
|||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<div id="age-confirmation-modal" class="modal age-confirmation">
|
<div id="age-confirmation-modal" class="modal age-confirmation" data-nosnippet hidden>
|
||||||
|
|
||||||
<div class="modal__wrapper">
|
<div class="modal__wrapper">
|
||||||
|
|
||||||
|
@ -13,12 +13,11 @@ defined( 'ABSPATH' ) OR exit;
|
|||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<div id="bbcodes-modal" class="bbcodes modal" data-nosnippet hidden>
|
<div id="bbcodes-modal" class="bbcodes modal" data-fictioneer-target="modal" data-action="click->fictioneer#backgroundCloseModals keydown.esc@document->fictioneer#closeModals" data-nosnippet hidden>
|
||||||
<label for="modal-bbcodes-toggle" class="background-close"></label>
|
|
||||||
<div class="modal__wrapper">
|
<div class="modal__wrapper">
|
||||||
<label class="close" for="modal-bbcodes-toggle" tabindex="0" aria-label="<?php esc_attr_e( 'Close modal', 'fictioneer' ); ?>">
|
|
||||||
<?php fictioneer_icon( 'fa-xmark' ); ?>
|
<button class="close" aria-label="<?php esc_attr_e( 'Close modal', 'fictioneer' ); ?>" data-action="click->fictioneer#closeModals"><?php fictioneer_icon( 'fa-xmark' ); ?></button>
|
||||||
</label>
|
|
||||||
<div class="modal__header drag-anchor"><?php echo fcntr( 'bbcodes_modal' ); ?></div>
|
<div class="modal__header drag-anchor"><?php echo fcntr( 'bbcodes_modal' ); ?></div>
|
||||||
|
|
||||||
<div class="modal__row modal__description _bbcodes _small-top">
|
<div class="modal__row modal__description _bbcodes _small-top">
|
||||||
|
@ -22,16 +22,16 @@ foreach ( $changelog as $entry ) {
|
|||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<div id="chapter-changelog-modal" class="chapter-changelog modal" data-nosnippet hidden>
|
<div id="chapter-changelog-modal" class="chapter-changelog modal" data-fictioneer-target="modal" data-action="click->fictioneer#backgroundCloseModals keydown.esc@document->fictioneer#closeModals" data-nosnippet hidden>
|
||||||
<label for="modal-chapter-changelog-toggle" class="background-close"></label>
|
|
||||||
<div class="modal__wrapper">
|
<div class="modal__wrapper">
|
||||||
<label class="close" for="modal-chapter-changelog-toggle" tabindex="0" aria-label="<?php esc_attr_e( 'Close modal', 'fictioneer' ); ?>">
|
|
||||||
<?php fictioneer_icon( 'fa-xmark' ); ?>
|
<button class="close" aria-label="<?php esc_attr_e( 'Close modal', 'fictioneer' ); ?>" data-action="click->fictioneer#closeModals"><?php fictioneer_icon( 'fa-xmark' ); ?></button>
|
||||||
</label>
|
|
||||||
<div class="modal__header drag-anchor"><?php _e( 'Changelog', 'fictioneer' ); ?></div>
|
<div class="modal__header drag-anchor"><?php _e( 'Changelog', 'fictioneer' ); ?></div>
|
||||||
|
|
||||||
<div class="modal__row _textarea _small-top">
|
<div class="modal__row _textarea _small-top">
|
||||||
<textarea class="modal__textarea _changelog" readonly><?php echo $output; ?></textarea>
|
<textarea class="modal__textarea _changelog" readonly><?php echo $output; ?></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -13,12 +13,11 @@ defined( 'ABSPATH' ) OR exit;
|
|||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<div id="formatting-modal" class="reader-settings modal" data-nosnippet hidden>
|
<div id="formatting-modal" class="reader-settings modal" data-fictioneer-target="modal" data-action="click->fictioneer#backgroundCloseModals keydown.esc@document->fictioneer#closeModals" data-nosnippet hidden>
|
||||||
<label for="modal-formatting-toggle" class="background-close"></label>
|
|
||||||
<div class="modal__wrapper narrow-inputs">
|
<div class="modal__wrapper narrow-inputs">
|
||||||
<label class="close" for="modal-formatting-toggle" tabindex="0" aria-label="<?php esc_attr_e( 'Close modal', 'fictioneer' ); ?>">
|
|
||||||
<?php fictioneer_icon( 'fa-xmark' ); ?>
|
<button class="close" aria-label="<?php esc_attr_e( 'Close modal', 'fictioneer' ); ?>" data-action="click->fictioneer#closeModals"><?php fictioneer_icon( 'fa-xmark' ); ?></button>
|
||||||
</label>
|
|
||||||
<div class="modal__header drag-anchor"><?php echo fcntr( 'formatting_modal' ); ?></div>
|
<div class="modal__header drag-anchor"><?php echo fcntr( 'formatting_modal' ); ?></div>
|
||||||
|
|
||||||
<div class="modal__row reader-settings__row _vertical-shrink-spacing _darken">
|
<div class="modal__row reader-settings__row _vertical-shrink-spacing _darken">
|
||||||
|
@ -13,12 +13,11 @@ defined( 'ABSPATH' ) OR exit;
|
|||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<div id="login-modal" class="login modal" data-nosnippet hidden>
|
<div id="login-modal" class="login modal" data-fictioneer-target="modal" data-action="click->fictioneer#backgroundCloseModals keydown.esc@document->fictioneer#closeModals" data-nosnippet hidden>
|
||||||
<label for="modal-login-toggle" class="background-close"></label>
|
|
||||||
<div class="modal__wrapper">
|
<div class="modal__wrapper">
|
||||||
<label class="close" for="modal-login-toggle" tabindex="0" aria-label="<?php esc_attr_e( 'Close modal', 'fictioneer' ); ?>">
|
|
||||||
<?php fictioneer_icon( 'fa-xmark' ); ?>
|
<button class="close" aria-label="<?php esc_attr_e( 'Close modal', 'fictioneer' ); ?>" data-action="click->fictioneer#closeModals"><?php fictioneer_icon( 'fa-xmark' ); ?></button>
|
||||||
</label>
|
|
||||||
<div class="modal__header drag-anchor"><?php echo fcntr( 'login_modal' ); ?></div>
|
<div class="modal__header drag-anchor"><?php echo fcntr( 'login_modal' ); ?></div>
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
@ -34,5 +33,6 @@ defined( 'ABSPATH' ) OR exit;
|
|||||||
<div class="modal__row modal__description _small-top"><?php echo $info; ?></div>
|
<div class="modal__row modal__description _small-top"><?php echo $info; ?></div>
|
||||||
|
|
||||||
<div class="modal__row login__options"><?php do_action( 'fictioneer_modal_login_option' ); ?></div>
|
<div class="modal__row login__options"><?php do_action( 'fictioneer_modal_login_option' ); ?></div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -18,12 +18,11 @@ $story_link = get_post_meta( get_the_ID(), 'fictioneer_story_redirect_link', tru
|
|||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<div id="sharing-modal" class="sharing modal" data-nosnippet hidden>
|
<div id="sharing-modal" class="sharing modal" data-fictioneer-target="modal" data-action="click->fictioneer#backgroundCloseModals keydown.esc@document->fictioneer#closeModals" data-nosnippet hidden>
|
||||||
<label for="modal-sharing-toggle" class="background-close"></label>
|
|
||||||
<div class="modal__wrapper">
|
<div class="modal__wrapper">
|
||||||
<label class="close" for="modal-sharing-toggle" tabindex="0" aria-label="<?php esc_attr_e( 'Close modal', 'fictioneer' ); ?>">
|
|
||||||
<?php fictioneer_icon( 'fa-xmark' ); ?>
|
<button class="close" aria-label="<?php esc_attr_e( 'Close modal', 'fictioneer' ); ?>" data-action="click->fictioneer#closeModals"><?php fictioneer_icon( 'fa-xmark' ); ?></button>
|
||||||
</label>
|
|
||||||
<div class="modal__header drag-anchor"><?php _ex( 'Share', 'Share modal heading.', 'fictioneer' ); ?></div>
|
<div class="modal__header drag-anchor"><?php _ex( 'Share', 'Share modal heading.', 'fictioneer' ); ?></div>
|
||||||
|
|
||||||
<div class="modal__row media-buttons _modal">
|
<div class="modal__row media-buttons _modal">
|
||||||
@ -65,7 +64,8 @@ $story_link = get_post_meta( get_the_ID(), 'fictioneer_story_redirect_link', tru
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="modal__row">
|
<div class="modal__row">
|
||||||
<input type="text" value="<?php echo $story_link; ?>" data-click="copy-to-clipboard" data-message="<?php _e( 'Link copied to clipboard!', 'fictioneer' ); ?>" name="permalink" readonly>
|
<input type="text" value="<?php echo $story_link; ?>" data-action="click->fictioneer#copyInput" data-message="<?php _e( 'Link copied to clipboard!', 'fictioneer' ); ?>" name="permalink" readonly>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -13,12 +13,11 @@ defined( 'ABSPATH' ) OR exit;
|
|||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<div id="site-settings-modal" class="site-settings modal" data-nosnippet hidden>
|
<div id="site-settings-modal" class="site-settings modal" data-fictioneer-target="modal" data-action="click->fictioneer#backgroundCloseModals keydown.esc@document->fictioneer#closeModals" data-nosnippet hidden>
|
||||||
<label for="modal-site-settings-toggle" class="background-close"></label>
|
|
||||||
<div class="modal__wrapper narrow-inputs">
|
<div class="modal__wrapper narrow-inputs">
|
||||||
<label class="close" for="modal-site-settings-toggle" tabindex="0" aria-label="<?php esc_attr_e( 'Close modal', 'fictioneer' ); ?>">
|
|
||||||
<?php fictioneer_icon( 'fa-xmark' ); ?>
|
<button class="close" aria-label="<?php esc_attr_e( 'Close modal', 'fictioneer' ); ?>" data-action="click->fictioneer#closeModals"><?php fictioneer_icon( 'fa-xmark' ); ?></button>
|
||||||
</label>
|
|
||||||
<div class="modal__header drag-anchor"><?php echo fcntr( 'site_settings' ); ?></div>
|
<div class="modal__header drag-anchor"><?php echo fcntr( 'site_settings' ); ?></div>
|
||||||
<div class="modal__description modal__row site-settings__description site-settings__row _small-top">
|
<div class="modal__description modal__row site-settings__description site-settings__row _small-top">
|
||||||
<p><?php _e( 'You can toggle selected features and styles per device/browser to boost performance. Some options may not be available.', 'fictioneer' ); ?></p>
|
<p><?php _e( 'You can toggle selected features and styles per device/browser to boost performance. Some options may not be available.', 'fictioneer' ); ?></p>
|
||||||
|
@ -13,15 +13,10 @@ defined( 'ABSPATH' ) OR exit;
|
|||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<div id="suggestions-modal" class="suggestions modal" data-nosnippet hidden>
|
<div id="suggestions-modal" class="suggestions modal" data-fictioneer-target="modal" data-action="click->fictioneer#backgroundCloseModals keydown.esc@document->fictioneer#closeModals" data-nosnippet hidden>
|
||||||
|
|
||||||
<label for="suggestions-modal-toggle" class="background-close"></label>
|
|
||||||
|
|
||||||
<div class="modal__wrapper suggestions__wrapper">
|
<div class="modal__wrapper suggestions__wrapper">
|
||||||
|
|
||||||
<label class="close" for="suggestions-modal-toggle" tabindex="0" aria-label="<?php esc_attr_e( 'Close modal', 'fictioneer' ); ?>">
|
<button class="close" aria-label="<?php esc_attr_e( 'Close modal', 'fictioneer' ); ?>" data-action="click->fictioneer#closeModals"><?php fictioneer_icon( 'fa-xmark' ); ?></button>
|
||||||
<?php fictioneer_icon( 'fa-xmark' ); ?>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<div class="modal__header drag-anchor"><?php _ex( 'Suggestion', 'Suggestion modal heading.', 'fictioneer' ); ?></div>
|
<div class="modal__header drag-anchor"><?php _ex( 'Suggestion', 'Suggestion modal heading.', 'fictioneer' ); ?></div>
|
||||||
|
|
||||||
@ -49,5 +44,4 @@ defined( 'ABSPATH' ) OR exit;
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -13,17 +13,10 @@ defined( 'ABSPATH' ) OR exit;
|
|||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<div id="tts-settings-modal" class="tts-settings modal" data-nosnippet hidden>
|
<div id="tts-settings-modal" class="tts-settings modal" data-fictioneer-target="modal" data-action="click->fictioneer#backgroundCloseModals keydown.esc@document->fictioneer#closeModals" data-nosnippet hidden>
|
||||||
<label for="modal-tts-settings-toggle" class="background-close"></label>
|
|
||||||
<div class="modal__wrapper narrow-inputs">
|
<div class="modal__wrapper narrow-inputs">
|
||||||
<label
|
|
||||||
class="close"
|
<button class="close" aria-label="<?php esc_attr_e( 'Close modal', 'fictioneer' ); ?>" data-action="click->fictioneer#closeModals"><?php fictioneer_icon( 'fa-xmark' ); ?></button>
|
||||||
for="modal-tts-settings-toggle"
|
|
||||||
tabindex="0"
|
|
||||||
aria-label="<?php esc_attr_e( 'Close modal', 'fictioneer' ); ?>"
|
|
||||||
>
|
|
||||||
<?php fictioneer_icon( 'fa-xmark' ); ?>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<div class="modal__header drag-anchor"><?php _ex( 'TTS Settings', 'TTS modal heading.', 'fictioneer' ); ?></div>
|
<div class="modal__header drag-anchor"><?php _ex( 'TTS Settings', 'TTS modal heading.', 'fictioneer' ); ?></div>
|
||||||
|
|
||||||
|
@ -51,13 +51,13 @@ if ( $header_style === 'wide' ) {
|
|||||||
|
|
||||||
<?php do_action( 'fictioneer_navigation_wrapper_start', $args ); ?>
|
<?php do_action( 'fictioneer_navigation_wrapper_start', $args ); ?>
|
||||||
|
|
||||||
<label for="mobile-menu-toggle" class="mobile-menu-button follows-alert-number">
|
<button class="mobile-menu-button follows-alert-number" data-fictioneer-follows-target="newDisplay" data-action="click->fictioneer#toggleMobileMenu">
|
||||||
<?php
|
<?php
|
||||||
fictioneer_icon( 'fa-bars', 'off' );
|
fictioneer_icon( 'fa-bars', 'off' );
|
||||||
fictioneer_icon( 'fa-xmark', 'on' );
|
fictioneer_icon( 'fa-xmark', 'on' );
|
||||||
?>
|
?>
|
||||||
<span class="mobile-menu-button__label"><?php _ex( 'Menu' , 'Mobile menu label', 'fictioneer' ); ?></span>
|
<span class="mobile-menu-button__label"><?php _ex( 'Menu' , 'Mobile menu label', 'fictioneer' ); ?></span>
|
||||||
</label>
|
</button>
|
||||||
|
|
||||||
<nav class="main-navigation__left" aria-label="<?php echo esc_attr__( 'Main Navigation', 'fictioneer' ); ?>">
|
<nav class="main-navigation__left" aria-label="<?php echo esc_attr__( 'Main Navigation', 'fictioneer' ); ?>">
|
||||||
<?php
|
<?php
|
||||||
|
@ -51,7 +51,7 @@ $meta_output['rating'] = '<span class="story__meta-item story__rating" title="'
|
|||||||
|
|
||||||
// Checkmark
|
// Checkmark
|
||||||
if ( $story['chapter_count'] > 0 ) {
|
if ( $story['chapter_count'] > 0 ) {
|
||||||
$meta_output['checkmark'] = '<button class="story__meta-item checkmark story__meta-checkmark" data-type="story" data-story-id="' . $story_id . '" data-id="' . $story_id . '" data-status="' . esc_attr( $story['status'] ) . '" role="checkbox" aria-checked="false" aria-label="' . sprintf( esc_attr__( 'Story checkmark for %s.', 'fictioneer' ), $story['title'] ) . '"><i class="fa-solid fa-check"></i></button>';
|
$meta_output['checkmark'] = '<button class="story__meta-item checkmark story__meta-checkmark" data-fictioneer-checkmarks-target="storyCheck" data-fictioneer-checkmarks-story-param="' . $story_id . '" data-action="click->fictioneer-checkmarks#toggleStory" data-status="' . esc_attr( $story['status'] ) . '" role="checkbox" aria-checked="false" aria-label="' . sprintf( esc_attr__( 'Story checkmark for %s.', 'fictioneer' ), $story['title'] ) . '"><i class="fa-solid fa-check"></i></button>';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter
|
// Filter
|
||||||
@ -62,9 +62,9 @@ $meta_output = apply_filters( 'fictioneer_filter_story_footer_meta', $meta_outpu
|
|||||||
<footer class="story__footer">
|
<footer class="story__footer">
|
||||||
<div class="story__extra">
|
<div class="story__extra">
|
||||||
<?php if ( $show_log ) : ?>
|
<?php if ( $show_log ) : ?>
|
||||||
<label class="story__changelog hide-below-400" for="modal-chapter-changelog-toggle" tabindex="-1">
|
<button class="story__changelog hide-below-400" data-action="click->fictioneer#toggleModal" data-fictioneer-id-param="chapter-changelog-modal">
|
||||||
<i class="fa-solid fa-clock-rotate-left"></i>
|
<i class="fa-solid fa-clock-rotate-left"></i>
|
||||||
</label>
|
</button>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
<div class="story__meta"><?php echo implode( '', $meta_output ); ?></div>
|
<div class="story__meta"><?php echo implode( '', $meta_output ); ?></div>
|
||||||
|
@ -45,7 +45,7 @@ if ( $args['seamless'] ?? 0 ) {
|
|||||||
</div>
|
</div>
|
||||||
<div class="card__content _small cell-desc bookmark-card__excerpt truncate _cq-2-3"></div>
|
<div class="card__content _small cell-desc bookmark-card__excerpt truncate _cq-2-3"></div>
|
||||||
</div>
|
</div>
|
||||||
<button class="card__delete button-delete-bookmark" data-bookmark-id><i class="fa-solid fa-trash-can"></i></button>
|
<button class="card__delete button-delete-bookmark" data-action="click->fictioneer-bookmarks#remove"><i class="fa-solid fa-trash-can"></i></button>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</template>
|
</template>
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
* @package WordPress
|
* @package WordPress
|
||||||
* @subpackage Fictioneer
|
* @subpackage Fictioneer
|
||||||
* @since 5.4.5
|
* @since 5.4.5
|
||||||
|
* @since 5.27.0 - Updated for Stimulus Controller.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@ -13,15 +14,20 @@ defined( 'ABSPATH' ) OR exit;
|
|||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<template class="comment-edit-actions-template">
|
<template id="template-comment-inline-edit-form">
|
||||||
<div class="fictioneer-comment__edit-actions">
|
<div class="fictioneer-comment__edit-actions" data-fictioneer-comment-target="inlineEditButtons">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="comment-inline-edit-submit button"
|
class="comment-inline-edit-submit button"
|
||||||
data-enabled="<?php echo esc_attr_x( 'Submit Changes', 'Comment inline edit submit button.', 'fictioneer' ); ?>"
|
data-enabled="<?php echo esc_attr_x( 'Submit Changes', 'Comment inline edit submit button.', 'fictioneer' ); ?>"
|
||||||
data-disabled="<?php esc_attr_e( 'Updating…', 'fictioneer' ); ?>"
|
data-disabled="<?php esc_attr_e( 'Updating…', 'fictioneer' ); ?>"
|
||||||
data-click="submit-inline-comment-edit"
|
data-fictioneer-comment-target="inlineEditSubmit"
|
||||||
|
data-action="click->fictioneer-comment#submitEditInline"
|
||||||
><?php _ex( 'Submit Changes', 'Comment inline edit submit button.', 'fictioneer' ); ?></button>
|
><?php _ex( 'Submit Changes', 'Comment inline edit submit button.', 'fictioneer' ); ?></button>
|
||||||
<button type="button" class="comment-inline-edit-cancel button _secondary" data-click="cancel-inline-comment-edit"><?php _ex( 'Cancel', 'Comment inline edit cancel button.', 'fictioneer' ); ?></button>
|
<button
|
||||||
|
type="button"
|
||||||
|
class="comment-inline-edit-cancel button _secondary"
|
||||||
|
data-action="click->fictioneer-comment#cancelEditInline"
|
||||||
|
><?php _ex( 'Cancel', 'Comment inline edit cancel button.', 'fictioneer' ); ?></button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -13,9 +13,9 @@ defined( 'ABSPATH' ) OR exit;
|
|||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<template id="mobile-bookmark-template" hidden>
|
<template id="mobile-bookmark-template">
|
||||||
<li class="mobile-menu__bookmark">
|
<li class="mobile-menu__bookmark">
|
||||||
<button class="mobile-menu-bookmark-delete-button" data-bookmark-id><i class="fa-solid fa-trash-alt"></i></button>
|
<button class="mobile-menu-bookmark-delete-button" data-fictioneer-mobile-menu-id-param data-action="click->fictioneer-mobile-menu#deleteBookmark"><i class="fa-solid fa-trash-alt"></i></button>
|
||||||
<i class="fa-solid fa-bookmark"></i>
|
<i class="fa-solid fa-bookmark"></i>
|
||||||
<a href="#"><span></span></a>
|
<a href="#"><span></span></a>
|
||||||
<div class="mobile-menu__bookmark-progress"><div><div class="mobile-menu__bookmark-bg" style></div></div></div>
|
<div class="mobile-menu__bookmark-progress"><div><div class="mobile-menu__bookmark-bg" style></div></div></div>
|
||||||
|
@ -36,10 +36,10 @@ defined( 'ABSPATH' ) OR exit;
|
|||||||
<i class="fa-solid fa-arrows-alt-v"></i>
|
<i class="fa-solid fa-arrows-alt-v"></i>
|
||||||
<span class="hide-below-375"><?php _e( 'Scroll', 'fictioneer' ); ?></span>
|
<span class="hide-below-375"><?php _e( 'Scroll', 'fictioneer' ); ?></span>
|
||||||
</button>
|
</button>
|
||||||
<label for="modal-tts-settings-toggle" class="button settings" role="button" tabindex="0">
|
<button class="button settings" type="button" tabindex="0" data-action="click->fictioneer#toggleModal" data-fictioneer-id-param="tts-settings-modal">
|
||||||
<i class="fa-solid fa-cog"></i>
|
<i class="fa-solid fa-cog"></i>
|
||||||
<span class="hide-below-480"><?php _e( 'Settings', 'fictioneer' ); ?></span>
|
<span class="hide-below-480"><?php _e( 'Settings', 'fictioneer' ); ?></span>
|
||||||
</label>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -271,7 +271,7 @@ $delete_bookmarks_prompt = sprintf(
|
|||||||
?></h3>
|
?></h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="card__main _small">
|
<div class="card__main _small">
|
||||||
<div class="card__content cell-data _small profile-bookmarks-stats">
|
<div class="card__content cell-data _small profile-bookmarks-stats" data-fictioneer-bookmarks-target="dataCard">
|
||||||
<?php _e( 'You have currently <strong>%s bookmark(s)</strong> set. Bookmarks are only processed in your browser.', 'fictioneer' ); ?>
|
<?php _e( 'You have currently <strong>%s bookmark(s)</strong> set. Bookmarks are only processed in your browser.', 'fictioneer' ); ?>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -7,7 +7,7 @@ Contributors: tetrakern
|
|||||||
Requires at least: 6.1.0
|
Requires at least: 6.1.0
|
||||||
Tested up to: 6.6.2
|
Tested up to: 6.6.2
|
||||||
Requires PHP: 7.4
|
Requires PHP: 7.4
|
||||||
Stable tag: 5.26.1
|
Stable tag: 5.27.0-beta2
|
||||||
License: GNU General Public License v3.0 or later
|
License: GNU General Public License v3.0 or later
|
||||||
License URI: http://www.gnu.org/licenses/gpl.html
|
License URI: http://www.gnu.org/licenses/gpl.html
|
||||||
|
|
||||||
|
@ -453,8 +453,6 @@ function validate_tags($content) {
|
|||||||
* Sends the user's Checkmarks as JSON via Ajax
|
* Sends the user's Checkmarks as JSON via Ajax
|
||||||
*
|
*
|
||||||
* @since 4.0.0
|
* @since 4.0.0
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_success/
|
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_error/
|
|
||||||
* @see fictioneer_get_validated_ajax_user()
|
* @see fictioneer_get_validated_ajax_user()
|
||||||
* @see fictioneer_load_checkmarks()
|
* @see fictioneer_load_checkmarks()
|
||||||
*/
|
*/
|
||||||
@ -487,8 +485,6 @@ if ( get_option( 'fictioneer_enable_checkmarks' ) ) {
|
|||||||
* Sends the user's Reminders as JSON via Ajax
|
* Sends the user's Reminders as JSON via Ajax
|
||||||
*
|
*
|
||||||
* @since 5.0.0
|
* @since 5.0.0
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_success/
|
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_error/
|
|
||||||
* @see fictioneer_get_validated_ajax_user()
|
* @see fictioneer_get_validated_ajax_user()
|
||||||
* @see fictioneer_load_reminders()
|
* @see fictioneer_load_reminders()
|
||||||
*/
|
*/
|
||||||
@ -521,8 +517,6 @@ if ( get_option( 'fictioneer_enable_reminders' ) ) {
|
|||||||
* Sends the user's Follows as JSON via Ajax
|
* Sends the user's Follows as JSON via Ajax
|
||||||
*
|
*
|
||||||
* @since 4.3.0
|
* @since 4.3.0
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_success/
|
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_error/
|
|
||||||
* @see fictioneer_get_validated_ajax_user()
|
* @see fictioneer_get_validated_ajax_user()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -570,8 +564,6 @@ if ( get_option( 'fictioneer_enable_follows' ) ) {
|
|||||||
* Sends the user's fingerprint via AJAX
|
* Sends the user's fingerprint via AJAX
|
||||||
*
|
*
|
||||||
* @since 5.0.0
|
* @since 5.0.0
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_success/
|
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_error/
|
|
||||||
* @see fictioneer_get_validated_ajax_user()
|
* @see fictioneer_get_validated_ajax_user()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -596,8 +588,6 @@ add_action( 'wp_ajax_fictioneer_ajax_get_fingerprint', 'fictioneer_ajax_get_fing
|
|||||||
* Get an user's bookmarks via AJAX
|
* Get an user's bookmarks via AJAX
|
||||||
*
|
*
|
||||||
* @since 4.0.0
|
* @since 4.0.0
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_success/
|
|
||||||
* @link https://developer.wordpress.org/reference/functions/wp_send_json_error/
|
|
||||||
* @see fictioneer_get_validated_ajax_user()
|
* @see fictioneer_get_validated_ajax_user()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
// Setup
|
// Setup
|
||||||
$password_required = post_password_required();
|
$password_required = post_password_required();
|
||||||
$post_id = get_the_ID();
|
$post_id = get_the_ID();
|
||||||
|
$story_id = fictioneer_get_chapter_story_id( $post_id );
|
||||||
|
|
||||||
// Header
|
// Header
|
||||||
get_header(
|
get_header(
|
||||||
@ -30,7 +31,7 @@ get_header(
|
|||||||
<div class="progress__bar"></div>
|
<div class="progress__bar"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<main id="main" class="main chapter">
|
<main id="main" class="main chapter" data-controller="fictioneer-chapter fictioneer-suggestion" data-fictioneer-chapter-chapter-id-value="<?php echo $post_id; ?>" data-fictioneer-chapter-story-id-value="<?php echo $story_id; ?>" data-action="fictioneer:bodyClick@window->fictioneer-chapter#clickOutside fictioneer:bodyClick@window->fictioneer-suggestion#clickOutside">
|
||||||
|
|
||||||
<?php do_action( 'fictioneer_main', 'chapter' ); ?>
|
<?php do_action( 'fictioneer_main', 'chapter' ); ?>
|
||||||
|
|
||||||
@ -49,7 +50,6 @@ get_header(
|
|||||||
$age_rating = get_post_meta( $post_id, 'fictioneer_chapter_rating', true );
|
$age_rating = get_post_meta( $post_id, 'fictioneer_chapter_rating', true );
|
||||||
$this_breadcrumb = [ $title, get_the_permalink() ];
|
$this_breadcrumb = [ $title, get_the_permalink() ];
|
||||||
|
|
||||||
$story_id = fictioneer_get_chapter_story_id( $post_id );
|
|
||||||
$story_data = null;
|
$story_data = null;
|
||||||
$story_post = null;
|
$story_post = null;
|
||||||
|
|
||||||
@ -152,12 +152,12 @@ get_header(
|
|||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<section id="chapter-content" class="chapter__content content-section"><?php
|
<section id="chapter-content" class="chapter__content content-section" data-fictioneer-chapter-target="content" data-action="mouseup->fictioneer-suggestion#toggleFloatingButton"><?php
|
||||||
if ( $password_required && $password_note ) {
|
if ( $password_required && $password_note ) {
|
||||||
echo '<div class="chapter__password-note infobox">' . $password_note . '</div>';
|
echo '<div class="chapter__password-note infobox">' . $password_note . '</div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
echo '<div class="resize-font chapter-formatting chapter-font-color chapter-font-family">';
|
echo '<div class="resize-font chapter-formatting chapter-font-color chapter-font-family" data-fictioneer-chapter-target="contentWrapper" data-action="mousedown->fictioneer-chapter#fastClick">';
|
||||||
|
|
||||||
if ( $password_required && get_option( 'fictioneer_show_protected_excerpt' ) ) {
|
if ( $password_required && get_option( 'fictioneer_show_protected_excerpt' ) ) {
|
||||||
echo '<p class="chapter__forced-excerpt">' . fictioneer_get_forced_excerpt( $post_id, 512 ) . '</p>';
|
echo '<p class="chapter__forced-excerpt">' . fictioneer_get_forced_excerpt( $post_id, 512 ) . '</p>';
|
||||||
|
@ -37,7 +37,7 @@ get_header(
|
|||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<main id="main" class="main story <?php echo get_option( 'fictioneer_enable_checkmarks' ) ? '' : '_no-checkmarks'; ?>">
|
<main id="main" class="main story <?php echo get_option( 'fictioneer_enable_checkmarks' ) ? '' : '_no-checkmarks'; ?>" data-controller="fictioneer-story" data-fictioneer-story-id-value="<?php echo $post_id; ?>">
|
||||||
|
|
||||||
<?php do_action( 'fictioneer_main', 'story' ); ?>
|
<?php do_action( 'fictioneer_main', 'story' ); ?>
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ get_header(
|
|||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<main id="main" class="main singular">
|
<main id="main" class="main singular" data-controller="fictioneer-story" data-fictioneer-story-id-value="<?php echo $story_id; ?>">
|
||||||
|
|
||||||
<?php do_action( 'fictioneer_main', 'singular-story' ); ?>
|
<?php do_action( 'fictioneer_main', 'singular-story' ); ?>
|
||||||
|
|
||||||
|
122
src/js/admin.js
122
src/js/admin.js
@ -1,31 +1,3 @@
|
|||||||
// =============================================================================
|
|
||||||
// PROGRESSIVE ACTIONS
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Toggles progression state of an element.
|
|
||||||
*
|
|
||||||
* @since 5.7.2
|
|
||||||
* @param {HTMLElement} element - The element.
|
|
||||||
* @param {Boolean|null} force - Whether to disable or enable. Defaults to
|
|
||||||
* the opposite of the current state.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function fcn_toggleInProgress(element, force = null) {
|
|
||||||
force = force !== null ? force : !element.disabled;
|
|
||||||
|
|
||||||
if (force) {
|
|
||||||
element.dataset.enableWith = element.innerHTML;
|
|
||||||
element.innerHTML = element.dataset.disableWith;
|
|
||||||
element.disabled = true;
|
|
||||||
element.classList.add('disabled');
|
|
||||||
} else {
|
|
||||||
element.innerHTML = element.dataset.enableWith;
|
|
||||||
element.disabled = false;
|
|
||||||
element.classList.remove('disabled');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// SCHEMAS
|
// SCHEMAS
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
@ -46,7 +18,7 @@ function fcn_purgeSchema(post_id) {
|
|||||||
actions.remove();
|
actions.remove();
|
||||||
|
|
||||||
// Request
|
// Request
|
||||||
fcn_ajaxPost({
|
FcnUtils.aPost({
|
||||||
'action': 'fictioneer_ajax_purge_schema',
|
'action': 'fictioneer_ajax_purge_schema',
|
||||||
'nonce': document.getElementById('fictioneer_admin_nonce').value,
|
'nonce': document.getElementById('fictioneer_admin_nonce').value,
|
||||||
'post_id': post_id
|
'post_id': post_id
|
||||||
@ -88,13 +60,13 @@ function fcn_purgeAllSchemas(offset = 0, total = null, processed = 0) {
|
|||||||
|
|
||||||
if ( total === null ) {
|
if ( total === null ) {
|
||||||
buttons.forEach(element => {
|
buttons.forEach(element => {
|
||||||
fcn_toggleInProgress(element, true);
|
FcnUtils.toggleInProgress(element, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Request ---------------------------------------------------------------
|
// --- Request ---------------------------------------------------------------
|
||||||
|
|
||||||
fcn_ajaxPost({
|
FcnUtils.aPost({
|
||||||
'action': 'fictioneer_ajax_purge_all_schemas',
|
'action': 'fictioneer_ajax_purge_all_schemas',
|
||||||
'offset': offset,
|
'offset': offset,
|
||||||
'nonce': document.getElementById('fictioneer_admin_nonce').value
|
'nonce': document.getElementById('fictioneer_admin_nonce').value
|
||||||
@ -115,7 +87,7 @@ function fcn_purgeAllSchemas(offset = 0, total = null, processed = 0) {
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
buttons.forEach(element => {
|
buttons.forEach(element => {
|
||||||
fcn_toggleInProgress(element, false);
|
FcnUtils.toggleInProgress(element, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
_$$('tr').forEach(row => {
|
_$$('tr').forEach(row => {
|
||||||
@ -159,7 +131,7 @@ _$$('[data-fcn-dialog-target="schema-dialog"]').forEach(element => {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function fcn_delete_epub(name) {
|
function fcn_delete_epub(name) {
|
||||||
fcn_ajaxPost({
|
FcnUtils.aPost({
|
||||||
'action': 'fictioneer_ajax_delete_epub',
|
'action': 'fictioneer_ajax_delete_epub',
|
||||||
'name': name,
|
'name': name,
|
||||||
'nonce': document.getElementById('fictioneer_admin_nonce').value
|
'nonce': document.getElementById('fictioneer_admin_nonce').value
|
||||||
@ -316,16 +288,54 @@ _$$('[data-confirm-dialog]').forEach(element => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// LOGOUT
|
// USER
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AJAX: Refresh local user data.
|
||||||
|
*
|
||||||
|
* @since 5.27.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
function fcn_fetchUserData() {
|
||||||
|
FcnUtils.aGet({
|
||||||
|
'action': 'fictioneer_ajax_get_user_data',
|
||||||
|
'fcn_fast_ajax': 1
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
if (response.success) {
|
||||||
|
const userData = response.data;
|
||||||
|
userData['lastLoaded'] = Date.now();
|
||||||
|
FcnUtils.setUserData(userData);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
localStorage.removeItem('fcnUserData');
|
||||||
|
console.error(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch new user data after purge
|
||||||
|
(() => {
|
||||||
|
const currentUserData = FcnUtils.parseJSON(localStorage.getItem('fcnUserData'));
|
||||||
|
|
||||||
|
if (!currentUserData) {
|
||||||
|
fcn_fetchUserData();
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
// Admin bar logout link
|
// Admin bar logout link
|
||||||
_$('#wp-admin-bar-logout a')?.addEventListener('click', () => {
|
_$('#wp-admin-bar-logout a')?.addEventListener('click', () => {
|
||||||
localStorage.removeItem('fcnProfileAvatar');
|
|
||||||
localStorage.removeItem('fcnUserData');
|
localStorage.removeItem('fcnUserData');
|
||||||
localStorage.removeItem('fcnAuth');
|
|
||||||
localStorage.removeItem('fcnBookshelfContent');
|
localStorage.removeItem('fcnBookshelfContent');
|
||||||
localStorage.removeItem('fcnChapterBookmarks');
|
});
|
||||||
|
|
||||||
|
// Data node purge
|
||||||
|
_$$('[data-action="click->fictioneer-admin-profile#purgeLocalUserData"]').forEach(link => {
|
||||||
|
link.addEventListener('click', () => {
|
||||||
|
localStorage.removeItem('fcnUserData');
|
||||||
|
localStorage.removeItem('fcnBookshelfContent');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
@ -534,6 +544,28 @@ _$$('[data-target="fcn-meta-field-ebook-remove"]').forEach(button => {
|
|||||||
// TOKENS META FIELD
|
// TOKENS META FIELD
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Split string into an array
|
||||||
|
*
|
||||||
|
* @since 5.7.4
|
||||||
|
*
|
||||||
|
* @param {string} list - The input string to split.
|
||||||
|
* @param {string} [separator=','] - The substring to use for splitting.
|
||||||
|
*
|
||||||
|
* @return {Array<string>} - An array of items.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function fcn_splitList(list, separator = ',') {
|
||||||
|
if (!list || list.trim() === '') {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
let array = list.replace(/\r?\n|\r/g, '').split(separator);
|
||||||
|
array = array.map(item => item.trim()).filter(item => item.length > 0);
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add or remove ID from token field
|
* Add or remove ID from token field
|
||||||
*
|
*
|
||||||
@ -551,7 +583,7 @@ function fcn_tokensToggle(id, parent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Setup
|
// Setup
|
||||||
const tokenOptions = JSON.parse(parent.querySelector('[data-target="fcn-meta-field-tokens-options"]').value);
|
const tokenOptions = FcnUtils.parseJSON(parent.querySelector('[data-target="fcn-meta-field-tokens-options"]').value);
|
||||||
const tokenTrack = parent.querySelector('[data-target="fcn-meta-field-tokens-track"]');
|
const tokenTrack = parent.querySelector('[data-target="fcn-meta-field-tokens-track"]');
|
||||||
const tokenInput = parent.querySelector('[data-target="fcn-meta-field-tokens-values"]');
|
const tokenInput = parent.querySelector('[data-target="fcn-meta-field-tokens-values"]');
|
||||||
const tokenValues = fcn_splitList(tokenInput.value).filter(item => !isNaN(item)).map(item => Math.abs(parseInt(item)));
|
const tokenValues = fcn_splitList(tokenInput.value).filter(item => !isNaN(item)).map(item => Math.abs(parseInt(item)));
|
||||||
@ -569,7 +601,7 @@ function fcn_tokensToggle(id, parent) {
|
|||||||
tokenTrack.innerHTML = '';
|
tokenTrack.innerHTML = '';
|
||||||
|
|
||||||
tokenValues.forEach(item => {
|
tokenValues.forEach(item => {
|
||||||
const name = fcn_sanitizeHTML(tokenOptions[item] ? tokenOptions[item] : item);
|
const name = FcnUtils.sanitizeHTML(tokenOptions[item] ? tokenOptions[item] : item);
|
||||||
|
|
||||||
tokenTrack.innerHTML += `<span class="fictioneer-meta-field__token" data-id="${item}"><span class="fictioneer-meta-field__token-name">${name}</span><button type="button" class="fictioneer-meta-field__token-button" data-id="${item}"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" focusable="false"><path d="M12 13.06l3.712 3.713 1.061-1.06L13.061 12l3.712-3.712-1.06-1.06L12 10.938 8.288 7.227l-1.061 1.06L10.939 12l-3.712 3.712 1.06 1.061L12 13.061z"></path></svg></button></span>`;
|
tokenTrack.innerHTML += `<span class="fictioneer-meta-field__token" data-id="${item}"><span class="fictioneer-meta-field__token-name">${name}</span><button type="button" class="fictioneer-meta-field__token-button" data-id="${item}"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" focusable="false"><path d="M12 13.06l3.712 3.713 1.061-1.06L13.061 12l3.712-3.712-1.06-1.06L12 10.938 8.288 7.227l-1.061 1.06L10.939 12l-3.712 3.712 1.06 1.061L12 13.061z"></path></svg></button></span>`;
|
||||||
});
|
});
|
||||||
@ -736,14 +768,14 @@ function fcn_setGroupDataList(source) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Request group options (if any)
|
// Request group options (if any)
|
||||||
fcn_ajaxGet({
|
FcnUtils.aGet({
|
||||||
'action': 'fictioneer_ajax_get_chapter_group_options',
|
'action': 'fictioneer_ajax_get_chapter_group_options',
|
||||||
'story_id': storyId,
|
'story_id': storyId,
|
||||||
'nonce': fictioneer_ajax.fictioneer_nonce
|
'nonce': fictioneer_ajax.fictioneer_nonce
|
||||||
})
|
})
|
||||||
.then(response => {
|
.then(response => {
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
const list = fcn_html`<datalist id="${listID}">${response.data.html}</datalist>>`;
|
const list = FcnUtils.html`<datalist id="${listID}">${response.data.html}</datalist>>`;
|
||||||
document.body.appendChild(list);
|
document.body.appendChild(list);
|
||||||
} else if (response.data.error) {
|
} else if (response.data.error) {
|
||||||
console.error('Error:', response.data.error);
|
console.error('Error:', response.data.error);
|
||||||
@ -973,7 +1005,7 @@ function fcn_queryRelationshipPosts(payload, container, append = true) {
|
|||||||
const selectedList = field.querySelector('[data-target="fcn-relationships-values"]');
|
const selectedList = field.querySelector('[data-target="fcn-relationships-values"]');
|
||||||
let errorMessage = null;
|
let errorMessage = null;
|
||||||
|
|
||||||
fcn_ajaxPost(payload)
|
FcnUtils.aPost(payload)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
// Remove observer (if any)
|
// Remove observer (if any)
|
||||||
container.querySelector('[data-target="fcn-relationships-observer"]')?.remove();
|
container.querySelector('[data-target="fcn-relationships-observer"]')?.remove();
|
||||||
@ -1164,7 +1196,7 @@ function fcn_unlockPostsSearch() {
|
|||||||
container.classList.add('ajax-in-progress');
|
container.classList.add('ajax-in-progress');
|
||||||
|
|
||||||
// Request
|
// Request
|
||||||
fcn_ajaxPost(payload)
|
FcnUtils.aPost(payload)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
results.innerHTML = response.data.html;
|
results.innerHTML = response.data.html;
|
||||||
@ -1268,7 +1300,7 @@ function fcn_intervalAction(trigger, action, payload = {}) {
|
|||||||
|
|
||||||
// Indicate process
|
// Indicate process
|
||||||
if (index < 1 || index >= goal) {
|
if (index < 1 || index >= goal) {
|
||||||
fcn_toggleInProgress(trigger, index < 1);
|
FcnUtils.toggleInProgress(trigger, index < 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index < goal) {
|
if (index < goal) {
|
||||||
@ -1281,7 +1313,7 @@ function fcn_intervalAction(trigger, action, payload = {}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Request
|
// Request
|
||||||
fcn_ajaxPost(payload)
|
FcnUtils.aPost(payload)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
if (!response?.data?.done) {
|
if (!response?.data?.done) {
|
||||||
fcn_intervalAction(
|
fcn_intervalAction(
|
||||||
|
@ -6,13 +6,9 @@ const fcn_bookshelfTarget = _$$$('ajax-bookshelf-target');
|
|||||||
|
|
||||||
// Initialize
|
// Initialize
|
||||||
if (fcn_bookshelfTarget) {
|
if (fcn_bookshelfTarget) {
|
||||||
if (fcn_theRoot.dataset.ajaxAuth) {
|
document.addEventListener('fcnUserDataReady', () => {
|
||||||
document.addEventListener('fcnAuthReady', () => {
|
|
||||||
fcn_updateBookshelfView();
|
fcn_updateBookshelfView();
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
fcn_updateBookshelfView();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
@ -23,11 +19,10 @@ if (fcn_bookshelfTarget) {
|
|||||||
* Get bookshelf content from web storage or create new JSON.
|
* Get bookshelf content from web storage or create new JSON.
|
||||||
*
|
*
|
||||||
* @since 4.3.0
|
* @since 4.3.0
|
||||||
* @see fcn_parseJSON()
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function fcn_getBookshelfContent() {
|
function fcn_getBookshelfContent() {
|
||||||
return fcn_parseJSON(localStorage.getItem('fcnBookshelfContent')) ?? { html: {}, count: {} };
|
return FcnUtils.parseJSON(localStorage.getItem('fcnBookshelfContent')) ?? { html: {}, count: {} };
|
||||||
}
|
}
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
@ -104,7 +99,7 @@ function fcn_browseBookshelfPage(page) {
|
|||||||
history.pushState(
|
history.pushState(
|
||||||
{},
|
{},
|
||||||
'',
|
'',
|
||||||
fcn_buildUrl({
|
FcnUtils.buildUrl({
|
||||||
tab: fcn_bookshelfTarget.dataset.tab,
|
tab: fcn_bookshelfTarget.dataset.tab,
|
||||||
pg: page,
|
pg: page,
|
||||||
order: fcn_bookshelfTarget.dataset.order
|
order: fcn_bookshelfTarget.dataset.order
|
||||||
@ -131,7 +126,7 @@ function fcn_fetchBookshelfPart(action, page, order, scroll = false) {
|
|||||||
const storage = fcn_getBookshelfContent();
|
const storage = fcn_getBookshelfContent();
|
||||||
|
|
||||||
// Request
|
// Request
|
||||||
fcn_ajaxGet({
|
FcnUtils.aGet({
|
||||||
'action': action,
|
'action': action,
|
||||||
'fcn_fast_ajax': 1,
|
'fcn_fast_ajax': 1,
|
||||||
'page': page,
|
'page': page,
|
||||||
@ -152,7 +147,7 @@ function fcn_fetchBookshelfPart(action, page, order, scroll = false) {
|
|||||||
_$('.item-number').innerHTML = `(${response.data.count})`;
|
_$('.item-number').innerHTML = `(${response.data.count})`;
|
||||||
} else {
|
} else {
|
||||||
fcn_bookshelfTarget.innerHTML = '';
|
fcn_bookshelfTarget.innerHTML = '';
|
||||||
fcn_bookshelfTarget.appendChild(fcn_buildErrorNotice(response.data.error));
|
fcn_bookshelfTarget.appendChild(FcnUtils.buildErrorNotice(response.data.error));
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
@ -161,7 +156,7 @@ function fcn_fetchBookshelfPart(action, page, order, scroll = false) {
|
|||||||
fcn_bookshelfTarget.innerHTML = '';
|
fcn_bookshelfTarget.innerHTML = '';
|
||||||
|
|
||||||
// Add error message
|
// Add error message
|
||||||
fcn_bookshelfTarget.appendChild(fcn_buildErrorNotice(`${error.status}: ${error.statusText}`));
|
fcn_bookshelfTarget.appendChild(FcnUtils.buildErrorNotice(`${error.status}: ${error.statusText}`));
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Regardless of outcome
|
// Regardless of outcome
|
||||||
|
@ -32,7 +32,7 @@ function fcn_getCommentSection(post_id = null, page = null, order = null, scroll
|
|||||||
|
|
||||||
// Setup
|
// Setup
|
||||||
let commentText = '';
|
let commentText = '';
|
||||||
let commentTextarea = _$(fictioneer_comments.form_selector ?? '#comment');
|
let commentTextarea = _$(FcnGlobals.commentFormSelector);
|
||||||
let errorNote;
|
let errorNote;
|
||||||
|
|
||||||
// Preserve comment text (in case of pagination)
|
// Preserve comment text (in case of pagination)
|
||||||
@ -50,7 +50,7 @@ function fcn_getCommentSection(post_id = null, page = null, order = null, scroll
|
|||||||
|
|
||||||
// Get page
|
// Get page
|
||||||
if (!page) {
|
if (!page) {
|
||||||
page = fcn_urlParams.pg ?? 1;
|
page = FcnGlobals.urlParams.pg ?? 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get order
|
// Get order
|
||||||
@ -72,12 +72,12 @@ function fcn_getCommentSection(post_id = null, page = null, order = null, scroll
|
|||||||
'fcn_fast_comment_ajax': 1
|
'fcn_fast_comment_ajax': 1
|
||||||
};
|
};
|
||||||
|
|
||||||
if (fcn_urlParams.commentcode) {
|
if (FcnGlobals.urlParams.commentcode) {
|
||||||
payload['commentcode'] = fcn_urlParams.commentcode;
|
payload['commentcode'] = FcnGlobals.urlParams.commentcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Request
|
// Request
|
||||||
fcn_ajaxGet(payload)
|
FcnUtils.aGet(payload)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
// Check for success
|
// Check for success
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
@ -106,7 +106,7 @@ function fcn_getCommentSection(post_id = null, page = null, order = null, scroll
|
|||||||
temp.remove();
|
temp.remove();
|
||||||
|
|
||||||
// Append stored content (in case of pagination)
|
// Append stored content (in case of pagination)
|
||||||
commentTextarea = _$(fictioneer_comments.form_selector ?? '#comment'); // Yes, query again!
|
commentTextarea = _$(FcnGlobals.commentFormSelector); // Yes, query again!
|
||||||
|
|
||||||
if (commentTextarea && !response.data.disabled) {
|
if (commentTextarea && !response.data.disabled) {
|
||||||
commentTextarea.value = commentText;
|
commentTextarea.value = commentText;
|
||||||
@ -115,18 +115,6 @@ function fcn_getCommentSection(post_id = null, page = null, order = null, scroll
|
|||||||
fcn_applyCommentStack(commentTextarea);
|
fcn_applyCommentStack(commentTextarea);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind events
|
|
||||||
fcn_addCommentMouseleaveEvents();
|
|
||||||
fcn_addCommentFormEvents();
|
|
||||||
fcn_bindAJAXCommentSubmit();
|
|
||||||
|
|
||||||
// JS trap (if active)
|
|
||||||
fcn_addJSTrap();
|
|
||||||
|
|
||||||
// Reveal edit/delete buttons
|
|
||||||
fcn_revealEditButton();
|
|
||||||
fcn_revealDeleteButton();
|
|
||||||
|
|
||||||
// Scroll to top of comment section
|
// Scroll to top of comment section
|
||||||
const scrollTargetSelector = location.hash.includes('#comment') ? location.hash : '.respond';
|
const scrollTargetSelector = location.hash.includes('#comment') ? location.hash : '.respond';
|
||||||
const scrollTarget = document.querySelector(scrollTargetSelector) ?? _$$$('respond');
|
const scrollTarget = document.querySelector(scrollTargetSelector) ?? _$$$('respond');
|
||||||
@ -138,15 +126,15 @@ function fcn_getCommentSection(post_id = null, page = null, order = null, scroll
|
|||||||
// Add page to URL and preserve params/anchor
|
// Add page to URL and preserve params/anchor
|
||||||
const refresh = window.location.protocol + '//' + window.location.host + window.location.pathname;
|
const refresh = window.location.protocol + '//' + window.location.host + window.location.pathname;
|
||||||
|
|
||||||
if (page > 1 || fcn_urlParams.pg) {
|
if (page > 1 || FcnGlobals.urlParams.pg) {
|
||||||
fcn_urlParams['pg'] = page;
|
FcnGlobals.urlParams['pg'] = page;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (order != 'desc' || fcn_urlParams.corder) {
|
if (order != 'desc' || FcnGlobals.urlParams.corder) {
|
||||||
fcn_urlParams['corder'] = order;
|
FcnGlobals.urlParams['corder'] = order;
|
||||||
}
|
}
|
||||||
|
|
||||||
let params = Object.entries(fcn_urlParams).map(([key, value]) => `${key}=${value}`).join('&');
|
let params = Object.entries(FcnGlobals.urlParams).map(([key, value]) => `${key}=${value}`).join('&');
|
||||||
|
|
||||||
if (params !== '') {
|
if (params !== '') {
|
||||||
params = `?${params}`;
|
params = `?${params}`;
|
||||||
@ -154,11 +142,11 @@ function fcn_getCommentSection(post_id = null, page = null, order = null, scroll
|
|||||||
|
|
||||||
window.history.pushState({ path: refresh }, '', refresh + params + location.hash);
|
window.history.pushState({ path: refresh }, '', refresh + params + location.hash);
|
||||||
} else {
|
} else {
|
||||||
errorNote = fcn_buildErrorNotice(response.data.error); // Also writes to the console
|
errorNote = FcnUtils.buildErrorNotice(response.data.error); // Also writes to the console
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
errorNote = fcn_buildErrorNotice(error); // Also writes to the console
|
errorNote = FcnUtils.buildErrorNotice(error); // Also writes to the console
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Update view regardless of success
|
// Update view regardless of success
|
||||||
@ -204,14 +192,9 @@ function fcn_jumpToCommentPage() {
|
|||||||
|
|
||||||
var /** @type {IntersectionObserver} */ fct_commentSectionObserver;
|
var /** @type {IntersectionObserver} */ fct_commentSectionObserver;
|
||||||
|
|
||||||
// In case of AJAX authentication...
|
document.addEventListener('fcnUserDataReady', () => {
|
||||||
if (fcn_theRoot.dataset.ajaxAuth) {
|
|
||||||
document.addEventListener('fcnAuthReady', () => {
|
|
||||||
fcn_setupCommentSectionObserver();
|
fcn_setupCommentSectionObserver();
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
fcn_setupCommentSectionObserver();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper to set up comment section observer.
|
* Helper to set up comment section observer.
|
||||||
@ -240,14 +223,9 @@ function fcn_setupCommentSectionObserver() {
|
|||||||
// SCROLL NEW COMMENT INTO VIEW SUBMITTING VIA RELOAD
|
// SCROLL NEW COMMENT INTO VIEW SUBMITTING VIA RELOAD
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
// In case of AJAX authentication...
|
document.addEventListener('fcnUserDataReady', () => {
|
||||||
if (fcn_theRoot.dataset.ajaxAuth) {
|
|
||||||
document.addEventListener('fcnAuthReady', () => {
|
|
||||||
fcn_loadCommentEarly();
|
fcn_loadCommentEarly();
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
fcn_loadCommentEarly();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load comment section early if there is a comment* anchor.
|
* Load comment section early if there is a comment* anchor.
|
||||||
@ -259,7 +237,7 @@ function fcn_loadCommentEarly() {
|
|||||||
// Check URL whether there is a comment anchor
|
// Check URL whether there is a comment anchor
|
||||||
if (fcn_commentSection && location.hash.includes('#comment')) {
|
if (fcn_commentSection && location.hash.includes('#comment')) {
|
||||||
// Start loading comments via AJAX if not done already
|
// Start loading comments via AJAX if not done already
|
||||||
if (!_$(fictioneer_comments.form_selector ?? '#comment')) {
|
if (!_$(FcnGlobals.commentFormSelector)) {
|
||||||
fct_commentSectionObserver.disconnect();
|
fct_commentSectionObserver.disconnect();
|
||||||
fcn_reloadCommentsPage();
|
fcn_reloadCommentsPage();
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,567 +1,181 @@
|
|||||||
// =============================================================================
|
// =============================================================================
|
||||||
// BOOKMARKS
|
// STIMULUS: FICTIONEER BOOKMARKS
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
const /** @const {HTMLElement[]} */ fcn_jumpToBookmarkButtons = _$$('.button--bookmark');
|
application.register('fictioneer-bookmarks', class extends Stimulus.Controller {
|
||||||
const /** @const {HTMLElement} */ fcn_mobileBookmarkJump = _$$$('mobile-menu-bookmark-jump');
|
static get targets() {
|
||||||
const /** @const {HTMLElement} */ fcn_mobileBookmarkList = _$('.mobile-menu__bookmark-list');
|
return ['bookmarkScroll', 'shortcodeBlock', 'dataCard', 'overviewPageIconLink', 'noBookmarksNote']
|
||||||
const /** @const {HTMLElement} */ fcn_bookmarksSmallCardBlock = _$('.bookmarks-block');
|
|
||||||
const /** @const {HTMLElement} */ fcn_bookmarksSmallCardTemplate = _$('.bookmark-small-card-template');
|
|
||||||
|
|
||||||
var /** @type {Object} */ fcn_bookmarks;
|
|
||||||
var /** @type {Number} */ fcn_userBookmarksTimeout;
|
|
||||||
|
|
||||||
// Initialize
|
|
||||||
fcn_initializeLocalBookmarks();
|
|
||||||
|
|
||||||
document.addEventListener('fcnUserDataReady', event => {
|
|
||||||
fcn_initializeUserBookmarks(event);
|
|
||||||
});
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
// INITIALIZE
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize local bookmarks.
|
|
||||||
*
|
|
||||||
* @description Looks for bookmarks in local storage, both for guests and logged-in
|
|
||||||
* users. If none are found, an empty bookmarks JSON is created and set.
|
|
||||||
*
|
|
||||||
* @since 4.0.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
function fcn_initializeLocalBookmarks() {
|
|
||||||
// Look for bookmarks in local storage
|
|
||||||
fcn_bookmarks = fcn_getBookmarks();
|
|
||||||
|
|
||||||
// Always update bookmarks in storage
|
|
||||||
fcn_setBookmarks(fcn_bookmarks, true);
|
|
||||||
|
|
||||||
// Update view
|
|
||||||
fcn_updateBookmarksView();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize bookmarks for logged-in users.
|
|
||||||
*
|
|
||||||
* @since 5.7.0
|
|
||||||
* @param {Event} event - The fcnUserDataReady event.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function fcn_initializeUserBookmarks(event) {
|
|
||||||
// Always update bookmarks in storage
|
|
||||||
fcn_setBookmarks(JSON.parse(event.detail.data.bookmarks), true);
|
|
||||||
|
|
||||||
// Update view
|
|
||||||
fcn_updateBookmarksView();
|
|
||||||
}
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
// GET BOOKMARKS
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get bookmarks from local storage.
|
|
||||||
*
|
|
||||||
* @since 5.7.0
|
|
||||||
* @see fcn_parseJSON()
|
|
||||||
* @return {Object} The bookmarks JSON.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function fcn_getBookmarks() {
|
|
||||||
let bookmarks = fcn_parseJSON(localStorage.getItem('fcnChapterBookmarks')) ?? { 'data': {} };
|
|
||||||
|
|
||||||
// Fix empty array that should be an object
|
|
||||||
if (Array.isArray(bookmarks.data) && bookmarks.data.length === 0) {
|
|
||||||
bookmarks.data = {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate and sanitize
|
timeout = 0;
|
||||||
bookmarks = fcn_fixBookmarks(bookmarks);
|
chapterId = _$('.chapter__article')?.id;
|
||||||
|
currentBookmark = null;
|
||||||
|
cardTemplate = _$('.bookmark-small-card-template');
|
||||||
|
|
||||||
// Last check and return
|
initialize() {
|
||||||
return (!bookmarks || Object.keys(bookmarks).length < 1) ? { 'data': {} } : bookmarks;
|
if (fcn()?.userReady || !FcnUtils.loggedIn()) {
|
||||||
}
|
this.#ready = true;
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
// VALIDATE & SANITIZE BOOKMARKS
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fixes bookmarks to only contain valid data.
|
|
||||||
*
|
|
||||||
* @since 5.7.4
|
|
||||||
* @param {JSON} bookmarks - The bookmarks JSON to be fixed.
|
|
||||||
* @return {JSON} The fixed bookmarks JSON.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function fcn_fixBookmarks(bookmarks) {
|
|
||||||
const fixedData = {};
|
|
||||||
|
|
||||||
for (const key in bookmarks.data) {
|
|
||||||
if (key.startsWith('ch-')) {
|
|
||||||
const node = fcn_fixBookmarksNode(bookmarks.data[key]);
|
|
||||||
|
|
||||||
if (node) {
|
|
||||||
fixedData[key] = node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return { data: fixedData };
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fixes a bookmark child node.
|
|
||||||
*
|
|
||||||
* @since 5.7.4
|
|
||||||
* @param {JSON} node - The child node to be fixed.
|
|
||||||
* @return {JSON} The fixed child node.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function fcn_fixBookmarksNode(node) {
|
|
||||||
const fixedNode = {};
|
|
||||||
const structure = {
|
|
||||||
'paragraph-id': '',
|
|
||||||
'progress': 0.0,
|
|
||||||
'date': '',
|
|
||||||
'color': '',
|
|
||||||
'chapter': '',
|
|
||||||
'link': '',
|
|
||||||
'thumb': '',
|
|
||||||
'image': '',
|
|
||||||
'story': '',
|
|
||||||
'content': ''
|
|
||||||
};
|
|
||||||
|
|
||||||
// Check structure and only leave allowed nodes
|
|
||||||
for (const key in structure) {
|
|
||||||
if (typeof node[key] === typeof structure[key]) {
|
|
||||||
fixedNode[key] = node[key];
|
|
||||||
} else {
|
} else {
|
||||||
return null;
|
document.addEventListener('fcnUserDataReady', () => {
|
||||||
}
|
this.#ready = true;
|
||||||
}
|
|
||||||
|
|
||||||
// Check date
|
this.refreshView();
|
||||||
const date = new Date(fixedNode['date']);
|
this.#watch();
|
||||||
|
|
||||||
if (!date || Object.prototype.toString.call(date) !== "[object Date]" || isNaN(date)) {
|
|
||||||
fixedNode['date'] = (new Date()).toISOString(); // This happens anyway when stringified
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check progress
|
|
||||||
if (typeof fixedNode['progress'] !== 'number' || fixedNode['progress'] < 0) {
|
|
||||||
fixedNode['progress'] = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Done
|
|
||||||
return fixedNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
// SET BOOKMARKS
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Save bookmarks to local storage (and database).
|
|
||||||
*
|
|
||||||
* @description Saves the bookmarks JSON to local storage, overriding any previous
|
|
||||||
* instance. If not set to silent, an update to the database is called as well,
|
|
||||||
* clearing the timeout of any previous enqueued update to avoid unnecessary
|
|
||||||
* requests. Since the bookmarks are always saved as complete collection, yet
|
|
||||||
* unfinished requests can be cancelled without loss of data.
|
|
||||||
*
|
|
||||||
* @since 4.0.0
|
|
||||||
* @see fcn_saveUserBookmarks()
|
|
||||||
* @param {Object} value - The bookmarks JSON to be set.
|
|
||||||
* @param {Boolean} [silent=false] - Whether or not to update the database.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function fcn_setBookmarks(value, silent = false) {
|
|
||||||
// Make sure this is a JSON object
|
|
||||||
if (typeof value !== 'object') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keep global updated
|
|
||||||
fcn_bookmarks = value;
|
|
||||||
localStorage.setItem('fcnChapterBookmarks', JSON.stringify(value));
|
|
||||||
|
|
||||||
// Keep user data updated as well
|
|
||||||
if (fcn_isLoggedIn) {
|
|
||||||
const currentUserData = fcn_getUserData();
|
|
||||||
|
|
||||||
if (currentUserData) {
|
|
||||||
currentUserData.bookmarks = JSON.stringify(value);
|
|
||||||
fcn_setUserData(currentUserData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do not save to database if silent update
|
|
||||||
if (silent) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update database for user
|
|
||||||
fcn_saveUserBookmarks(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
// UPDATE BOOKMARKS VIEW
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the view with the current Bookmarks state.
|
|
||||||
*
|
|
||||||
* @since 5.7.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
function fcn_updateBookmarksView() {
|
|
||||||
// Abort if bookmarks are not set
|
|
||||||
if (!fcn_bookmarks || !fcn_bookmarks.data) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup
|
|
||||||
const stats = _$('.profile-bookmarks-stats'),
|
|
||||||
count = Object.keys(fcn_bookmarks.data).length;
|
|
||||||
|
|
||||||
// Insert bookmarks count on user profile page
|
|
||||||
if (stats) {
|
|
||||||
stats.innerHTML = stats.innerHTML.replace('%s', count);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bookmark icons
|
|
||||||
if (count > 0) {
|
|
||||||
_$$('.icon-menu-bookmarks').forEach(element => {
|
|
||||||
element.classList.remove('hidden');
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Render bookmark cards if already logged-in
|
connect() {
|
||||||
fcn_showBookmarkCards();
|
window.FictioneerApp.Controllers.fictioneerBookmarks = this;
|
||||||
|
|
||||||
// Chapter bookmark
|
if (this.#ready) {
|
||||||
fcn_showChapterBookmark();
|
this.refreshView();
|
||||||
}
|
this.#watch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// =============================================================================
|
data() {
|
||||||
// SAVE USER BOOKMARKS
|
this.bookmarksCachedData = FcnUtils.loggedIn() ? this.#getUserBookmarks() : this.#getLocalBookmarks();
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
/**
|
return this.#fixBookmarks(this.bookmarksCachedData).data;
|
||||||
* Save bookmarks JSON to the database via AJAX.
|
}
|
||||||
*
|
|
||||||
* @description Saves the bookmarks JSON to the database if an user is logged in,
|
|
||||||
* otherwise the function aborts to avoid unnecessary requests. This can only
|
|
||||||
* happen once every n seconds, as set by the timeout interval, to avoid further
|
|
||||||
* unnecessary requests in case someone triggers multiple updates.
|
|
||||||
*
|
|
||||||
* @since 4.0.0
|
|
||||||
* @param {JSON} bookmarks - The bookmarks JSON to be saved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function fcn_saveUserBookmarks(bookmarks) {
|
toggle(paragraphId, color = 'none') {
|
||||||
// Do not proceed if not logged in
|
if (!this.chapterId) {
|
||||||
if (!fcn_isLoggedIn) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear previous timeout (if still pending)
|
const bookmarksData = this.data();
|
||||||
clearTimeout(fcn_userBookmarksTimeout);
|
const currentBookmark = bookmarksData[this.chapterId];
|
||||||
|
|
||||||
// Validate and sanitize
|
if (currentBookmark && currentBookmark['paragraph-id'] == paragraphId) {
|
||||||
bookmarks = fcn_fixBookmarks(bookmarks);
|
if (color !== 'none' && color !== currentBookmark['color']) {
|
||||||
|
bookmarksData[this.chapterId]['color'] = color;
|
||||||
// Only one save request every n seconds
|
|
||||||
fcn_userBookmarksTimeout = setTimeout(() => {
|
|
||||||
fcn_ajaxPost({
|
|
||||||
'action': 'fictioneer_ajax_save_bookmarks',
|
|
||||||
'fcn_fast_ajax': 1,
|
|
||||||
'bookmarks': JSON.stringify(bookmarks)
|
|
||||||
})
|
|
||||||
.then(response => {
|
|
||||||
if (!response.success) {
|
|
||||||
fcn_showNotification(
|
|
||||||
response.data.failure ?? response.data.error ?? fictioneer_tl.notification.error,
|
|
||||||
3,
|
|
||||||
'warning'
|
|
||||||
);
|
|
||||||
|
|
||||||
// Make sure the actual error (if any) is printed to the console too
|
|
||||||
if (response.data.error || response.data.failure) {
|
|
||||||
console.error('Error:', response.data.error ?? response.data.failure);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
if (error.status && error.statusText) {
|
|
||||||
fcn_showNotification(`${error.status}: ${error.statusText}`, 3, 'warning');
|
|
||||||
}
|
|
||||||
|
|
||||||
console.error(error);
|
|
||||||
});
|
|
||||||
}, fictioneer_ajax.post_debounce_rate); // Debounce synchronization
|
|
||||||
}
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
// TOGGLE BOOKMARKS
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Toggle bookmark on chapter pages.
|
|
||||||
*
|
|
||||||
* @description Toggles a chapter bookmark, either saving all relevant data in
|
|
||||||
* the bookmarks JSON or removing them. Updates any available buttons, lists,
|
|
||||||
* and calls to persist the updated JSON.
|
|
||||||
*
|
|
||||||
* @since 4.0.0
|
|
||||||
* @see fcn_getBookmarks()
|
|
||||||
* @see fcn_removeBookmark()
|
|
||||||
* @see fcn_offset()
|
|
||||||
* @see fcn_setMobileMenuBookmarks()
|
|
||||||
* @see fcn_setBookmarks()
|
|
||||||
* @param {Number} id - The ID of the chapter.
|
|
||||||
* @param {String} [color=none] - The color of the bookmark.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function fcn_toggleBookmark(id, color = 'none') {
|
|
||||||
// Synchronize with local storage again
|
|
||||||
fcn_bookmarks = fcn_getBookmarks();
|
|
||||||
|
|
||||||
// Get article node with chapter data
|
|
||||||
const chapter = _$('.chapter__article');
|
|
||||||
const currentBookmark = _$('.current-bookmark');
|
|
||||||
|
|
||||||
// Check whether an article has been found or abort
|
|
||||||
if (!chapter) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look for existing bookmark...
|
|
||||||
const b = fcn_bookmarks.data[chapter.id];
|
|
||||||
|
|
||||||
// Add, update, or remove bookmark...
|
|
||||||
if (b && b['paragraph-id'] == id && currentBookmark) {
|
|
||||||
if (color != 'none' && color != b['color']) {
|
|
||||||
// --- Update bookmark color ---------------------------------------------
|
|
||||||
_$('.current-bookmark').dataset.bookmarkColor = color;
|
|
||||||
b['color'] = color;
|
|
||||||
} else {
|
} else {
|
||||||
// --- Remove bookmark ---------------------------------------------------
|
delete bookmarksData[this.chapterId];
|
||||||
fcn_removeBookmark(chapter.id);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// --- Add new bookmark ----------------------------------------------------
|
if (Object.keys(bookmarksData).length >= 50) {
|
||||||
|
delete bookmarksData[Object.keys(bookmarksData)[0]];
|
||||||
// Maximum of 50 bookmarks
|
|
||||||
if (Object.keys(fcn_bookmarks.data).length >= 50) {
|
|
||||||
// Remove oldest
|
|
||||||
fcn_removeBookmark(Object.keys(fcn_bookmarks.data)[0]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup
|
const p = _$(`[data-paragraph-id="${paragraphId}"]`);
|
||||||
const p = _$(`[data-paragraph-id="${id}"]`);
|
const chapterBookmarkData = _$$$('chapter-bookmark-data').dataset;
|
||||||
const fcn_chapterBookmarkData = _$$$('chapter-bookmark-data').dataset;
|
|
||||||
|
|
||||||
// Add data node (chapter-id: {}) to bookmarks JSON
|
bookmarksData[this.chapterId] = {
|
||||||
fcn_bookmarks.data[chapter.id] = {
|
'paragraph-id': paragraphId,
|
||||||
'paragraph-id': id,
|
'progress': (FcnUtils.offset(p).top - FcnUtils.offset(p.parentElement).top) * 100 / p.parentElement.clientHeight,
|
||||||
'progress': (fcn_offset(p).top - fcn_offset(p.parentElement).top) * 100 / p.parentElement.clientHeight,
|
|
||||||
'date': (new Date()).toISOString(), // This happens anyway when stringified
|
'date': (new Date()).toISOString(), // This happens anyway when stringified
|
||||||
'color': color,
|
'color': color,
|
||||||
'chapter': fcn_chapterBookmarkData.title.trim(),
|
'chapter': chapterBookmarkData.title.trim(),
|
||||||
'link': fcn_chapterBookmarkData.link,
|
'link': chapterBookmarkData.link,
|
||||||
'thumb': fcn_chapterBookmarkData.thumb,
|
'thumb': chapterBookmarkData.thumb,
|
||||||
'image': fcn_chapterBookmarkData.image,
|
'image': chapterBookmarkData.image,
|
||||||
'story': fcn_chapterBookmarkData.storyTitle.trim(),
|
'story': chapterBookmarkData.storyTitle.trim(),
|
||||||
'content': p.querySelector('span').innerHTML.substring(0, 128) + '…'
|
'content': FcnUtils.extractTextNodes(p).substring(0, 128) + '…'
|
||||||
};
|
};
|
||||||
|
|
||||||
// Reveal jump buttons
|
|
||||||
fcn_jumpToBookmarkButtons.forEach(element => {
|
|
||||||
element.classList.remove('hidden');
|
|
||||||
});
|
|
||||||
|
|
||||||
fcn_mobileBookmarkJump?.removeAttribute('hidden');
|
|
||||||
|
|
||||||
// Remove current-bookmark class from previous paragraph (if any)
|
|
||||||
currentBookmark?.classList.remove('current-bookmark');
|
|
||||||
|
|
||||||
// Add new current-bookmark class to paragraph
|
|
||||||
p.classList.add('current-bookmark');
|
|
||||||
p.setAttribute('data-bookmark-color', color);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset HTML in mobile menu
|
this.set(bookmarksData);
|
||||||
fcn_setMobileMenuBookmarks();
|
this.refreshView();
|
||||||
|
}
|
||||||
|
|
||||||
// Save bookmarks
|
remove({ params: { id } }) {
|
||||||
fcn_setBookmarks(fcn_bookmarks);
|
const bookmarksData = this.data();
|
||||||
}
|
|
||||||
|
|
||||||
// =============================================================================
|
delete bookmarksData[id];
|
||||||
// SHOW CHAPTER BOOKMARK
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
/**
|
this.set(bookmarksData);
|
||||||
* Shows the bookmark on a chapter page.
|
this.refreshView();
|
||||||
*
|
}
|
||||||
* @description If the current page is a chapter and has a bookmark, the
|
|
||||||
* 'current-bookmark' class is added to the bookmarked paragraph to show
|
|
||||||
* the colored bookmark line and the jump buttons are revealed.
|
|
||||||
*
|
|
||||||
* @since 4.0.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
function fcn_showChapterBookmark() {
|
clear() {
|
||||||
// Cleanup (in case of error)
|
this.set({ data: {} });
|
||||||
_$('.current-bookmark')?.classList.remove('current-bookmark');
|
this.refreshView();
|
||||||
|
}
|
||||||
|
|
||||||
// Get current chapter node
|
set(data) {
|
||||||
const chapter = _$('.chapter__article');
|
if (typeof data !== 'object') {
|
||||||
|
|
||||||
// Abort if not a chapter or no bookmark set for chapter
|
|
||||||
if (!chapter || !fcn_bookmarks.data[chapter.id]) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect necessary data to show bookmark in chapter
|
data = this.#fixBookmarks({ data: data });
|
||||||
const id = fcn_bookmarks.data[chapter.id]['paragraph-id'];
|
const stringifiedBookmarks = JSON.stringify(data);
|
||||||
const p = _$(`[data-paragraph-id="${id}"]`);
|
|
||||||
const color = fcn_bookmarks.data[chapter.id]['color'] ?? 'none';
|
|
||||||
|
|
||||||
// If bookmarked paragraph has been found...
|
if (FcnUtils.loggedIn()) {
|
||||||
if (id && p) {
|
const userData = fcn().userData();
|
||||||
// Reveal bookmark jump buttons in chapter
|
|
||||||
fcn_jumpToBookmarkButtons.forEach(element => {
|
|
||||||
element.classList.remove('hidden');
|
|
||||||
});
|
|
||||||
|
|
||||||
// Reveal bookmark jump button in mobile menu
|
if (userData) {
|
||||||
fcn_mobileBookmarkJump?.removeAttribute('hidden');
|
userData.bookmarks = stringifiedBookmarks;
|
||||||
|
|
||||||
// Add bookmark line and color
|
fcn().setUserData(userData);
|
||||||
p.classList.add('current-bookmark');
|
|
||||||
p.setAttribute('data-bookmark-color', color);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// =============================================================================
|
this.#upload(stringifiedBookmarks);
|
||||||
// SET MOBILE MENU BOOKMARKS
|
localStorage.removeItem('fcnChapterBookmarks');
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set up bookmarks frame in mobile menu.
|
|
||||||
*
|
|
||||||
* @description Clears any previous HTML and rebuilds the bookmarks list for the
|
|
||||||
* mobile menu (usually when a new bookmark is added or the menu panel opened for
|
|
||||||
* the first time per page load).
|
|
||||||
*
|
|
||||||
* @since 4.0.0
|
|
||||||
* @since 5.9.4 - Refactored with DocumentFragment.
|
|
||||||
* @see fcn_bookmarkDeleteHandler()
|
|
||||||
*/
|
|
||||||
|
|
||||||
function fcn_setMobileMenuBookmarks() {
|
|
||||||
// Clear target container of previous entries
|
|
||||||
fcn_mobileBookmarkList.innerHTML = '';
|
|
||||||
|
|
||||||
const bookmarks = Object.entries(fcn_bookmarks.data);
|
|
||||||
const template = _$('#mobile-bookmark-template');
|
|
||||||
|
|
||||||
if (bookmarks.length > 0) {
|
|
||||||
// Use fragment to collect nodes
|
|
||||||
const fragment = document.createDocumentFragment();
|
|
||||||
|
|
||||||
// Append bookmarks to fragment
|
|
||||||
bookmarks.forEach(([id, { color, progress, link, chapter, 'paragraph-id': paragraphId }]) => {
|
|
||||||
const clone = template.content.cloneNode(true);
|
|
||||||
const bookmarkElement = clone.querySelector('.mobile-menu__bookmark');
|
|
||||||
|
|
||||||
bookmarkElement.classList.add(`bookmark-${id}`);
|
|
||||||
bookmarkElement.dataset.color = color;
|
|
||||||
clone.querySelector('.mobile-menu__bookmark-progress > div > div').style.width = `${progress.toFixed(1)}%`;
|
|
||||||
clone.querySelector('.mobile-menu__bookmark a').href = `${link}#paragraph-${paragraphId}`;
|
|
||||||
clone.querySelector('.mobile-menu__bookmark a span').innerText = chapter;
|
|
||||||
clone.querySelector('.mobile-menu-bookmark-delete-button').setAttribute('data-bookmark-id', id);
|
|
||||||
|
|
||||||
fragment.appendChild(clone);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Append fragment to DOM
|
|
||||||
fcn_mobileBookmarkList.appendChild(fragment);
|
|
||||||
|
|
||||||
// Register events for delete buttons
|
|
||||||
fcn_bookmarkDeleteHandler(_$$('.mobile-menu-bookmark-delete-button'));
|
|
||||||
} else {
|
} else {
|
||||||
// No bookmarks found!
|
localStorage.setItem('fcnChapterBookmarks', stringifiedBookmarks);
|
||||||
const node = document.createElement('li');
|
}
|
||||||
|
|
||||||
// Create text node with notice
|
|
||||||
node.classList.add('no-bookmarks');
|
|
||||||
node.textContent = fcn_mobileBookmarkList.dataset.empty;
|
|
||||||
|
|
||||||
// Append node
|
|
||||||
fcn_mobileBookmarkList.appendChild(node);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// =============================================================================
|
refreshView() {
|
||||||
// BOOKMARK CARDS
|
const bookmarksData = this.data();
|
||||||
// =============================================================================
|
const count = Object.keys(bookmarksData).length;
|
||||||
|
|
||||||
/**
|
if (this.hasOverviewPageIconLinkTarget) {
|
||||||
* Renders bookmark cards within the bookmarks block if provided.
|
this.overviewPageIconLinkTargets.forEach(element => {
|
||||||
*
|
element.classList.toggle('hidden', count < 1);
|
||||||
* @description If the current page has a bookmarks card block and template
|
});
|
||||||
* (via shortcode), bookmarks are rendered as cards up to the count specified
|
}
|
||||||
* in the block as data-attribute (or all for -1).
|
|
||||||
*
|
|
||||||
* @since 4.0.0
|
|
||||||
* @since 5.9.4 - Refactored with DocumentFragment.
|
|
||||||
* @see fcn_bookmarkDeleteHandler()
|
|
||||||
*/
|
|
||||||
|
|
||||||
function fcn_showBookmarkCards() {
|
this.refreshChapterBookmark();
|
||||||
// Check whether bookmark cards need to be rendered
|
this.refreshCards();
|
||||||
if (
|
this.refreshProfile();
|
||||||
!fcn_bookmarks ||
|
}
|
||||||
!fcn_bookmarksSmallCardBlock ||
|
|
||||||
!fcn_bookmarksSmallCardTemplate ||
|
refreshCards() {
|
||||||
Object.keys(fcn_bookmarks.data).length < 1 ||
|
if (!this.hasShortcodeBlockTarget) {
|
||||||
_$('.bookmark-card')
|
|
||||||
) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make elements visible (if any)
|
const bookmarksData = this.data();
|
||||||
fcn_bookmarksSmallCardBlock.classList.remove('hidden');
|
const hidden = Object.keys(bookmarksData).length < 1;
|
||||||
_$('.bookmarks-block__no-bookmarks')?.remove();
|
|
||||||
_$$('.show-if-bookmarks').forEach(element => element.classList.remove('hidden'));
|
|
||||||
|
|
||||||
// Max number of rendered bookmarks (-1 for all)
|
this.shortcodeBlockTargets.forEach(element => {
|
||||||
let count = parseInt(fcn_bookmarksSmallCardBlock.dataset.count);
|
element.classList.toggle('hidden', hidden);
|
||||||
|
});
|
||||||
|
|
||||||
// Use fragment to collect nodes
|
_$$('.show-if-bookmarks').forEach(element => {
|
||||||
|
element.classList.toggle('hidden', hidden);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (this.hasNoBookmarksNoteTarget) {
|
||||||
|
this.noBookmarksNoteTargets.forEach(element => {
|
||||||
|
element.classList.toggle('hidden', !hidden);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hidden || !this.cardTemplate) {
|
||||||
|
this.shortcodeBlockTargets.forEach(block => {
|
||||||
|
block.querySelector('ul').innerHTML = '';
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.shortcodeBlockTargets.forEach(block => {
|
||||||
|
const ul = block.querySelector('ul');
|
||||||
const fragment = document.createDocumentFragment();
|
const fragment = document.createDocumentFragment();
|
||||||
|
const sorted = Object.entries(bookmarksData).sort((a, b) => new Date(b[1].date) - new Date(a[1].date));
|
||||||
|
|
||||||
// Sort bookmarks by date, newest to oldest
|
let cardsToRender = parseInt(block.dataset.count) ?? 8; // -1 for all
|
||||||
const sorted = Object.entries(fcn_bookmarks.data).sort((a, b) => new Date(b[1].date) - new Date(a[1].date));
|
|
||||||
|
|
||||||
// Append bookmarks to fragment (if any)
|
|
||||||
sorted.forEach(([id, { color, progress, link, chapter, 'paragraph-id': paragraphId, date, image, thumb, content }]) => {
|
sorted.forEach(([id, { color, progress, link, chapter, 'paragraph-id': paragraphId, date, image, thumb, content }]) => {
|
||||||
// Limit rendered bookmarks
|
if (0 == cardsToRender--) {
|
||||||
if (count == 0) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
count--;
|
const clone = this.cardTemplate.content.cloneNode(true);
|
||||||
|
|
||||||
// Clone template and get data from JSON
|
|
||||||
const clone = fcn_bookmarksSmallCardTemplate.content.cloneNode(true);
|
|
||||||
const formattedDate = new Date(date).toLocaleDateString(
|
const formattedDate = new Date(date).toLocaleDateString(
|
||||||
navigator.language ?? 'en-US',
|
navigator.language ?? 'en-US',
|
||||||
{ year: '2-digit', month: 'short', day: 'numeric' }
|
{ year: '2-digit', month: 'short', day: 'numeric' }
|
||||||
@ -582,101 +196,175 @@ function fcn_showBookmarkCards() {
|
|||||||
clone.querySelector('.bookmark-card__percentage').innerText = `${progress.toFixed(1)} %`;
|
clone.querySelector('.bookmark-card__percentage').innerText = `${progress.toFixed(1)} %`;
|
||||||
clone.querySelector('.bookmark-card__progress').style.width = `calc(${progress.toFixed(1)}% - var(--bookmark-progress-offset, 0px))`;
|
clone.querySelector('.bookmark-card__progress').style.width = `calc(${progress.toFixed(1)}% - var(--bookmark-progress-offset, 0px))`;
|
||||||
clone.querySelector('time').innerText = formattedDate;
|
clone.querySelector('time').innerText = formattedDate;
|
||||||
clone.querySelector('.button-delete-bookmark').setAttribute('data-bookmark-id', id);
|
clone.querySelector('.button-delete-bookmark').setAttribute('data-fictioneer-bookmarks-id-param', id);
|
||||||
|
|
||||||
fragment.appendChild(clone);
|
fragment.appendChild(clone);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Append fragment to DOM
|
ul.innerHTML = '';
|
||||||
fcn_bookmarksSmallCardBlock.querySelector('ul').appendChild(fragment);
|
ul.appendChild(fragment);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Register events for delete buttons
|
refreshProfile() {
|
||||||
fcn_bookmarkDeleteHandler(_$$('.button-delete-bookmark'));
|
if (this.hasDataCardTarget) {
|
||||||
}
|
this.dataCardTarget.innerHTML = this.dataCardTarget
|
||||||
|
.innerHTML.replace('%s', Object.keys(this.data()).length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// =============================================================================
|
refreshChapterBookmark() {
|
||||||
// BOOKMARK DELETION
|
const bookmarkData = this.data();
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
/**
|
this.currentBookmark?.classList.remove('current-bookmark');
|
||||||
* Register event handler for bookmark delete button(s).
|
|
||||||
|
if (!this.chapterId || !bookmarkData[this.chapterId]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const paragraphId = bookmarkData[this.chapterId]['paragraph-id'];
|
||||||
|
const p = _$(`[data-paragraph-id="${paragraphId}"]`);
|
||||||
|
const color = bookmarkData[this.chapterId]['color'] ?? 'none';
|
||||||
|
|
||||||
|
if (paragraphId && p) {
|
||||||
|
p.classList.add('current-bookmark');
|
||||||
|
p.setAttribute('data-bookmark-color', color);
|
||||||
|
|
||||||
|
this.currentBookmark = p;
|
||||||
|
|
||||||
|
if (this.hasBookmarkScrollTarget) {
|
||||||
|
this.bookmarkScrollTargets.forEach(element => element.removeAttribute('hidden'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// =====================
|
||||||
|
// ====== PRIVATE ======
|
||||||
|
// =====================
|
||||||
|
|
||||||
|
#ready = false;
|
||||||
|
#paused = false;
|
||||||
|
|
||||||
|
#getLocalBookmarks() {
|
||||||
|
return FcnUtils.parseJSON(localStorage.getItem('fcnChapterBookmarks')) ?? { data: {} };
|
||||||
|
}
|
||||||
|
|
||||||
|
#getUserBookmarks() {
|
||||||
|
return FcnUtils.parseJSON(FcnUtils.userData()?.bookmarks) ?? { data: {} };
|
||||||
|
}
|
||||||
|
|
||||||
|
#fixBookmarks(bookmarks) {
|
||||||
|
if (
|
||||||
|
typeof bookmarks !== 'object' ||
|
||||||
|
!('data' in bookmarks) ||
|
||||||
|
(Array.isArray(bookmarks.data) && bookmarks.data.length === 0)
|
||||||
|
) {
|
||||||
|
return { data: {} };
|
||||||
|
}
|
||||||
|
|
||||||
|
const fixedNodes = {};
|
||||||
|
|
||||||
|
for (const key in bookmarks.data) {
|
||||||
|
if (key.startsWith('ch-')) {
|
||||||
|
const node = this.#fixNode(bookmarks.data[key]);
|
||||||
|
|
||||||
|
if (node) {
|
||||||
|
fixedNodes[key] = node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { data: fixedNodes };
|
||||||
|
}
|
||||||
|
|
||||||
|
#fixNode(node) {
|
||||||
|
const fixedNode = {};
|
||||||
|
const structure = {
|
||||||
|
'paragraph-id': '',
|
||||||
|
'progress': 0.0,
|
||||||
|
'date': '',
|
||||||
|
'color': '',
|
||||||
|
'chapter': '',
|
||||||
|
'link': '',
|
||||||
|
'thumb': '',
|
||||||
|
'image': '',
|
||||||
|
'story': '',
|
||||||
|
'content': ''
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const key in structure) {
|
||||||
|
if (typeof node[key] === typeof structure[key]) {
|
||||||
|
fixedNode[key] = node[key];
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const date = new Date(fixedNode['date']);
|
||||||
|
|
||||||
|
if (!date || Object.prototype.toString.call(date) !== '[object Date]' || isNaN(date)) {
|
||||||
|
fixedNode['date'] = (new Date()).toISOString(); // This happens anyway when stringified
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof fixedNode['progress'] !== 'number' || fixedNode['progress'] < 0) {
|
||||||
|
fixedNode['progress'] = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fixedNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
#userDataChanged() {
|
||||||
|
return JSON.stringify(this.bookmarksCachedData ?? 0) !== JSON.stringify(this.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
#startRefreshInterval() {
|
||||||
|
if (this.refreshInterval) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.refreshInterval = setInterval(() => {
|
||||||
|
if (!this.#paused && this.#userDataChanged()) {
|
||||||
|
this.refreshView()
|
||||||
|
}
|
||||||
|
}, 30000 + Math.random() * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
#watch() {
|
||||||
|
this.#startRefreshInterval();
|
||||||
|
|
||||||
|
this.visibilityStateCheck = () => {
|
||||||
|
if (document.visibilityState === 'visible') {
|
||||||
|
this.#paused = false;
|
||||||
|
this.refreshView();
|
||||||
|
this.#startRefreshInterval();
|
||||||
|
} else {
|
||||||
|
this.#paused = true;
|
||||||
|
clearInterval(this.refreshInterval);
|
||||||
|
this.refreshInterval = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener('visibilitychange', this.visibilityStateCheck);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AJAX: Update user bookmarks in database.
|
||||||
*
|
*
|
||||||
* @since 4.0.0
|
* Note: The upload AJAX call is debounced and only fires
|
||||||
* @see fcn_removeBookmark()
|
* every n seconds to ease the load on the server.
|
||||||
* @see fcn_setBookmarks()
|
*
|
||||||
* @param {HTMLElement|HTMLElement[]} targets - One or more delete buttons.
|
* @since 5.27.0
|
||||||
|
* @param {String} bookmarksString - Stringified JSON.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function fcn_bookmarkDeleteHandler(targets) {
|
#upload(bookmarksString) {
|
||||||
// Make sure to have an iterable collection for convenience
|
clearTimeout(this.timeout);
|
||||||
(typeof targets === 'object' ? targets : [targets]).forEach((item) => {
|
|
||||||
// Listen for click on delete button per item
|
|
||||||
item.addEventListener('click', (e) => {
|
|
||||||
// Remove bookmark
|
|
||||||
fcn_removeBookmark(e.currentTarget.dataset.bookmarkId);
|
|
||||||
|
|
||||||
// Update bookmarks
|
this.timeout = setTimeout(() => {
|
||||||
fcn_setBookmarks(fcn_bookmarks);
|
FcnUtils.remoteAction(
|
||||||
|
'fictioneer_ajax_save_bookmarks',
|
||||||
// Hide bookmarks block if emptied
|
{ payload: { bookmarks: bookmarksString } }
|
||||||
if (Object.keys(fcn_bookmarks.data).length < 1) {
|
|
||||||
_$('.bookmarks-block')?.classList.add('hidden');
|
|
||||||
_$$('.show-if-bookmarks').forEach(element => {
|
|
||||||
element.classList.add('hidden');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove bookmark from JSON and view.
|
|
||||||
*
|
|
||||||
* @since 4.0.0
|
|
||||||
* @param {Number} id - ID of the bookmark (chapter ID).
|
|
||||||
*/
|
|
||||||
|
|
||||||
function fcn_removeBookmark(id) {
|
|
||||||
// Setup
|
|
||||||
const chapter = _$('.chapter__article');
|
|
||||||
const currentBookmark = _$('.current-bookmark');
|
|
||||||
|
|
||||||
// Remove bookmark from JSON
|
|
||||||
delete fcn_bookmarks.data[id];
|
|
||||||
|
|
||||||
// If on bookmark's chapter page...
|
|
||||||
if (chapter && chapter.id == id) {
|
|
||||||
// Hide jump buttons
|
|
||||||
fcn_jumpToBookmarkButtons.forEach(element => {
|
|
||||||
element.classList.add('hidden');
|
|
||||||
});
|
|
||||||
|
|
||||||
fcn_mobileBookmarkJump?.setAttribute('hidden', true);
|
|
||||||
|
|
||||||
// Remove current-bookmark class from paragraph
|
|
||||||
if (currentBookmark) {
|
|
||||||
currentBookmark.classList.remove('current-bookmark');
|
|
||||||
currentBookmark.removeAttribute('data-bookmark-color');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove any other bookmark instances (e.g. mobile menu)
|
|
||||||
_$$(`.bookmark-${id}`)?.forEach(element => {
|
|
||||||
element.remove();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
// BOOKMARKS EVENT LISTENERS
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
fcn_jumpToBookmarkButtons.forEach(button => {
|
|
||||||
button.addEventListener(
|
|
||||||
'click',
|
|
||||||
() => {
|
|
||||||
const target = _$(`[data-paragraph-id="${fcn_bookmarks.data[_$('article').id]['paragraph-id']}"]`);
|
|
||||||
|
|
||||||
target.scrollIntoView({ behavior: 'smooth' });
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
}, FcnGlobals.debounceRate); // Debounce
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user