(function () { 'use strict'; var rootData = window.aksrtData || {}; var restRoot = (function () { var siteUrl = String(rootData.siteUrl || '/').replace(/\/+$/, ''); return siteUrl + '/wp-json/aksrt/v1'; })(); function request(path, options) { var config = options || {}; var headers = config.headers || {}; return fetch(restRoot + path, { method: config.method || 'GET', headers: Object.assign({ 'Content-Type': 'application/json', 'X-WP-Nonce': rootData.restNonce || '', }, headers), body: config.body || null, credentials: 'same-origin', }).then(function (response) { return response.json().catch(function () { return {}; }).then(function (payload) { if (!response.ok || payload.success === false) { throw new Error(payload.message || ('HTTP ' + response.status)); } return payload; }); }); } function setFeedback(node, text, state) { if (!node) { return; } node.textContent = text || ''; node.classList.remove('is-success', 'is-error', 'is-loading'); if (state) { node.classList.add(state); } } function bindComposeToolbar(form) { // §7.4: toolbar replaced by wp_editor TinyMCE — no-op stub kept for boot() compat } function insertTextAtCursor(textarea, text, after, start, end) { var value = textarea.value; textarea.value = value.substring(0, start) + text + (after || '') + value.substring(end); textarea.focus(); } function askUrlInline(anchor, placeholder, callback) { // kept for potential quicktags fallback var existing = document.querySelector('.aksrt-inline-url-input'); if (existing) existing.remove(); var input = document.createElement('input'); input.type = 'url'; input.className = 'aksrt-inline-url-input'; input.placeholder = placeholder || 'https://'; input.value = 'https://'; input.style.cssText = 'display:block;width:100%;max-width:320px;margin:4px 0;padding:6px 10px;border:1px solid #dce3ec;border-radius:8px;font-size:13px;'; var parent = anchor.parentElement; parent.insertBefore(input, anchor.nextSibling); input.focus(); input.select(); function done() { var val = input.value.trim(); input.remove(); callback(val); } input.addEventListener('keydown', function (e) { if (e.key === 'Enter') { e.preventDefault(); done(); } if (e.key === 'Escape') { input.remove(); callback(''); } }); input.addEventListener('blur', function () { done(); }); } function bindComposeVoteToggle(form) { var toggle = form.querySelector('#compose-vote-enabled'); var fields = form.querySelector('.aksrt-forum-compose__vote-fields'); if (!toggle || !fields) { return; } function sync() { fields.hidden = !toggle.checked; } toggle.addEventListener('change', sync); sync(); } function getEditorContent() { if (typeof tinymce !== 'undefined') { var editor = tinymce.get('compose-content'); if (editor && !editor.isHidden()) { return editor.getContent(); } } var textarea = document.querySelector('#compose-content'); return textarea ? textarea.value : ''; } function bindComposeDraft(form) { var draftButton = form.querySelector('#compose-draft'); var feedback = form.querySelector('.js-aksrt-action-feedback'); var ajaxUrl = form.getAttribute('data-ajax'); var nonce = form.getAttribute('data-nonce'); if (!draftButton || !ajaxUrl || !nonce) { return; } draftButton.addEventListener('click', function () { draftButton.disabled = true; setFeedback(feedback, '正在保存草稿…', 'is-loading'); var data = new FormData(form); data.set('content', getEditorContent()); data.append('action', 'aksrt_forum_save_draft'); data.append('_nonce', nonce); var draftId = form.getAttribute('data-draft-id') || '0'; if (draftId && draftId !== '0') { data.append('draft_id', draftId); } fetch(ajaxUrl, { method: 'POST', body: data, credentials: 'same-origin', }).then(function (r) { return r.json(); }).then(function (payload) { if (!payload.success) { throw new Error((payload.data && payload.data.message) || '保存失败'); } if (payload.data && payload.data.post_id) { form.setAttribute('data-draft-id', String(payload.data.post_id)); } setFeedback(feedback, payload.data.message || '草稿已保存', 'is-success'); draftButton.disabled = false; }).catch(function (error) { setFeedback(feedback, error.message || '保存失败', 'is-error'); draftButton.disabled = false; }); }); } function bindComposeSubmit(form) { var submitButton = form.querySelector('#compose-submit'); var feedback = form.querySelector('.js-aksrt-action-feedback'); var ajaxUrl = form.getAttribute('data-ajax'); var nonce = form.getAttribute('data-nonce'); if (!submitButton || !ajaxUrl || !nonce) { return; } form.addEventListener('submit', function (event) { event.preventDefault(); var board = form.querySelector('#compose-board') || form.querySelector('[name="board_id"]'); var title = form.querySelector('#compose-title'); var content = getEditorContent(); if (!board || !board.value || !title || !title.value.trim() || !content.trim()) { setFeedback(feedback, '请填写版块、标题和主题内容。', 'is-error'); return; } submitButton.disabled = true; setFeedback(feedback, '正在提交主题…', 'is-loading'); var data = new FormData(form); data.set('content', content); data.append('action', 'aksrt_forum_create_topic'); data.append('_nonce', nonce); var draftId = form.getAttribute('data-draft-id') || '0'; if (draftId && draftId !== '0') { data.append('draft_id', draftId); } fetch(ajaxUrl, { method: 'POST', body: data, credentials: 'same-origin', }).then(function (response) { return response.json(); }).then(function (payload) { if (!payload.success) { throw new Error((payload.data && payload.data.message) || '提交失败'); } if (payload.data && payload.data.redirect) { window.location.href = payload.data.redirect; return; } setFeedback(feedback, (payload.data && payload.data.message) || '主题已提交。', 'is-success'); }).catch(function (error) { setFeedback(feedback, error.message || '提交失败,请稍后重试。', 'is-error'); submitButton.disabled = false; }); }); } function bindModeratorApplyForm(form) { var feedback = form.querySelector('.js-aksrt-action-feedback'); var submitButton = form.querySelector('button[type="submit"]'); form.addEventListener('submit', function (event) { event.preventDefault(); var boardId = parseInt(form.getAttribute('data-board-id') || '0', 10); var reasonField = form.querySelector('[name="reason"]'); var reason = reasonField ? reasonField.value.trim() : ''; if (!boardId || !reason) { setFeedback(feedback, '请填写完整的申请理由。', 'is-error'); return; } if (submitButton) { submitButton.disabled = true; } setFeedback(feedback, '正在提交申请…', 'is-loading'); request('/forum/moderator/apply', { method: 'POST', body: JSON.stringify({ board_id: boardId, reason: reason, }), }).then(function (payload) { setFeedback(feedback, payload.message || '申请已提交', 'is-success'); if (submitButton) submitButton.disabled = true; // Disable the form to prevent re-submission var reasonField = form.querySelector('[name="reason"]'); if (reasonField) reasonField.disabled = true; }).catch(function (error) { setFeedback(feedback, error.message || '申请提交失败。', 'is-error'); if (submitButton) { submitButton.disabled = false; } }); }); } function bindVoteForm(form) { var feedback = form.querySelector('.js-aksrt-action-feedback'); var submitButton = form.querySelector('button[type="submit"]'); form.addEventListener('submit', function (event) { event.preventDefault(); var topicId = parseInt(form.getAttribute('data-topic-id') || '0', 10); var checked = Array.prototype.slice.call(form.querySelectorAll('input[name="option_ids[]"]:checked')).map(function (input) { return input.value; }); if (!topicId || checked.length === 0) { setFeedback(feedback, '请选择至少一个投票选项。', 'is-error'); return; } if (submitButton) { submitButton.disabled = true; } setFeedback(feedback, '正在提交投票…', 'is-loading'); request('/forum/topics/' + topicId + '/vote', { method: 'POST', body: JSON.stringify({ option_ids: checked }), }).then(function (payload) { setFeedback(feedback, payload.message || '投票成功', 'is-success'); // Disable all checkboxes and submit after vote var checkboxes = form.querySelectorAll('input[type="checkbox"]'); for (var i = 0; i < checkboxes.length; i++) checkboxes[i].disabled = true; if (submitButton) submitButton.disabled = true; }).catch(function (error) { setFeedback(feedback, error.message || '投票失败。', 'is-error'); if (submitButton) { submitButton.disabled = false; } }); }); } function buildModerationPayload(form, action) { var noteField = form.querySelector('[name="note"]'); var payload = { action: action, note: noteField ? noteField.value.trim() : '', }; if (action === 'review') { payload.review_status = (form.querySelector('[name="review_status"]') || {}).value || ''; } else if (action === 'move_board') { payload.target_board_id = parseInt((form.querySelector('[name="target_board_id"]') || {}).value || '0', 10); } else if (action === 'visibility') { payload.visibility = (form.querySelector('[name="visibility"]') || {}).value || ''; if (payload.visibility === 'credits') { payload.credits_cost = parseInt((form.querySelector('[name="credits_cost"]') || {}).value || '0', 10); } else if (payload.visibility === 'pay') { payload.pay_price = (form.querySelector('[name="pay_price"]') || {}).value || ''; } else if (payload.visibility === 'role') { payload.visibility_roles = Array.prototype.slice.call(form.querySelectorAll('[name="visibility_roles[]"] option:checked')).map(function (option) { return option.value; }); } } else if (action === 'sticky') { // 置顶分级(§7.3):发送 0~3 整数,而非布尔值。 payload.value = parseInt((form.querySelector('[name="sticky_value"]') || {}).value || '0', 10); } else if (action === 'question_status') { payload.value = parseInt((form.querySelector('[name="question_status_value"]') || {}).value || '0', 10); } else if (action === 'delete' || action === 'undelete') { payload.value = true; } else { var valueFieldName = action + '_value'; payload.value = ((form.querySelector('[name="' + valueFieldName + '"]') || {}).value || '0') === '1'; } return payload; } function bindModerationFieldToggle(form) { var actionField = form.querySelector('.js-aksrt-moderation-action'); var groups = form.querySelectorAll('.js-aksrt-moderation-field'); var visibilitySelect = form.querySelector('[name="visibility"]'); var visibilityExtras = form.querySelectorAll('.js-aksrt-visibility-extra'); if (!actionField || !groups.length) { return; } function syncVisibilityExtras() { if (!visibilitySelect || !visibilityExtras.length) { return; } var visibility = visibilitySelect.value; visibilityExtras.forEach(function (group) { group.hidden = actionField.value !== 'visibility' || group.getAttribute('data-visibility-field') !== visibility; }); } function sync() { var action = actionField.value; groups.forEach(function (group) { var fieldName = group.getAttribute('data-field'); if (group.classList.contains('js-aksrt-visibility-extra')) { return; } group.hidden = fieldName !== action; }); syncVisibilityExtras(); } actionField.addEventListener('change', sync); if (visibilitySelect) { visibilitySelect.addEventListener('change', syncVisibilityExtras); } sync(); } function bindModerationForm(form) { var feedback = form.querySelector('.js-aksrt-action-feedback'); var submitButton = form.querySelector('button[type="submit"]'); bindModerationFieldToggle(form); form.addEventListener('submit', function (event) { event.preventDefault(); var topicId = parseInt(form.getAttribute('data-topic-id') || '0', 10); var actionField = form.querySelector('.js-aksrt-moderation-action'); var action = actionField ? actionField.value : ''; if (!topicId || !action) { setFeedback(feedback, '请选择治理动作。', 'is-error'); return; } if (submitButton) { submitButton.disabled = true; } if (action === 'delete' && !window.confirm('确认将该主题移入回收站吗?')) { if (submitButton) submitButton.disabled = false; return; } if (action === 'undelete' && !window.confirm('确认恢复该主题吗?')) { if (submitButton) submitButton.disabled = false; return; } setFeedback(feedback, '正在执行治理动作…', 'is-loading'); request('/forum/topics/' + topicId + '/moderate', { method: 'POST', body: JSON.stringify(buildModerationPayload(form, action)), }).then(function (payload) { setFeedback(feedback, payload.message || '治理动作已执行', 'is-success'); if (submitButton) submitButton.disabled = true; }).catch(function (error) { setFeedback(feedback, error.message || '治理动作执行失败。', 'is-error'); if (submitButton) { submitButton.disabled = false; } }); }); } function bindQuickTopicAction(button) { button.addEventListener('click', function () { var topicId = parseInt(button.getAttribute('data-topic-id') || '0', 10); var action = button.getAttribute('data-action') || ''; var rawValue = button.getAttribute('data-value') || '0'; var valueType = button.getAttribute('data-value-type') || 'bool'; // 置顶分级(§7.3):data-value-type="int" 时发送整数级别,否则发送布尔值。 var value = valueType === 'int' ? parseInt(rawValue, 10) : rawValue === '1'; if (!topicId || !action) { return; } button.disabled = true; request('/forum/topics/' + topicId + '/moderate', { method: 'POST', body: JSON.stringify({ action: action, value: value, }), }).then(function () { // Toggle button visual state instead of reloading var icon = button.querySelector('i'); if (valueType === 'int' ? value > 0 : value) { button.classList.add('is-active'); if (icon) icon.className = icon.className.replace('far', 'fas'); } else { button.classList.remove('is-active'); if (icon) icon.className = icon.className.replace('fas', 'far'); } button.disabled = false; }).catch(function (error) { var msg = error.message || '治理动作执行失败。'; if (typeof window.aksrtToast === 'function') { window.aksrtToast(msg, 'error'); } else { window.alert(msg); } button.disabled = false; }); }); } function bindFavoriteButton(button) { button.addEventListener('click', function () { var topicId = button.getAttribute('data-topic-id'); if (!topicId || button.disabled) { return; } button.disabled = true; request('/forum/topics/' + topicId + '/favorite', { method: 'POST', body: JSON.stringify({}), }).then(function (payload) { var isFav = !!(payload.favorited); var icon = button.querySelector('i'); var label = button.querySelector('.js-aksrt-favorite-label'); button.setAttribute('data-favorited', isFav ? '1' : '0'); if (icon) { icon.className = isFav ? 'fas fa-bookmark' : 'far fa-bookmark'; } if (label) { label.textContent = isFav ? '已收藏' : '收藏'; } button.disabled = false; }).catch(function (error) { var msg = error.message || '操作失败'; if (typeof window.aksrtToast === 'function') { window.aksrtToast(msg, 'error'); } else { window.alert(msg); } button.disabled = false; }); }); } function bindScoreButton(button) { button.addEventListener('click', function () { var container = button.closest('.aksrt-forum-topic__score-actions'); if (!container || button.disabled) { return; } var topicId = container.getAttribute('data-topic-id'); var amount = parseInt(button.getAttribute('data-amount') || '0', 10); var feedback = container.querySelector('.js-aksrt-action-feedback'); if (!topicId || amount === 0) { return; } button.disabled = true; setFeedback(feedback, '提交中…', 'is-loading'); request('/forum/topics/' + topicId + '/score', { method: 'POST', body: JSON.stringify({ amount: amount }), }).then(function (payload) { var scoreEl = container.querySelector('.js-aksrt-score-value'); if (scoreEl && payload.score !== undefined) { scoreEl.textContent = String(payload.score); } setFeedback(feedback, payload.message || '评分成功', 'is-success'); // Disable both score buttons after success (one-time per user) container.querySelectorAll('.js-aksrt-topic-score').forEach(function (btn) { btn.disabled = true; }); }).catch(function (error) { setFeedback(feedback, error.message || '评分失败', 'is-error'); button.disabled = false; }); }); } function bindAdoptButton(button) { button.addEventListener('click', function () { var topicId = button.getAttribute('data-topic-id'); var commentId = button.getAttribute('data-comment-id'); if (!topicId || !commentId || button.disabled) { return; } if (!window.confirm('确认采纳该回复为最佳答案?')) { return; } button.disabled = true; request('/forum/topics/' + topicId + '/adopt', { method: 'POST', body: JSON.stringify({ comment_id: parseInt(commentId, 10) }), }).then(function (payload) { button.textContent = '✓ 已采纳'; button.classList.add('is-adopted'); // Disable all other adopt buttons document.querySelectorAll('.js-aksrt-adopt-answer').forEach(function (btn) { btn.disabled = true; }); }).catch(function (error) { var msg = error.message || '采纳失败'; if (typeof window.aksrtToast === 'function') { window.aksrtToast(msg, 'error'); } else { window.alert(msg); } button.disabled = false; }); }); } function bindReportModal(modal) { var form = modal.querySelector('.js-aksrt-report-form'); var feedback = modal.querySelector('.js-aksrt-action-feedback'); var targetLabel = modal.querySelector('.js-aksrt-report-target'); var targetTypeField = form ? form.querySelector('[name="target_type"]') : null; var targetIdField = form ? form.querySelector('[name="target_id"]') : null; var closeButtons = modal.querySelectorAll('.js-aksrt-report-close'); function openModal(trigger) { if (!form) return; var targetType = trigger.getAttribute('data-target-type') || 'post'; var targetId = trigger.getAttribute('data-target-id') || ''; var targetTitle = trigger.getAttribute('data-target-title') || ''; if (targetTypeField) targetTypeField.value = targetType; if (targetIdField) targetIdField.value = targetId; if (targetLabel) { targetLabel.textContent = '举报对象:' + (targetTitle || ('#' + targetId)); } modal.hidden = false; document.body.classList.add('is-report-modal-open'); } function closeModal() { modal.hidden = true; document.body.classList.remove('is-report-modal-open'); if (form) form.reset(); setFeedback(feedback, '', ''); } document.querySelectorAll('.js-aksrt-report-trigger').forEach(function (trigger) { trigger.addEventListener('click', function () { openModal(trigger); }); }); closeButtons.forEach(function (btn) { btn.addEventListener('click', closeModal); }); if (!form) return; form.addEventListener('submit', function (event) { event.preventDefault(); var reason = (form.querySelector('[name="reason"]') || {}).value || ''; if (!reason.trim()) { setFeedback(feedback, '请填写举报说明。', 'is-error'); return; } setFeedback(feedback, '正在提交举报…', 'is-loading'); request('/report/submit', { method: 'POST', body: JSON.stringify({ target_type: targetTypeField ? targetTypeField.value : 'post', target_id: parseInt(targetIdField ? targetIdField.value : '0', 10), category: (form.querySelector('[name="category"]') || {}).value || 'other', reason: reason, }), }).then(function (payload) { setFeedback(feedback, payload.message || '举报已提交', 'is-success'); setTimeout(closeModal, 900); }).catch(function (error) { setFeedback(feedback, error.message || '举报提交失败。', 'is-error'); }); }); } function insertForumEditorContent(html) { if (window.tinymce) { var ed = window.tinymce.get('compose-content') || window.tinymce.get('post_content'); if (ed && !ed.isHidden()) { ed.focus(); ed.execCommand('mceInsertContent', false, html); return; } } var ta = document.getElementById('compose-content') || document.getElementById('post_content'); if (!ta) return; var start = ta.selectionStart || 0; var end = ta.selectionEnd || 0; var val = ta.value || ''; ta.value = val.slice(0, start) + html + val.slice(end); ta.focus(); } function bindComposeShortcodeTools(root) { root = root || document; root.addEventListener('click', function (e) { var btn = e.target.closest('[data-insert-shortcode]'); if (!btn) return; e.preventDefault(); var type = btn.getAttribute('data-insert-shortcode'); if (type === 'hide') { insertForumEditorContent('[hidecontent type="login"]隐藏内容[/hidecontent]'); } else if (type === 'reply') { insertForumEditorContent('[hidecontent type="reply"]回复后可见[/hidecontent]'); } else if (type === 'payshow') { insertForumEditorContent('[hidecontent type="payshow"]付费可见内容[/hidecontent]'); } else if (type === 'vip') { insertForumEditorContent('[vip]VIP 可见内容[/vip]'); } }); } function bindComposeVisibilityToggle(form) { var visSelect = form.querySelector('#compose-visibility'); var creditsField = form.querySelector('#compose-credits-cost-field'); var payField = form.querySelector('#compose-pay-price-field'); var roleField = form.querySelector('#compose-role-field'); if (!visSelect) return; function syncVisFields() { var val = visSelect.value; if (creditsField) creditsField.style.display = val === 'credits' ? '' : 'none'; if (payField) payField.style.display = val === 'pay' ? '' : 'none'; if (roleField) roleField.style.display = val === 'role' ? '' : 'none'; } visSelect.addEventListener('change', syncVisFields); syncVisFields(); } function bindUnlockButton(button) { button.addEventListener('click', function () { var topicId = parseInt(button.getAttribute('data-topic-id') || '0', 10); var cost = button.getAttribute('data-cost') || '0'; var feedback = button.parentElement ? button.parentElement.querySelector('.js-aksrt-action-feedback') : null; if (!topicId || !window.confirm('确认使用 ' + cost + ' 积分解锁此主题?')) { return; } button.disabled = true; setFeedback(feedback, '正在解锁…', 'is-loading'); var data = new FormData(); data.append('action', 'aksrt_forum_unlock_topic'); data.append('topic_id', topicId); data.append('_nonce', rootData.forumNonce || ''); fetch((rootData.ajaxUrl || '/wp-admin/admin-ajax.php'), { method: 'POST', body: data, credentials: 'same-origin', }).then(function (r) { return r.json(); }).then(function (payload) { if (!payload.success) { throw new Error((payload.data && payload.data.message) || '解锁失败'); } setFeedback(feedback, '解锁成功,正在刷新…', 'is-success'); setTimeout(function () { window.location.reload(); }, 800); }).catch(function (error) { setFeedback(feedback, error.message || '解锁失败', 'is-error'); button.disabled = false; }); }); } function formatFollowPayLabel(pay) { pay = pay || {}; if (pay.is_free) { return 'VIP 免费关注'; } if (pay.label) { return String(pay.label); } if (pay.modo === 'points') { return String(pay.amount || 0) + ' 积分'; } return '¥' + String(pay.amount || '0'); } function purchasePlateFollow(plateId, button, payHint) { payHint = payHint || {}; var modo = String(payHint.modo || 'money'); // Cash (paid or VIP free): multi-gateway cashier — free VIP still creates 0-order for ledger. // No Credits×100 bypass. if (modo === 'money') { button.disabled = false; if (typeof window.aksrtOpenCashier === 'function') { window.aksrtOpenCashier(plateId, button, '', '', 'plate_follow'); return; } var msgCashier = '收银台未加载,请刷新页面后重试'; if (typeof window.aksrtToast === 'function') { window.aksrtToast(msgCashier, 'error'); } else { window.alert(msgCashier); } return; } // Points / points VIP free: keep AJAX purchase path. var confirmMsg = '确认付费关注该版块?'; if (payHint.is_free) { confirmMsg = '确认使用 VIP 免费关注该版块?'; } else { confirmMsg = '确认支付 ' + formatFollowPayLabel(payHint) + ' 关注该版块?'; } if (!window.confirm(confirmMsg)) { button.disabled = false; return; } var data = new FormData(); data.append('action', 'aksrt_forum_purchase_plate_follow'); data.append('plate_id', plateId); data.append('_nonce', rootData.forumNonce || ''); fetch((rootData.ajaxUrl || '/wp-admin/admin-ajax.php'), { method: 'POST', body: data, credentials: 'same-origin', }).then(function (r) { return r.json(); }).then(function (payload) { if (!payload.success) { var errData = payload.data || {}; // Server may redirect money path to cashier. if (errData.require_cashier && typeof window.aksrtOpenCashier === 'function') { button.disabled = false; window.aksrtOpenCashier(plateId, button, '', '', 'plate_follow'); return; } throw new Error(errData.message || '支付失败'); } var res = payload.data || {}; button.setAttribute('data-followed', '1'); button.classList.add('is-followed'); if (button.querySelector('i') && button.childNodes.length) { button.innerHTML = ' 已关注'; } else { button.textContent = '已关注'; } if (typeof window.aksrtToast === 'function') { window.aksrtToast(res.message || '关注成功', 'success'); } setTimeout(function () { window.location.reload(); }, 600); }).catch(function (error) { var msg = error.message || '支付失败'; if (typeof window.aksrtToast === 'function') { window.aksrtToast(msg, 'error'); } else { window.alert(msg); } button.disabled = false; }); } function bindFollowPlateButton(button) { button.addEventListener('click', function () { var plateId = parseInt(button.getAttribute('data-plate-id') || '0', 10); if (!plateId || button.disabled) { return; } button.disabled = true; var data = new FormData(); data.append('action', 'aksrt_forum_follow_plate'); data.append('plate_id', plateId); data.append('_nonce', rootData.forumNonce || ''); fetch((rootData.ajaxUrl || '/wp-admin/admin-ajax.php'), { method: 'POST', body: data, credentials: 'same-origin', }).then(function (r) { return r.json(); }).then(function (payload) { // Paid follow required if (!payload.success && payload.data && payload.data.require_pay) { purchasePlateFollow(plateId, button, payload.data.pay || {}); return; } if (!payload.success) { throw new Error((payload.data && payload.data.message) || '操作失败'); } var res = payload.data || {}; var followed = !!res.followed; button.setAttribute('data-followed', followed ? '1' : '0'); button.classList.toggle('is-followed', followed); button.innerHTML = followed ? ' 已关注' : ' 关注'; button.disabled = false; }).catch(function (error) { var msg = error.message || '操作失败'; if (typeof window.aksrtToast === 'function') { window.aksrtToast(msg, 'error'); } else { window.alert(msg); } button.disabled = false; }); }); } function bindComposeCoverToggle(form) { var coverTypeSelect = form.querySelector('#compose-cover-type'); var imageField = form.querySelector('#compose-cover-image-field'); var slideField = form.querySelector('#compose-cover-slide-field'); var videoField = form.querySelector('#compose-cover-video-field'); if (!coverTypeSelect) return; function syncCoverFields() { var val = coverTypeSelect.value; if (imageField) imageField.style.display = val === 'image' ? '' : 'none'; if (slideField) slideField.style.display = val === 'slide' ? '' : 'none'; if (videoField) videoField.style.display = val === 'video' ? '' : 'none'; } coverTypeSelect.addEventListener('change', syncCoverFields); syncCoverFields(); var imageInput = form.querySelector('#compose-cover-image'); var imagePreview = form.querySelector('#compose-cover-preview'); var imageBtn = form.querySelector('#compose-cover-upload-btn'); if (imageBtn && typeof wp !== 'undefined' && wp.media) { imageBtn.addEventListener('click', function () { var frame = wp.media({ title: '选择封面图片', multiple: false, library: { type: 'image' } }); frame.on('select', function () { var attachment = frame.state().get('selection').first().toJSON(); if (imageInput) imageInput.value = attachment.url; if (imagePreview) imagePreview.innerHTML = ''; }); frame.open(); }); } var slideInput = form.querySelector('#compose-featured-slide'); var slidePreview = form.querySelector('#compose-slide-preview'); var slideBtn = form.querySelector('#compose-slide-upload-btn'); if (slideBtn && typeof wp !== 'undefined' && wp.media) { slideBtn.addEventListener('click', function () { var frame = wp.media({ title: '选择幻灯片图片', multiple: true, library: { type: 'image' } }); frame.on('select', function () { var urls = frame.state().get('selection').map(function (a) { return a.toJSON().url; }); urls = urls.slice(0, 9); if (slideInput) slideInput.value = JSON.stringify(urls); if (slidePreview) { slidePreview.innerHTML = urls.map(function (u) { return ''; }).join(''); } }); frame.open(); }); } } function bindEditPlateButton(button) { button.addEventListener('click', function () { var plateId = button.getAttribute('data-plate-id'); var name = window.prompt('版块名称:', button.getAttribute('data-name') || ''); if (name === null) return; var description = window.prompt('版块描述:', button.getAttribute('data-description') || ''); if (description === null) description = ''; request('/forum/front/plates/' + plateId, { method: 'POST', body: JSON.stringify({ name: name, description: description }), }).then(function () { window.location.reload(); }).catch(function (error) { window.alert(error.message || '编辑失败'); }); }); } function bindDeletePlateButton(button) { button.addEventListener('click', function () { var plateId = button.getAttribute('data-plate-id'); var topicCount = parseInt(button.getAttribute('data-topic-count') || '0', 10); var msg = '确认删除此版块?'; if (topicCount > 0) { msg += '\n该版块下有 ' + topicCount + ' 个主题,删除后将移入回收站。'; } if (!window.confirm(msg)) return; request('/forum/front/plates/' + plateId, { method: 'DELETE', body: JSON.stringify({ cascade: 'trash' }), }).then(function () { window.location.href = (rootData.siteUrl || '') + '/forums/'; }).catch(function (error) { window.alert(error.message || '删除失败'); }); }); } // ────────────────────────────────────────────────────────── // §7.4 — Remote search selector // ────────────────────────────────────────────────────────── function bindRemoteSelects(container) { var selects = container.querySelectorAll('.aksrt-remote-select'); selects.forEach(function (wrapper) { var searchAction = wrapper.getAttribute('data-search-action'); var hiddenInput = wrapper.querySelector('input[type="hidden"]'); var textInput = wrapper.querySelector('.js-aksrt-remote-input'); var dropdown = wrapper.querySelector('.aksrt-remote-select__dropdown'); if (!searchAction || !hiddenInput || !textInput || !dropdown) return; var debounceTimer = null; var ajaxUrl = (rootData.ajaxUrl || '/wp-admin/admin-ajax.php'); textInput.addEventListener('input', function () { clearTimeout(debounceTimer); var q = textInput.value.trim(); debounceTimer = setTimeout(function () { fetch(ajaxUrl + '?action=' + encodeURIComponent(searchAction) + '&q=' + encodeURIComponent(q), { credentials: 'same-origin', }).then(function (r) { return r.json(); }).then(function (payload) { if (!payload.success || !payload.data) return; dropdown.innerHTML = ''; payload.data.forEach(function (item) { var div = document.createElement('div'); div.className = 'aksrt-remote-select__option'; div.textContent = item.name; div.setAttribute('data-id', String(item.id)); div.addEventListener('mousedown', function (e) { e.preventDefault(); hiddenInput.value = item.id; textInput.value = item.name; dropdown.hidden = true; }); dropdown.appendChild(div); }); dropdown.hidden = payload.data.length === 0; }); }, 250); }); textInput.addEventListener('focus', function () { if (dropdown.children.length > 0) dropdown.hidden = false; textInput.dispatchEvent(new Event('input')); }); textInput.addEventListener('blur', function () { setTimeout(function () { dropdown.hidden = true; }, 200); }); }); } // ────────────────────────────────────────────────────────── // §7.4 — Tag tokenizer // ────────────────────────────────────────────────────────── function bindTagInputs(container) { var wrappers = container.querySelectorAll('.aksrt-tag-input'); wrappers.forEach(function (wrapper) { var searchAction = wrapper.getAttribute('data-search-action'); var maxTags = parseInt(wrapper.getAttribute('data-max') || '5', 10); var hiddenInput = wrapper.querySelector('input[type="hidden"]'); var tokenContainer = wrapper.querySelector('.aksrt-tag-input__tokens'); var textInput = wrapper.querySelector('.js-aksrt-tag-search'); var dropdown = wrapper.querySelector('.aksrt-tag-input__dropdown'); if (!hiddenInput || !tokenContainer || !textInput) return; var tags = []; var initialVal = (hiddenInput.value || '').trim(); if (initialVal) { initialVal.split(/[,,]/).forEach(function (t) { t = t.trim(); if (t && tags.indexOf(t) === -1) tags.push(t); }); } function syncHidden() { hiddenInput.value = tags.join(', '); } function renderTokens() { tokenContainer.innerHTML = ''; tags.forEach(function (tag, idx) { var span = document.createElement('span'); span.className = 'aksrt-tag-input__token'; span.textContent = tag; var close = document.createElement('button'); close.type = 'button'; close.className = 'aksrt-tag-input__token-remove'; close.innerHTML = '×'; close.addEventListener('click', function () { tags.splice(idx, 1); syncHidden(); renderTokens(); }); span.appendChild(close); tokenContainer.appendChild(span); }); } function addTag(name) { name = name.trim(); if (!name || tags.indexOf(name) !== -1 || tags.length >= maxTags) return; tags.push(name); syncHidden(); renderTokens(); textInput.value = ''; } renderTokens(); textInput.addEventListener('keydown', function (e) { if (e.key === 'Enter' || e.key === ',') { e.preventDefault(); addTag(textInput.value); if (dropdown) dropdown.hidden = true; } if (e.key === 'Backspace' && textInput.value === '' && tags.length > 0) { tags.pop(); syncHidden(); renderTokens(); } }); if (searchAction && dropdown) { var ajaxUrl = (rootData.ajaxUrl || '/wp-admin/admin-ajax.php'); var debounce = null; textInput.addEventListener('input', function () { clearTimeout(debounce); var q = textInput.value.trim(); if (!q) { dropdown.hidden = true; return; } debounce = setTimeout(function () { fetch(ajaxUrl + '?action=' + encodeURIComponent(searchAction) + '&q=' + encodeURIComponent(q), { credentials: 'same-origin', }).then(function (r) { return r.json(); }).then(function (payload) { if (!payload.success || !payload.data) return; dropdown.innerHTML = ''; payload.data.forEach(function (item) { var div = document.createElement('div'); div.className = 'aksrt-tag-input__suggestion'; div.textContent = item.name + (item.count !== undefined ? ' (' + item.count + ')' : ''); div.addEventListener('mousedown', function (e) { e.preventDefault(); addTag(item.name); dropdown.hidden = true; }); dropdown.appendChild(div); }); dropdown.hidden = payload.data.length === 0; }); }, 250); }); textInput.addEventListener('blur', function () { setTimeout(function () { dropdown.hidden = true; }, 200); }); } }); } // ────────────────────────────────────────────────────────── // §7.4 — Title character counter // ────────────────────────────────────────────────────────── function bindTitleCounter(form) { var titleInput = form.querySelector('#compose-title'); var counterCurrent = form.querySelector('.js-aksrt-counter-current'); if (!titleInput || !counterCurrent) return; function update() { counterCurrent.textContent = String(titleInput.value.length); var max = parseInt(titleInput.getAttribute('data-aksrt-maxlength') || '30', 10); var parent = counterCurrent.closest('.aksrt-forum-compose__char-counter'); if (parent) { parent.classList.toggle('is-over', titleInput.value.length > max); parent.classList.toggle('is-near', titleInput.value.length > max * 0.8 && titleInput.value.length <= max); } } titleInput.addEventListener('input', update); update(); } // ────────────────────────────────────────────────────────── // §7.4 — Draft list toggle & delete // ────────────────────────────────────────────────────────── function bindDraftUI() { var toggle = document.querySelector('.js-aksrt-draft-toggle'); var list = document.querySelector('#compose-draft-list'); if (toggle && list) { toggle.addEventListener('click', function () { list.hidden = !list.hidden; var icon = toggle.querySelector('i.fa-chevron-down, i.fa-chevron-up'); if (icon) { icon.classList.toggle('fa-chevron-down'); icon.classList.toggle('fa-chevron-up'); } }); } document.querySelectorAll('.js-aksrt-delete-draft').forEach(function (btn) { btn.addEventListener('click', function () { var draftId = btn.getAttribute('data-draft-id'); if (!draftId || !window.confirm('确认删除此草稿?')) return; var ajaxUrl = (rootData.ajaxUrl || '/wp-admin/admin-ajax.php'); var nonce = ''; var form = document.querySelector('.js-aksrt-forum-compose-form'); if (form) nonce = form.getAttribute('data-nonce') || ''; var data = new FormData(); data.append('action', 'aksrt_forum_delete_draft'); data.append('_nonce', nonce); data.append('draft_id', draftId); fetch(ajaxUrl, { method: 'POST', body: data, credentials: 'same-origin' }) .then(function (r) { return r.text().then(function (text) { var payload = null; try { payload = text ? JSON.parse(text) : null; } catch (e) { payload = null; } return { ok: r.ok, status: r.status, payload: payload, raw: text }; }); }) .then(function (res) { if (res.payload && res.payload.success) { var item = btn.closest('.aksrt-forum-compose__draft-item'); if (item) item.remove(); return; } var msg = (res.payload && res.payload.data && res.payload.data.message) || (res.payload && res.payload.message) || (res.status === 500 ? '服务器错误:请确认主题已更新到最新 main(Forum.php 草稿 autoload 修复)' : '删除失败'); if (window.console && console.warn) { console.warn('[aksrt] delete draft failed', res.status, msg); } window.alert(msg); }) .catch(function (err) { if (window.console && console.warn) { console.warn('[aksrt] delete draft network error', err); } window.alert('删除失败,请稍后重试'); }); }); }); } // ────────────────────────────────────────────────────────── // §7.4 — Edit form AJAX submit // ────────────────────────────────────────────────────────── function bindEditForm(form) { var submitButton = form.querySelector('#compose-submit'); var feedback = form.querySelector('.js-aksrt-action-feedback'); var ajaxUrl = form.getAttribute('data-ajax'); var nonce = form.getAttribute('data-nonce'); var topicId = form.getAttribute('data-topic-id'); if (!submitButton || !ajaxUrl || !nonce || !topicId) return; form.addEventListener('submit', function (event) { event.preventDefault(); var title = form.querySelector('#compose-title'); var content = getEditorContent(); if (!title || !title.value.trim() || !content.trim()) { setFeedback(feedback, '标题和内容不能为空。', 'is-error'); return; } submitButton.disabled = true; setFeedback(feedback, '正在保存…', 'is-loading'); var data = new FormData(form); data.set('content', content); data.append('action', 'aksrt_forum_edit_topic'); data.append('_nonce', nonce); data.append('topic_id', topicId); fetch(ajaxUrl, { method: 'POST', body: data, credentials: 'same-origin', }).then(function (r) { return r.json(); }).then(function (payload) { if (!payload.success) { throw new Error((payload.data && payload.data.message) || '保存失败'); } if (payload.data && payload.data.redirect) { window.location.href = payload.data.redirect; return; } setFeedback(feedback, payload.data.message || '已保存', 'is-success'); submitButton.disabled = false; }).catch(function (error) { setFeedback(feedback, error.message || '保存失败', 'is-error'); submitButton.disabled = false; }); }); } // ── §7.6 Forum comment engine ───────────────────────────────────────── function bindForumCommentEngine() { var section = document.getElementById('aksrt-forum-replies'); if (!section) return; var topicId = section.dataset.topicId; var nonce = section.dataset.nonce; var list = section.querySelector('.js-aksrt-forum-replies-list'); var loadMore = section.querySelector('.js-aksrt-forum-load-more'); var currentSort = 'newest'; var currentAuthorOnly = false; // Sort tabs section.querySelectorAll('.aksrt-forum-replies__tab').forEach(function (tab) { tab.addEventListener('click', function () { section.querySelectorAll('.aksrt-forum-replies__tab').forEach(function (t) { t.classList.remove('is-active'); }); tab.classList.add('is-active'); currentSort = tab.dataset.sort || 'newest'; loadComments(1); }); }); // Author-only toggle var authorToggle = section.querySelector('.aksrt-forum-replies__author-toggle'); if (authorToggle) { authorToggle.addEventListener('change', function () { currentAuthorOnly = authorToggle.checked; loadComments(1); }); } // Load more button if (loadMore) { loadMore.addEventListener('click', function () { var page = parseInt(loadMore.dataset.page, 10) || 1; loadComments(page + 1, true); }); } function loadComments(page, append) { var fd = new FormData(); fd.append('action', 'aksrt_forum_comments'); fd.append('nonce', nonce); fd.append('topic_id', topicId); fd.append('sort', currentSort); fd.append('author_only', currentAuthorOnly ? '1' : ''); fd.append('page', page); list.style.opacity = append ? '1' : '0.5'; fetch(window.aksrtForumGovernance ? window.aksrtForumGovernance.ajaxUrl : (window.ajaxurl || '/wp-admin/admin-ajax.php'), { method: 'POST', body: fd, credentials: 'same-origin' }).then(function (r) { return r.json(); }) .then(function (res) { list.style.opacity = '1'; if (!res.success) return; if (append) { list.insertAdjacentHTML('beforeend', res.data.html); } else { list.innerHTML = res.data.html; } if (loadMore) { loadMore.dataset.page = String(page); loadMore.dataset.max = String(res.data.max_pages); loadMore.closest('.aksrt-forum-replies__load-more').style.display = res.data.has_more ? '' : 'none'; } bindDynamicCommentActions(list); }).catch(function () { list.style.opacity = '1'; }); } bindDynamicCommentActions(list); } function bindDynamicCommentActions(container) { if (!container) return; container.querySelectorAll('.js-aksrt-comment-like').forEach(bindCommentLike); container.querySelectorAll('.js-aksrt-adopt-answer').forEach(bindAdoptButton); container.querySelectorAll('.js-aksrt-comment-reply').forEach(bindCommentReply); container.querySelectorAll('.js-aksrt-comment-top').forEach(bindCommentTop); } function bindCommentLike(btn) { if (btn._likebound) return; btn._likebound = true; btn.addEventListener('click', function () { var commentId = btn.dataset.commentId; var active = btn.dataset.active === '1'; var newActive = !active; btn.disabled = true; fetch(window.aksrtForumGovernance ? window.aksrtForumGovernance.restUrl + 'aksrt/v1/comment/like' : '/wp-json/aksrt/v1/comment/like', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-WP-Nonce': window.aksrtForumGovernance ? window.aksrtForumGovernance.restNonce : '' }, body: JSON.stringify({ comment_id: parseInt(commentId, 10), active: newActive }), credentials: 'same-origin' }).then(function (r) { return r.json(); }) .then(function (res) { btn.disabled = false; if (!res.success && !res.data) return; var data = res.data || res; btn.dataset.active = data.active ? '1' : '0'; btn.classList.toggle('is-active', !!data.active); var icon = btn.querySelector('i'); if (icon) { icon.className = data.active ? 'fas fa-thumbs-up' : 'far fa-thumbs-up'; } var count = btn.querySelector('.aksrt-forum-reply__like-count'); if (count) { count.textContent = data.count > 0 ? String(data.count) : ''; } }).catch(function () { btn.disabled = false; }); }); } function bindCommentReply(btn) { if (btn._replybound) return; btn._replybound = true; btn.addEventListener('click', function () { var commentId = btn.dataset.commentId; var author = btn.dataset.author || ''; var form = document.querySelector('.aksrt-forum-topic__reply-form'); if (!form) return; var textarea = form.querySelector('textarea[name="comment"]'); if (!textarea) return; // Set reply parent var parentInput = form.querySelector('input[name="comment_parent"]'); if (!parentInput) { parentInput = document.createElement('input'); parentInput.type = 'hidden'; parentInput.name = 'comment_parent'; form.querySelector('form').appendChild(parentInput); } parentInput.value = commentId; textarea.placeholder = '@' + author + ' '; textarea.focus(); form.scrollIntoView({ behavior: 'smooth', block: 'center' }); }); } function bindCommentTop(btn) { if (btn._topbound) return; btn._topbound = true; btn.addEventListener('click', function () { var commentId = btn.dataset.commentId; var currentLevel = parseInt(btn.dataset.level, 10) || 0; var newLevel = currentLevel > 0 ? 0 : 1; btn.disabled = true; var section = document.getElementById('aksrt-forum-replies'); var nonce = section ? section.dataset.nonce : ''; var fd = new FormData(); fd.append('action', 'aksrt_forum_comment_top'); fd.append('nonce', nonce); fd.append('comment_id', commentId); fd.append('level', newLevel); fetch(window.aksrtForumGovernance ? window.aksrtForumGovernance.ajaxUrl : (window.ajaxurl || '/wp-admin/admin-ajax.php'), { method: 'POST', body: fd, credentials: 'same-origin' }).then(function (r) { return r.json(); }) .then(function (res) { btn.disabled = false; if (res.success) { btn.dataset.level = String(newLevel); var icon = btn.querySelector('i'); btn.childNodes.forEach(function (n) { if (n.nodeType === 3) n.textContent = newLevel > 0 ? ' 取消置顶' : ' 置顶'; }); // Reload comments to reflect pin ordering var activeTab = section && section.querySelector('.aksrt-forum-replies__tab.is-active'); if (activeTab) activeTab.click(); } }).catch(function () { btn.disabled = false; }); }); } // ── §7.10 Forum home tab engine ────────────────────────────────────── function bindForumHomeTabs() { var nav = document.getElementById('aksrt-forum-home-tabs'); if (!nav) return; var content = document.getElementById('aksrt-forum-home-content'); if (!content) return; var nonce = nav.dataset.nonce || ''; var ajaxUrl = nav.dataset.ajaxUrl || (window.aksrtForumGovernance ? window.aksrtForumGovernance.ajaxUrl : '/wp-admin/admin-ajax.php'); nav.querySelectorAll('.aksrt-forum-home-tabs__btn').forEach(function (btn) { btn.addEventListener('click', function () { var tabType = btn.dataset.tabType; nav.querySelectorAll('.aksrt-forum-home-tabs__btn').forEach(function (b) { b.classList.remove('is-active'); }); btn.classList.add('is-active'); loadHomeTab(tabType, 1); }); }); // Load-more on home content content.addEventListener('click', function (e) { var moreBtn = e.target.closest('.js-aksrt-home-load-more'); if (!moreBtn) return; var page = parseInt(moreBtn.dataset.page, 10) || 1; var tabType = moreBtn.dataset.tab || 'synthesis'; loadHomeTab(tabType, page + 1, true, moreBtn); }); function loadHomeTab(tabType, page, append, moreBtn) { var fd = new FormData(); fd.append('action', 'aksrt_forum_home_tab'); fd.append('nonce', nonce); fd.append('tab_type', tabType); fd.append('page', page); if (!append) { content.style.opacity = '0.5'; } if (moreBtn) moreBtn.disabled = true; fetch(ajaxUrl, { method: 'POST', body: fd, credentials: 'same-origin' }) .then(function (r) { return r.json(); }) .then(function (res) { content.style.opacity = '1'; if (!res.success) return; if (res.data.type === 'plate') { // Plate tab — reload the whole page to get server-rendered board grid window.location.href = window.location.pathname + '?forum_tab=plate'; return; } if (append) { var list = content.querySelector('.js-aksrt-home-topic-list'); if (list) { list.insertAdjacentHTML('beforeend', res.data.html); } if (moreBtn) { moreBtn.disabled = false; moreBtn.dataset.page = String(page); if (!res.data.has_more) { moreBtn.closest('.aksrt-forum-home__load-more').style.display = 'none'; } } } else { var html = '
' + res.data.html + '
'; if (res.data.has_more) { html += '
' + '
'; } content.innerHTML = html; } }).catch(function () { content.style.opacity = '1'; if (moreBtn) moreBtn.disabled = false; }); } } function bindBoardSortTabs() { var root = document.querySelector('.aksrt-forum-board[data-plate-id], .aksrt-forum-board[data-board-id]'); if (!root) return; var list = root.querySelector('.js-aksrt-board-topic-list'); var tabs = root.querySelectorAll('.js-aksrt-board-sort-tab'); if (!list || !tabs.length) return; var plateId = root.getAttribute('data-plate-id') || ''; var boardId = root.getAttribute('data-board-id') || ''; var nonce = root.getAttribute('data-nonce') || (window.aksrtForumGovernance && aksrtForumGovernance.publicNonce) || (window.aksrtData && aksrtData.nonce) || ''; var ajaxUrl = (window.aksrtForumGovernance && aksrtForumGovernance.ajaxUrl) || (window.aksrtData && aksrtData.ajaxUrl) || ''; function loadSort(sort, pushUrl) { if (!ajaxUrl) return; list.style.opacity = '0.55'; var fd = new FormData(); fd.append('action', 'aksrt_forum_board_topics'); fd.append('nonce', nonce); fd.append('page', '1'); fd.append('orderby', sort); if (plateId) fd.append('plate_id', plateId); if (boardId) fd.append('board_id', boardId); fetch(ajaxUrl, { method: 'POST', body: fd, credentials: 'same-origin' }) .then(function (r) { return r.json(); }) .then(function (res) { list.style.opacity = '1'; if (!res || !res.success) return; list.innerHTML = res.data.html || ''; root.setAttribute('data-active-sort', sort); tabs.forEach(function (t) { t.classList.toggle('is-active', (t.getAttribute('data-sort') || '') === sort); }); if (pushUrl && window.history && history.replaceState) { try { var u = new URL(window.location.href); u.searchParams.set('forum_sort', sort); history.replaceState({}, '', u.toString()); } catch (e) {} } }) .catch(function () { list.style.opacity = '1'; }); } tabs.forEach(function (tab) { tab.addEventListener('click', function (e) { e.preventDefault(); var sort = tab.getAttribute('data-sort') || 'date'; if (sort === (root.getAttribute('data-active-sort') || '')) return; loadSort(sort, true); }); }); } function boot() { var composeForm = document.querySelector('.js-aksrt-forum-compose-form'); if (composeForm) { bindComposeToolbar(composeForm); bindComposeVoteToggle(composeForm); bindComposeCoverToggle(composeForm); bindComposeVisibilityToggle(composeForm); bindComposeDraft(composeForm); bindComposeSubmit(composeForm); bindRemoteSelects(composeForm); bindTagInputs(composeForm); bindTitleCounter(composeForm); bindDraftUI(); } var editForm = document.querySelector('.js-aksrt-forum-edit-form'); if (editForm) { bindComposeVoteToggle(editForm); bindComposeCoverToggle(editForm); bindComposeVisibilityToggle(editForm); bindRemoteSelects(editForm); bindTagInputs(editForm); bindTitleCounter(editForm); bindEditForm(editForm); } document.querySelectorAll('.js-aksrt-moderator-apply-form').forEach(bindModeratorApplyForm); document.querySelectorAll('.js-aksrt-topic-vote-form').forEach(bindVoteForm); document.querySelectorAll('.js-aksrt-topic-moderation-form').forEach(bindModerationForm); document.querySelectorAll('.js-aksrt-topic-action').forEach(bindQuickTopicAction); document.querySelectorAll('.js-aksrt-topic-favorite').forEach(bindFavoriteButton); document.querySelectorAll('.js-aksrt-topic-score').forEach(bindScoreButton); document.querySelectorAll('.js-aksrt-adopt-answer').forEach(bindAdoptButton); document.querySelectorAll('.js-aksrt-unlock-topic').forEach(bindUnlockButton); document.querySelectorAll('.js-aksrt-follow-plate').forEach(bindFollowPlateButton); bindForumCommentEngine(); bindForumHomeTabs(); bindBoardSortTabs(); document.querySelectorAll('.js-aksrt-edit-plate').forEach(bindEditPlateButton); document.querySelectorAll('.js-aksrt-delete-plate').forEach(bindDeletePlateButton); var reportModal = document.querySelector('#aksrt-report-modal'); if (reportModal) { bindReportModal(reportModal); } } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', boot); } else { boot(); } })();