$opts edit (0.52.0: true also loads the editable cells' script, `rooster-table-edit`, * which depends on the engine); local (0.62.0: true also loads the local table's * glue, `rooster-table-local`: roosterTable.local( frame ); 0.65.7: and its totals * row's script, `rooster-table-totals`, out of the glue); filters (0.64.4: true * also loads the filter controls, `rooster-table-filters`: the calendar, the * presets, the slider and the buckets of a table's declared filters; it depends on * nothing); counts (0.65.6: true also loads a declared filter's counts, * `rooster-table-counts`, after the glue: `local` comes with it); text_size * (0.68.0: true also loads a table's text size, `rooster-table-size`, which * depends on nothing: rooster_table_text_size_attrs() makes its button). */ function rooster_table_engine( string $dir, string $url, array $opts = array() ): string { $handle = 'rooster-table'; $dir = rtrim( str_replace( '\\', '/', $dir ), '/' ); $read = is_file( $dir . '/version.php' ) ? include $dir . '/version.php' : ''; $ver = is_string( $read ) && 1 === preg_match( '/^\d+\.\d+\.\d+/', $read ) ? $read : '0.0.0'; $known = wp_scripts()->query( $handle, 'registered' ); if ( false === $known || version_compare( $ver, (string) $known->ver, '>' ) ) { wp_deregister_script( $handle ); $min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min'; wp_register_script( $handle, rtrim( $url, '/' ) . '/assets/table' . $min . '.js', array(), $ver, array( 'in_footer' => true, 'strategy' => 'defer', ) ); } wp_enqueue_script( $handle ); if ( ! empty( $opts['edit'] ) ) { $known = wp_scripts()->query( $handle . '-edit', 'registered' ); if ( false === $known || version_compare( $ver, (string) $known->ver, '>' ) ) { wp_deregister_script( $handle . '-edit' ); $min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min'; wp_register_script( $handle . '-edit', rtrim( $url, '/' ) . '/assets/table-edit' . $min . '.js', array( $handle ), $ver, array( 'in_footer' => true, 'strategy' => 'defer', ) ); } wp_add_inline_script( $handle . '-edit', 'window.roosterTableEditLabels = ' . wp_json_encode( rooster_table_edit_labels() ) . ';', 'before' ); wp_enqueue_script( $handle . '-edit' ); } if ( ! empty( $opts['local'] ) || ! empty( $opts['counts'] ) ) { $known = wp_scripts()->query( $handle . '-local', 'registered' ); if ( false === $known || version_compare( $ver, (string) $known->ver, '>' ) ) { wp_deregister_script( $handle . '-local' ); $min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min'; wp_register_script( $handle . '-local', rtrim( $url, '/' ) . '/assets/table-local' . $min . '.js', array( $handle ), $ver, array( 'in_footer' => true, 'strategy' => 'defer', ) ); } wp_enqueue_script( $handle . '-local' ); $known = wp_scripts()->query( $handle . '-totals', 'registered' ); if ( false === $known || version_compare( $ver, (string) $known->ver, '>' ) ) { wp_deregister_script( $handle . '-totals' ); $min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min'; wp_register_script( $handle . '-totals', rtrim( $url, '/' ) . '/assets/table-totals' . $min . '.js', array( $handle . '-local' ), $ver, array( 'in_footer' => true, 'strategy' => 'defer', ) ); } wp_enqueue_script( $handle . '-totals' ); // 0.65.7: out of the glue; a front-end table's totals as before } if ( ! empty( $opts['counts'] ) ) { $known = wp_scripts()->query( $handle . '-counts', 'registered' ); if ( false === $known || version_compare( $ver, (string) $known->ver, '>' ) ) { wp_deregister_script( $handle . '-counts' ); $min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min'; wp_register_script( $handle . '-counts', rtrim( $url, '/' ) . '/assets/table-counts' . $min . '.js', array( $handle . '-local' ), $ver, array( 'in_footer' => true, 'strategy' => 'defer', ) ); } wp_enqueue_script( $handle . '-counts' ); } if ( ! empty( $opts['text_size'] ) ) { $known = wp_scripts()->query( $handle . '-size', 'registered' ); if ( false === $known || version_compare( $ver, (string) $known->ver, '>' ) ) { wp_deregister_script( $handle . '-size' ); $min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min'; wp_register_script( $handle . '-size', rtrim( $url, '/' ) . '/assets/table-size' . $min . '.js', array(), $ver, array( 'in_footer' => true, 'strategy' => 'defer', ) ); } wp_enqueue_script( $handle . '-size' ); } if ( ! empty( $opts['filters'] ) ) { $known = wp_scripts()->query( $handle . '-filters', 'registered' ); if ( false === $known || version_compare( $ver, (string) $known->ver, '>' ) ) { wp_deregister_script( $handle . '-filters' ); $min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min'; wp_register_script( $handle . '-filters', rtrim( $url, '/' ) . '/assets/filters' . $min . '.js', array(), $ver, array( 'in_footer' => true, 'strategy' => 'defer', ) ); } wp_enqueue_script( $handle . '-filters' ); } if ( ! empty( $opts['select'] ) ) { // 0.90.0: the searchable select on the storefront, for a table whose filter is a multiple choice (the chips // control's combobox): its script (assets/select.js, upgrading only the comboboxes inside the table's // `.rooster-admin-front` scope) and its sheet (assets/front-select.css: the combobox and its popup in the // theme's tokens, the closed box from the first paint), with the words in the site's language. $known = wp_scripts()->query( $handle . '-select', 'registered' ); if ( false === $known || version_compare( $ver, (string) $known->ver, '>' ) ) { wp_deregister_script( $handle . '-select' ); wp_deregister_style( $handle . '-select' ); $min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min'; wp_register_script( $handle . '-select', rtrim( $url, '/' ) . '/assets/select' . $min . '.js', array(), $ver, array( 'in_footer' => true, 'strategy' => 'defer', ) ); wp_register_style( $handle . '-select', rtrim( $url, '/' ) . '/assets/front-select' . $min . '.css', array(), $ver ); wp_add_inline_script( $handle . '-select', 'window.roosterSelectL10n = ' . wp_json_encode( rooster_table_select_words() ) . ';', 'before' ); } wp_enqueue_script( $handle . '-select' ); wp_enqueue_style( $handle . '-select' ); } return $handle; } } if ( ! function_exists( 'rooster_table_select_words' ) ) { /** * The searchable select's words in the site's language on the storefront (0.90.0), the chrome's own (Chrome.php). * * @return array */ function rooster_table_select_words(): array { return array( 'search' => __( 'Search…', 'ai-eshop-optimizer' ), 'choose' => __( 'Choose…', 'ai-eshop-optimizer' ), 'noResults' => __( 'No results', 'ai-eshop-optimizer' ), 'searching' => __( 'Searching…', 'ai-eshop-optimizer' ), /* translators: %d: a number of characters. */ 'typeMore' => __( 'Type at least %d characters to search', 'ai-eshop-optimizer' ), /* translators: %d: a number of options. */ 'more' => __( '%d more: type to narrow the list', 'ai-eshop-optimizer' ), /* translators: %s: the chosen option's label. */ 'remove' => __( 'Remove %s', 'ai-eshop-optimizer' ), 'clear' => __( 'Clear', 'ai-eshop-optimizer' ), /* translators: %d: a number of options. */ 'selectAll' => __( 'Select all shown (%d)', 'ai-eshop-optimizer' ), /* translators: %d: a number of options. */ 'selected' => __( '%d selected', 'ai-eshop-optimizer' ), 'separator' => _x( ', ', 'between chosen labels', 'ai-eshop-optimizer' ), 'error' => __( 'The search failed. Try again.', 'ai-eshop-optimizer' ), ); } } if ( ! function_exists( 'rooster_table_text_size' ) ) { /** * A front-end table's text size for the signed-in person (0.68.0): its level, 1 to 5 (80, 90, 100, 110, 125 %), * 3 when they chose none or nobody is signed in. Read from the library's preferences (the user meta * `rooster_admin_prefs`, key `text_sizes`, per product: Prefs::TEXT_SIZES), so the admin and the front end share a * table's size. Print it on the table's container as data-ra-text-size, so the first paint has it. * * @param string $key The table's key (its DOM id). * @param string $product The product's slug ("rooster-lms"). */ function rooster_table_text_size( string $key, string $product ): int { $user = get_current_user_id(); $row = $user > 0 ? get_user_meta( $user, 'rooster_admin_prefs', true ) : null; $size = is_array( $row ) && is_array( $row['text_sizes'][ $product ] ?? null ) ? (int) ( $row['text_sizes'][ $product ][ $key ] ?? 3 ) : 3; return $size >= 1 && $size <= 5 ? $size : 3; } } if ( ! function_exists( 'rooster_table_text_size_attrs' ) ) { /** * A front-end table's text size button's attributes (0.68.0), escaped, for the product's own `