WooCommerce 尺寸图表插件

BDFG Size Chart for WooCommerce是一个功能强大且灵活的插件,可让您为WooCommerce产品创建可自定义的尺寸图表。通过显示全面的尺寸信息,帮助您的客户选择合适的尺寸并降低回报率。

插件特征 

相关文章: WooCommerce 产品比较工具

– 为您的产品创建无限尺寸图表
– 三个显示选项:选项卡,弹出窗口或直列
– 在产品页面上选择大小图表的位置
– 将尺寸图表分配给特定产品或产品类别
– 使用预定义的模板或创建自定义尺寸图表
– 易于使用的表构建器,带有添加/删除行和列
– 导入和导出大小图表,用于多个站点
– 在所有设备上都起作用的完全响应迅速的设计
– 短代码支持以在任何地方显示尺寸图表

<?php
/**
* Plugin Name: BDFG Size Chart for WooCommerce
* Plugin URI: https://beiduofengou.net/2024/12/15/bdfg-size-chart-for-woocommerce/
* Description: Add customizable size charts to your WooCommerce products. Choose from available templates or create your own to improve your customers' shopping experience and reduce return rates.
* Version: 2.3.0
* Author: beiduofengou
* Author URI: https://beiduofengou.net
* Text Domain: bdfg-size-chart
* Domain Path: /languages
* WC requires at least: 3.0.0
* WC tested up to: 7.0.0
*
* @package BDFG_Size_Chart
* @category Core
* @author beiduofengou
*/

// Direct access protection
if (!defined('ABSPATH')) {
exit; // Exit if accessed directly
}

