File: /home/ayxmplky/public_html/wp-content/themes/tactic/inc/admin-translations.php
<?php
/**
* WP Admin: страница управления переводами
* WP Admin → TACTIC → Переводы
*
* @package tactic
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/* ── Меню в сайдбаре WP Admin ───────────────────────────────── */
function tactic_add_translations_menu(): void {
add_menu_page(
'TACTIC — Управление переводами',
'TACTIC',
'manage_options',
'tactic-translations',
'tactic_translations_page',
'dashicons-translation',
60
);
add_submenu_page(
'tactic-translations',
'TACTIC — Переводы (локали)',
'Переводы (локали)',
'manage_options',
'tactic-translations',
'tactic_translations_page'
);
add_submenu_page(
'tactic-translations',
'TACTIC — Слайдер Hero',
'Слайдер Hero',
'manage_options',
'tactic-hero-slider',
'tactic_hero_slider_page'
);
add_submenu_page(
'tactic-translations',
'TACTIC — About (главная)',
'About (главная)',
'manage_options',
'tactic-about-home',
'tactic_about_home_page'
);
add_submenu_page(
'tactic-translations',
'TACTIC — Плашки карты',
'Плашки карты',
'manage_options',
'tactic-map-stats',
'tactic_map_stats_page'
);
}
add_action( 'admin_menu', 'tactic_add_translations_menu' );
/* ── Подключение media uploader для Hero Slider ─────────────── */
function tactic_admin_hero_slider_assets( string $hook ): void {
if ( ! in_array( $hook, [ 'tactic_page_tactic-hero-slider', 'tactic_page_tactic-about-home', 'tactic_page_tactic-map-stats' ], true ) ) {
return;
}
wp_enqueue_media();
}
add_action( 'admin_enqueue_scripts', 'tactic_admin_hero_slider_assets' );
/* ── Стили страницы ─────────────────────────────────────────── */
function tactic_translations_admin_styles( string $hook ): void {
if ( $hook !== 'toplevel_page_tactic-translations' ) {
return;
}
?>
<style>
.tactic-wrap { max-width: 1200px; }
.tactic-wrap h1 { display: flex; align-items: center; gap: 10px; }
.tactic-group { margin: 28px 0 0; }
.tactic-group h2 { font-size: 15px; color: #1d2327; margin-bottom: 6px;
padding: 8px 12px; background: #f0f0f1; border-left: 4px solid #2271b1; }
.tactic-table { width: 100%; border-collapse: collapse; background: #fff;
box-shadow: 0 1px 3px rgba(0,0,0,.08); margin-bottom: 4px; }
.tactic-table th, .tactic-table td { padding: 10px 14px; border: 1px solid #e0e0e0; vertical-align: top; }
.tactic-table th { background: #f6f7f7; font-weight: 600; font-size: 13px; white-space: nowrap; }
.tactic-table td:first-child { width: 160px; color: #646970; font-family: monospace;
font-size: 12px; background: #fafafa; }
.tactic-table textarea { width: 100%; min-height: 52px; resize: vertical;
font-size: 14px; line-height: 1.5; border: 1px solid #c3c4c7; border-radius: 3px;
padding: 6px 8px; box-sizing: border-box; }
.tactic-table textarea:focus { border-color: #2271b1; box-shadow: 0 0 0 1px #2271b1; outline: none; }
.tactic-th-zh { background: #fff8e1 !important; }
.tactic-th-en { background: #e8f4fd !important; }
.tactic-td-zh textarea { background: #fffdf0; }
.tactic-td-en textarea { background: #f0f8ff; }
.tactic-save-bar { position: sticky; bottom: 0; background: #fff;
padding: 14px 0; border-top: 1px solid #ddd; margin-top: 20px; z-index: 10; }
.tactic-notice { background: #d1e7dd; border: 1px solid #a3cfbb;
color: #0a3622; padding: 10px 16px; border-radius: 4px; margin: 12px 0; font-weight: 500; }
.tactic-reset-link { float: right; font-size: 12px; color: #b32d2e; text-decoration: none; margin-top: 4px; }
.tactic-reset-link:hover { text-decoration: underline; }
</style>
<?php
}
add_action( 'admin_head', 'tactic_translations_admin_styles' );
/* ── Основная страница ──────────────────────────────────────── */
function tactic_translations_page(): void {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
$saved_notice = '';
/* Сохранение */
if ( isset( $_POST['tactic_translations_nonce'] )
&& wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['tactic_translations_nonce'] ) ), 'tactic_save_translations' )
) {
$defaults = require TACTIC_DIR . '/inc/strings.php';
$input = isset( $_POST['tactic_s'] ) && is_array( $_POST['tactic_s'] ) ? $_POST['tactic_s'] : []; // phpcs:ignore WordPress.Security.NonceVerification
$saved = [];
foreach ( $defaults as $key => $pair ) {
$saved[ $key ] = [
'zh' => sanitize_textarea_field( wp_unslash( $input[ $key ]['zh'] ?? $pair['zh'] ) ),
'en' => sanitize_textarea_field( wp_unslash( $input[ $key ]['en'] ?? $pair['en'] ) ),
];
}
update_option( 'tactic_translations', $saved );
tactic_s( '__reset__' ); // сбрасываем статический кэш
$saved_notice = '<div class="tactic-notice">✓ Переводы сохранены.</div>';
}
/* Сброс к умолчаниям */
if ( isset( $_GET['tactic_reset'] ) && check_admin_referer( 'tactic_reset_translations' ) ) {
delete_option( 'tactic_translations' );
tactic_s( '__reset__' );
$saved_notice = '<div class="tactic-notice">✓ Переводы сброшены к значениям по умолчанию.</div>';
}
$defaults = require TACTIC_DIR . '/inc/strings.php';
$overrides = (array) get_option( 'tactic_translations', [] );
$strings = array_replace_recursive( $defaults, $overrides );
/* Группы */
$groups = [
'🎯 Главный баннер (Hero)' => [ 'hero_title', 'hero_subtitle', 'hero_btn1', 'hero_btn2', 'hero_aria', 'hero_pagination_aria' ],
'📄 Страница «О нас» — верхний блок' => [ 'abt_hero_title', 'abt_hero_subtitle', 'abt_lead', 'abt_p1', 'abt_p2', 'abt_p3', 'abt_p4' ],
'🏭 О компании (About)' => [ 'about_title', 'about_subtitle', 'about_p1', 'about_p2', 'about_p3', 'about_btn', 'about_tools_title', 'about_tools_subtitle', 'about_tools_list_aria', 'explore_tools_prev_aria', 'explore_tools_next_aria' ],
'🌍 Глобальная карта (Map)' => [ 'map_title', 'map_subtitle', 'map_cta', 'map_img_alt', 'map_stats_controls_aria', 'map_stats_prev_aria', 'map_stats_next_aria', 'stat1', 'stat2', 'stat3', 'stat4', 'stat5' ],
'📰 Новости (News)' => [ 'news_title', 'news_subtitle', 'news_all_btn', 'news_hero_title', 'news_hero_subtitle', 'archive_news_showcase_aria', 'archive_articles_aria', 'news_archive_articles_title', 'news_archive_articles_subtitle', 'news_single_breadcrumb_aria', 'news_breadcrumb_archive', 'news_article_list_aria', 'news_articles_title', 'news_prev_article_aria', 'news_next_article_aria', 'home_news_empty_featured_title', 'home_news_empty_list_title', 'home_news_empty_list_desc', 'common_read_more' ],
'🛍 Product Line' => [ 'product_line_title', 'product_empty_title', 'product_empty_desc' ],
'🎬 Отзывы И Видео' => [ 'testimonials_title', 'testimonials_subtitle', 'testimonials_view_more', 'testimonials_list_aria', 'testimonials_fallback_full_name', 'testimonials_fallback_position', 'testimonials_fallback_company', 'testimonials_empty_title', 'testimonials_empty_desc', 'testimonials_slider_nav_aria', 'video_modal_aria', 'video_modal_close_aria', 'common_play_video_aria' ],
'📬 Футер (Footer)' => [ 'footer_contacts', 'footer_email_eu', 'footer_email_global', 'footer_qr_alt', 'footer_charger_aria', 'footer_charger_alt', 'footer_instagram_aria', 'footer_wechat_aria', 'footer_linkedin_aria', 'footer_dnb_aria', 'footer_dnb_alt' ],
'✉️ Страница Contact Us' => [
'contact_title', 'contact_qr_label', 'contact_qr_desc',
'contact_qr_alt',
'contact_form_title',
'contact_field_name', 'contact_field_company', 'contact_field_country',
'contact_field_email', 'contact_field_phone', 'contact_field_mobile', 'contact_field_address', 'contact_field_industry', 'contact_field_message',
'contact_field_gender_male', 'contact_field_gender_female',
'contact_gender_aria',
'contact_submit', 'contact_success', 'contact_error', 'contact_security_error',
'contact_required_name', 'contact_required_company', 'contact_required_mobile', 'contact_required_email',
'contact_required_phone', 'contact_required_address', 'contact_required_gender', 'contact_required_message', 'contact_required_terms',
'contact_invalid_email', 'contact_invalid_phone',
'contact_modal_title', 'contact_modal_text', 'contact_modal_stay', 'contact_modal_go',
'contact_office_cn', 'contact_phone_label', 'contact_postal_label', 'contact_email_cn_label', 'contact_email_eu_label',
'contact_terms', 'contact_placeholder_email',
],
'🗺 Навигация' => [ 'nav_home', 'nav_about', 'nav_blog', 'nav_awards', 'nav_contact', 'nav_aria', 'menu_btn_aria', 'common_breadcrumb_aria', 'common_page_navigation_aria' ],
'🧩 Общие Страницы' => [ 'common_no_content', 'common_demo_section_in_dev', 'archive_date_format', 'archive_default_title', 'single_post_nav_aria', 'error_404_title', 'error_404_text', 'error_404_home' ],
];
$reset_url = wp_nonce_url(
add_query_arg( 'tactic_reset', '1', menu_page_url( 'tactic-translations', false ) ),
'tactic_reset_translations'
);
?>
<div class="wrap tactic-wrap">
<h1>
<span class="dashicons dashicons-translation" style="font-size:26px;height:26px;"></span>
TACTIC — Управление переводами
</h1>
<p style="color:#646970;">Все UI-тексты сайта в одном месте. Изменения применяются мгновенно без правки кода.</p>
<a href="<?php echo esc_url( $reset_url ); ?>"
class="tactic-reset-link"
onclick="return confirm('Сбросить все переводы к значениям по умолчанию?')">
↺ Сбросить к умолчаниям
</a>
<?php echo wp_kses_post( $saved_notice ); ?>
<form method="post">
<?php wp_nonce_field( 'tactic_save_translations', 'tactic_translations_nonce' ); ?>
<?php foreach ( $groups as $group_label => $keys ) : ?>
<div class="tactic-group">
<h2><?php echo esc_html( $group_label ); ?></h2>
<table class="tactic-table">
<thead>
<tr>
<th>Ключ</th>
<th class="tactic-th-zh">🇨🇳 Китайский (zh)</th>
<th class="tactic-th-en">🇬🇧 Английский (en)</th>
</tr>
</thead>
<tbody>
<?php foreach ( $keys as $key ) : ?>
<?php if ( ! isset( $strings[ $key ] ) ) : continue; endif; ?>
<tr>
<td><?php echo esc_html( $key ); ?></td>
<td class="tactic-td-zh">
<textarea name="tactic_s[<?php echo esc_attr( $key ); ?>][zh]"><?php echo esc_textarea( $strings[ $key ]['zh'] ); ?></textarea>
</td>
<td class="tactic-td-en">
<textarea name="tactic_s[<?php echo esc_attr( $key ); ?>][en]"><?php echo esc_textarea( $strings[ $key ]['en'] ); ?></textarea>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endforeach; ?>
<div class="tactic-save-bar">
<?php submit_button( 'Сохранить переводы', 'primary large', 'submit', false ); ?>
<span style="color:#646970; margin-left: 12px; font-size:13px;">
Активный язык сайта: <strong><?php echo esc_html( strtoupper( tactic_current_lang() ) ); ?></strong>
(переключается по ?lang=zh / ?lang=en)
</span>
</div>
</form>
</div>
<?php
}
/* ── Отдельная страница: Hero Slider ───────────────────────── */
function tactic_hero_slider_page(): void {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
$notice = '';
if (
isset( $_POST['tactic_hero_slider_nonce'] )
&& wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['tactic_hero_slider_nonce'] ) ), 'tactic_save_hero_slider' )
) {
$raw_ids = isset( $_POST['tactic_hero_slide_ids'] ) ? (string) wp_unslash( $_POST['tactic_hero_slide_ids'] ) : '';
$ids = array_filter( array_map( 'absint', explode( ',', $raw_ids ) ) );
update_option( 'tactic_hero_slider_ids', implode( ',', $ids ) );
$notice = '<div class="notice notice-success is-dismissible"><p>Слайдер Hero сохранён.</p></div>';
}
$current_ids = (string) get_option( 'tactic_hero_slider_ids', '' );
$id_list = array_filter( array_map( 'absint', explode( ',', $current_ids ) ) );
?>
<div class="wrap">
<h1>TACTIC — Слайдер Hero</h1>
<p style="max-width:900px;color:#646970;">Здесь настраиваются изображения слайдера главного баннера. Порядок выбранных изображений = порядок слайдов.</p>
<?php echo wp_kses_post( $notice ); ?>
<form method="post">
<?php wp_nonce_field( 'tactic_save_hero_slider', 'tactic_hero_slider_nonce' ); ?>
<table class="form-table" role="presentation">
<tbody>
<tr>
<th scope="row"><label for="tactic_hero_slide_ids">Слайды Hero</label></th>
<td>
<input type="hidden" id="tactic_hero_slide_ids" name="tactic_hero_slide_ids" value="<?php echo esc_attr( implode( ',', $id_list ) ); ?>">
<button type="button" class="button button-secondary" id="tactic-hero-pick">Выбрать изображения</button>
<button type="button" class="button" id="tactic-hero-clear">Очистить</button>
<p class="description">Можно выбрать несколько изображений. Используется на главной странице как слайдер с точками.</p>
<div id="tactic-hero-preview" style="display:flex;gap:10px;flex-wrap:wrap;margin-top:10px;">
<?php foreach ( $id_list as $img_id ) : ?>
<?php echo wp_kses_post( wp_get_attachment_image( $img_id, 'thumbnail', false, [ 'style' => 'width:140px;height:90px;object-fit:cover;border:1px solid #dcdcde;' ] ) ); ?>
<?php endforeach; ?>
</div>
</td>
</tr>
</tbody>
</table>
<?php submit_button( 'Сохранить слайды' ); ?>
</form>
</div>
<script>
(function($){
'use strict';
var frame = null;
var $input = $('#tactic_hero_slide_ids');
var $preview = $('#tactic-hero-preview');
function renderPreview(items) {
var html = '';
items.forEach(function(item){
var thumb = (item.sizes && item.sizes.thumbnail) ? item.sizes.thumbnail.url : item.url;
html += '<img src="' + thumb + '" style="width:140px;height:90px;object-fit:cover;border:1px solid #dcdcde;" />';
});
$preview.html(html);
}
$('#tactic-hero-pick').on('click', function(e){
e.preventDefault();
if (!frame) {
frame = wp.media({
title: 'Выберите слайды Hero',
button: { text: 'Использовать выбранные' },
multiple: true,
library: { type: 'image' }
});
frame.on('select', function(){
var selection = frame.state().get('selection');
var ids = [];
var items = [];
selection.each(function(model){
var item = model.toJSON();
ids.push(item.id);
items.push(item);
});
$input.val(ids.join(','));
renderPreview(items);
});
}
frame.open();
});
$('#tactic-hero-clear').on('click', function(e){
e.preventDefault();
$input.val('');
$preview.html('');
});
})(jQuery);
</script>
<?php
}
/* ── Отдельная страница: About на главной ───────────────────── */
function tactic_about_home_page(): void {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
$notice = '';
if (
isset( $_POST['tactic_about_home_nonce'] )
&& wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['tactic_about_home_nonce'] ) ), 'tactic_save_about_home' )
) {
$image_id = isset( $_POST['tactic_about_home_building_id'] ) ? absint( $_POST['tactic_about_home_building_id'] ) : 0;
update_option( 'tactic_about_home_building_id', $image_id );
$notice = '<div class="notice notice-success is-dismissible"><p>Картинка блока About сохранена.</p></div>';
}
$current_id = (int) get_option( 'tactic_about_home_building_id', 0 );
?>
<div class="wrap">
<h1>TACTIC — About (главная)</h1>
<p style="max-width:900px;color:#646970;">Выберите изображение здания для правой части блока About на главной странице.</p>
<?php echo wp_kses_post( $notice ); ?>
<form method="post">
<?php wp_nonce_field( 'tactic_save_about_home', 'tactic_about_home_nonce' ); ?>
<table class="form-table" role="presentation">
<tbody>
<tr>
<th scope="row"><label for="tactic_about_home_building_id">Изображение здания</label></th>
<td>
<input type="hidden" id="tactic_about_home_building_id" name="tactic_about_home_building_id" value="<?php echo esc_attr( (string) $current_id ); ?>">
<button type="button" class="button button-secondary" id="tactic-about-pick">Выбрать изображение</button>
<button type="button" class="button" id="tactic-about-clear">Очистить</button>
<p class="description">Рекомендуется PNG на прозрачном фоне.</p>
<div id="tactic-about-preview" style="margin-top:10px;max-width:420px;">
<?php if ( $current_id ) : ?>
<?php echo wp_kses_post( wp_get_attachment_image( $current_id, 'medium', false, [ 'style' => 'width:100%;height:auto;border:1px solid #dcdcde;' ] ) ); ?>
<?php endif; ?>
</div>
</td>
</tr>
</tbody>
</table>
<?php submit_button( 'Сохранить изображение' ); ?>
</form>
</div>
<script>
(function($){
'use strict';
var frame = null;
var $input = $('#tactic_about_home_building_id');
var $preview = $('#tactic-about-preview');
$('#tactic-about-pick').on('click', function(e){
e.preventDefault();
if (!frame) {
frame = wp.media({
title: 'Выберите изображение здания',
button: { text: 'Использовать изображение' },
multiple: false,
library: { type: 'image' }
});
frame.on('select', function(){
var item = frame.state().get('selection').first().toJSON();
var thumb = (item.sizes && item.sizes.medium) ? item.sizes.medium.url : item.url;
$input.val(item.id);
$preview.html('<img src="' + thumb + '" style="width:100%;height:auto;border:1px solid #dcdcde;" />');
});
}
frame.open();
});
$('#tactic-about-clear').on('click', function(e){
e.preventDefault();
$input.val('0');
$preview.html('');
});
})(jQuery);
</script>
<?php
}
/**
* Дефолтные плашки карты (zh/en) из strings.php с учётом overrides.
*
* @return array<int, array{zh:string,en:string}>
*/
function tactic_get_default_map_stats_rows(): array {
$defaults = require TACTIC_DIR . '/inc/strings.php';
$overrides = (array) get_option( 'tactic_translations', [] );
$strings = array_replace_recursive( $defaults, $overrides );
$keys = [ 'stat1', 'stat2', 'stat3', 'stat4', 'stat5' ];
$rows = [];
foreach ( $keys as $key ) {
$rows[] = [
'zh' => (string) ( $strings[ $key ]['zh'] ?? '' ),
'en' => (string) ( $strings[ $key ]['en'] ?? '' ),
];
}
return $rows;
}
/**
* Отдельная страница: Плашки карты (вертикальный слайдер на главной).
*/
function tactic_map_stats_page(): void {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
$notice = '';
if (
isset( $_POST['tactic_map_stats_nonce'] )
&& wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['tactic_map_stats_nonce'] ) ), 'tactic_save_map_stats' )
) {
$map_image_id = isset( $_POST['tactic_map_image_id'] ) ? absint( $_POST['tactic_map_image_id'] ) : 0;
update_option( 'tactic_map_image_id', $map_image_id );
$raw_rows = isset( $_POST['tactic_map_stats'] ) && is_array( $_POST['tactic_map_stats'] )
? wp_unslash( $_POST['tactic_map_stats'] )
: [];
$rows = [];
foreach ( $raw_rows as $row ) {
if ( ! is_array( $row ) ) {
continue;
}
$zh = sanitize_text_field( (string) ( $row['zh'] ?? '' ) );
$en = sanitize_text_field( (string) ( $row['en'] ?? '' ) );
if ( '' === $zh && '' === $en ) {
continue;
}
$rows[] = [
'zh' => $zh,
'en' => $en,
];
}
update_option( 'tactic_map_stats', $rows );
$notice = '<div class="notice notice-success is-dismissible"><p>Плашки карты сохранены.</p></div>';
}
$current_rows = get_option( 'tactic_map_stats', [] );
if ( ! is_array( $current_rows ) || empty( $current_rows ) ) {
$current_rows = tactic_get_default_map_stats_rows();
}
$current_map_image_id = (int) get_option( 'tactic_map_image_id', 0 );
?>
<div class="wrap">
<h1>TACTIC — Плашки карты</h1>
<p style="max-width:900px;color:#646970;">Управление картой и плашками вертикального слайдера в блоке Global Industrial Cooperation на главной.</p>
<?php echo wp_kses_post( $notice ); ?>
<form method="post">
<?php wp_nonce_field( 'tactic_save_map_stats', 'tactic_map_stats_nonce' ); ?>
<table class="form-table" role="presentation" style="max-width:1000px;margin-bottom:18px;">
<tbody>
<tr>
<th scope="row"><label for="tactic_map_image_id">Изображение карты</label></th>
<td>
<input type="hidden" id="tactic_map_image_id" name="tactic_map_image_id" value="<?php echo esc_attr( (string) $current_map_image_id ); ?>">
<button type="button" class="button button-secondary" id="tactic-map-pick">Выбрать изображение</button>
<button type="button" class="button" id="tactic-map-clear">Очистить</button>
<p class="description">Выбор картинки карты через вкладку TACTIC. Используется на главной странице.</p>
<div id="tactic-map-preview" style="margin-top:10px;max-width:420px;">
<?php if ( $current_map_image_id ) : ?>
<?php echo wp_kses_post( wp_get_attachment_image( $current_map_image_id, 'medium', false, [ 'style' => 'width:100%;height:auto;border:1px solid #dcdcde;' ] ) ); ?>
<?php endif; ?>
</div>
</td>
</tr>
</tbody>
</table>
<table class="widefat fixed" id="tactic-map-stats-table" style="max-width:1000px;">
<thead>
<tr>
<th style="width:45%;">Текст (zh)</th>
<th style="width:45%;">Text (en)</th>
<th style="width:10%;">Действие</th>
</tr>
</thead>
<tbody>
<?php foreach ( $current_rows as $index => $row ) : ?>
<tr>
<td>
<input type="text" class="regular-text" style="width:100%;" name="tactic_map_stats[<?php echo esc_attr( (string) $index ); ?>][zh]" value="<?php echo esc_attr( (string) ( $row['zh'] ?? '' ) ); ?>">
</td>
<td>
<input type="text" class="regular-text" style="width:100%;" name="tactic_map_stats[<?php echo esc_attr( (string) $index ); ?>][en]" value="<?php echo esc_attr( (string) ( $row['en'] ?? '' ) ); ?>">
</td>
<td>
<button type="button" class="button tactic-remove-stat-row">Удалить</button>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<p style="margin-top:12px;display:flex;gap:8px;align-items:center;">
<button type="button" class="button button-secondary" id="tactic-add-stat-row">+ Добавить плашку</button>
<span style="color:#646970;">Пустые строки при сохранении автоматически удаляются.</span>
</p>
<?php submit_button( 'Сохранить плашки' ); ?>
</form>
</div>
<script>
(function($){
'use strict';
const table = document.getElementById('tactic-map-stats-table');
const tbody = table ? table.querySelector('tbody') : null;
const addBtn = document.getElementById('tactic-add-stat-row');
const mapInput = document.getElementById('tactic_map_image_id');
const mapPreview = document.getElementById('tactic-map-preview');
const mapPickBtn = document.getElementById('tactic-map-pick');
const mapClearBtn = document.getElementById('tactic-map-clear');
let mapFrame = null;
if (!tbody || !addBtn) {
return;
}
const buildRow = (index) => {
const tr = document.createElement('tr');
tr.innerHTML =
'<td><input type="text" class="regular-text" style="width:100%;" name="tactic_map_stats[' + index + '][zh]" value=""></td>' +
'<td><input type="text" class="regular-text" style="width:100%;" name="tactic_map_stats[' + index + '][en]" value=""></td>' +
'<td><button type="button" class="button tactic-remove-stat-row">Удалить</button></td>';
return tr;
};
const reindexRows = () => {
const rows = tbody.querySelectorAll('tr');
rows.forEach((row, idx) => {
const zhInput = row.querySelector('input[name*="[zh]"]');
const enInput = row.querySelector('input[name*="[en]"]');
if (zhInput) {
zhInput.name = 'tactic_map_stats[' + idx + '][zh]';
}
if (enInput) {
enInput.name = 'tactic_map_stats[' + idx + '][en]';
}
});
};
addBtn.addEventListener('click', () => {
const nextIndex = tbody.querySelectorAll('tr').length;
tbody.appendChild(buildRow(nextIndex));
});
if (mapPickBtn && mapInput && mapPreview) {
mapPickBtn.addEventListener('click', (event) => {
event.preventDefault();
if (!mapFrame) {
mapFrame = wp.media({
title: 'Выберите изображение карты',
button: { text: 'Использовать изображение' },
multiple: false,
library: { type: 'image' }
});
mapFrame.on('select', () => {
const item = mapFrame.state().get('selection').first().toJSON();
const preview = (item.sizes && item.sizes.medium) ? item.sizes.medium.url : item.url;
mapInput.value = String(item.id || 0);
mapPreview.innerHTML = '<img src="' + preview + '" style="width:100%;height:auto;border:1px solid #dcdcde;" />';
});
}
mapFrame.open();
});
}
if (mapClearBtn && mapInput && mapPreview) {
mapClearBtn.addEventListener('click', (event) => {
event.preventDefault();
mapInput.value = '0';
mapPreview.innerHTML = '';
});
}
tbody.addEventListener('click', (event) => {
const target = event.target;
if (!(target instanceof HTMLElement)) {
return;
}
if (!target.classList.contains('tactic-remove-stat-row')) {
return;
}
const row = target.closest('tr');
if (row) {
row.remove();
reindexRows();
}
});
})(jQuery);
</script>
<?php
}