/** * Comment expand tools — shortcode inserts and comment image upload. */ (function () { 'use strict'; var uploadStates = new WeakMap(); function findTextarea(from) { var form = from && from.closest ? from.closest('form') : null; if (form) { return form.querySelector('textarea.grin, textarea#comment, textarea[name="comment"]'); } return document.querySelector('#comment, textarea.grin'); } function insertAtCursor(textarea, value) { if (!textarea) return; var start = textarea.selectionStart || 0; var end = textarea.selectionEnd || 0; var val = textarea.value || ''; textarea.value = val.slice(0, start) + value + val.slice(end); var pos = start + value.length; textarea.selectionStart = textarea.selectionEnd = pos; textarea.focus(); textarea.dispatchEvent(new Event('input')); } function notify(message, type) { if (typeof window.notyf === 'function') { window.notyf(message, type); } } function showImageTab(trigger) { var selector = trigger.getAttribute('data-image-tab'); var wrapper = trigger.closest('.comment-image-tabs'); if (!selector || !wrapper) return null; var target = wrapper.querySelector(selector); if (!target) return null; wrapper.querySelectorAll('.tab-pane').forEach(function (pane) { pane.classList.remove('in', 'active'); }); target.classList.add('in', 'active'); return target; } function getUploadState(form) { var state = uploadStates.get(form); if (state) return state; var preview = form.querySelector('.preview'); state = { file: null, uploading: false, previewHtml: preview ? preview.innerHTML : '' }; uploadStates.set(form, state); return state; } function resetUpload(form) { var state = getUploadState(form); var input = form.querySelector('.comment-image-file'); var preview = form.querySelector('.preview'); state.file = null; state.uploading = false; if (input) { input.disabled = false; input.value = ''; } if (preview) preview.innerHTML = state.previewHtml; } function restoreUploadButton(button, html) { button.disabled = false; button.innerHTML = html; } function validateImage(input, file) { var accepts = (input.getAttribute('accept') || '') .split(',') .map(function (type) { return type.trim().toLowerCase(); }) .filter(Boolean); var fileType = (file.type || '').toLowerCase(); if (accepts.length && accepts.indexOf(fileType) === -1) { notify('图片格式错误:' + file.name, 'danger'); return false; } var maxSize = Number((window.aksrtData || {}).commentUploadMaxSize) || 0; if (maxSize > 0 && file.size > maxSize) { notify('图片大小不能超过 ' + Math.round(maxSize / 1024 / 1024) + 'MB', 'danger'); return false; } return true; } function previewImage(form, file) { var preview = form.querySelector('.preview'); if (!preview) return; if (typeof FileReader === 'undefined') { notify('当前浏览器不支持图片预览', 'danger'); return; } var reader = new FileReader(); reader.onload = function (event) { if (getUploadState(form).file !== file) return; var image = document.createElement('img'); image.className = 'fit-cover'; image.alt = ''; image.src = event.target.result; preview.innerHTML = ''; preview.appendChild(image); }; reader.readAsDataURL(file); } function parseUploadResponse(xhr) { try { return JSON.parse(xhr.responseText || '{}'); } catch (error) { return null; } } function uploadImage(button) { var form = button.closest('.comment-image-upload'); if (!form) return; var input = form.querySelector('.comment-image-file'); var state = getUploadState(form); if (!input || !state.file) { notify('请先选择待上传的图片', 'danger'); return; } if (state.uploading) return; var data = window.aksrtData || {}; var uploadUrl = data.commentUploadUrl || ''; if (!uploadUrl) { notify('图片上传服务不可用', 'danger'); return; } var originalHtml = button.innerHTML; var formData = new FormData(); formData.append('image', state.file, state.file.name); state.uploading = true; button.disabled = true; input.disabled = true; button.innerHTML = '上传中'; var xhr = new XMLHttpRequest(); xhr.open('POST', uploadUrl, true); if (data.restNonce) xhr.setRequestHeader('X-WP-Nonce', data.restNonce); xhr.upload.onprogress = function (event) { if (!event.lengthComputable) return; var percent = Math.round((event.loaded / event.total) * 100); var count = button.querySelector('count'); var progress = button.querySelector('.progress-bar'); var loadingText = button.querySelector('.loading-text'); if (count) count.textContent = percent + '%'; if (progress) progress.style.width = percent + '%'; if (percent >= 100 && loadingText) loadingText.firstChild.nodeValue = '处理中'; }; xhr.onload = function () { var response = parseUploadResponse(xhr); var url = response && response.success === true && response.data ? response.data.url : ''; if (xhr.status < 200 || xhr.status >= 300 || typeof url !== 'string' || url.length < 6) { var message = response && response.message ? response.message : '图片上传失败'; notify(message, 'danger'); restoreUploadButton(button, originalHtml); resetUpload(form); return; } notify(response.message || '图片已上传', 'success'); insertAtCursor(findTextarea(button), '[img=' + url + ']\n'); restoreUploadButton(button, originalHtml); resetUpload(form); }; xhr.onerror = function () { notify('网络错误,图片上传失败', 'danger'); restoreUploadButton(button, originalHtml); resetUpload(form); }; xhr.send(formData); } document.addEventListener('change', function (event) { var input = event.target && event.target.closest ? event.target.closest('.comment-image-file') : null; if (!input) return; var form = input.closest('.comment-image-upload'); var file = input.files && input.files[0]; if (!form || !file) return; if (!validateImage(input, file)) { resetUpload(form); return; } var state = getUploadState(form); state.file = file; previewImage(form, file); var button = form.querySelector('[data-comment-upload-submit]'); if (button) uploadImage(button); }); document.addEventListener('click', function (event) { var linkBtn = event.target && event.target.closest ? event.target.closest('.input-link-submit') : null; if (linkBtn) { event.preventDefault(); var linkBox = linkBtn.closest('.dropdown-link'); var linkTextarea = linkBox ? linkBox.querySelector('textarea.link-textarea') : null; var linkUrl = linkTextarea ? (linkTextarea.value || '').trim() : ''; if (!/^https?:\/\/\S+$/i.test(linkUrl)) { notify('请输入有效链接地址', 'warning'); return; } var linkTextInput = linkBox ? linkBox.querySelector('.link-text') : null; var linkText = linkTextInput ? linkTextInput.value || '' : ''; insertAtCursor(findTextarea(linkBtn), '[link=' + linkUrl + ']' + (linkText.trim() || linkUrl) + '[/link]'); if (linkTextarea) linkTextarea.value = ''; if (linkTextInput) linkTextInput.value = ''; var linkWrapper = linkBtn.closest('span.dropup'); if (linkWrapper) linkWrapper.classList.remove('open'); return; } var codeBtn = event.target && event.target.closest ? event.target.closest('.input-code-submit') : null; if (codeBtn) { event.preventDefault(); var codeBox = codeBtn.closest('.dropdown-code, .input-expand-code'); var codeTextarea = codeBox ? codeBox.querySelector('textarea') : null; var code = codeTextarea ? codeTextarea.value : ''; if (!code || code.length < 2) { notify('请输入代码', 'warning'); return; } insertAtCursor(findTextarea(codeBtn), '[code]\n' + code + '\n[/code]\n'); if (codeTextarea) codeTextarea.value = ''; var codeWrapper = codeBtn.closest('span.dropup'); if (codeWrapper) codeWrapper.classList.remove('open'); return; } var imageSubmit = event.target && event.target.closest ? event.target.closest('.input-image-submit') : null; if (imageSubmit) { event.preventDefault(); var imageBox = imageSubmit.closest('.dropdown-image'); var imageInput = imageBox ? imageBox.querySelector('.input-image-url') : null; var imageUrl = imageInput ? (imageInput.value || '').trim() : ''; if (imageUrl.length < 6) { notify('请输入有效图片地址', 'warning'); return; } insertAtCursor(findTextarea(imageSubmit), '[img=' + imageUrl + ']\n'); return; } var uploadTab = event.target && event.target.closest ? event.target.closest('.input-image-upload-tab') : null; if (uploadTab) { event.preventDefault(); var uploadPane = showImageTab(uploadTab); var uploadInput = uploadPane ? uploadPane.querySelector('.comment-image-file') : null; if (uploadInput) uploadInput.click(); return; } var addressTab = event.target && event.target.closest ? event.target.closest('.input-image-address-tab') : null; if (addressTab) { event.preventDefault(); showImageTab(addressTab); return; } var uploadButton = event.target && event.target.closest ? event.target.closest('[data-comment-upload-submit]') : null; if (uploadButton) { event.preventDefault(); uploadImage(uploadButton); } }); document.addEventListener('keydown', function (event) { if (!(event.ctrlKey || event.metaKey) || event.key !== 'Enter') return; var textarea = event.target; if (!textarea || textarea.id !== 'comment') return; var form = textarea.closest('#commentform'); if (!form) return; event.preventDefault(); var submit = form.querySelector('#submit, [type="submit"]'); if (submit) submit.click(); }); })();