// Define plugin constants
define('BDFG_SC_VERSION', '2.3.0');
define('BDFG_SC_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('BDFG_SC_PLUGIN_URL', plugin_dir_url(__FILE__));
define('BDFG_SC_PLUGIN_BASENAME', plugin_basename(__FILE__));

/**
* Main plugin class
*
* Handles initialization and core functionality of the plugin
*/
class BDFG_Size_Chart {

/**
* Single instance of the class
*
* @var object
*/
protected static $instance = null;

/**
* Main class constructor - sets up the plugin
*/
public function __construct() {
// Load plugin text domain for translations
add_action('plugins_loaded', array($this, 'load_plugin_textdomain'));

// Check if WooCommerce is active before initializing
if ($this->is_woocommerce_active()) {
$this->init();
} else {
// Show notice if WooCommerce is missing
add_action('admin_notices', array($this, 'woocommerce_missing_notice'));
}
}

/**
* Check if WooCommerce is active
*
* @since 1.0.0
* @return boolean True if WooCommerce is active
*/
private function is_woocommerce_active() {
// Get active plugins
$active_plugins = (array) get_option('active_plugins', array());

// Check for multisite
if (is_multisite()) {
$active_plugins = array_merge($active_plugins, get_site_option('active_sitewide_plugins', array()));
}

// Check if WooCommerce is in the active plugins list
return in_array('woocommerce/woocommerce.php', $active_plugins) || array_key_exists('woocommerce/woocommerce.php', $active_plugins);
}

/**
* Admin notice for missing WooCommerce
*
* @since 1.0.0
*/
public function woocommerce_missing_notice() {
?>
<div class="notice notice-error">
<p><?php _e('BDFG Size Chart requires WooCommerce to be installed and active. You can download WooCommerce from the WordPress plugin repository.', 'bdfg-size-chart'); ?></p>
</div>
<?php
}

/**
* Load plugin text domain
*
* @since 1.0.0
*/
public function load_plugin_textdomain() {
load_plugin_textdomain('bdfg-size-chart', false, dirname(plugin_basename(__FILE__)) . '/languages/');
}

/**
* Initialize plugin components
*
* @since 1.0.0
*/
private function init() {
// Include required files
$this->includes();

// Register custom post type for size charts
add_action('init', array($this, 'register_post_type'));

// Register and enqueue admin scripts and styles
add_action('admin_enqueue_scripts', array($this, 'admin_scripts'));

// Register and enqueue frontend scripts and styles
add_action('wp_enqueue_scripts', array($this, 'frontend_scripts'));

// Add plugin action links
add_filter('plugin_action_links_' . BDFG_SC_PLUGIN_BASENAME, array($this, 'add_action_links'));

// Add meta boxes to size chart and product edit screens
add_action('add_meta_boxes', array($this, 'add_meta_boxes'));

// Save meta box data when post is saved
add_action('save_post', array($this, 'save_meta_box_data'));

// Display size chart on product page
add_action('woocommerce_before_single_product_summary', array($this, 'display_size_chart'), 25);

// Add plugin admin menu
add_action('admin_menu', array($this, 'admin_menu'));

// Register AJAX handler for template loading
add_action('wp_ajax_bdfg_load_template', array($this, 'ajax_load_template'));

// Register shortcode for displaying size charts
add_shortcode('bdfg_size_chart', array($this, 'shortcode_size_chart'));
}

/**
* Include required files
*
* @since 1.0.0
*/
private function includes() {
// Include template functions
require_once BDFG_SC_PLUGIN_DIR . 'includes/bdfg-size-chart-template-functions.php';

// Include admin functions if in admin area
if (is_admin()) {
require_once BDFG_SC_PLUGIN_DIR . 'includes/admin/bdfg-size-chart-admin-functions.php';
}
}

/**
* Register size chart post type
*
* @since 1.0.0
*/
public function register_post_type() {
$labels = array(
'name' => _x('Size Charts', 'post type general name', 'bdfg-size-chart'),
'singular_name' => _x('Size Chart', 'post type singular name', 'bdfg-size-chart'),
'menu_name' => _x('Size Charts', 'admin menu', 'bdfg-size-chart'),
'name_admin_bar' => _x('Size Chart', 'add new on admin bar', 'bdfg-size-chart'),
'add_new' => _x('Add New', 'size chart', 'bdfg-size-chart'),
'add_new_item' => __('Add New Size Chart', 'bdfg-size-chart'),
'new_item' => __('New Size Chart', 'bdfg-size-chart'),
'edit_item' => __('Edit Size Chart', 'bdfg-size-chart'),
'view_item' => __('View Size Chart', 'bdfg-size-chart'),
'all_items' => __('All Size Charts', 'bdfg-size-chart'),
'search_items' => __('Search Size Charts', 'bdfg-size-chart'),
'parent_item_colon' => __('Parent Size Charts:', 'bdfg-size-chart'),
'not_found' => __('No size charts found.', 'bdfg-size-chart'),
'not_found_in_trash' => __('No size charts found in Trash.', 'bdfg-size-chart')
);

$args = array(
'labels' => $labels,
'description' => __('Size Charts for WooCommerce products.', 'bdfg-size-chart'),
'public' => false,
'publicly_queryable' => false,
'show_ui' => true,
'show_in_menu' => false,
'query_var' => true,
'rewrite' => false,
'capability_type' => 'post',
'has_archive' => false,
'hierarchical' => false,
'menu_position' => null,
'supports' => array('title', 'editor')
);

register_post_type('bdfg_size_chart', $args);
}

/**
* Enqueue admin scripts and styles
*
* @since 1.0.0
* @param string $hook Current admin page
*/
public function admin_scripts($hook) {
$screen = get_current_screen();

// Only load on size chart edit screen or products page
if (($hook == 'post.php' || $hook == 'post-new.php') &&
($screen->post_type == 'bdfg_size_chart' || $screen->post_type == 'product')) {

// Admin styles
wp_enqueue_style(
'bdfg-size-chart-admin',
BDFG_SC_PLUGIN_URL . 'assets/css/admin.css',
array(),
BDFG_SC_VERSION
);

// Admin scripts
wp_enqueue_script(
'bdfg-size-chart-admin',
BDFG_SC_PLUGIN_URL . 'assets/js/admin.js',
array('jquery', 'jquery-ui-sortable'),
BDFG_SC_VERSION,
true
);

// Localize script with required data and translations
wp_localize_script(
'bdfg-size-chart-admin',
'bdfg_size_chart_params',
array(
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('bdfg_size_chart_nonce'),
'strings' => array(
'confirm_delete' => __('Are you sure you want to delete this chart?', 'bdfg-size-chart'),
'add_row' => __('Add Row', 'bdfg-size-chart'),
'add_column' => __('Add Column', 'bdfg-size-chart'),
'remove' => __('Remove', 'bdfg-size-chart'),
'loading' => __('Loading...', 'bdfg-size-chart'),
'save_success' => __('Size chart data saved successfully.', 'bdfg-size-chart'),
'save_error' => __('Error saving size chart data.', 'bdfg-size-chart'),
),
)
);
}

// Size chart list page
if ($hook == 'woocommerce_page_bdfg-size-charts') {
wp_enqueue_style(
'bdfg-size-chart-list',
BDFG_SC_PLUGIN_URL . 'assets/css/admin-list.css',
array(),
BDFG_SC_VERSION
);
}
}

/**
* Enqueue frontend scripts and styles
*
* @since 1.0.0
*/
public function frontend_scripts() {
// Only load on product pages
if (is_product()) {
wp_enqueue_style(
'bdfg-size-chart-frontend',
BDFG_SC_PLUGIN_URL . 'assets/css/frontend.css',
array(),
BDFG_SC_VERSION
);

wp_enqueue_script(
'bdfg-size-chart-frontend',
BDFG_SC_PLUGIN_URL . 'assets/js/frontend.js',
array('jquery'),
BDFG_SC_VERSION,
true
);

// Localize script
wp_localize_script(
'bdfg-size-chart-frontend',
'bdfg_frontend_params',
array(
'i18n_close' => __('Close', 'bdfg-size-chart')
)
);
}
}

/**
* Add custom action links on plugin page
*
* @since 1.0.0
* @param array $links Default plugin action links
* @return array Modified plugin action links
*/
public function add_action_links($links) {
$custom_links = array(
'<a href="' . admin_url('admin.php?page=bdfg-size-charts') . '">' . __('Settings', 'bdfg-size-chart') . '</a>'
);

return array_merge($custom_links, $links);
}

/**
* Add meta boxes to size chart and product edit screens
*
* @since 1.0.0
*/
public function add_meta_boxes() {
// Size chart settings meta box
add_meta_box(
'bdfg_size_chart_settings',
__('Size Chart Settings', 'bdfg-size-chart'),
array($this, 'render_settings_meta_box'),
'bdfg_size_chart',
'normal',
'high'
);

// Size chart categories meta box
add_meta_box(
'bdfg_size_chart_categories',
__('Product Categories', 'bdfg-size-chart'),
array($this, 'render_categories_meta_box'),
'bdfg_size_chart',
'side',
'default'
);

// Product settings meta box
add_meta_box(
'bdfg_product_size_chart',
__('Size Chart', 'bdfg-size-chart'),
array($this, 'render_product_meta_box'),
'product',
'side',
'default'
);
}

/**
* Render settings meta box
*
* @since 1.0.0
* @param WP_Post $post Current post object
*/
public function render_settings_meta_box($post) {
// Add a nonce field for security
wp_nonce_field('bdfg_size_chart_settings_meta_box', 'bdfg_size_chart_settings_meta_box_nonce');

// Get current values
$chart_type = get_post_meta($post->ID, '_bdfg_chart_type', true);
$chart_position = get_post_meta($post->ID, '_bdfg_chart_position', true);
$chart_label = get_post_meta($post->ID, '_bdfg_chart_label', true);

// Set default values if empty
if (empty($chart_type)) {
$chart_type = 'tab';
}

if (empty($chart_position)) {
$chart_position = 'before_add_to_cart';
}

if (empty($chart_label)) {
$chart_label = __('Size Chart', 'bdfg-size-chart');
}

?>
<table class="form-table">
<tr>
<th scope="row">
<label for="bdfg_chart_type"><?php _e('Display Type', 'bdfg-size-chart'); ?></label>
</th>
<td>
<select id="bdfg_chart_type" name="bdfg_chart_type">
<option value="tab" <?php selected($chart_type, 'tab'); ?>><?php _e('Tab', 'bdfg-size-chart'); ?></option>
<option value="popup" <?php selected($chart_type, 'popup'); ?>><?php _e('Popup', 'bdfg-size-chart'); ?></option>
<option value="inline" <?php selected($chart_type, 'inline'); ?>><?php _e('Inline', 'bdfg-size-chart'); ?></option>
</select>
<p class="description"><?php _e('Choose how to display the size chart on product pages.', 'bdfg-size-chart'); ?></p>
</td>
</tr>
<tr>
<th scope="row">
<label for="bdfg_chart_position"><?php _e('Chart Position', 'bdfg-size-chart'); ?></label>
</th>
<td>
<select id="bdfg_chart_position" name="bdfg_chart_position">
<option value="before_add_to_cart" <?php selected($chart_position, 'before_add_to_cart'); ?>><?php _e('Before Add to Cart button', 'bdfg-size-chart'); ?></option>
<option value="after_add_to_cart" <?php selected($chart_position, 'after_add_to_cart'); ?>><?php _e('After Add to Cart button', 'bdfg-size-chart'); ?></option>
<option value="after_product_summary" <?php selected($chart_position, 'after_product_summary'); ?>><?php _e('After Product Summary', 'bdfg-size-chart'); ?></option>
</select>
<p class="description"><?php _e('Choose where to display the size chart on the product page.', 'bdfg-size-chart'); ?></p>
</td>
</tr>
<tr>
<th scope="row">
<label for="bdfg_chart_label"><?php _e('Button/Tab Label', 'bdfg-size-chart'); ?></label>
</th>
<td>
<input type="text" id="bdfg_chart_label" name="bdfg_chart_label" value="<?php echo esc_attr($chart_label); ?>" class="regular-text">
<p class="description"><?php _e('Text that will appear on the button or tab.', 'bdfg-size-chart'); ?></p>
</td>
</tr>
</table>

<div class="bdfg-chart-builder">
<h3><?php _e('Size Chart Builder', 'bdfg-size-chart'); ?></h3>
<p><?php _e('Build your size chart using the table below. Use the buttons to add or remove rows and columns as needed.', 'bdfg-size-chart'); ?></p>

<?php
// Get saved table data
$table_data = get_post_meta($post->ID, '_bdfg_chart_table', true);

// Default table if empty
if (empty($table_data)) {
$table_data = array(
array('Size', 'Chest (inches)', 'Waist (inches)'),
array('S', '36-38', '30-32'),
array('M', '39-41', '33-35'),
array('L', '42-44', '36-38'),
array('XL', '45-47', '39-41')
);
}
?>

<div class="bdfg-table-controls">
<button type="button" class="button bdfg-add-row"><?php _e('Add Row', 'bdfg-size-chart'); ?></button>
<button type="button" class="button bdfg-add-column"><?php _e('Add Column', 'bdfg-size-chart'); ?></button>
</div>

<div class="bdfg-table-container">
<table class="bdfg-chart-table">
<tbody>
<?php foreach ($table_data as $row_index => $row) : ?>
<tr class="bdfg-table-row">
<?php foreach ($row as $col_index => $cell) : ?>
<td>
<input type="text" name="bdfg_chart_table[<?php echo $row_index; ?>][<?php echo $col_index; ?>]" value="<?php echo esc_attr($cell); ?>">
<?php if ($row_index === 0 && $col_index === 0) : ?>
<span class="bdfg-cell-actions">
<a href="#" class="bdfg-remove-row" title="<?php _e('Remove Row', 'bdfg-size-chart'); ?>">-</a>
<a href="#" class="bdfg-remove-column" title="<?php _e('Remove Column', 'bdfg-size-chart'); ?>">-</a>
</span>
<?php elseif ($row_index === 0) : ?>
<a href="#" class="bdfg-remove-column" title="<?php _e('Remove Column', 'bdfg-size-chart'); ?>">-</a>
<?php elseif ($col_index === 0) : ?>
<a href="#" class="bdfg-remove-row" title="<?php _e('Remove Row', 'bdfg-size-chart'); ?>">-</a>
<?php endif; ?>
</td>
<?php endforeach; ?>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>

<div class="bdfg-template-selection">
<h3><?php _e('Chart Templates', 'bdfg-size-chart'); ?></h3>
<p><?php _e('Select a predefined template to get started quickly:', 'bdfg-size-chart'); ?></p>

<select id="bdfg_chart_template" name="bdfg_chart_template">
<option value=""><?php _e('Custom Chart', 'bdfg-size-chart'); ?></option>
<option value="mens_clothing"><?php _e("Men's Clothing", 'bdfg-size-chart'); ?></option>
<option value="womens_clothing"><?php _e("Women's Clothing", 'bdfg-size-chart'); ?></option>
<option value="shoes"><?php _e('Shoes', 'bdfg-size-chart'); ?></option>
<option value="kids_clothing"><?php _e("Kid's Clothing", 'bdfg-size-chart'); ?></option>
</select>

<button type="button" class="button bdfg-load-template"><?php _e('Load Template', 'bdfg-size-chart'); ?></button>
<span class="spinner bdfg-spinner"></span>
</div>
</div>
<?php
}

/**
* Render categories meta box
*
* @since 1.0.0
* @param WP_Post $post Current post object
*/
public function render_categories_meta_box($post) {
wp_nonce_field('bdfg_size_chart_categories_meta_box', 'bdfg_size_chart_categories_meta_box_nonce');

// Get product categories
$product_categories = get_terms(array(
'taxonomy' => 'product_cat',
'hide_empty' => false,
));

// Get saved categories
$selected_categories = get_post_meta($post->ID, '_bdfg_chart_categories', true);

if (!is_array($selected_categories)) {
$selected_categories = array();
}

if (!empty($product_categories)) :
?>
<p><?php _e('Select product categories to apply this size chart automatically:', 'bdfg-size-chart'); ?></p>

<div class="bdfg-categories-wrapper">
<ul class="bdfg-categories-list">
<?php foreach ($product_categories as $category) : ?>
<li>
<label>
<input type="checkbox" name="bdfg_chart_categories[]" value="<?php echo esc_attr($category->term_id); ?>" <?php checked(in_array($category->term_id, $selected_categories)); ?>>
<?php echo esc_html($category->name); ?>
</label>
</li>
<?php endforeach; ?>
</ul>
</div>

<p class="howto"><?php _e('If no category is selected, this size chart will not be automatically applied to any product.', 'bdfg-size-chart'); ?></p>
<?php
else :
?>
<p><?php _e('No product categories found. Create some categories first.', 'bdfg-size-chart'); ?></p>
<?php
endif;
}

/**
* Render product meta box
*
* @since 1.0.0
* @param WP_Post $post Current post object
*/
public function render_product_meta_box($post) {
wp_nonce_field('bdfg_product_size_chart_meta_box', 'bdfg_product_size_chart_meta_box_nonce');

// Get size charts
$size_charts = get_posts(array(
'post_type' => 'bdfg_size_chart',
'posts_per_page' => -1,
'orderby' => 'title',
'order' => 'ASC',
));

// Get selected chart
$selected_chart = get_post_meta($post->ID, '_bdfg_product_size_chart', true);

// Get product categories
$product_categories = wp_get_post_terms($post->ID, 'product_cat', array('fields' => 'ids'));

// Get default chart based on category
$default_chart = 0;
if (empty($selected_chart) && !empty($product_categories)) {
foreach ($size_charts as $chart) {
$chart_categories = get_post_meta($chart->ID, '_bdfg_chart_categories', true);
if (!is_array($chart_categories)) {
continue;
}

$intersect = array_intersect($product_categories, $chart_categories);
if (!empty($intersect)) {
$default_chart = $chart->ID;
break;
}
}
}

if (empty($selected_chart) && !empty($default_chart)) {
$selected_chart = $default_chart;
}

?>
<p><?php _e('Select a size chart for this product:', 'bdfg-size-chart'); ?></p>
<select name="bdfg_product_size_chart" id="bdfg_product_size_chart">
<option value=""><?php _e('None', 'bdfg-size-chart'); ?></option>
<?php foreach ($size_charts as $chart) : ?>
<option value="<?php echo esc_attr($chart->ID); ?>" <?php selected($selected_chart, $chart->ID); ?>>
<?php echo esc_html($chart->post_title); ?>
</option>
<?php endforeach; ?>
</select>

<?php if (empty($size_charts)) : ?>
<p><?php _e('No size charts found.', 'bdfg-size-chart'); ?></p>
<?php endif; ?>

<p>
<a href="<?php echo admin_url('post-new.php?post_type=bdfg_size_chart'); ?>" target="_blank">
<?php _e('Create new size chart', 'bdfg-size-chart'); ?>
</a>
</p>

<?php if (!empty($selected_chart)) : ?>
<p>
<a href="<?php echo admin_url('post.php?post=' . $selected_chart . '&action=edit'); ?>" target="_blank">
<?php _e('Edit selected chart', 'bdfg-size-chart'); ?>
</a>
</p>
<?php endif; ?>
<?php
}

/**
* Save meta box data
*
* @since 1.0.0
* @param int $post_id Post ID
*/
public function save_meta_box_data($post_id) {
// Check if post is a size chart
if (get_post_type($post_id) === 'bdfg_size_chart') {
// Save size chart settings
if (isset($_POST['bdfg_size_chart_settings_meta_box_nonce']) &&
wp_verify_nonce($_POST['bdfg_size_chart_settings_meta_box_nonce'], 'bdfg_size_chart_settings_meta_box')) {

// Save chart type
if (isset($_POST['bdfg_chart_type'])) {
update_post_meta($post_id, '_bdfg_chart_type', sanitize_text_field($_POST['bdfg_chart_type']));
}

// Save chart position
if (isset($_POST['bdfg_chart_position'])) {
update_post_meta($post_id, '_bdfg_chart_position', sanitize_text_field($_POST['bdfg_chart_position']));
}

// Save chart label
if (isset($_POST['bdfg_chart_label'])) {
update_post_meta($post_id, '_bdfg_chart_label', sanitize_text_field($_POST['bdfg_chart_label']));
}

// Save table data
if (isset($_POST['bdfg_chart_table']) && is_array($_POST['bdfg_chart_table'])) {
$table_data = array();

foreach ($_POST['bdfg_chart_table'] as $row) {
$clean_row = array();
foreach ($row as $cell) {
$clean_row[] = sanitize_text_field($cell);
}
$table_data[] = $clean_row;
}

update_post_meta($post_id, '_bdfg_chart_table', $table_data);
}
}

// Save categories
if (isset($_POST['bdfg_size_chart_categories_meta_box_nonce']) &&
wp_verify_nonce($_POST['bdfg_size_chart_categories_meta_box_nonce'], 'bdfg_size_chart_categories_meta_box')) {

$categories = isset($_POST['bdfg_chart_categories']) ? array_map('intval', $_POST['bdfg_chart_categories']) : array();
update_post_meta($post_id, '_bdfg_chart_categories', $categories);
}
}

// Check if post is a product
if (get_post_type($post_id) === 'product') {
// Save product size chart
if (isset($_POST['bdfg_product_size_chart_meta_box_nonce']) &&
wp_verify_nonce($_POST['bdfg_product_size_chart_meta_box_nonce'], 'bdfg_product_size_chart_meta_box')) {

$chart_id = isset($_POST['bdfg_product_size_chart']) ? intval($_POST['bdfg_product_size_chart']) : '';
update_post_meta($post_id, '_bdfg_product_size_chart', $chart_id);
}
}
}

/**
* Display size chart on product page
*
* @since 1.0.0
*/
public function display_size_chart() {
global $product;

if (!$product) {
return;
}

$product_id = $product->get_id();

// Get assigned size chart for this product
$size_chart_id = get_post_meta($product_id, '_bdfg_product_size_chart', true);

// If no chart is assigned, try to find a chart based on product categories
if (empty($size_chart_id)) {
$product_categories = wp_get_post_terms($product_id, 'product_cat', array('fields' => 'ids'));

if (!empty($product_categories)) {
// Get all size charts
$size_charts = get_posts(array(
'post_type' => 'bdfg_size_chart',
'posts_per_page' => -1,
));

foreach ($size_charts as $chart) {
$chart_categories = get_post_meta($chart->ID, '_bdfg_chart_categories', true);

if (!is_array($chart_categories)) {
continue;
}

$intersect = array_intersect($product_categories, $chart_categories);

if (!empty($intersect)) {
$size_chart_id = $chart->ID;
break;
}
}
}
}

if (empty($size_chart_id)) {
return;
}

// Get chart data
$chart_type = get_post_meta($size_chart_id, '_bdfg_chart_type', true);
$chart_label = get_post_meta($size_chart_id, '_bdfg_chart_label', true);
$chart_content = get_post_field('post_content', $size_chart_id);
$chart_title = get_the_title($size_chart_id);
$table_data = get_post_meta($size_chart_id, '_bdfg_chart_table', true);

// Render chart based on type
switch ($chart_type) {
case 'popup':
$this->render_popup_chart($size_chart_id, $chart_title, $chart_label, $chart_content, $table_data);
break;

case 'tab':
$this->add_size_chart_tab($size_chart_id, $chart_title, $chart_label, $chart_content, $table_data);
break;

case 'inline':
default:
$this->render_inline_chart($size_chart_id, $chart_title, $chart_content, $table_data);
break;
}
}

/**
* Render popup size chart
*
* @since 1.0.0
* @param int $chart_id Chart ID
* @param string $chart_title Chart title
* @param string $chart_label Chart label
* @param string $chart_content Chart content
* @param array $table_data Chart table data
*/
private function render_popup_chart($chart_id, $chart_title, $chart_label, $chart_content, $table_data) {
if (empty($chart_label)) {
$chart_label = __('Size Chart', 'bdfg-size-chart');
}

// Check chart position
$chart_position = get_post_meta($chart_id, '_bdfg_chart_position', true);

if ($chart_position === 'after_add_to_cart') {
add_action('woocommerce_after_add_to_cart_button', function() use ($chart_id, $chart_title, $chart_label, $chart_content, $table_data) {
$this->output_popup_html($chart_id, $chart_title, $chart_label, $chart_content, $table_data);
}, 10);
} elseif ($chart_position === 'after_product_summary') {
add_action('woocommerce_after_single_product_summary', function() use ($chart_id, $chart_title, $chart_label, $chart_content, $table_data) {
$this->output_popup_html($chart_id, $chart_title, $chart_label, $chart_content, $table_data);
}, 10);
} else {
// Default: before add to cart
add_action('woocommerce_before_add_to_cart_button', function() use ($chart_id, $chart_title, $chart_label, $chart_content, $table_data) {
$this->output_popup_html($chart_id, $chart_title, $chart_label, $chart_content, $table_data);
}, 10);
}
}

/**
* Output popup HTML
*
* @since 1.0.0
* @param int $chart_id Chart ID
* @param string $chart_title Chart title
* @param string $chart_label Chart label
* @param string $chart_content Chart content
* @param array $table_data Chart table data
*/
private function output_popup_html($chart_id, $chart_title, $chart_label, $chart_content, $table_data) {
?>
<div class="bdfg-size-chart-button-wrapper">
<button type="button" class="button bdfg-size-chart-button" data-chart-id="<?php echo esc_attr($chart_id); ?>">
<?php echo esc_html($chart_label); ?>
</button>
</div>

<div id="bdfg-size-chart-popup-<?php echo esc_attr($chart_id); ?>" class="bdfg-size-chart-popup" style="display: none;">
<div class="bdfg-size-chart-popup-inner">
<div class="bdfg-size-chart-popup-header">
<h2><?php echo esc_html($chart_title); ?></h2>
<button type="button" class="bdfg-size-chart-close">&times;</button>
</div>
<div class="bdfg-size-chart-popup-content">
<?php if (!empty($chart_content)) : ?>
<div class="bdfg-size-chart-description">
<?php echo wp_kses_post($chart_content); ?>
</div>
<?php endif; ?>

<?php if (!empty($table_data)) : ?>
<div class="bdfg-size-chart-table-container">
<table class="bdfg-size-chart-table">
<tbody>
<?php foreach ($table_data as $row_index => $row) : ?>
<tr class="<?php echo $row_index === 0 ? 'bdfg-chart-heading' : 'bdfg-chart-row'; ?>">
<?php foreach ($row as $cell) : ?>
<<?php echo $row_index === 0 ? 'th' : 'td'; ?>>
<?php echo esc_html($cell); ?>
</<?php echo $row_index === 0 ? 'th' : 'td'; ?>>
<?php endforeach; ?>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
</div>
<div class="bdfg-size-chart-popup-footer">
<span class="bdfg-copyright"><?php _e('Size Chart by', 'bdfg-size-chart'); ?> <a href="https://beiduofengou.net" target="_blank">beiduofengou</a></span>
</div>
</div>
</div>
<?php
}

/**
* Add size chart tab
*
* @since 1.0.0
* @param int $chart_id Chart ID
* @param string $chart_title Chart title
* @param string $chart_label Chart label
* @param string $chart_content Chart content
* @param array $table_data Chart table data
*/
private function add_size_chart_tab($chart_id, $chart_title, $chart_label, $chart_content, $table_data) {
if (empty($chart_label)) {
$chart_label = __('Size Chart', 'bdfg-size-chart');
}

// Add a new tab to product tabs
add_filter('woocommerce_product_tabs', function($tabs) use ($chart_id, $chart_title, $chart_label, $chart_content, $table_data) {
$tabs['bdfg_size_chart'] = array(
'title' => $chart_label,
'callback' => function() use ($chart_id, $chart_title, $chart_content, $table_data) {
$this->output_tab_content($chart_id, $chart_title, $chart_content, $table_data);
},
'priority' => 30
);

return $tabs;
});
}

/**
* Output tab content
*
* @since 1.0.0
* @param int $chart_id Chart ID
* @param string $chart_title Chart title
* @param string $chart_content Chart content
* @param array $table_data Chart table data
*/
private function output_tab_content($chart_id, $chart_title, $chart_content, $table_data) {
?>
<div class="bdfg-size-chart-tab-content">
<h2><?php echo esc_html($chart_title); ?></h2>

<?php if (!empty($chart_content)) : ?>
<div class="bdfg-size-chart-description">
<?php echo wp_kses_post($chart_content); ?>
</div>
<?php endif; ?>

<?php if (!empty($table_data)) : ?>
<div class="bdfg-size-chart-table-container">
<table class="bdfg-size-chart-table">
<tbody>
<?php foreach ($table_data as $row_index => $row) : ?>
<tr class="<?php echo $row_index === 0 ? 'bdfg-chart-heading' : 'bdfg-chart-row'; ?>">
<?php foreach ($row as $cell) : ?>
<<?php echo $row_index === 0 ? 'th' : 'td'; ?>>
<?php echo esc_html($cell); ?>
</<?php echo $row_index === 0 ? 'th' : 'td'; ?>>
<?php endforeach; ?>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>

<div class="bdfg-size-chart-footer">
<span class="bdfg-copyright"><?php _e('Size Chart by', 'bdfg-size-chart'); ?> <a href="https://beiduofengou.net" target="_blank">beiduofengou</a></span>
</div>
</div>
<?php
}

/**
* Render inline size chart
*
* @since 1.0.0
* @param int $chart_id Chart ID
* @param string $chart_title Chart title
* @param string $chart_content Chart content
* @param array $table_data Chart table data
*/
private function render_inline_chart($chart_id, $chart_title, $chart_content, $table_data) {
// Check chart position
$chart_position = get_post_meta($chart_id, '_bdfg_chart_position', true);

if ($chart_position === 'after_add_to_cart') {
add_action('woocommerce_after_add_to_cart_button', function() use ($chart_id, $chart_title, $chart_content, $table_data) {
$this->output_inline_html($chart_id, $chart_title, $chart_content, $table_data);
}, 10);
} elseif ($chart_position === 'after_product_summary') {
add_action('woocommerce_after_single_product_summary', function() use ($chart_id, $chart_title, $chart_content, $table_data) {
$this->output_inline_html($chart_id, $chart_title, $chart_content, $table_data);
}, 10);
} else {
// Default: before add to cart
add_action('woocommerce_before_add_to_cart_button', function() use ($chart_id, $chart_title, $chart_content, $table_data) {
$this->output_inline_html($chart_id, $chart_title, $chart_content, $table_data);
}, 10);
}
}

/**
* Output inline HTML
*
* @since 1.0.0
* @param int $chart_id Chart ID
* @param string $chart_title Chart title
* @param string $chart_content Chart content
* @param array $table_data Chart table data
*/
private function output_inline_html($chart_id, $chart_title, $chart_content, $table_data) {
?>
<div class="bdfg-size-chart-inline" id="bdfg-size-chart-<?php echo esc_attr($chart_id); ?>">
<h3><?php echo esc_html($chart_title); ?></h3>

<?php if (!empty($chart_content)) : ?>
<div class="bdfg-size-chart-description">
<?php echo wp_kses_post($chart_content); ?>
</div>
<?php endif; ?>

<?php if (!empty($table_data)) : ?>
<div class="bdfg-size-chart-table-container">
<table class="bdfg-size-chart-table">
<tbody>
<?php foreach ($table_data as $row_index => $row) : ?>
<tr class="<?php echo $row_index === 0 ? 'bdfg-chart-heading' : 'bdfg-chart-row'; ?>">
<?php foreach ($row as $cell) : ?>
<<?php echo $row_index === 0 ? 'th' : 'td'; ?>>
<?php echo esc_html($cell); ?>
</<?php echo $row_index === 0 ? 'th' : 'td'; ?>>
<?php endforeach; ?>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>

<div class="bdfg-size-chart-footer">
<span class="bdfg-copyright"><?php _e('Size Chart by', 'bdfg-size-chart'); ?> <a href="https://beiduofengou.net" target="_blank">beiduofengou</a></span>
</div>
</div>
<?php
}

/**
* Admin menu
*
* @since 1.0.0
*/
public function admin_menu() {
add_submenu_page(
'woocommerce',
__('Size Charts', 'bdfg-size-chart'),
__('Size Charts', 'bdfg-size-chart'),
'manage_woocommerce',
'bdfg-size-charts',
array($this, 'size_charts_page')
);
}

/**
* Size charts admin page
*
* @since 1.0.0
*/
public function size_charts_page() {
include_once BDFG_SC_PLUGIN_DIR . 'includes/admin/views/html-size-charts-page.php';
}

/**
* AJAX handler for loading template data
*
* @since 1.0.0
*/
public function ajax_load_template() {
// Check nonce
if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'bdfg_size_chart_nonce')) {
wp_send_json_error(array('message' => __('Security check failed', 'bdfg-size-chart')));
}

// Check if template ID is provided
if (!isset($_POST['template_id']) || empty($_POST['template_id'])) {
wp_send_json_error(array('message' => __('Invalid template ID', 'bdfg-size-chart')));
}

$template_id = sanitize_text_field($_POST['template_id']);

// Load template data from our template functions
$template_data = bdfg_load_template_data($template_id);

if (empty($template_data)) {
wp_send_json_error(array('message' => __('Template not found', 'bdfg-size-chart')));
}

wp_send_json_success($template_data);
}

