Add Splide

commit e76d41be04166ad5a9a1a17d327a9b47d46149f7
Merge: 9490b992 48b6cf37
Author: Tetrakern <26898880+Tetrakern@users.noreply.github.com>
Date:   Fri Sep 6 01:26:29 2024 +0200

    Merge branch 'main' into splide

commit 9490b9925ff2ff78f3057a2762aa41aa61028a68
Author: Tetrakern <26898880+Tetrakern@users.noreply.github.com>
Date:   Fri Sep 6 00:02:52 2024 +0200

    Add height and aspect_ratio params to showcase

commit 8043e35abb95d04192ba5a9399480a37db647b27
Author: Tetrakern <26898880+Tetrakern@users.noreply.github.com>
Date:   Thu Sep 5 23:02:12 2024 +0200

    Add Splide to showcase shortcode

commit bc7344d3a89eea93a0727b88c7d7998a2f73b54b
Author: Tetrakern <26898880+Tetrakern@users.noreply.github.com>
Date:   Thu Sep 5 22:52:26 2024 +0200

    Start documentation

commit 3e3183e5ec3da66c585f022af1214b3690ad84f6
Author: Tetrakern <26898880+Tetrakern@users.noreply.github.com>
Date:   Thu Sep 5 22:13:41 2024 +0200

    Add option to enable Splide globally

commit 60935c24e647889beab8b158bb50aa1f4948e4da
Author: Tetrakern <26898880+Tetrakern@users.noreply.github.com>
Date:   Thu Sep 5 20:48:44 2024 +0200

    Elementor compatibility

commit 1f7c0ca40289597af0b6a250c62ed22621a9668a
Author: Tetrakern <26898880+Tetrakern@users.noreply.github.com>
Date:   Thu Sep 5 20:39:08 2024 +0200

    Optimize Splide for paginated article cards

commit 911c0f6f20d0c3a5bddda280618064eb1309ac5f
Author: Tetrakern <26898880+Tetrakern@users.noreply.github.com>
Date:   Thu Sep 5 20:24:52 2024 +0200

    Turn off arrows by default

commit 567205b42031b9e075060c208d1fb93507c7acfa
Author: Tetrakern <26898880+Tetrakern@users.noreply.github.com>
Date:   Thu Sep 5 14:05:46 2024 +0200

    Move SCSS to own file

commit 5a91f1dcf0982a78e22362262d4b982784cfdd21
Author: Tetrakern <26898880+Tetrakern@users.noreply.github.com>
Date:   Thu Sep 5 13:57:22 2024 +0200

    Update style

commit e3c920ab33c5d6065fd7b8a7f2211d8809630df3
Author: Tetrakern <26898880+Tetrakern@users.noreply.github.com>
Date:   Thu Sep 5 11:58:52 2024 +0200

    Add Splide to other shortcodes

commit 7c2275a0c336e7ca7072165d633dd3fbc8a19524
Author: Tetrakern <26898880+Tetrakern@users.noreply.github.com>
Date:   Thu Sep 5 11:55:39 2024 +0200

    Update style

commit 68bff5aef85af82f1a844de293f443172a5e5d1e
Author: Tetrakern <26898880+Tetrakern@users.noreply.github.com>
Date:   Wed Sep 4 19:16:55 2024 +0200

    Improve error handling of invalid JSON

commit ce9159425a6d6674cdef7d8f356724c79db3130b
Author: Tetrakern <26898880+Tetrakern@users.noreply.github.com>
Date:   Wed Sep 4 19:05:01 2024 +0200

    Improve Splide loading and initialization

commit 263848a53ddfb77980f88b5b5f973311d792e712
Author: Tetrakern <26898880+Tetrakern@users.noreply.github.com>
Date:   Wed Sep 4 16:39:18 2024 +0200

    Improve JSON preparation

commit 8c39131008a50119bd8666b558f01354140c0b00
Merge: d4373db4 57638cdc
Author: Tetrakern <26898880+Tetrakern@users.noreply.github.com>
Date:   Wed Sep 4 14:19:28 2024 +0200

    Merge branch 'main' into splide

commit d4373db473e80b05c52565f25ba13034eb81d648
Author: Tetrakern <26898880+Tetrakern@users.noreply.github.com>
Date:   Wed Sep 4 13:48:00 2024 +0200

    Prototype
This commit is contained in:
Tetrakern 2024-09-06 01:26:42 +02:00
parent 48b6cf3719
commit a39a4ceb9b
34 changed files with 2961 additions and 2183 deletions

View File

