feat: rewrite schema-driven widget system
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
(function ($) {
|
||||
'use strict';
|
||||
|
||||
const config = window.aksrtWidgetAdmin || {};
|
||||
|
||||
function initForm(root) {
|
||||
const $root = $(root);
|
||||
$root.find('.aksrt-widget-color').wpColorPicker();
|
||||
$root.find('.aksrt-widget-repeater__rows').sortable({
|
||||
handle: '.dashicons-move',
|
||||
axis: 'y',
|
||||
update: renumberRepeaters,
|
||||
});
|
||||
$root.find('input[type="range"]').each(function () {
|
||||
const output = this.parentElement.querySelector('output');
|
||||
if (output) this.addEventListener('input', () => { output.textContent = this.value; });
|
||||
});
|
||||
evaluateDependencies($root);
|
||||
}
|
||||
|
||||
function loadForm(container) {
|
||||
const $container = $(container);
|
||||
if ($container.data('loading') || $container.data('loaded')) return;
|
||||
$container.data('loading', true).find('.aksrt-widget-form-lazy__status').text(config.i18n?.loading || 'Loading…');
|
||||
$.post(config.ajaxUrl, {
|
||||
action: config.action,
|
||||
nonce: config.nonce,
|
||||
id_base: $container.data('id-base'),
|
||||
widget_number: $container.data('widget-number'),
|
||||
}).done((response) => {
|
||||
if (!response?.success || !response.data?.html) throw new Error('Invalid response');
|
||||
const $form = $(response.data.html);
|
||||
$container.replaceWith($form);
|
||||
initForm($form);
|
||||
}).fail(() => {
|
||||
$container.data('loading', false).find('.aksrt-widget-form-lazy__status').text(config.i18n?.error || 'Failed to load.');
|
||||
});
|
||||
}
|
||||
|
||||
function renumberRepeaters(_event, ui) {
|
||||
const $form = $(ui?.item || this).closest('.aksrt-widget-form');
|
||||
$form.find('.aksrt-widget-repeater__rows').each(function () {
|
||||
$(this).children('.aksrt-widget-repeater__row').each(function (index) {
|
||||
this.dataset.rowIndex = String(index);
|
||||
});
|
||||
});
|
||||
$form.find('[name]').each(function () {
|
||||
const rowIndexes = $(this).parents('.aksrt-widget-repeater__row').get().reverse().map((row) => Number(row.dataset.rowIndex || 0));
|
||||
if (!rowIndexes.length) return;
|
||||
let foundWidgetNumber = false;
|
||||
let cursor = 0;
|
||||
this.name = this.name.replace(/\[(\d+|__index_[a-f0-9]+__)\]/g, (match, index) => {
|
||||
if (!foundWidgetNumber && /^\d+$/.test(index)) {
|
||||
foundWidgetNumber = true;
|
||||
return match;
|
||||
}
|
||||
return cursor < rowIndexes.length ? `[${rowIndexes[cursor++]}]` : match;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function fieldValue($form, id) {
|
||||
const $field = $form.find(`.aksrt-widget-field[data-field-id="${CSS.escape(id)}"]`).first();
|
||||
const $checked = $field.find('input:checked').first();
|
||||
if ($checked.length) return String($checked.val());
|
||||
return String($field.find('input,select,textarea').first().val() ?? '');
|
||||
}
|
||||
|
||||
function evaluateDependencies($form) {
|
||||
$form.find('[data-dependency]').each(function () {
|
||||
let rule;
|
||||
try { rule = JSON.parse(this.dataset.dependency || '[]'); } catch (_error) { return; }
|
||||
if (!Array.isArray(rule) || rule.length < 3) return;
|
||||
const $row = $(this).closest('.aksrt-widget-repeater__row');
|
||||
const current = fieldValue($row.length ? $row : $form, String(rule[0]));
|
||||
const expected = String(rule[2]);
|
||||
const visible = rule[1] === '==' ? current === expected : current !== expected;
|
||||
this.hidden = !visible;
|
||||
});
|
||||
}
|
||||
|
||||
$(document)
|
||||
.on('click', '.aksrt-widget-form-lazy__load', function () { loadForm($(this).closest('.aksrt-widget-form-lazy')); })
|
||||
.on('click', '.widget.open .aksrt-widget-form-lazy', function () { loadForm(this); })
|
||||
.on('change input', '.aksrt-widget-form input, .aksrt-widget-form select, .aksrt-widget-form textarea', function () { evaluateDependencies($(this).closest('.aksrt-widget-form')); })
|
||||
.on('click', '.aksrt-widget-repeater__add', function () {
|
||||
const $repeater = $(this).closest('.aksrt-widget-repeater');
|
||||
const max = Number($repeater.data('max-items') || 50);
|
||||
const $rows = $repeater.children('.aksrt-widget-repeater__rows');
|
||||
if ($rows.children().length >= max) return;
|
||||
const index = $rows.children().length;
|
||||
const token = String($repeater.data('index-token') || '__index__');
|
||||
const html = $repeater.children('template').html().replaceAll(token, String(index));
|
||||
const $row = $(html).appendTo($rows);
|
||||
initForm($row);
|
||||
renumberRepeaters.call($rows[0]);
|
||||
})
|
||||
.on('click', '.aksrt-widget-repeater__remove', function () {
|
||||
const $rows = $(this).closest('.aksrt-widget-repeater__rows');
|
||||
$(this).closest('.aksrt-widget-repeater__row').remove();
|
||||
renumberRepeaters.call($rows[0]);
|
||||
})
|
||||
.on('click', '.aksrt-widget-upload__choose', function () {
|
||||
const $wrap = $(this).closest('.aksrt-widget-upload');
|
||||
const frame = wp.media({ title: '选择媒体', multiple: false });
|
||||
frame.on('select', () => {
|
||||
const attachment = frame.state().get('selection').first().toJSON();
|
||||
$wrap.find('input[type="url"]').val(attachment.url).trigger('change');
|
||||
let $image = $wrap.find('img');
|
||||
if (!$image.length) $image = $('<img alt="">').prependTo($wrap);
|
||||
$image.attr('src', attachment.url);
|
||||
});
|
||||
frame.open();
|
||||
})
|
||||
.on('click', '.aksrt-widget-upload__remove', function () {
|
||||
const $wrap = $(this).closest('.aksrt-widget-upload');
|
||||
$wrap.find('input[type="url"]').val('').trigger('change');
|
||||
$wrap.find('img').remove();
|
||||
});
|
||||
|
||||
$(document).on('widget-added widget-updated', function (_event, widget) {
|
||||
$(widget).find('.aksrt-widget-form-lazy').each(function () { loadForm(this); });
|
||||
});
|
||||
|
||||
$(function () {
|
||||
$('.aksrt-widget-form').each(function () { initForm(this); });
|
||||
$('.widget.open .aksrt-widget-form-lazy').each(function () { loadForm(this); });
|
||||
});
|
||||
})(jQuery);
|
||||
Reference in New Issue
Block a user