/**
* Shortcode handler for displaying size charts
*
* @since 1.0.0
* @param array $atts Shortcode attributes
* @return string Shortcode output
*/
public function shortcode_size_chart($atts) {
$atts = shortcode_atts(array(
'id' => 0,
), $atts);

$chart_id = intval($atts['id']);

if (empty($chart_id) || get_post_type($chart_id) !== 'bdfg_size_chart') {
return '';
}

// Get chart data
$chart_title = get_the_title($chart_id);
$chart_content = get_post_field('post_content', $chart_id);
$table_data = get_post_meta($chart_id, '_bdfg_chart_table', true);

// Start output buffer
ob_start();

?>
<div class="bdfg-size-chart-shortcode" id="bdfg-size-chart-<?php echo esc_attr($chart_id); ?>">
<h3><?php echo esc_html($chart_title); ?></h3>

<?php if (!empty($chart_content)) : ?>
<div class="bdfg-size-chart-description">
<?php echo wp_kses_post($chart_content); ?>
</div>
<?php endif; ?>

<?php if (!empty($table_data)) : ?>
<div class="bdfg-size-chart-table-container">
<table class="bdfg-size-chart-table">
<tbody>
<?php foreach ($table_data as $row_index => $row) : ?>
<tr class="<?php echo $row_index === 0 ? 'bdfg-chart-heading' : 'bdfg-chart-row'; ?>">
<?php foreach ($row as $cell) : ?>
<<?php echo $row_index === 0 ? 'th' : 'td'; ?>>
<?php echo esc_html($cell); ?>
</<?php echo $row_index === 0 ? 'th' : 'td'; ?>>
<?php endforeach; ?>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>

<div class="bdfg-size-chart-footer">
<span class="bdfg-copyright"><?php _e('Size Chart by', 'bdfg-size-chart'); ?> <a href="https://beiduofengou.net" target="_blank">beiduofengou</a></span>
</div>
</div>
<?php

return ob_get_clean();
}