@ -1327,6 +1327,8 @@ Renders dynamic grid of thumbnails with title, showing the latest eight posts of
* **exclude_cat_ids:** Comma-separated list of category IDs to exclude.
* **exclude_tag_ids:** Comma-separated list of tag IDs to exclude.
* **no_cap:** Set `true` if you want to hide the caption.
* **aspect_ratio:** CSS [aspect-ratio](https://developer.mozilla.org/en-US/docs/Web/CSS/aspect-ratio) value for the item (X/Y). Superseded by `height`.
* **height:** Override the item height.
* **class:** Additional CSS classes, separated by whitespace.
```
@ -1339,6 +1341,18 @@ Renders dynamic grid of thumbnails with title, showing the latest eight posts of
![Showcase](repo/assets/shortcode_example_showcase.jpg?raw=true)
### Slider
Any shortcode with the `splide` parameter listed can be turned into a slider. [Splide](https://splidejs.com/) is a flexible and lightweight slider that comes with [many options](https://splidejs.com/guides/options/) for customization, although applying them may be challenging if you are not familiar with JSONs. You can look up the details yourself.
The `splide` parameter only accepts JSON strings, such as `splide="{'type':'loop','perPage':3}"`. Note that you need to use single straight quotes due to the shortcode syntax. If there is even a minor error, the JSON will be rejected with a note, and the shortcode will default to its standard layout. Not all parameter combinations have been tested with Splide, so custom CSS may be required.
If you do not want to initialize a slider on page load, you can add the `no-auto-splide` class via the `class` parameter in the shortcode or custom HTML (where the `splide` class is). Normally, Splides assets are only enqueued when a shortcode with the necessary parameter is found in the post content, but you can enable Splide globally under **Fictioneer > General > Compatibility**.
### Sidebar
Renders the theme sidebar (not displayed anywhere by default). Requires the "Disable all widgets" theme setting to be off. Note that the sidebar has next to no styling.

View File

@ -640,6 +640,18 @@
"oF" : 1,
"pg" : 0
},
"\/css\/splide.css" : {
"aP" : 1,
"bl" : 0,
"ci" : 0,
"co" : 0,
"ft" : 16,
"ma" : 0,
"oA" : 0,
"oAP" : "\/css\/splide-min.css",
"oF" : 0,
"pg" : 0
},
"\/css\/story.css" : {
"aP" : 1,
"bl" : 0,
@ -1796,6 +1808,17 @@
"sC" : 3,
"tS" : 0
},
"\/js\/splide.min.js" : {
"bF" : 0,
"ft" : 64,
"ma" : 0,
"mi" : 1,
"oA" : 0,
"oAP" : "\/js\/splide.min.min.js",
"oF" : 0,
"sC" : 3,
"tS" : 0
},
"\/js\/story.min.js" : {
"bF" : 0,
"ft" : 64,
@ -3983,6 +4006,21 @@
"pg" : 0,
"sct" : 0
},
"\/src\/scss\/splide.scss" : {
"aP" : 0,
"bl" : 0,
"co" : 0,
"dP" : 10,
"ec" : 0,
"ft" : 4,
"ma" : 0,
"oA" : 0,
"oAP" : "\/css\/splide.css",
"oF" : 2,
"oS" : 3,
"pg" : 0,
"sct" : 0
},
"\/src\/scss\/story.scss" : {
"aP" : 0,
"bl" : 0,

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

1
css/splide.css Normal file

File diff suppressed because one or more lines are too long

View File

@ -215,7 +215,8 @@ function fictioneer_get_default_shortcode_args( $attr, $def_count = -1 ) {
'footer_rating' => filter_var( $attr['footer_rating'] ?? 1, FILTER_VALIDATE_BOOLEAN ),
'classes' => esc_attr( wp_strip_all_tags( $attr['classes'] ?? $attr['class'] ?? '' ) ),
'infobox' => filter_var( $attr['infobox'] ?? 1, FILTER_VALIDATE_BOOLEAN ),
'source' => filter_var( $attr['source'] ?? 1, FILTER_VALIDATE_BOOLEAN )
'source' => filter_var( $attr['source'] ?? 1, FILTER_VALIDATE_BOOLEAN ),
'splide' => sanitize_text_field( $attr['splide'] ?? '' )
);
//--- Fixes ------------------------------------------------------------------
@ -225,6 +226,24 @@ function fictioneer_get_default_shortcode_args( $attr, $def_count = -1 ) {
$args['count'] = count( $args['post_ids'] );
}
// Prepare Splide JSON
if ( ! empty( $args['splide'] ) ) {
$args['splide'] = str_replace( "'", '"', $args['splide'] );
if ( ! fictioneer_is_valid_json( $args['splide'] ) ) {
$args['splide'] = false;
} else {
$splide = json_decode( $args['splide'], true );
// Turn arrows are off by default
if ( ! preg_match( '/"arrows"\s*:\s*true/', $args['splide'] ) ) {
$splide['arrows'] = false;
}
$args['splide'] = json_encode( $splide );
}
}
//--- Finish -----------------------------------------------------------------
return $args;
@ -381,10 +400,12 @@ function fictioneer_get_shortcode_tax_query( $args ) {
* @param string|null $attr['rel'] Optional. Relationship between taxonomies. Default 'AND'.
* @param string|null $attr['vertical'] Optional. Whether to show the vertical variant.
* @param string|null $attr['seamless'] Optional. Whether to render the image seamless. Default false (Customizer).
* @param string|null $attr['aspect_ratio'] Optional. Aspect ratio for the image. Only with vertical.
* @param string|null $attr['aspect_ratio'] Optional. Aspect ratio of the item. Supersedes by height. Default empty.
* @param string|null $attr['height'] Optional. Override the item height. Default empty.
* @param string|null $attr['lightbox'] Optional. Whether the thumbnail is opened in the lightbox. Default true.
* @param string|null $attr['thumbnail'] Optional. Whether to show the thumbnail. Default true (Customizer).
* @param string|null $attr['class'] Optional. Additional CSS classes, separated by whitespace.
* @param string|null $args['splide'] Configuration JSON for the Splide slider. Default empty.
*
* @return string The captured shortcode HTML.
*/
@ -398,6 +419,9 @@ function fictioneer_shortcode_showcase( $attr ) {
// Defaults
$args = fictioneer_get_default_shortcode_args( $attr, 8 );
// Height
$args['height'] = sanitize_text_field( $attr['height'] ?? '' );
// Specifics
$args['no_cap'] = filter_var( $attr['no_cap'] ?? 0, FILTER_VALIDATE_BOOLEAN );
@ -421,6 +445,11 @@ function fictioneer_shortcode_showcase( $attr ) {
return '';
}
// Extra classes
if ( $args['splide'] ?? 0 ) {
$args['classes'] .= ' splide';
}
// Transient?
if ( FICTIONEER_SHORTCODE_TRANSIENTS_ENABLED ) {
$base = serialize( $args ) . serialize( $attr );
@ -440,6 +469,10 @@ function fictioneer_shortcode_showcase( $attr ) {
$html = fictioneer_minify_html( ob_get_clean() );
if ( ( $args['splide'] ?? 0 ) && strpos( $args['classes'], 'no-auto-splide' ) === false ) {
$html .= '<script class="temp-script">document.querySelectorAll(".splide:not(.no-auto-splide, .is-initialized)").forEach(e=>{"undefined"!=typeof Splide&&new Splide(e).mount()}),document.querySelector(".temp-script").remove();</script>';
}
if ( FICTIONEER_SHORTCODE_TRANSIENTS_ENABLED ) {
set_transient( $transient_key, $html, FICTIONEER_SHORTCODE_TRANSIENT_EXPIRATION );
}
@ -491,6 +524,7 @@ add_shortcode( 'fictioneer_showcase', 'fictioneer_shortcode_showcase' );
* @param string|null $attr['footer_status'] Optional. Whether to show the chapter status. Default true.
* @param string|null $attr['footer_rating'] Optional. Whether to show the story/chapter age rating. Default true.
* @param string|null $attr['class'] Optional. Additional CSS classes, separated by whitespace.
* @param string|null $args['splide'] Configuration JSON for the Splide slider. Default empty.
*
* @return string The captured shortcode HTML.
*/
@ -506,6 +540,11 @@ function fictioneer_shortcode_latest_chapters( $attr ) {
// Type
$type = sanitize_text_field( $attr['type'] ?? 'default' );
// Extra classes
if ( $args['splide'] ?? 0 ) {
$args['classes'] .= ' splide';
}
// Transient?
if ( FICTIONEER_SHORTCODE_TRANSIENTS_ENABLED ) {
$base = serialize( $args ) . serialize( $attr );
@ -534,6 +573,10 @@ function fictioneer_shortcode_latest_chapters( $attr ) {
$html = fictioneer_minify_html( ob_get_clean() );
if ( ( $args['splide'] ?? 0 ) && strpos( $args['classes'], 'no-auto-splide' ) === false ) {
$html .= '<script class="temp-script">document.querySelectorAll(".splide:not(.no-auto-splide, .is-initialized)").forEach(e=>{"undefined"!=typeof Splide&&new Splide(e).mount()}),document.querySelector(".temp-script").remove();</script>';
}
if ( FICTIONEER_SHORTCODE_TRANSIENTS_ENABLED ) {
set_transient( $transient_key, $html, FICTIONEER_SHORTCODE_TRANSIENT_EXPIRATION );
}
@ -588,6 +631,7 @@ add_shortcode( 'fictioneer_chapter_cards', 'fictioneer_shortcode_latest_chapters
* @param string|null $attr['footer_status'] Optional. Whether to show the story status. Default true.
* @param string|null $attr['footer_rating'] Optional. Whether to show the story age rating. Default true.
* @param string|null $attr['class'] Optional. Additional CSS classes, separated by whitespace.
* @param string|null $args['splide'] Configuration JSON for the Splide slider. Default empty.
*
* @return string The captured shortcode HTML.
*/
@ -603,6 +647,11 @@ function fictioneer_shortcode_latest_stories( $attr ) {
$args['terms'] = fictioneer_sanitize_query_var( $attr['terms'] ?? 0, ['inline', 'pills', 'none', 'false'], 'inline' );
$args['max_terms'] = absint( ( $attr['max_terms'] ?? 10 ) ?: 10 );
// Extra classes
if ( $args['splide'] ?? 0 ) {
$args['classes'] .= ' splide';
}
// Transient?
if ( FICTIONEER_SHORTCODE_TRANSIENTS_ENABLED ) {
$base = serialize( $args ) . serialize( $attr );
@ -630,6 +679,10 @@ function fictioneer_shortcode_latest_stories( $attr ) {
$html = fictioneer_minify_html( ob_get_clean() );
if ( ( $args['splide'] ?? 0 ) && strpos( $args['classes'], 'no-auto-splide' ) === false ) {
$html .= '<script class="temp-script">document.querySelectorAll(".splide:not(.no-auto-splide, .is-initialized)").forEach(e=>{"undefined"!=typeof Splide&&new Splide(e).mount()}),document.querySelector(".temp-script").remove();</script>';
}
if ( FICTIONEER_SHORTCODE_TRANSIENTS_ENABLED ) {
set_transient( $transient_key, $html, FICTIONEER_SHORTCODE_TRANSIENT_EXPIRATION );
}
@ -686,6 +739,7 @@ add_shortcode( 'fictioneer_story_cards', 'fictioneer_shortcode_latest_stories' )
* @param string|null $attr['footer_status'] Optional. Whether to show the story status. Default true.
* @param string|null $attr['footer_rating'] Optional. Whether to show the story/chapter age rating. Default true.
* @param string|null $attr['class'] Optional. Additional CSS classes, separated by whitespace.
* @param string|null $args['splide'] Configuration JSON for the Splide slider. Default empty.
*
* @return string The captured shortcode HTML.
*/
@ -702,6 +756,11 @@ function fictioneer_shortcode_latest_story_updates( $attr ) {
$args['terms'] = fictioneer_sanitize_query_var( $attr['terms'] ?? 0, ['inline', 'pills', 'none', 'false'], 'inline' );
$args['max_terms'] = absint( ( $attr['max_terms'] ?? 10 ) ?: 10 );
// Extra classes
if ( $args['splide'] ?? 0 ) {
$args['classes'] .= ' splide';
}
// Transient?
if ( FICTIONEER_SHORTCODE_TRANSIENTS_ENABLED ) {
$base = serialize( $args ) . serialize( $attr );
@ -729,6 +788,10 @@ function fictioneer_shortcode_latest_story_updates( $attr ) {
$html = fictioneer_minify_html( ob_get_clean() );
if ( ( $args['splide'] ?? 0 ) && strpos( $args['classes'], 'no-auto-splide' ) === false ) {
$html .= '<script class="temp-script">document.querySelectorAll(".splide:not(.no-auto-splide, .is-initialized)").forEach(e=>{"undefined"!=typeof Splide&&new Splide(e).mount()}),document.querySelector(".temp-script").remove();</script>';
}
if ( FICTIONEER_SHORTCODE_TRANSIENTS_ENABLED ) {
set_transient( $transient_key, $html, FICTIONEER_SHORTCODE_TRANSIENT_EXPIRATION );
}
@ -772,6 +835,7 @@ add_shortcode( 'fictioneer_update_cards', 'fictioneer_shortcode_latest_story_upd
* @param string|null $attr['lightbox'] Optional. Whether the thumbnail is opened in the lightbox. Default true.
* @param string|null $attr['thumbnail'] Optional. Whether to show the thumbnail. Default true (Customizer).
* @param string|null $attr['class'] Optional. Additional CSS classes, separated by whitespace.
* @param string|null $args['splide'] Configuration JSON for the Splide slider. Default empty.
*
* @return string The captured shortcode HTML.
*/
@ -787,6 +851,11 @@ function fictioneer_shortcode_latest_recommendations( $attr ) {
$args['terms'] = fictioneer_sanitize_query_var( $attr['terms'] ?? 0, ['inline', 'pills', 'none', 'false'], 'inline' );
$args['max_terms'] = absint( ( $attr['max_terms'] ?? 10 ) ?: 10 );
// Extra classes
if ( $args['splide'] ?? 0 ) {
$args['classes'] .= ' splide';
}
// Transient?
if ( FICTIONEER_SHORTCODE_TRANSIENTS_ENABLED ) {
$base = serialize( $args ) . serialize( $attr );
@ -811,6 +880,10 @@ function fictioneer_shortcode_latest_recommendations( $attr ) {
$html = fictioneer_minify_html( ob_get_clean() );
if ( ( $args['splide'] ?? 0 ) && strpos( $args['classes'], 'no-auto-splide' ) === false ) {
$html .= '<script class="temp-script">document.querySelectorAll(".splide:not(.no-auto-splide, .is-initialized)").forEach(e=>{"undefined"!=typeof Splide&&new Splide(e).mount()}),document.querySelector(".temp-script").remove();</script>';
}
if ( FICTIONEER_SHORTCODE_TRANSIENTS_ENABLED ) {
set_transient( $transient_key, $html, FICTIONEER_SHORTCODE_TRANSIENT_EXPIRATION );
}
@ -1608,6 +1681,7 @@ add_shortcode( 'fictioneer_blog', 'fictioneer_shortcode_blog' );
* @param string|null $attr['footer_date'] Optional. Whether to show the post date. Default true.
* @param string|null $attr['footer_comments'] Optional. Whether to show the post comment count. Default true.
* @param string|null $attr['class'] Optional. Additional CSS classes, separated by whitespace.
* @param string|null $args['splide'] Configuration JSON for the Splide slider. Default empty.
*
* @return string The captured shortcode HTML.
*/
@ -1657,6 +1731,11 @@ function fictioneer_shortcode_article_cards( $attr ) {
// ... add to args
$args['post_type'] = $query_post_types;
// Extra classes
if ( $args['splide'] ?? 0 ) {
$args['classes'] .= ' splide';
}
// Transient?
if ( FICTIONEER_SHORTCODE_TRANSIENTS_ENABLED ) {
$base = serialize( $args ) . serialize( $attr );
@ -1675,6 +1754,10 @@ function fictioneer_shortcode_article_cards( $attr ) {
$html = fictioneer_minify_html( ob_get_clean() );
if ( ( $args['splide'] ?? 0 ) && strpos( $args['classes'], 'no-auto-splide' ) === false ) {
$html .= '<script class="temp-script">document.querySelectorAll(".splide:not(.no-auto-splide, .is-initialized)").forEach(e=>{"undefined"!=typeof Splide&&new Splide(e).mount()}),document.querySelector(".temp-script").remove();</script>';
}
if ( FICTIONEER_SHORTCODE_TRANSIENTS_ENABLED ) {
set_transient( $transient_key, $html, FICTIONEER_SHORTCODE_TRANSIENT_EXPIRATION );
}

View File

@ -940,7 +940,7 @@ function fictioneer_style_queue() {
// Shortcodes
if (
( $post && preg_match( '/\[fictioneer_latest_[^\]]*type="list"[^\]]*\]/', $post->post_content ) ) ||
is_admin() // Accounts for page editors like Elementor
strpos( $_SERVER['REQUEST_URI'], 'elementor' ) !== false // Accounts for page editors like Elementor
) {
wp_enqueue_style(
'fictioneer-post-list',
@ -969,6 +969,20 @@ function fictioneer_style_queue() {
$cache_bust
);
}
// Enqueue Splide CSS
if (
get_option( 'fictioneer_enable_global_splide' ) ||
( $post && preg_match( '/\[fictioneer_[a-zA-Z0-9_]*[^\]]*splide="([^"]+)"[^\]]*\]/', $post->post_content ) ) ||
strpos( $_SERVER['REQUEST_URI'], 'elementor' ) !== false // Accounts for page editors like Elementor
) {
wp_enqueue_style(
'fictioneer-splide',
get_template_directory_uri() . '/css/splide.css',
[],
$cache_bust
);
}
}
add_action( 'wp_enqueue_scripts', 'fictioneer_style_queue' );
@ -1173,6 +1187,8 @@ function fictioneer_build_dynamic_scripts() {
*/
function fictioneer_add_custom_scripts() {
global $post;
// Setup
$post_type = get_post_type();
$cache_bust = fictioneer_get_cache_bust();
@ -1350,6 +1366,15 @@ function fictioneer_add_custom_scripts() {
wp_enqueue_script( 'comment-reply' );
}
// Enqueue Splide
if (
get_option( 'fictioneer_enable_global_splide' ) ||
( $post && preg_match( '/\[fictioneer_[a-zA-Z0-9_]*[^\]]*splide="([^"]+)"[^\]]*\]/', $post->post_content ) ) ||
strpos( $_SERVER['REQUEST_URI'], 'elementor' ) !== false // Accounts for page editors like Elementor
) {
wp_enqueue_script( 'fictioneer-splide', get_template_directory_uri() . '/js/splide.min.js', [], $cache_bust, false );
}
// DEV Utilities
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
wp_register_script( 'fictioneer-dev-scripts', get_template_directory_uri() . '/js/dev-tools.min.js', [], $cache_bust, $strategy );
@ -1491,7 +1516,23 @@ if ( ! is_admin() && ! get_option( 'fictioneer_enable_jquery_migrate' ) ) {
function fictioneer_ao_exclude_css( $exclude ) {
return $exclude . ', fonts-base.css, fonts-full.css, bundled-fonts.css';
}
add_filter( 'autoptimize_filter_css_exclude', 'fictioneer_ao_exclude_css', 10, 1 );
add_filter( 'autoptimize_filter_css_exclude', 'fictioneer_ao_exclude_css' );
/**
* Exclude scripts from Autoptimize (if installed)
*
* @since 5.23.1
* @link https://github.com/wp-plugins/autoptimize
*
* @param string $exclude List of current excludes.
*
* @return string The updated exclusion string.
*/
function fictioneer_ao_exclude_js( $exclude ) {
return $exclude . ', fictioneer/js/splide.min.js';
}
add_filter( 'autoptimize_filter_js_exclude', 'fictioneer_ao_exclude_js' );
// =============================================================================
// OUTPUT HEAD FONTS

View File

@ -695,6 +695,12 @@ define( 'FICTIONEER_OPTIONS', array(
'group' => 'fictioneer-settings-general-group',
'sanitize_callback' => 'fictioneer_sanitize_checkbox',
'default' => 0
),
'fictioneer_enable_global_splide' => array(
'name' => 'fictioneer_enable_global_splide',
'group' => 'fictioneer-settings-general-group',
'sanitize_callback' => 'fictioneer_sanitize_checkbox',
'default' => 0
)
),
'integers' => array(
@ -1162,6 +1168,7 @@ function fictioneer_get_option_label( $option ) {
'fictioneer_enable_story_card_caching' => __( 'Enable caching of story cards', 'fictioneer' ),
'fictioneer_enable_query_result_caching' => __( 'Enable caching of large query results', 'fictioneer' ),
'fictioneer_allow_rest_save_actions' => __( 'Allow REST requests to trigger save actions', 'fictioneer' ),
'fictioneer_enable_global_splide' => __( 'Enable Splide slider globally', 'fictioneer' ),
);
}

View File

@ -1319,6 +1319,20 @@ $images = get_template_directory_uri() . '/img/documentation/';
?>
</div>
<div class="fictioneer-card__row">
<?php
fictioneer_settings_label_checkbox(
'fictioneer_enable_global_splide',
__( 'Enable Splide slider globally', 'fictioneer' ),
__( 'Instead of limiting it to shortcodes.', 'fictioneer' ),
sprintf(
__( 'Normally, the <a href="%s" target="_blank" rel="noopener noreferrer">Splide slider</a> script and style are only loaded when a shortcode with the required parameter is found in the post content. However, if you want to use Splide in other ways, you can enable the assets globally here.', 'fictioneer' ),
'https://splidejs.com/guides/options/'
)
);
?>
</div>
<div class="fictioneer-card__row">
<?php
fictioneer_settings_label_checkbox(

File diff suppressed because one or more lines are too long

8
js/complete.min.js vendored

File diff suppressed because one or more lines are too long

9
js/splide.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -33,6 +33,7 @@
* @internal $args['footer_date'] Whether to show the post date. Default true.
* @internal $args['footer_comments'] Whether to show the post comment count. Default true.
* @internal $args['classes'] String of additional CSS classes. Default empty.
* @internal $args['splide'] Configuration JSON for the Splide slider. Default empty.
*/
@ -40,6 +41,7 @@
defined( 'ABSPATH' ) OR exit;
// Setup
$splide = $args['splide'] ?? 0;
$show_terms = ! in_array( $args['terms'], ['none', 'false'] );
// Arguments
@ -122,13 +124,29 @@ $pag_args = array(
'add_fragment' => "#{$unique_id}"
);
// Extra attributes
$attributes = [];
if ( $splide ) {
$attributes[] = "data-splide='{$splide}'";
}
?>
<section id="<?php echo $unique_id; ?>" class="scroll-margin-top article-card-block <?php echo esc_attr( $args['classes'] ); ?>">
<section id="<?php echo $unique_id; ?>" class="scroll-margin-top article-card-block <?php echo esc_attr( $args['classes'] ); ?>" <?php echo implode( ' ', $attributes ); ?>>
<?php
if ( $args['splide'] === false ) {
echo '<div class="shortcode-json-invalid">' . __( 'Splide JSON is invalid and has been ignored.', 'fictioneer' ) . '</div>';
}
if ( $splide ) {
echo '<div class="splide__track">';
}
?>
<?php if ( $query->have_posts() ) : ?>
<ul class="grid-columns _collapse-on-mobile">
<ul class="grid-columns _collapse-on-mobile <?php if ( $splide ) { echo 'splide__list'; } ?>">
<?php
while ( $query->have_posts() ) {
$query->the_post();
@ -179,6 +197,10 @@ $pag_args = array(
$card_classes[] = '_no-footer-comments';
}
if ( $splide ) {
$card_classes[] = 'splide__slide';
}
// Card attributes
$attributes = [];
@ -299,6 +321,8 @@ $pag_args = array(
?>
</ul>
<?php if ( $splide ) { echo '<ul class="splide__pagination"></ul>'; } ?>
<?php if ( $args['count'] < 1 && $query->max_num_pages > 1 ) : ?>
<nav class="pagination"><?php echo fictioneer_paginate_links( $pag_args ); ?></nav>
<?php endif; ?>
@ -309,4 +333,5 @@ $pag_args = array(
<?php endif; ?>
<?php if ( $splide ) { echo '</div>'; } ?>
</section>

View File

@ -34,6 +34,7 @@
* @internal $args['footer_author'] Whether to show the chapter author. Default true.
* @internal $args['footer_words'] Whether to show the chapter word count. Default true.
* @internal $args['footer_date'] Whether to show the chapter date. Default true.
* @internal $args['splide'] Configuration JSON for the Splide slider. Default empty.
*/
@ -41,6 +42,7 @@
defined( 'ABSPATH' ) OR exit;
// Setup
$splide = $args['splide'] ?? 0;
$card_counter = 0;
// Prepare query
@ -118,12 +120,29 @@ $entries = fictioneer_shortcode_query( $query_args );
// Remove temporary filters
remove_filter( 'posts_where', 'fictioneer_exclude_protected_posts' );
// Extra attributes
$attributes = [];
if ( $splide ) {
$attributes[] = "data-splide='{$splide}'";
}
?>
<section class="small-card-block latest-chapters _compact <?php echo $args['classes']; ?>" <?php echo implode( ' ', $attributes ); ?>>
<?php
if ( $args['splide'] === false ) {
echo '<div class="shortcode-json-invalid">' . __( 'Splide JSON is invalid and has been ignored.', 'fictioneer' ) . '</div>';
}
if ( $splide ) {
echo '<div class="splide__track">';
}
?>
<section class="small-card-block latest-chapters _compact <?php echo $args['classes']; ?>">
<?php if ( $entries->have_posts() ) : ?>
<ul class="grid-columns _collapse-on-mobile">
<ul class="grid-columns _collapse-on-mobile <?php if ( $splide ) { echo 'splide__list'; } ?>">
<?php while ( $entries->have_posts() ) : $entries->the_post(); ?>
<?php
@ -167,6 +186,10 @@ remove_filter( 'posts_where', 'fictioneer_exclude_protected_posts' );
$card_classes[] = '_no-footer-date';
}
if ( $splide ) {
$card_classes[] = 'splide__slide';
}
// Count actually rendered cards to account for buffer
if ( ++$card_counter > $args['count'] ) {
break;
@ -293,4 +316,6 @@ remove_filter( 'posts_where', 'fictioneer_exclude_protected_posts' );
<div class="no-results"><?php _e( 'Nothing to show.', 'fictioneer' ); ?></div>
<?php endif; wp_reset_postdata(); ?>
<?php if ( $splide ) { echo '</div>'; } ?>
</section>

View File

@ -38,6 +38,7 @@
* @internal $args['footer_status'] Whether to show the chapter story status. Default true.
* @internal $args['footer_rating'] Whether to show the story/chapter age rating. Default true.
* @internal $args['classes'] String of additional CSS classes. Default empty.
* @internal $args['splide'] Configuration JSON for the Splide slider. Default empty.
*/
@ -45,6 +46,7 @@
defined( 'ABSPATH' ) OR exit;
// Setup
$splide = $args['splide'] ?? 0;
$render_count = 0;
$content_list_style = get_theme_mod( 'content_list_style', 'default' );
@ -123,12 +125,29 @@ $entries = fictioneer_shortcode_query( $query_args );
// Remove temporary filters
remove_filter( 'posts_where', 'fictioneer_exclude_protected_posts' );
// Extra attributes
$attributes = [];
if ( $splide ) {
$attributes[] = "data-splide='{$splide}'";
}
?>
<section class="latest-chapters _list <?php echo $args['classes']; ?>" <?php echo implode( ' ', $attributes ); ?>>
<?php
if ( $args['splide'] === false ) {
echo '<div class="shortcode-json-invalid">' . __( 'Splide JSON is invalid and has been ignored.', 'fictioneer' ) . '</div>';
}
if ( $splide ) {
echo '<div class="splide__track">';
}
?>
<section class="latest-chapters _list <?php echo $args['classes']; ?>">
<?php if ( $entries->have_posts() ) : ?>
<ul class="post-list _latest-chapters">
<ul class="post-list _latest-chapters <?php if ( $splide ) { echo 'splide__list'; } ?>">
<?php while ( $entries->have_posts() ) : $entries->the_post(); ?>
<?php
@ -213,6 +232,10 @@ remove_filter( 'posts_where', 'fictioneer_exclude_protected_posts' );
$classes[] = '_no-footer-rating';
}
if ( $splide ) {
$classes[] = 'splide__slide';
}
// Meta
$meta = [];
@ -303,4 +326,6 @@ remove_filter( 'posts_where', 'fictioneer_exclude_protected_posts' );
<div class="no-results"><?php _e( 'Nothing to show.', 'fictioneer' ); ?></div>
<?php endif; wp_reset_postdata(); ?>
<?php if ( $splide ) { echo '</div>'; } ?>
</section>

View File

@ -39,6 +39,7 @@
* @internal $args['footer_status'] Whether to show the chapter story status. Default true.
* @internal $args['footer_rating'] Whether to show the chapter age rating. Default true.
* @internal $args['classes'] String of additional CSS classes. Default empty.
* @internal $args['splide'] Configuration JSON for the Splide slider. Default empty.
*/
@ -46,6 +47,7 @@
defined( 'ABSPATH' ) OR exit;
// Setup
$splide = $args['splide'] ?? 0;
$card_counter = 0;
// Prepare query
@ -123,12 +125,29 @@ $entries = fictioneer_shortcode_query( $query_args );
// Remove temporary filters
remove_filter( 'posts_where', 'fictioneer_exclude_protected_posts' );
// Extra attributes
$attributes = [];
if ( $splide ) {
$attributes[] = "data-splide='{$splide}'";
}
?>
<section class="small-card-block latest-chapters <?php echo $args['classes']; ?>" <?php echo implode( ' ', $attributes ); ?>>
<?php
if ( $args['splide'] === false ) {
echo '<div class="shortcode-json-invalid">' . __( 'Splide JSON is invalid and has been ignored.', 'fictioneer' ) . '</div>';
}
if ( $splide ) {
echo '<div class="splide__track">';
}
?>
<section class="small-card-block latest-chapters <?php echo $args['classes']; ?>">
<?php if ( $entries->have_posts() ) : ?>
<ul class="grid-columns _collapse-on-mobile">
<ul class="grid-columns _collapse-on-mobile <?php if ( $splide ) { echo 'splide__list'; } ?>">
<?php while ( $entries->have_posts() ) : $entries->the_post(); ?>
<?php
@ -188,6 +207,10 @@ remove_filter( 'posts_where', 'fictioneer_exclude_protected_posts' );
$card_classes[] = '_no-footer-rating';
}
if ( $splide ) {
$card_classes[] = 'splide__slide';
}
// Truncate factor
$truncate_factor = $args['vertical'] ? '_4-4' : '_cq-3-4';
@ -362,4 +385,6 @@ remove_filter( 'posts_where', 'fictioneer_exclude_protected_posts' );
<div class="no-results"><?php _e( 'Nothing to show.', 'fictioneer' ); ?></div>
<?php endif; wp_reset_postdata(); ?>
<?php if ( $splide ) { echo '</div>'; } ?>
</section>

View File

@ -30,6 +30,7 @@
* @internal $args['max_terms'] Maximum number of shown taxonomies. Default 10.
* @internal $args['classes'] String of additional CSS classes. Default empty.
* @internal $args['infobox'] Whether to show the info box and toggle.
* @internal $args['splide'] Configuration JSON for the Splide slider. Default empty.
*/
@ -37,6 +38,7 @@
defined( 'ABSPATH' ) OR exit;
// Setup
$splide = $args['splide'] ?? 0;
$show_terms = ! in_array( $args['terms'], ['none', 'false'] ) &&
! get_option( 'fictioneer_hide_taxonomies_on_recommendation_cards' );
@ -97,12 +99,29 @@ $entries = fictioneer_shortcode_query( $query_args );
// Remove temporary filters
remove_filter( 'posts_where', 'fictioneer_exclude_protected_posts' );
// Extra attributes
$attributes = [];
if ( $splide ) {
$attributes[] = "data-splide='{$splide}'";
}
?>
<section class="small-card-block latest-recommendations _compact <?php echo $args['classes']; ?>" <?php echo implode( ' ', $attributes ); ?>>
<?php
if ( $args['splide'] === false ) {
echo '<div class="shortcode-json-invalid">' . __( 'Splide JSON is invalid and has been ignored.', 'fictioneer' ) . '</div>';
}
if ( $splide ) {
echo '<div class="splide__track">';
}
?>
<section class="small-card-block latest-recommendations _compact <?php echo $args['classes']; ?>">
<?php if ( $entries->have_posts() ) : ?>
<ul class="grid-columns _collapse-on-mobile">
<ul class="grid-columns _collapse-on-mobile <?php if ( $splide ) { echo 'splide__list'; } ?>">
<?php while ( $entries->have_posts() ) : $entries->the_post(); ?>
<?php
@ -139,6 +158,10 @@ remove_filter( 'posts_where', 'fictioneer_exclude_protected_posts' );
$card_classes[] = '_no-tax';
}
if ( $splide ) {
$card_classes[] = 'splide__slide';
}
// Truncate factor
$truncate_factor = $args['vertical'] ? '_4-4' : '_cq-3-4';
@ -251,4 +274,6 @@ remove_filter( 'posts_where', 'fictioneer_exclude_protected_posts' );
<div class="no-results"><?php _e( 'Nothing to show.', 'fictioneer' ); ?></div>
<?php endif; wp_reset_postdata(); ?>
<?php if ( $splide ) { echo '</div>'; } ?>
</section>

View File

@ -29,6 +29,7 @@
* @internal $args['lightbox'] Whether the image is opened in the lightbox. Default true.
* @internal $args['thumbnail'] Whether the image is rendered. Default true (Customizer).
* @internal $args['classes'] String of additional CSS classes. Default empty.
* @internal $args['splide'] Configuration JSON for the Splide slider. Default empty.
*/
@ -36,6 +37,7 @@
defined( 'ABSPATH' ) OR exit;
// Setup
$splide = $args['splide'] ?? 0;
$show_terms = ! get_option( 'fictioneer_hide_taxonomies_on_recommendation_cards' );
// Prepare query
@ -94,13 +96,29 @@ $entries = fictioneer_shortcode_query( $query_args );
// Remove temporary filters
remove_filter( 'posts_where', 'fictioneer_exclude_protected_posts' );
// Extra attributes
$attributes = [];
if ( $splide ) {
$attributes[] = "data-splide='{$splide}'";
}
?>
<section class="small-card-block latest-recommendations <?php echo $args['classes']; ?>">
<section class="small-card-block latest-recommendations <?php echo $args['classes']; ?>" <?php echo implode( ' ', $attributes ); ?>>
<?php
if ( $args['splide'] === false ) {
echo '<div class="shortcode-json-invalid">' . __( 'Splide JSON is invalid and has been ignored.', 'fictioneer' ) . '</div>';
}
if ( $splide ) {
echo '<div class="splide__track">';
}
?>
<?php if ( $entries->have_posts() ) : ?>
<ul class="grid-columns _collapse-on-mobile">
<ul class="grid-columns _collapse-on-mobile <?php if ( $splide ) { echo 'splide__list'; } ?>">
<?php while ( $entries->have_posts() ) : $entries->the_post(); ?>
<?php
@ -133,6 +151,10 @@ remove_filter( 'posts_where', 'fictioneer_exclude_protected_posts' );
$card_classes[] = '_no-tax';
}
if ( $splide ) {
$card_classes[] = 'splide__slide';
}
// Truncate factor
$truncate_factor = $args['vertical'] ? '_4-4' : '_3-3';
@ -268,4 +290,5 @@ remove_filter( 'posts_where', 'fictioneer_exclude_protected_posts' );
<?php endif; wp_reset_postdata(); ?>
<?php if ( $splide ) { echo '</div>'; } ?>
</section>

View File

@ -37,6 +37,7 @@
* @internal $args['footer_date'] Whether to show the date. Default true.
* @internal $args['footer_status'] Whether to show the status. Default true.
* @internal $args['footer_rating'] Whether to show the age rating. Default true.
* @internal $args['splide'] Configuration JSON for the Splide slider. Default empty.
*/
@ -44,6 +45,7 @@
defined( 'ABSPATH' ) OR exit;
// Setup
$splide = $args['splide'] ?? 0;
$show_terms = ! in_array( $args['terms'], ['none', 'false'] ) &&
! get_option( 'fictioneer_hide_taxonomies_on_story_cards' );
@ -122,12 +124,28 @@ $entries = fictioneer_shortcode_query( $query_args );
// Remove temporary filters
remove_filter( 'posts_where', 'fictioneer_exclude_protected_posts' );
// Extra attributes
$attributes = [];
if ( $splide ) {
$attributes[] = "data-splide='{$splide}'";
}
?>
<section class="small-card-block latest-stories _compact <?php echo $args['classes']; ?>">
<section class="small-card-block latest-stories _compact <?php echo $args['classes']; ?>" <?php echo implode( ' ', $attributes ); ?>>
<?php
if ( $args['splide'] === false ) {
echo '<div class="shortcode-json-invalid">' . __( 'Splide JSON is invalid and has been ignored.', 'fictioneer' ) . '</div>';
}
if ( $splide ) {
echo '<div class="splide__track">';
}
?>
<?php if ( $entries->have_posts() ) : ?>
<ul class="grid-columns _collapse-on-mobile">
<ul class="grid-columns _collapse-on-mobile <?php if ( $splide ) { echo 'splide__list'; } ?>">
<?php while ( $entries->have_posts() ) : $entries->the_post(); ?>
<?php
@ -199,6 +217,10 @@ remove_filter( 'posts_where', 'fictioneer_exclude_protected_posts' );
$card_classes[] = '_no-footer-rating';
}
if ( $splide ) {
$card_classes[] = 'splide__slide';
}
// Truncate factor
$truncate_factor = $args['vertical'] ? '_4-4' : '_cq-3-4';
@ -369,4 +391,6 @@ remove_filter( 'posts_where', 'fictioneer_exclude_protected_posts' );
<div class="no-results"><?php _e( 'Nothing to show.', 'fictioneer' ); ?></div>
<?php endif; wp_reset_postdata(); ?>
<?php if ( $splide ) { echo '</div>'; } ?>
</section>

View File

@ -38,6 +38,7 @@
* @internal $args['footer_status'] Whether to show the story status. Default true.
* @internal $args['footer_rating'] Whether to show the story age rating. Default true.
* @internal $args['classes'] String of additional CSS classes. Default empty.
* @internal $args['splide'] Configuration JSON for the Splide slider. Default empty.
*/
@ -45,6 +46,7 @@
defined( 'ABSPATH' ) OR exit;
// Setup
$splide = $args['splide'] ?? 0;
$show_terms = ! in_array( $args['terms'], ['none', 'false'] );
$content_list_style = get_theme_mod( 'content_list_style', 'default' );
@ -123,12 +125,29 @@ $entries = fictioneer_shortcode_query( $query_args );
// Remove temporary filters
remove_filter( 'posts_where', 'fictioneer_exclude_protected_posts' );
// Extra attributes
$attributes = [];
if ( $splide ) {
$attributes[] = "data-splide='{$splide}'";
}
?>
<section class="latest-stories _list <?php echo $args['classes']; ?>" <?php echo implode( ' ', $attributes ); ?>>
<?php
if ( $args['splide'] === false ) {
echo '<div class="shortcode-json-invalid">' . __( 'Splide JSON is invalid and has been ignored.', 'fictioneer' ) . '</div>';
}
if ( $splide ) {
echo '<div class="splide__track">';
}
?>
<section class="latest-stories _list <?php echo $args['classes']; ?>">
<?php if ( $entries->have_posts() ) : ?>
<ul class="post-list _latest-stories">
<ul class="post-list _latest-stories <?php if ( $splide ) { echo 'splide__list'; } ?>">
<?php while ( $entries->have_posts() ) : $entries->the_post(); ?>
<?php
@ -208,6 +227,10 @@ remove_filter( 'posts_where', 'fictioneer_exclude_protected_posts' );
$classes[] = '_no-footer-rating';
}
if ( $splide ) {
$classes[] = 'splide__slide';
}
// Meta
$meta = [];
@ -310,4 +333,6 @@ remove_filter( 'posts_where', 'fictioneer_exclude_protected_posts' );
<div class="no-results"><?php _e( 'Nothing to show.', 'fictioneer' ); ?></div>
<?php endif; wp_reset_postdata(); ?>
<?php if ( $splide ) { echo '</div>'; } ?>
</section>

View File

@ -38,6 +38,7 @@
* @internal $args['footer_status'] Whether to show the status. Default true.
* @internal $args['footer_rating'] Whether to show the age rating. Default true.
* @internal $args['classes'] String of additional CSS classes. Default empty.
* @internal $args['splide'] Configuration JSON for the Splide slider. Default empty.
*/
@ -45,6 +46,7 @@
defined( 'ABSPATH' ) OR exit;
// Setup
$splide = $args['splide'] ?? 0;
$show_terms = ! in_array( $args['terms'], ['none', 'false'] ) &&
! get_option( 'fictioneer_hide_taxonomies_on_story_cards' );
@ -123,12 +125,29 @@ $entries = fictioneer_shortcode_query( $query_args );
// Remove temporary filters
remove_filter( 'posts_where', 'fictioneer_exclude_protected_posts' );
// Extra attributes
$attributes = [];
if ( $splide ) {
$attributes[] = "data-splide='{$splide}'";
}
?>
<section class="small-card-block latest-stories <?php echo $args['classes']; ?>" <?php echo implode( ' ', $attributes ); ?>>
<?php
if ( $args['splide'] === false ) {
echo '<div class="shortcode-json-invalid">' . __( 'Splide JSON is invalid and has been ignored.', 'fictioneer' ) . '</div>';
}
if ( $splide ) {
echo '<div class="splide__track">';
}
?>
<section class="small-card-block latest-stories <?php echo $args['classes']; ?>">
<?php if ( $entries->have_posts() ) : ?>
<ul class="grid-columns _collapse-on-mobile">
<ul class="grid-columns _collapse-on-mobile <?php if ( $splide ) { echo 'splide__list'; } ?>">
<?php while ( $entries->have_posts() ) : $entries->the_post(); ?>
<?php
@ -189,6 +208,10 @@ remove_filter( 'posts_where', 'fictioneer_exclude_protected_posts' );
$card_classes[] = '_no-footer-rating';
}
if ( $splide ) {
$card_classes[] = 'splide__slide';
}
// Truncate factor
$truncate_factor = $args['vertical'] ? '_4-4' : '_cq-3-4';
@ -354,4 +377,6 @@ remove_filter( 'posts_where', 'fictioneer_exclude_protected_posts' );
<div class="no-results"><?php _e( 'Nothing to show.', 'fictioneer' ); ?></div>
<?php endif; wp_reset_postdata(); ?>
<?php if ( $splide ) { echo '</div>'; } ?>
</section>

View File

@ -41,6 +41,7 @@
* @internal $args['footer_rating'] Whether to show the story age rating. Default true.
* @internal $args['classes'] String of additional CSS classes. Default empty.
* @internal $args['infobox'] Whether to show the info box and toggle.
* @internal $args['splide'] Configuration JSON for the Splide slider. Default empty.
*/
@ -48,6 +49,7 @@
defined( 'ABSPATH' ) OR exit;
// Setup
$splide = $args['splide'] ?? 0;
$card_counter = 0;
// Prepare query
@ -131,12 +133,29 @@ $entries = fictioneer_shortcode_query( $query_args );
// Remove temporary filters
remove_filter( 'posts_where', 'fictioneer_exclude_protected_posts' );
// Extra attributes
$attributes = [];
if ( $splide ) {
$attributes[] = "data-splide='{$splide}'";
}
?>
<section class="small-card-block latest-updates <?php echo $args['classes']; ?>" <?php echo implode( ' ', $attributes ); ?>>
<?php
if ( $args['splide'] === false ) {
echo '<div class="shortcode-json-invalid">' . __( 'Splide JSON is invalid and has been ignored.', 'fictioneer' ) . '</div>';
}
if ( $splide ) {
echo '<div class="splide__track">';
}
?>
<section class="small-card-block latest-updates <?php echo $args['classes']; ?>">
<?php if ( $entries->have_posts() ) : ?>
<ul class="grid-columns _collapse-on-mobile">
<ul class="grid-columns _collapse-on-mobile <?php if ( $splide ) { echo 'splide__list'; } ?>">
<?php while ( $entries->have_posts() ) : $entries->the_post(); ?>
<?php
@ -180,6 +199,10 @@ remove_filter( 'posts_where', 'fictioneer_exclude_protected_posts' );
$card_classes[] = '_no-chapter-dates';
}
if ( $splide ) {
$card_classes[] = 'splide__slide';
}
// Search for viable chapters...
$search_list = array_reverse( $story['chapter_ids'] );
@ -352,4 +375,6 @@ remove_filter( 'posts_where', 'fictioneer_exclude_protected_posts' );
<div class="no-results"><?php _e( 'Nothing to show.', 'fictioneer' ); ?></div>
<?php endif; wp_reset_postdata(); ?>
<?php if ( $splide ) { echo '</div>'; } ?>
</section>

View File

@ -42,6 +42,7 @@
* @internal $args['footer_date'] Whether to show the chapter date. Default true.
* @internal $args['footer_rating'] Whether to show the story/chapter age rating. Default true.
* @internal $args['classes'] String of additional CSS classes. Default empty.
* @internal $args['splide'] Configuration JSON for the Splide slider. Default empty.
*/
@ -49,6 +50,7 @@
defined( 'ABSPATH' ) OR exit;
// Setup
$splide = $args['splide'] ?? 0;
$render_count = 0;
$show_terms = ! in_array( $args['terms'], ['none', 'false'] );
$content_list_style = get_theme_mod( 'content_list_style', 'default' );
@ -134,12 +136,29 @@ $entries = fictioneer_shortcode_query( $query_args );
// Remove temporary filters
remove_filter( 'posts_where', 'fictioneer_exclude_protected_posts' );
// Extra attributes
$attributes = [];
if ( $splide ) {
$attributes[] = "data-splide='{$splide}'";
}
?>
<section class="latest-updates _list <?php echo $args['classes']; ?>" <?php echo implode( ' ', $attributes ); ?>>
<?php
if ( $args['splide'] === false ) {
echo '<div class="shortcode-json-invalid">' . __( 'Splide JSON is invalid and has been ignored.', 'fictioneer' ) . '</div>';
}
if ( $splide ) {
echo '<div class="splide__track">';
}
?>
<section class="latest-updates _list <?php echo $args['classes']; ?>">
<?php if ( $entries->have_posts() ) : ?>
<ul class="post-list _latest-updates">
<ul class="post-list _latest-updates <?php if ( $splide ) { echo 'splide__list'; } ?>">
<?php while ( $entries->have_posts() ) : $entries->the_post(); ?>
<?php
@ -221,6 +240,10 @@ remove_filter( 'posts_where', 'fictioneer_exclude_protected_posts' );
$classes[] = '_no-footer-rating';
}
if ( $splide ) {
$classes[] = 'splide__slide';
}
// Search for viable chapters...
$search_list = array_reverse( $story['chapter_ids'] );
$chapter_post = null;
@ -346,4 +369,6 @@ remove_filter( 'posts_where', 'fictioneer_exclude_protected_posts' );
<div class="no-results"><?php _e( 'Nothing to show.', 'fictioneer' ); ?></div>
<?php endif; wp_reset_postdata(); ?>
<?php if ( $splide ) { echo '</div>'; } ?>
</section>

View File

@ -44,6 +44,7 @@
* @internal $args['footer_status'] Whether to show the story status. Default true.
* @internal $args['footer_rating'] Whether to show the story age rating. Default true.
* @internal $args['classes'] String of additional CSS classes. Default empty.
* @internal $args['splide'] Configuration JSON for the Splide slider. Default empty.
*/
@ -51,6 +52,7 @@
defined( 'ABSPATH' ) OR exit;
// Setup
$splide = $args['splide'] ?? 0;
$card_counter = 0;
$show_terms = ! get_option( 'fictioneer_hide_taxonomies_on_story_cards' ) &&
! in_array( $args['type'], ['simple', 'single'] ) &&
@ -137,12 +139,29 @@ $entries = fictioneer_shortcode_query( $query_args );
// Remove temporary filters
remove_filter( 'posts_where', 'fictioneer_exclude_protected_posts' );
// Extra attributes
$attributes = [];
if ( $splide ) {
$attributes[] = "data-splide='{$splide}'";
}
?>
<section class="small-card-block latest-updates <?php echo $args['classes']; ?>" <?php echo implode( ' ', $attributes ); ?>>
<?php
if ( $args['splide'] === false ) {
echo '<div class="shortcode-json-invalid">' . __( 'Splide JSON is invalid and has been ignored.', 'fictioneer' ) . '</div>';
}
if ( $splide ) {
echo '<div class="splide__track">';
}
?>
<section class="small-card-block latest-updates <?php echo $args['classes']; ?>">
<?php if ( $entries->have_posts() ) : ?>
<ul class="grid-columns _collapse-on-mobile">
<ul class="grid-columns _collapse-on-mobile <?php if ( $splide ) { echo 'splide__list'; } ?>">
<?php while ( $entries->have_posts() ) : $entries->the_post(); ?>
<?php
@ -213,6 +232,10 @@ remove_filter( 'posts_where', 'fictioneer_exclude_protected_posts' );
$card_classes[] = '_no-footer-rating';
}
if ( $splide ) {
$card_classes[] = 'splide__slide';
}
// Search for viable chapters...
$search_list = array_reverse( $story['chapter_ids'] );
@ -466,4 +489,6 @@ remove_filter( 'posts_where', 'fictioneer_exclude_protected_posts' );
<div class="no-results"><?php _e( 'Nothing to show.', 'fictioneer' ); ?></div>
<?php endif; wp_reset_postdata(); ?>
<?php if ( $splide ) { echo '</div>'; } ?>
</section>

View File

@ -25,12 +25,18 @@
* @internal $args['taxonomies'] Array of taxonomy arrays. Default empty.
* @internal $args['relation'] Relationship between taxonomies.
* @internal $args['classes'] String of additional CSS classes. Default empty.
* @internal $args['splide'] Configuration JSON for the Splide slider. Default empty.
* @internal $args['height'] Override the item height. Default empty.
* @internal $args['aspect_ratio'] Aspect ratio of the item. Superseded by height. Default empty.
*/
// No direct access!
defined( 'ABSPATH' ) OR exit;
// Setup
$splide = $args['splide'] ?? 0;
// Prepare query
$query_args = array (
'fictioneer_query_name' => 'showcase',
@ -88,13 +94,64 @@ $query = fictioneer_shortcode_query( $query_args );
// Remove temporary filters
remove_filter( 'posts_where', 'fictioneer_exclude_protected_posts' );
// Extra attributes
$attributes = [];
if ( $splide ) {
$attributes[] = "data-splide='{$splide}'";
}
?>
<?php if ( $query->have_posts() ) : ?>
<section class="showcase container-inline-size <?php echo $args['classes']; ?>">
<ul class="showcase__list">
<section class="showcase container-inline-size <?php echo $args['classes']; ?>" <?php echo implode( ' ', $attributes ); ?>>
<?php
if ( $args['splide'] === false ) {
echo '<div class="shortcode-json-invalid">' . __( 'Splide JSON is invalid and has been ignored.', 'fictioneer' ) . '</div>';
}
if ( $splide ) {
echo '<div class="splide__track">';
}
// Item classes
$item_classes = '';
if ( $args['aspect_ratio'] ) {
$item_classes .= ' _aspect-ratio';
}
if ( $args['height'] ) {
$item_classes .= ' _custom-height';
}
if ( $splide ) {
$item_classes .= ' splide__slide';
}
// Item attributes
$attributes = array(
'style' => ''
);
if ( $args['aspect_ratio'] ) {
$attributes['style'] .= "--showcase-item-aspect-ratio: {$args['aspect_ratio']};";
}
if ( $args['height'] ) {
$attributes['style'] .= "--showcase-item-height: {$args['height']};";
}
$item_attributes = '';
foreach ( $attributes as $key => $value ) {
$item_attributes .= esc_attr( $key ) . '="' . esc_attr( $value ) . '" ';
}
?>
<ul class="showcase__list <?php if ( $splide ) { echo 'splide__list'; } ?>">
<?php while ( $query->have_posts() ) : $query->the_post(); ?>
<li class="showcase__list-item">
<li class="showcase__list-item <?php echo $item_classes; ?>" <?php echo $item_attributes; ?>>
<a class="showcase__list-item-link polygon" href="<?php the_permalink(); ?>">
<figure class="showcase__list-item-figure">
<?php
@ -149,5 +206,7 @@ remove_filter( 'posts_where', 'fictioneer_exclude_protected_posts' );
</li>
<?php endwhile; ?>
</ul>
<?php if ( $splide ) { echo '</div>'; } ?>
</section>
<?php endif; wp_reset_postdata(); ?>

View File

@ -2262,3 +2262,15 @@ function fcn_showAgeConfirmationModal() {
localStorage.removeItem('fcnAgeConfirmation');
});
}
// =============================================================================
// SPLIDE SLIDER (IF ANY)
// =============================================================================
document.addEventListener('DOMContentLoaded', () => {
_$$('.splide:not(.no-auto-splide, .is-initialized)').forEach(slider => {
if (typeof Splide !== 'undefined') {
new Splide(slider).mount();
}
});
});

View File

@ -21,7 +21,7 @@
}
}
&__list {
&__list:where(:not(.splide__list)) {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(#{get_clamp(160, 175, 375, 480)}, 1fr));
gap: var(--showcase-row-gap, max(3cqw, 1.5rem)) var(--showcase-row-col, max(3cqw, 1.5rem));
@ -35,13 +35,21 @@
&__list-item {
--focus-offset: 2px;
position: relative;
aspect-ratio: var(--showcase-item-aspect-ratio);
border-radius: var(--layout-border-radius-small);
box-shadow: var(--showcase-box-shadow, var(--box-shadow-m));
overflow: hidden;
max-width: max(420px, 100%);
height: max(64px, #{get_clamp(64, 96, 375, 768)});
contain: layout paint style; // Improve performance
&:where(:not(._aspect-ratio, ._custom-height)) {
height: max(64px, #{get_clamp(64, 96, 375, 768)});
}
&._custom-height {
height: var(--showcase-item-height);
}
@include bp(mobile-l) {
&:first-child:last-child {
width: max(360px, 50%);

View File

@ -605,11 +605,16 @@ button[type=submit]:where(:not(._inline)),
opacity: 0.5;
}
.no-results {
.no-results,
.shortcode-json-invalid {
color: var(--fg-950);
padding: 0 2px;
}
.shortcode-json-invalid {
margin: 2rem 0;
}
html:not(.logged-in) body:not(.logged-in) {
.checkmark {
display: none;

View File

@ -59,6 +59,15 @@
--strong-filter: none;
--invert-filter: invert(1); // Checkbox check
// === SPLIDE ================================================================
--splide-arrow: var(--bg-400);
--splide-arrow-hover: var(--bg-700);
--splide-arrow-active: var(--bg-700);
--splide-pagination: var(--bg-400);
--splide-pagination-hover: var(--bg-500);
--splide-pagination-active: var(--bg-700);
// === LITRPG ================================================================
--litrpg-background: var(--bg-50);

View File

@ -157,6 +157,15 @@
--strong-filter: brightness(1.05);
--invert-filter: invert(0); // Checkbox check
// === SPLIDE ================================================================
--splide-arrow: var(--bg-400);
--splide-arrow-hover: var(--bg-100);
--splide-arrow-active: var(--bg-100);
--splide-pagination: var(--bg-400);
--splide-pagination-hover: var(--bg-300);
--splide-pagination-active: var(--bg-100);
// === LITRPG ================================================================
--litrpg-background: var(--bg-50);

View File

@ -53,7 +53,7 @@ body:not(.is-editor):not(.is-admin) {
}
}
.grid-columns {
.grid-columns:where(:not(.splide__list)) {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(var(--grid-columns-min, 308px), 1fr));
gap:

172
src/scss/splide.scss Normal file
View File

@ -0,0 +1,172 @@
@import 'common/_functions';
@import 'common/_mixins';
@import 'common/_variables';
// Core
@keyframes splide-loading{0%{transform:rotate(0)}to{transform:rotate(1turn)}}.splide__track--draggable{-webkit-touch-callout:none;-webkit-user-select:none;-ms-user-select:none;user-select:none}.splide__track--fade>.splide__list>.splide__slide{margin:0!important;opacity:0;z-index:0}.splide__track--fade>.splide__list>.splide__slide.is-active{opacity:1;z-index:1}.splide--rtl{direction:rtl}.splide__track--ttb>.splide__list{display:block}.splide__container{box-sizing:border-box;position:relative}.splide__list{backface-visibility:hidden;display:-ms-flexbox;display:flex;height:100%;margin:0!important;padding:0!important}.splide.is-initialized:not(.is-active) .splide__list{display:block}.splide__pagination{-ms-flex-align:center;align-items:center;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-pack:center;justify-content:center;margin:0;pointer-events:none}.splide__pagination li{display:inline-block;line-height:1;list-style-type:none;margin:0;pointer-events:auto}.splide:not(.is-overflow) .splide__pagination{display:none}.splide__progress__bar{width:0}.splide{position:relative;visibility:hidden}.splide.is-initialized,.splide.is-rendered{visibility:visible}.splide__slide{backface-visibility:hidden;box-sizing:border-box;-ms-flex-negative:0;flex-shrink:0;list-style-type:none!important;margin:0;position:relative}.splide__slide img{vertical-align:bottom}.splide__spinner{animation:splide-loading 1s linear infinite;border:2px solid #999;border-left-color:transparent;border-radius:50%;bottom:0;contain:strict;display:inline-block;height:20px;left:0;margin:auto;position:absolute;right:0;top:0;width:20px}.splide__sr{clip:rect(0 0 0 0);border:0;height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.splide__toggle.is-active .splide__toggle__play,.splide__toggle__pause{display:none}.splide__toggle.is-active .splide__toggle__pause{display:inline}.splide__track{overflow:hidden;position:relative;z-index:0}
.splide {
--this-arrow-size: #{get_clamp(20, 40, 320, 640)};
--this-outset: 6px;
width: calc(100% + 2 * var(--this-outset));
max-width: 100vw;
transform: translateX(calc(-1 * var(--this-outset)));
padding-top: var(--this-arrow-vertical-padding, 0px);
padding-left: calc(var(--this-arrow-horizontal-padding, 0px));
padding-bottom: var(--this-arrow-vertical-padding, 0px);
padding-right: calc(var(--this-arrow-horizontal-padding, 0px) + var(--this-pagination-side-padding, 0px));
&:not(.is-initialized) {
visibility: visible;
.splide__slide:first-child {
width: 100%;
}
}
&.splide--ttb {
--this-outset: 0px;
.splide__slide {
height: auto !important;
}
.splide__track {
padding: 0 !important;
}
}
&:has(.splide__pagination) {
--this-arrow-offset: 9px; // Offset bottom pagination
}
&:has(.splide__arrows) {
--this-arrow-horizontal-padding: var(--this-arrow-size);
}
&:has(.splide__arrows--ttb) {
--this-arrow-offset: 0px; // No bottom pagination
--this-arrow-horizontal-padding: 0px;
--this-arrow-vertical-padding: var(--this-arrow-size);
}
&:has(.splide__pagination--ttb) {
--this-pagination-side-padding: 24px;
.splide__arrow--next {
right: 16px;
}
}
&__track {
padding: var(--this-outset) var(--this-outset) var(--this-pagination-vertical-padding, 16px) !important;
}
&.article-card-block .splide__track {
--this-pagination-vertical-padding: 0px;
.splide__pagination:not(.splide__pagination--ttb) {
margin-top: 16px;
}
}
&__arrow {
position: absolute;
z-index: 10;
top: calc(50% - var(--this-arrow-offset, 0px));
display: grid;
place-content: center;
line-height: 1;
height: calc(var(--this-arrow-size) * 2);
width: var(--this-arrow-size);
&--prev {
left: 0;
transform: translateY(-50%) scale(-1, 1);
}
&--next {
right: 0;
transform: translateY(-50%);
}
svg {
height: calc(var(--this-arrow-size) * .675);
width: calc(var(--this-arrow-size) * .675);
fill: var(--splide-arrow);
transition: fill .15s;
}
&:hover svg {
fill: var(--splide-arrow-hover);
}
&:active svg {
fill: var(--splide-arrow-active);
}
}
&__arrows--ttb {
.splide__arrow {
top: unset;
left: 50%;
right: unset;
transform: translateX(-50%) rotate(-90deg);
height: var(--this-arrow-size);
&--prev {
top: 0;
}
&--next {
bottom: 0;
transform: translateX(-50%) rotate(90deg);
}
}
}
&__pagination {
display: flex;
align-items: flex-start;
flex-wrap: wrap;
li {
display: block;
}
button {
--this-background: var(--splide-pagination);
cursor: pointer;
position: relative;
display: block;
padding: 8px;
transition: background-color .15s;
contain: strict;
&::after {
content: '';
position: absolute;
inset: 4px;
display: block;
background: var(--this-background);
border-radius: 50%;
}
&.is-active {
--this-background: var(--splide-pagination-active);
}
&:where(:not(.is-active)):hover {
--this-background: var(--splide-pagination-hover, var(--splide-pagination));
}
}
&--ttb {
position: absolute;
top: 50%;
right: 0;
flex-direction: column;
transform: translateY(-50%);
}
}
}