/**
* Return instance of this class
*
* @since 1.0.0
* @return BDFG_Size_Chart
*/
public static function get_instance() {
if (null === self::$instance) {
self::$instance = new self();
}

return self::$instance;
}
}

// Initialize the plugin
function bdfg_size_chart_init() {
return BDFG_Size_Chart::get_instance();
}

// Start the plugin
add_action('plugins_loaded', 'bdfg_size_chart_init');

// Create the necessary files and directories upon plugin activation
register_activation_hook(__FILE__, 'bdfg_size_chart_activation');

/**
* Plugin activation hook
*
* Creates necessary directories and files when plugin is activated
*
* @since 1.0.0
*/
function bdfg_size_chart_activation() {
// Create necessary directories
$dirs = array(
BDFG_SC_PLUGIN_DIR . 'includes/',
BDFG_SC_PLUGIN_DIR . 'includes/admin/',
BDFG_SC_PLUGIN_DIR . 'includes/admin/views/',
BDFG_SC_PLUGIN_DIR . 'assets/',
BDFG_SC_PLUGIN_DIR . 'assets/css/',
BDFG_SC_PLUGIN_DIR . 'assets/js/',
BDFG_SC_PLUGIN_DIR . 'languages/'
);

foreach ($dirs as $dir) {
if (!file_exists($dir)) {
wp_mkdir_p($dir);
}
}
}

/**
* Add shortcode for displaying size charts
*
* @since 1.0.0
*/
add_shortcode('bdfg_size_chart', array(BDFG_Size_Chart::get_instance(), 'shortcode_size_chart'));

includes/bdfg-size-chart-template-functions.php

相关文章: WordPress 地图定位插件

<?php
/**
* BDFG Size Chart Template Functions
*
* Functions for the templating system.
*
* @package BDFG_Size_Chart
* @version 2.3.0
* @since 1.0.0
* @author beiduofengou
* @modified 2025-03-05
*/

// Exit if accessed directly
if (!defined('ABSPATH')) {
exit;
}

/**
* Get size chart for a product
*
* @param int $product_id The product ID
* @return int|false Size chart ID or false if not found
*/
function bdfg_get_product_size_chart($product_id) {
// Get assigned size chart for this product
$size_chart_id = get_post_meta($product_id, '_bdfg_product_size_chart', true);

// If no chart is assigned, try to find a chart based on product categories
if (empty($size_chart_id)) {
$product_categories = wp_get_post_terms($product_id, 'product_cat', array('fields' => 'ids'));

if (!empty($product_categories)) {
// Get all size charts
$size_charts = get_posts(array(
'post_type' => 'bdfg_size_chart',
'posts_per_page' => -1,
'meta_query' => array(
array(
'key' => '_bdfg_chart_status',
'value' => 'inactive',
'compare' => '!=',
),
),
));

foreach ($size_charts as $chart) {
$chart_categories = get_post_meta($chart->ID, '_bdfg_chart_categories', true);

if (!is_array($chart_categories)) {
continue;
}

$intersect = array_intersect($product_categories, $chart_categories);

if (!empty($intersect)) {
$size_chart_id = $chart->ID;
break;
}
}
}
}

return !empty($size_chart_id) ? intval($size_chart_id) : false;
}

/**
* Get size chart table data
*
* @param int $chart_id The size chart ID
* @return array Size chart table data
*/
function bdfg_get_size_chart_table($chart_id) {
$table_data = get_post_meta($chart_id, '_bdfg_chart_table', true);

if (empty($table_data) || !is_array($table_data)) {
return array();
}

return $table_data;
}

/**
* Get size chart display type
*
* @param int $chart_id The size chart ID
* @return string Display type (tab, popup, inline)
*/
function bdfg_get_size_chart_type($chart_id) {
$chart_type = get_post_meta($chart_id, '_bdfg_chart_type', true);

if (empty($chart_type)) {
return 'tab';
}

return $chart_type;
}

/**
* Get size chart position
*
* @param int $chart_id The size chart ID
* @return string Chart position
*/
function bdfg_get_size_chart_position($chart_id) {
$chart_position = get_post_meta($chart_id, '_bdfg_chart_position', true);

if (empty($chart_position)) {
return 'before_add_to_cart';
}

return $chart_position;
}

/**
* Get size chart label
*
* @param int $chart_id The size chart ID
* @return string Chart label
*/
function bdfg_get_size_chart_label($chart_id) {
$chart_label = get_post_meta($chart_id, '_bdfg_chart_label', true);

if (empty($chart_label)) {
return __("Size Chart", "bdfg-size-chart");
}

return $chart_label;
}

/**
* Render size chart HTML
*
* @param int $chart_id The size chart ID
* @param string $context Optional context (product, category, shortcode)
* @return string HTML output
*/
function bdfg_render_size_chart($chart_id, $context = 'product') {
if (empty($chart_id)) {
return '';
}

// Get chart data
$chart_type = bdfg_get_size_chart_type($chart_id);
$chart_title = get_the_title($chart_id);
$chart_content = get_post_field('post_content', $chart_id);
$table_data = bdfg_get_size_chart_table($chart_id);

// Start output buffer
ob_start();

if ($chart_type === 'popup' && $context === 'product') {
$chart_label = bdfg_get_size_chart_label($chart_id);
?>
<div class="bdfg-size-chart-button-wrapper">
<button type="button" class="button bdfg-size-chart-button" data-chart-id="<?php echo esc_attr($chart_id); ?>">
<?php echo esc_html($chart_label); ?>
</button>
</div>

<div id="bdfg-size-chart-popup-<?php echo esc_attr($chart_id); ?>" class="bdfg-size-chart-popup" style="display: none;">
<div class="bdfg-size-chart-popup-inner">
<div class="bdfg-size-chart-popup-header">
<h2><?php echo esc_html($chart_title); ?></h2>
<button type="button" class="bdfg-size-chart-close">&times;</button>
</div>
<div class="bdfg-size-chart-popup-content">
<?php if (!empty($chart_content)) : ?>
<div class="bdfg-size-chart-description">
<?php echo wp_kses_post($chart_content); ?>
</div>
<?php endif; ?>

<?php if (!empty($table_data)) : ?>
<div class="bdfg-size-chart-table-container">
<table class="bdfg-size-chart-table">
<tbody>
<?php foreach ($table_data as $row_index => $row) : ?>
<tr class="<?php echo $row_index === 0 ? 'bdfg-chart-heading' : 'bdfg-chart-row'; ?>">
<?php foreach ($row as $cell) : ?>
<<?php echo $row_index === 0 ? 'th' : 'td'; ?>>
<?php echo esc_html($cell); ?>
</<?php echo $row_index === 0 ? 'th' : 'td'; ?>>
<?php endforeach; ?>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
</div>
<div class="bdfg-size-chart-popup-footer">
<span class="bdfg-copyright"><?php _e('Size Chart by', 'bdfg-size-chart'); ?> <a href="https://beiduofengou.net" target="_blank">beiduofengou</a></span>
</div>
</div>
</div>
<?php
} else {
// Inline display
?>
<div class="bdfg-size-chart-inline" id="bdfg-size-chart-<?php echo esc_attr($chart_id); ?>">
<h3><?php echo esc_html($chart_title); ?></h3>
<?php if (!empty($chart_content)) : ?>
<div class="bdfg-size-chart-description">
<?php echo wp_kses_post($chart_content); ?>
</div>
<?php endif; ?>

<?php if (!empty($table_data)) : ?>
<div class="bdfg-size-chart-table-container">
<table class="bdfg-size-chart-table">
<tbody>
<?php foreach ($table_data as $row_index => $row) : ?>
<tr class="<?php echo $row_index === 0 ? 'bdfg-chart-heading' : 'bdfg-chart-row'; ?>">
<?php foreach ($row as $cell) : ?>
<<?php echo $row_index === 0 ? 'th' : 'td'; ?>>
<?php echo esc_html($cell); ?>
</<?php echo $row_index === 0 ? 'th' : 'td'; ?>>
<?php endforeach; ?>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>

<div class="bdfg-size-chart-footer">
<span class="bdfg-copyright"><?php _e('Size Chart by', 'bdfg-size-chart'); ?> <a href="https://beiduofengou.net" target="_blank">beiduofengou</a></span>
</div>
</div>
<?php
}

return ob_get_clean();
}

/**
* Get default size chart templates
*
* @return array Default templates
*/
function bdfg_get_default_templates() {
return array(
'mens_clothing' => array(
'title' => __("Men's Clothing Size Chart", "bdfg-size-chart"),
'table' => array(
array('Size', 'Chest (inches)', 'Waist (inches)', 'Hips (inches)', 'Sleeve Length (inches)'),
array('XS', '33-34', '27-28', '33-34', '31-32'),
array('S', '35-37', '29-31', '35-37', '32-33'),
array('M', '38-40', '32-34', '38-40', '33-34'),
array('L', '41-43', '35-37', '41-43', '34-35'),
array('XL', '44-46', '38-40', '44-46', '35-36'),
array('XXL', '47-49', '41-43', '47-49', '36-37'),
),
),
'womens_clothing' => array(
'title' => __("Women's Clothing Size Chart", "bdfg-size-chart"),
'table' => array(
array('Size', 'Bust (inches)', 'Waist (inches)', 'Hips (inches)'),
array('XS (0-2)', '31-33', '23-25', '33-35'),
array('S (4-6)', '34-36', '26-28', '36-38'),
array('M (8-10)', '37-39', '29-31', '39-41'),
array('L (12-14)', '40-42', '32-34', '42-44'),
array('XL (16-18)', '43-45', '35-37', '45-47'),
array('XXL (20-22)', '46-48', '38-40', '48-50'),
),
),
'shoes' => array(
'title' => __("Shoe Size Chart", "bdfg-size-chart"),
'table' => array(
array('US Size', 'EU Size', 'UK Size', 'Inches', 'CM'),
array('5', '35-36', '3', '8.5', '21.6'),
array('6', '36-37', '4', '9', '22.9'),
array('7', '37-38', '5', '9.5', '23.8'),
array('8', '38-39', '6', '10', '24.8'),
array('9', '39-40', '7', '10.5', '25.7'),
array('10', '40-41', '8', '11', '26.7'),
array('11', '41-42', '9', '11.5', '27.6'),
array('12', '42-43', '10', '12', '28.6'),
),
),
'kids_clothing' => array(
'title' => __("Kid's Clothing Size Chart", "bdfg-size-chart"),
'table' => array(
array('Size', 'Age', 'Height (inches)', 'Weight (lbs)', 'Chest (inches)', 'Waist (inches)'),
array('2T', '2 years', '33-35', '30-32', '21', '20'),
array('3T', '3 years', '36-38', '33-36', '22', '20.5'),
array('4T', '4 years', '39-41', '37-41', '23', '21'),
array('5', '5 years', '42-44', '42-46', '24', '21.5'),
array('6', '6 years', '45-47', '47-53', '25', '22'),
array('7', '7 years', '48-50', '54-61', '26', '22.5'),
array('8', '8 years', '51-53', '62-71', '27', '23'),
array('10', '10 years', '54-56', '72-85', '28', '24'),
array('12', '12 years', '57-60', '86-100', '30', '25'),
array('14', '14 years', '61-62', '101-114', '32', '26'),
),
),
);
}

/**
* Load template data
*
* @param string $template_id Template ID
* @return array Template data or empty array if not found
*/
function bdfg_load_template_data($template_id) {
$templates = bdfg_get_default_templates();

if (isset($templates[$template_id])) {
return $templates[$template_id];
}

return array();
}

/**
* Check if a product has a size chart
*
* @param int $product_id Product ID
* @return bool Whether product has a size chart
*/
function bdfg_product_has_size_chart($product_id) {
$chart_id = bdfg_get_product_size_chart($product_id);
return !empty($chart_id);
}

/**
* Generate responsive size chart table HTML
*
* @param array $table_data Size chart table data
* @return string HTML table markup
*/
function bdfg_generate_size_chart_table($table_data) {
if (empty($table_data) || !is_array($table_data)) {
return '';
}

ob_start();
?>
<div class="bdfg-size-chart-table-container">
<table class="bdfg-size-chart-table">
<tbody>
<?php foreach ($table_data as $row_index => $row) : ?>
<tr class="<?php echo $row_index === 0 ? 'bdfg-chart-heading' : 'bdfg-chart-row'; ?>">
<?php foreach ($row as $cell) : ?>
<<?php echo $row_index === 0 ? 'th' : 'td'; ?>>
<?php echo esc_html($cell); ?>
</<?php echo $row_index === 0 ? 'th' : 'td'; ?>>
<?php endforeach; ?>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php

return ob_get_clean();
}

includes/admin/bdfg-size-chart-admin-functions.php

<?php
/**
* BDFG Size Chart Admin Functions
*
* Functions for the admin area.
*
* @package BDFG_Size_Chart
* @version 2.3.0
* @since 1.0.0
* @author beiduofengou
* @modified 2025-03-05 by beiduofengou
*/

// Exit if accessed directly
if (!defined('ABSPATH')) {
exit;
}

/**
* Admin AJAX handler for loading template data
*/
function bdfg_admin_load_template() {
// Check nonce
if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'bdfg_size_chart_nonce')) {
wp_send_json_error(array('message' => __("Security check failed", "bdfg-size-chart")));
}

// Check if template ID is provided
if (!isset($_POST['template_id']) || empty($_POST['template_id'])) {
wp_send_json_error(array('message' => __("Invalid template ID", "bdfg-size-chart")));
}

$template_id = sanitize_text_field($_POST['template_id']);

// Load template data
$template_data = bdfg_load_template_data($template_id);

if (empty($template_data)) {
wp_send_json_error(array('message' => __("Template not found", "bdfg-size-chart")));
}

wp_send_json_success($template_data);
}
add_action('wp_ajax_bdfg_load_template', 'bdfg_admin_load_template');

/**
* Get all size charts
*
* @return array Array of size chart posts
*/
function bdfg_get_all_size_charts() {
return get_posts(array(
'post_type' => 'bdfg_size_chart',
'posts_per_page' => -1,
'orderby' => 'title',
'order' => 'ASC',
));
}

/**
* Get the products assigned to a size chart
*
* @param int $chart_id The size chart ID
* @return array Array of product posts
*/
function bdfg_get_products_by_chart($chart_id) {
return get_posts(array(
'post_type' => 'product',
'posts_per_page' => -1,
'meta_key' => '_bdfg_product_size_chart',
'meta_value' => $chart_id,
));
}

/**
* Get product categories assigned to a size chart
*
* @param int $chart_id The size chart ID
* @return array Array of category terms
*/
function bdfg_get_categories_by_chart($chart_id) {
$chart_categories = get_post_meta($chart_id, '_bdfg_chart_categories', true);

if (empty($chart_categories) || !is_array($chart_categories)) {
return array();
}

return get_terms(array(
'taxonomy' => 'product_cat',
'include' => $chart_categories,
'hide_empty' => false,
));
}

/**
* Check if a size chart is assigned to a category
*
* @param int $chart_id The size chart ID
* @param int $category_id The category ID
* @return bool Whether the chart is assigned to the category
*/
function bdfg_chart_is_assigned_to_category($chart_id, $category_id) {
$chart_categories = get_post_meta($chart_id, '_bdfg_chart_categories', true);

if (empty($chart_categories) || !is_array($chart_categories)) {
return false;
}

return in_array($category_id, $chart_categories);
}

/**
* Duplicate a size chart
*
* @param int $chart_id The size chart ID to duplicate
* @return int|bool The new chart ID on success, false on failure
*/
function bdfg_duplicate_size_chart($chart_id) {
// Get the original chart data
$chart = get_post($chart_id);

if (!$chart) {
return false;
}

// Create the duplicate
$new_chart_args = array(
'post_title' => sprintf(__('Copy of %s', 'bdfg-size-chart'), $chart->post_title),
'post_content' => $chart->post_content,
'post_status' => 'publish',
'post_type' => 'bdfg_size_chart',
'comment_status' => 'closed',
'ping_status' => 'closed',
);

// Insert the new chart
$new_chart_id = wp_insert_post($new_chart_args);

if (is_wp_error($new_chart_id)) {
return false;
}

// Copy all meta data
$meta_keys = array(
'_bdfg_chart_type',
'_bdfg_chart_position',
'_bdfg_chart_label',
'_bdfg_chart_table',
'_bdfg_chart_categories',
);

foreach ($meta_keys as $meta_key) {
$meta_value = get_post_meta($chart_id, $meta_key, true);
update_post_meta($new_chart_id, $meta_key, $meta_value);
}

return $new_chart_id;
}

/**
* Export size chart data as JSON
*
* @param int $chart_id The size chart ID to export
* @return array Chart data for export
*/
function bdfg_export_size_chart($chart_id) {
// Get chart post
$chart = get_post($chart_id);

if (!$chart) {
return array();
}

// Get chart meta data
$chart_type = get_post_meta($chart_id, '_bdfg_chart_type', true);
$chart_position = get_post_meta($chart_id, '_bdfg_chart_position', true);
$chart_label = get_post_meta($chart_id, '_bdfg_chart_label', true);
$chart_table = get_post_meta($chart_id, '_bdfg_chart_table', true);
$chart_categories = get_post_meta($chart_id, '_bdfg_chart_categories', true);

// Build export data
$export_data = array(
'title' => $chart->post_title,
'content' => $chart->post_content,
'type' => $chart_type,
'position' => $chart_position,
'label' => $chart_label,
'table' => $chart_table,
'categories' => $chart_categories,
'version' => BDFG_SC_VERSION,
'exported' => date('Y-m-d H:i:s'),
'exported_by' => 'beiduofengou',
);

return $export_data;
}

/**
* Import size chart data from JSON
*
* @param array $import_data The chart data to import
* @return int|bool The new chart ID on success, false on failure
*/
function bdfg_import_size_chart($import_data) {
// Validate import data
if (!isset($import_data['title']) || empty($import_data['title'])) {
return false;
}

// Create new chart
$new_chart_args = array(
'post_title' => sanitize_text_field($import_data['title']),
'post_content' => isset($import_data['content']) ? wp_kses_post($import_data['content']) : '',
'post_status' => 'publish',
'post_type' => 'bdfg_size_chart',
'comment_status' => 'closed',
'ping_status' => 'closed',
);

// Insert the new chart
$new_chart_id = wp_insert_post($new_chart_args);

if (is_wp_error($new_chart_id)) {
return false;
}

// Set chart meta data
if (isset($import_data['type'])) {
update_post_meta($new_chart_id, '_bdfg_chart_type', sanitize_text_field($import_data['type']));
}

if (isset($import_data['position'])) {
update_post_meta($new_chart_id, '_bdfg_chart_position', sanitize_text_field($import_data['position']));
}

if (isset($import_data['label'])) {
update_post_meta($new_chart_id, '_bdfg_chart_label', sanitize_text_field($import_data['label']));
}

if (isset($import_data['table']) && is_array($import_data['table'])) {
update_post_meta($new_chart_id, '_bdfg_chart_table', $import_data['table']);
}

if (isset($import_data['categories']) && is_array($import_data['categories'])) {
$categories = array_map('intval', $import_data['categories']);
update_post_meta($new_chart_id, '_bdfg_chart_categories', $categories);
}

// Add import note
update_post_meta($new_chart_id, '_bdfg_import_info', array(
'imported_date' => current_time('mysql'),
'imported_by' => 'beiduofengou',
'version' => isset($import_data['version']) ? $import_data['version'] : 'unknown',
));

return $new_chart_id;
}

/**
* Get size chart usage statistics
*
* @return array Chart usage stats
*/
function bdfg_get_size_chart_stats() {
$stats = array(
'total_charts' => 0,
'charts_in_use' => 0,
'products_with_charts' => 0,
'categories_with_charts' => 0,
'charts_by_type' => array(
'tab' => 0,
'popup' => 0,
'inline' => 0,
),
);

// Get all charts
$charts = bdfg_get_all_size_charts();
$stats['total_charts'] = count($charts);

// Count charts in use and by type
$used_chart_ids = array();
$category_ids_with_charts = array();

foreach ($charts as $chart) {
// Count by type
$chart_type = get_post_meta($chart->ID, '_bdfg_chart_type', true);
if (!empty($chart_type) && isset($stats['charts_by_type'][$chart_type])) {
$stats['charts_by_type'][$chart_type]++;
}

// Check if chart is used by products
$products = bdfg_get_products_by_chart($chart->ID);
if (!empty($products)) {
$used_chart_ids[] = $chart->ID;
$stats['products_with_charts'] += count($products);
}

// Check assigned categories
$chart_categories = get_post_meta($chart->ID, '_bdfg_chart_categories', true);
if (!empty($chart_categories) && is_array($chart_categories)) {
$category_ids_with_charts = array_merge($category_ids_with_charts, $chart_categories);
}
}

// Count unique charts in use
$stats['charts_in_use'] = count(array_unique($used_chart_ids));

// Count unique categories with charts
$stats['categories_with_charts'] = count(array_unique($category_ids_with_charts));

return $stats;
}

includes/admin/views/html-size-charts-page.php

相关文章: WordPress优惠券提醒插件系统

<?php
/**
* Admin View: Size Charts Page
*
* @package BDFG_Size_Chart
* @version 2.3.0
* @since 1.0.0
* @author beiduofengou
* @updated 2025-03-05 15:32:54
*/

// Exit if accessed directly
if (!defined('ABSPATH')) {
exit;
}

// Get all size charts
$size_charts = bdfg_get_all_size_charts();

// Get stats
$stats = bdfg_get_size_chart_stats();
?>

<div class="wrap bdfg-size-charts-page">
<h1 class="wp-heading-inline"><?php _e('BDFG Size Charts', 'bdfg-size-chart'); ?></h1>
<a href="<?php echo admin_url('post-new.php?post_type=bdfg_size_chart'); ?>" class="page-title-action"><?php _e('Add New', 'bdfg-size-chart'); ?></a>
<hr class="wp-header-end">

<?php
// Display notices
if (isset($_GET['imported']) && $_GET['imported'] == 1) {
echo '<div class="notice notice-success is-dismissible"><p>' . esc_html__('Size chart imported successfully.', 'bdfg-size-chart') . '</p></div>';
} elseif (isset($_GET['duplicated']) && $_GET['duplicated'] == 1) {
echo '<div class="notice notice-success is-dismissible"><p>' . esc_html__('Size chart duplicated successfully.', 'bdfg-size-chart') . '</p></div>';
}
?>

<div class="bdfg-dashboard-stats">
<div class="bdfg-stats-card">
<h3><?php _e('Total Size Charts', 'bdfg-size-chart'); ?></h3>
<span class="bdfg-stat-number"><?php echo esc_html($stats['total_charts']); ?></span>
</div>
<div class="bdfg-stats-card">
<h3><?php _e('Products With Charts', 'bdfg-size-chart'); ?></h3>
<span class="bdfg-stat-number"><?php echo esc_html($stats['products_with_charts']); ?></span>
</div>
<div class="bdfg-stats-card">
<h3><?php _e('Categories With Charts', 'bdfg-size-chart'); ?></h3>
<span class="bdfg-stat-number"><?php echo esc_html($stats['categories_with_charts']); ?></span>
</div>
</div>

<?php if (empty($size_charts)) : ?>
<div class="bdfg-no-charts">
<p><?php _e('No size charts found. Create your first size chart to get started.', 'bdfg-size-chart'); ?></p>
<a href="<?php echo admin_url('post-new.php?post_type=bdfg_size_chart'); ?>" class="button button-primary"><?php _e('Create Size Chart', 'bdfg-size-chart'); ?></a>
</div>
<?php else : ?>
<div class="bdfg-charts-list">
<table class="wp-list-table widefat fixed striped">
<thead>
<tr>
<th scope="col"><?php _e('Title', 'bdfg-size-chart'); ?></th>
<th scope="col"><?php _e('Display Type', 'bdfg-size-chart'); ?></th>
<th scope="col"><?php _e('Assigned Products', 'bdfg-size-chart'); ?></th>
<th scope="col"><?php _e('Assigned Categories', 'bdfg-size-chart'); ?></th>
<th scope="col"><?php _e('Actions', 'bdfg-size-chart'); ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($size_charts as $chart) :
$chart_type = get_post_meta($chart->ID, '_bdfg_chart_type', true);
$products = bdfg_get_products_by_chart($chart->ID);
$categories = bdfg_get_categories_by_chart($chart->ID);

$display_type = '';
switch ($chart_type) {
case 'tab':
$display_type = __('Tab', 'bdfg-size-chart');
break;
case 'popup':
$display_type = __('Popup', 'bdfg-size-chart');
break;
case 'inline':
$display_type = __('Inline', 'bdfg-size-chart');
break;
default:
$display_type = __('Tab', 'bdfg-size-chart');
}
?>
<tr>
<td>
<strong>
<a href="<?php echo get_edit_post_link($chart->ID); ?>"><?php echo esc_html($chart->post_title); ?></a>
</strong>
<div class="row-actions">
<span class="edit"><a href="<?php echo get_edit_post_link($chart->ID); ?>"><?php _e('Edit', 'bdfg-size-chart'); ?></a> | </span>
<span class="duplicate"><a href="<?php echo wp_nonce_url(admin_url('admin.php?page=bdfg-size-charts&action=duplicate&chart_id=' . $chart->ID), 'bdfg_duplicate_chart_' . $chart->ID); ?>"><?php _e('Duplicate', 'bdfg-size-chart'); ?></a> | </span>
<span class="export"><a href="<?php echo wp_nonce_url(admin_url('admin.php?page=bdfg-size-charts&action=export&chart_id=' . $chart->ID), 'bdfg_export_chart_' . $chart->ID); ?>"><?php _e('Export', 'bdfg-size-chart'); ?></a> | </span>
<span class="trash"><a href="<?php echo get_delete_post_link($chart->ID); ?>" class="submitdelete" onclick="return confirm('<?php _e('Are you sure you want to delete this size chart?', 'bdfg-size-chart'); ?>');"><?php _e('Delete', 'bdfg-size-chart'); ?></a></span>
</div>
</td>
<td><?php echo esc_html($display_type); ?></td>
<td>
<?php
if (!empty($products)) {
echo count($products) . ' ' . __("products", "bdfg-size-chart");
if (count($products) <= 3) {
echo '<div class="row-products">';
foreach ($products as $product) {
echo '<a href="' . get_edit_post_link($product->ID) . '">' . esc_html($product->post_title) . '</a>, ';
}
echo '</div>';
}
} else {
_e("No products", "bdfg-size-chart");
}
?>
</td>
<td>
<?php
if (!empty($categories)) {
$category_names = array();
foreach ($categories as $category) {
$category_names[] = $category->name;
}
echo esc_html(implode(', ', $category_names));
} else {
_e("No categories", "bdfg-size-chart");
}
?>
</td>
<td>
<a href="<?php echo get_edit_post_link($chart->ID); ?>" class="button button-small"><?php _e('Edit', 'bdfg-size-chart'); ?></a>
<a href="<?php echo get_permalink($chart->ID); ?>" class="button button-small" target="_blank"><?php _e('Preview', 'bdfg-size-chart'); ?></a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>

<div class="bdfg-import-section">
<h2><?php _e('Import Size Chart', 'bdfg-size-chart'); ?></h2>
<form method="post" enctype="multipart/form-data">
<?php wp_nonce_field('bdfg_import_chart', 'bdfg_import_chart_nonce'); ?>
<input type="hidden" name="action" value="bdfg_import_chart">
<p>
<input type="file" name="import_file" accept=".json">
<button type="submit" class="button"><?php _e('Import', 'bdfg-size-chart'); ?></button>
</p>
<p class="description"><?php _e('Import a size chart from a JSON file.', 'bdfg-size-chart'); ?></p>
</form>
</div>
<?php endif; ?>

<div class="bdfg-help-section">
<h2><?php _e('How to Use Size Charts', 'bdfg-size-chart'); ?></h2>
<ol>
<li><?php _e('Create a new size chart with your size information', 'bdfg-size-chart'); ?></li>
<li><?php _e('Assign the size chart to specific products or product categories', 'bdfg-size-chart'); ?></li>
<li><?php _e('Choose how to display the size chart (tab, popup, or inline)', 'bdfg-size-chart'); ?></li>
<li><?php _e('The size chart will automatically appear on the product page', 'bdfg-size-chart'); ?></li>
</ol>

<h2><?php _e('Shortcode Usage', 'bdfg-size-chart'); ?></h2>
<p><?php _e('You can also display a size chart anywhere on your site using the shortcode:', 'bdfg-size-chart'); ?></p>
<code>[bdfg_size_chart id="123"]</code>
<p class="description"><?php _e('Replace "123" with the ID of your size chart.', 'bdfg-size-chart'); ?></p>

<div class="bdfg-footer">
<p>
<?php
/* translators: %s: beiduofengou.net URL */
printf(__('BDFG Size Chart for WooCommerce v%s by <a href="%s" target="_blank">beiduofengou</a>', 'bdfg-size-chart'),
BDFG_SC_VERSION,
'https://beiduofengou.net'
);
?>
</p>
<p class="bdfg-updated-time">
<?php _e('Last updated:', 'bdfg-size-chart'); ?> 2025-03-05 15:34:42 by beiduofengou
</p>
</div>
</div>
</div>

assets/js/admin.js

/**
* BDFG Size Chart Admin Scripts
*
* @package BDFG_Size_Chart
* @version 2.3.0
* @author beiduofengou
* @updated 2025-03-05 15:34:42 by beiduofengou
*/
(function($) {
'use strict';

// Size chart table builder
var BDFGSizeChart = {
init: function() {
this.bindEvents();
this.initSortable();
},

bindEvents: function() {
// Add row button
$('.bdfg-add-row').on('click', this.addRow);

// Add column button
$('.bdfg-add-column').on('click', this.addColumn);

// Remove row button
$(document).on('click', '.bdfg-remove-row', this.removeRow);

// Remove column button
$(document).on('click', '.bdfg-remove-column', this.removeColumn);

// Load template button
$('.bdfg-load-template').on('click', this.loadTemplate);
},

initSortable: function() {
// Make rows sortable
$('.bdfg-chart-table tbody').sortable({
axis: 'y',
handle: 'td:first-child',
helper: function(e, ui) {
ui.children().each(function() {
$(this).width($(this).width());
});
return ui;
},
update: function(event, ui) {
BDFGSizeChart.reindexTable();
}
});
},

addRow: function(e) {
e.preventDefault();

var $table = $('.bdfg-chart-table');
var columnCount = $table.find('tr:first td').length;
var rowIndex = $table.find('tr').length;

var $newRow = $('<tr class="bdfg-table-row"></tr>');

for (var i = 0; i < columnCount; i++) {
var $cell = $('<td></td>');
var $input = $('<input type="text" name="bdfg_chart_table[' + rowIndex + '][' + i + ']" value="">');
$cell.append($input);

// Add remove button to the first cell
if (i === 0) {
$cell.append('<a href="#" class="bdfg-remove-row" title="' + bdfg_size_chart_params.strings.remove + '">-</a>');
}

$newRow.append($cell);
}

$table.find('tbody').append($newRow);
},

addColumn: function(e) {
e.preventDefault();

var $table = $('.bdfg-chart-table');
var $rows = $table.find('tr');
var columnIndex = $rows.first().find('td').length;

$rows.each(function(rowIndex, row) {
var $cell = $('<td></td>');
var $input = $('<input type="text" name="bdfg_chart_table[' + rowIndex + '][' + columnIndex + ']" value="">');
$cell.append($input);

// Add remove button to the first row
if (rowIndex === 0) {
$cell.append('<a href="#" class="bdfg-remove-column" title="' + bdfg_size_chart_params.strings.remove + '">-</a>');
}

$(row).append($cell);
});
},

removeRow: function(e) {
e.preventDefault();

if (confirm(bdfg_size_chart_params.strings.confirm_delete)) {
var $row = $(this).closest('tr');
$row.remove();
BDFGSizeChart.reindexTable();
}
},

removeColumn: function(e) {
e.preventDefault();

if (confirm(bdfg_size_chart_params.strings.confirm_delete)) {
var $cell = $(this).closest('td');
var columnIndex = $cell.index();
var $table = $('.bdfg-chart-table');

$table.find('tr').each(function() {
$(this).find('td').eq(columnIndex).remove();
});

BDFGSizeChart.reindexTable();
}
},

reindexTable: function() {
var $table = $('.bdfg-chart-table');
var $rows = $table.find('tr');

$rows.each(function(rowIndex, row) {
$(row).find('td').each(function(colIndex, cell) {
var $input = $(cell).find('input');
$input.attr('name', 'bdfg_chart_table[' + rowIndex + '][' + colIndex + ']');
});
});
},

loadTemplate: function(e) {
e.preventDefault();

var templateId = $('#bdfg_chart_template').val();

if (!templateId) {
return;
}

var $spinner = $('.bdfg-spinner');
$spinner.addClass('is-active');

$.ajax({
url: bdfg_size_chart_params.ajax_url,
type: 'POST',
data: {
action: 'bdfg_load_template',
template_id: templateId,
nonce: bdfg_size_chart_params.nonce
},
success: function(response) {
if (response.success && response.data) {
// Update chart title
if (response.data.title && !$('#title').val()) {
$('#title').val(response.data.title);
}

// Update chart table
if (response.data.table && Array.isArray(response.data.table)) {
var $table = $('.bdfg-chart-table');
var $tbody = $table.find('tbody').empty();

// Add rows and cells
$.each(response.data.table, function(rowIndex, row) {
var $row = $('<tr class="bdfg-table-row"></tr>');

$.each(row, function(colIndex, cell) {
var $cell = $('<td></td>');
var $input = $('<input type="text" name="bdfg_chart_table[' + rowIndex + '][' + colIndex + ']" value="' + cell + '">');
$cell.append($input);

// Add action buttons to first row/column
if (rowIndex === 0 && colIndex === 0) {
$cell.append('<span class="bdfg-cell-actions"><a href="#" class="bdfg-remove-row" title="' + bdfg_size_chart_params.strings.remove + '">-</a><a href="#" class="bdfg-remove-column" title="' + bdfg_size_chart_params.strings.remove + '">-</a></span>');
} else if (rowIndex === 0) {
$cell.append('<a href="#" class="bdfg-remove-column" title="' + bdfg_size_chart_params.strings.remove + '">-</a>');
} else if (colIndex === 0) {
$cell.append('<a href="#" class="bdfg-remove-row" title="' + bdfg_size_chart_params.strings.remove + '">-</a>');
}

$row.append($cell);
});

$tbody.append($row);
});
}
} else {
alert(response.data.message || 'Error loading template');
}
},
error: function() {
alert('Error loading template. Please try again.');
},
complete: function() {
$spinner.removeClass('is-active');
}
});
}
};

$(document).ready(function() {
BDFGSizeChart.init();
});

})(jQuery);

assets/js/frontend.js

相关文章: WordPress 智能缓存管理

/**
* BDFG Size Chart Frontend Scripts
*
* @package BDFG_Size_Chart
* @version 2.3.0
* @author beiduofengou
* @updated 2025-03-05 15:34:42 by beiduofengou
*/
(function($) {
'use strict';

// Size chart popup functionality
var BDFGSizeChartFrontend = {
init: function() {
this.bindEvents();
this.setupResponsiveTables();
},

bindEvents: function() {
// Open popup on button click
$(document).on('click', '.bdfg-size-chart-button', this.openPopup);

// Close popup on close button click
$(document).on('click', '.bdfg-size-chart-close', this.closePopup);

// Close popup on background click
$(document).on('click', '.bdfg-size-chart-popup', function(e) {
if ($(e.target).hasClass('bdfg-size-chart-popup')) {
BDFGSizeChartFrontend.closePopup(e);
}
});

// Close popup on ESC key press
$(document).on('keyup', function(e) {
if (e.key === "Escape" && $('.bdfg-size-chart-popup:visible').length) {
BDFGSizeChartFrontend.closePopup(e);
}
});
},

openPopup: function(e) {
e.preventDefault();

var chartId = $(this).data('chart-id');
var popup = $('#bdfg-size-chart-popup-' + chartId);

// Show popup
popup.fadeIn(300);

// Add active class to body
$('body').addClass('bdfg-size-chart-open');

// Add active class to button
$(this).addClass('active');
},

closePopup: function(e) {
e.preventDefault();

// Hide all popups
$('.bdfg-size-chart-popup').fadeOut(200);

// Remove active class from body
$('body').removeClass('bdfg-size-chart-open');

// Remove active class from buttons
$('.bdfg-size-chart-button').removeClass('active');
},

setupResponsiveTables: function() {
$('.bdfg-size-chart-table').each(function() {
var $table = $(this);
var headerTexts = [];

// Get header texts
$table.find('tr:first-child th').each(function() {
headerTexts.push($(this).text());
});

// Add data attributes for responsive labels
$table.find('tr:not(:first-child)').each(function() {
$(this).find('td').each(function(index) {
if (headerTexts[index]) {
$(this).attr('data-label', headerTexts[index]);
}
});
});
});
}
};

$(document).ready(function() {
BDFGSizeChartFrontend.init();
});

})(jQuery);

assets/css/admin.css

/**
* BDFG Size Chart Admin Styles
*
* @package BDFG_Size_Chart
* @version 2.3.0
* @author beiduofengou
* @updated 2025-03-05 15:34:42 by beiduofengou
*/

/* Size Chart Builder */
.bdfg-chart-builder {
margin-top: 20px;
padding: 15px;
background: #fff;
border: 1px solid #ddd;
border-radius: 4px;
}

.bdfg-table-controls {
margin-bottom: 15px;
}

.bdfg-table-container {
margin-bottom: 20px;
overflow-x: auto;
}

.bdfg-chart-table {
width: 100%;
border-collapse: collapse;
margin-top: 10px;
}

.bdfg-chart-table td {
position: relative;
padding: 8px;
vertical-align: top;
border: 1px solid #ddd;
}

.bdfg-chart-table input[type="text"] {
width: 100%;
padding: 6px;
box-sizing: border-box;
}

.bdfg-remove-row,
.bdfg-remove-column {
position: absolute;
top: 3px;
right: 3px;
display: block;
width: 16px;
height: 16px;
line-height: 14px;
font-size: 16px;
text-align: center;
background: #f1f1f1;
color: #999;
border-radius: 50%;
text-decoration: none;
z-index: 10;
}

.bdfg-remove-row:hover,
.bdfg-remove-column:hover {
background: #e14d43;
color: #fff;
}

.bdfg-cell-actions {
position: absolute;
top: 3px;
right: 3px;
}

.bdfg-cell-actions .bdfg-remove-column {
right: 20px;
}
.bdfg-template-selection {
margin-top: 20px;
padding-top: 15px;
border-top: 1px solid #eee;
}

.bdfg-spinner {
float: none;
margin: 0 0 0 5px;
vertical-align: middle;
}

/* Categories Meta Box */
.bdfg-categories-wrapper {
max-height: 200px;
overflow-y: auto;
border: 1px solid #ddd;
padding: 10px;
margin-bottom: 10px;
background: #f9f9f9;
}

.bdfg-categories-list {
margin: 0;
}

.bdfg-categories-list li {
margin: 0;
padding: 3px 0;
}

/* Size Chart Admin Page */
.bdfg-size-charts-page .wp-list-table th {
font-weight: 600;
}

.bdfg-dashboard-stats {
display: flex;
flex-wrap: wrap;
margin: 20px 0;
gap: 20px;
}

.bdfg-stats-card {
background-color: #fff;
border: 1px solid #ddd;
border-radius: 4px;
padding: 15px;
width: calc(33.333% - 14px);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
text-align: center;
box-sizing: border-box;
}

.bdfg-stats-card h3 {
margin-top: 0;
color: #23282d;
}

.bdfg-stat-number {
font-size: 32px;
font-weight: 600;
color: #0073aa;
}

.bdfg-no-charts {
background: #fff;
padding: 20px;
border: 1px solid #ddd;
border-radius: 4px;
margin: 20px 0;
text-align: center;
}

.bdfg-help-section {
margin-top: 30px;
background: #fff;
padding: 20px;
border: 1px solid #ddd;
border-radius: 4px;
}

.bdfg-help-section h2 {
margin-top: 0;
padding-bottom: 10px;
border-bottom: 1px solid #eee;
}

.bdfg-help-section code {
display: inline-block;
padding: 8px 12px;
margin: 10px 0;
background: #f5f5f5;
border: 1px solid #ddd;
border-radius: 3px;
}

.bdfg-import-section {
margin: 20px 0;
background: #fff;
padding: 20px;
border: 1px solid #ddd;
border-radius: 4px;
}

.bdfg-footer {
margin-top: 30px;
padding-top: 15px;
border-top: 1px solid #eee;
color: #666;
font-style: italic;
}

.bdfg-updated-time {
margin: 5px 0 0;
font-size: 12px;
color: #888;
}

@media screen and (max-width: 782px) {
.bdfg-stats-card {
width: 100%;
}
}

assets/css/admin-list.css

/**
* BDFG Size Chart Admin List Styles
*
* @package BDFG_Size_Chart
* @version 2.3.0
* @author beiduofengou
* @updated 2025-03-05 15:35:49 by beiduofengou
*/

.bdfg-charts-list .row-products {
margin-top: 5px;
font-size: 12px;
color: #666;
}

.bdfg-charts-list .row-products a {
text-decoration: none;
}

.bdfg-charts-list .column-actions {
text-align: right;
}

assets/css/frontend.css

/**
* BDFG Size Chart Frontend Styles
*
* @package BDFG_Size_Chart
* @version 2.3.0
* @author beiduofengou
* @updated 2025-03-05 15:35:49 by beiduofengou
*/

/* Button Styles */
.bdfg-size-chart-button-wrapper {
margin: 15px 0;
}

.bdfg-size-chart-button {
background: #f7f7f7;
border: 1px solid #ccc;
color: #555;
padding: 8px 15px;
font-size: 14px;
line-height: 1.5;
cursor: pointer;
border-radius: 3px;
text-decoration: none;
transition: all 0.2s ease;
}

.bdfg-size-chart-button:hover,
.bdfg-size-chart-button:focus,
.bdfg-size-chart-button.active {
background: #ebebeb;
border-color: #aaa;
color: #333;
}

/* Popup Styles */
.bdfg-size-chart-popup {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 999999;
display: none;
overflow-y: auto;
}

.bdfg-size-chart-popup-inner {
position: relative;
width: 90%;
max-width: 900px;
max-height: 90vh;
margin: 30px auto;
background: #fff;
border-radius: 5px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.2);
overflow: hidden;
display: flex;
flex-direction: column;
}

.bdfg-size-chart-popup-header {
padding: 15px 20px;
border-bottom: 1px solid #eee;
display: flex;
align-items: center;
justify-content: space-between;
}

.bdfg-size-chart-popup-header h2 {
margin: 0;
padding: 0;
font-size: 18px;
line-height: 1.4;
color: #333;
}

.bdfg-size-chart-close {
padding: 0;
background: none;
border: none;
color: #999;
font-size: 26px;
line-height: 1;
cursor: pointer;
transition: color 0.2s ease;
}

.bdfg-size-chart-close:hover {
color: #333;
}

.bdfg-size-chart-popup-content {
padding: 20px;
overflow-y: auto;
flex: 1;
}

.bdfg-size-chart-popup-footer {
padding: 10px 20px;
border-top: 1px solid #eee;
text-align: right;
font-size: 12px;
color: #999;
}

.bdfg-size-chart-popup-footer a {
color: #0073aa;
text-decoration: none;
}

/* Tab Styles */
.bdfg-size-chart-tab-content {
padding: 20px 0;
}

.bdfg-size-chart-tab-content h2 {
margin-top: 0;
margin-bottom: 15px;
}

/* Inline Styles */
.bdfg-size-chart-inline {
margin: 20px 0;
padding: 20px;
background: #f9f9f9;
border: 1px solid #eee;
border-radius: 3px;
}

.bdfg-size-chart-inline h3 {
margin-top: 0;
margin-bottom: 15px;
}

/* Common Styles */
.bdfg-size-chart-description {
margin-bottom: 20px;
}

.bdfg-size-chart-description p:last-child {
margin-bottom: 0;
}

.bdfg-size-chart-table-container {
overflow-x: auto;
margin-bottom: 20px;
}

.bdfg-size-chart-table {
width: 100%;
border-collapse: collapse;
border: 1px solid #ddd;
}

.bdfg-size-chart-table th,
.bdfg-size-chart-table td {
padding: 10px;
border: 1px solid #ddd;
text-align: center;
}

.bdfg-size-chart-table th {
background: #f5f5f5;
font-weight: 600;
}

.bdfg-size-chart-table tr:nth-child(even) td {
background: #fafafa;
}

.bdfg-size-chart-footer {
margin-top: 20px;
padding-top: 10px;
border-top: 1px solid #eee;
font-size: 12px;
color: #999;
text-align: right;
}

.bdfg-size-chart-footer a {
color: #0073aa;
text-decoration: none;
}

.bdfg-copyright {
font-size: 12px;
}

/* Responsive Styles */
@media screen and (max-width: 600px) {
.bdfg-size-chart-table,
.bdfg-size-chart-table tbody,
.bdfg-size-chart-table th,
.bdfg-size-chart-table td,
.bdfg-size-chart-table tr {
display: block;
}

.bdfg-size-chart-table tr:first-child {
position: absolute;
top: -9999px;
left: -9999px;
}

.bdfg-size-chart-table tr {
border: 1px solid #ddd;
margin-bottom: 5px;
}

.bdfg-size-chart-table td {
border: none;
border-bottom: 1px solid #eee;
position: relative;
padding-left: 50%;
text-align: left;
min-height: 30px;
}

.bdfg-size-chart-table td:before {
position: absolute;
left: 10px;
width: 45%;
padding-right: 10px;
white-space: nowrap;
font-weight: 600;
content: attr(data-label);
}

.bdfg-size-chart-table td:last-child {
border-bottom: none;
}

.bdfg-size-chart-popup-inner {
width: 95%;
margin: 20px auto;
}
}

.bdfg-size-chart-shortcode {
margin: 20px 0;
padding: 15px;
background: #f9f9f9;
border: 1px solid #eee;
border-radius: 3px;
}

Leave a Comment