Release v2.17.4: add API region sorting and indexed placeholders
This commit is contained in:
1 parent
bc8075379a
commit
46636939de
18 files changed
+709
-232
No files matched your search
@@ -3716,47 +3716,81 @@ html[data-bs-theme='dark'] .template-field-card .tox .tox-collection {
|
||||
|
||||
.api-region-placeholder-section {
|
||||
display: grid;
|
||||
gap: 0.5rem;
|
||||
padding-top: 0.25rem;
|
||||
padding-bottom: 0.5rem;
|
||||
gap: 0.4rem;
|
||||
padding-top: 0.125rem;
|
||||
padding-bottom: 0.25rem;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.api-region-placeholder-title {
|
||||
color: var(--bs-primary);
|
||||
font-size: 0.8rem;
|
||||
font-weight: 800;
|
||||
letter-spacing: 0.06em;
|
||||
text-transform: uppercase;
|
||||
color: var(--bs-secondary-color);
|
||||
font-size: 0.78rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.api-region-placeholder-title-help {
|
||||
font-size: 0.9rem;
|
||||
font-weight: 800;
|
||||
font-size: 0.8rem;
|
||||
font-weight: 600;
|
||||
letter-spacing: normal;
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
.api-region-sample-accordion {
|
||||
padding: 0.85rem 1rem 1rem;
|
||||
margin-bottom: 0.75rem;
|
||||
.api-region-placeholder-section .chip {
|
||||
padding: 0.2rem 0.45rem;
|
||||
border: 1px solid var(--bs-border-color);
|
||||
border-radius: 0.85rem;
|
||||
background: var(--bs-secondary-bg);
|
||||
border-radius: 0.3rem;
|
||||
background: transparent;
|
||||
color: var(--bs-secondary-color);
|
||||
font-family: var(--bs-font-monospace);
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
.api-region-sample-accordion > summary {
|
||||
.api-region-placeholder-section .chip:hover {
|
||||
border-color: var(--bs-secondary-color);
|
||||
background: var(--bs-tertiary-bg);
|
||||
}
|
||||
|
||||
.api-region-placeholder-section .chip:focus-visible {
|
||||
outline: 2px solid var(--bs-primary);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.api-region-sample-accordion {
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.api-region-sample-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.api-region-sample-toggle {
|
||||
display: flex;
|
||||
flex: 1 1 auto;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 0.75rem;
|
||||
box-sizing: border-box;
|
||||
height: 2.5rem;
|
||||
padding: 0.375rem 0.75rem;
|
||||
cursor: pointer;
|
||||
list-style: none;
|
||||
color: var(--bs-primary);
|
||||
font-size: 0.8rem;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 800;
|
||||
letter-spacing: 0.06em;
|
||||
text-transform: uppercase;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.api-region-sample-accordion > summary::-webkit-details-marker {
|
||||
display: none;
|
||||
.api-region-sample-toggle:focus-visible {
|
||||
outline: 2px solid var(--bs-primary);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.api-region-sample-chevron {
|
||||
transition: transform 120ms ease;
|
||||
}
|
||||
|
||||
.api-region-sample-accordion.is-open .api-region-sample-chevron {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.api-region-sample-body {
|
||||
@@ -3765,19 +3799,21 @@ html[data-bs-theme='dark'] .template-field-card .tox .tox-collection {
|
||||
margin-top: 0.75rem;
|
||||
}
|
||||
|
||||
.api-region-sample-body[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.api-region-sample-meta {
|
||||
color: var(--bs-secondary-color);
|
||||
font-size: 0.78rem;
|
||||
}
|
||||
|
||||
.api-region-sample-preview {
|
||||
max-height: 12rem;
|
||||
overflow: auto;
|
||||
margin: 0;
|
||||
padding: 0.75rem;
|
||||
border-radius: 0.65rem;
|
||||
background: var(--bs-body-bg);
|
||||
border: 1px solid var(--bs-border-color-translucent);
|
||||
border: 0;
|
||||
border-radius: 0.375rem;
|
||||
background: var(--bs-secondary-bg);
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
font-size: 0.78rem;
|
||||
|
||||
@@ -47,15 +47,16 @@
|
||||
return String(overridePath || '').trim();
|
||||
}
|
||||
|
||||
function getItems(sourceId, sources, itemsPathOverride) {
|
||||
function getItems(sourceId, sources, itemsPathOverride, sortBy, sortDirection) {
|
||||
var source = getSourceById(sourceId, sources);
|
||||
var responseJson = source && source.responseJson && typeof source.responseJson === 'object' ? source.responseJson : null;
|
||||
var itemsPath = getSourceItemsPath(source, itemsPathOverride);
|
||||
return placeholderUtils.resolveApiItems(responseJson, itemsPath);
|
||||
var items = placeholderUtils.resolveApiItems(responseJson, itemsPath);
|
||||
return typeof placeholderUtils.sortApiItems === 'function' ? placeholderUtils.sortApiItems(items, sortBy, sortDirection) : items;
|
||||
}
|
||||
|
||||
function getItemCount(sourceId, sources, itemsPathOverride) {
|
||||
return getItems(sourceId, sources, itemsPathOverride).length;
|
||||
function getItemCount(sourceId, sources, itemsPathOverride, sortBy, sortDirection) {
|
||||
return getItems(sourceId, sources, itemsPathOverride, sortBy, sortDirection).length;
|
||||
}
|
||||
|
||||
function getCurrentConfig(region, existingContent, sources) {
|
||||
@@ -66,15 +67,21 @@
|
||||
source_id: current.source_id === undefined || current.source_id === null || current.source_id === '' ? '' : Number(current.source_id),
|
||||
item_number: Number.isFinite(parsedItemNumber) && parsedItemNumber > 0 ? parsedItemNumber : 1,
|
||||
items_path: Object.prototype.hasOwnProperty.call(current, 'items_path') ? String(current.items_path === undefined || current.items_path === null ? '' : current.items_path) : undefined,
|
||||
sort_by: String(current.sort_by || ''),
|
||||
sort_direction: String(current.sort_direction || 'asc').toLowerCase() === 'desc' ? 'desc' : 'asc',
|
||||
default_items_path: String(source && (source.items_path || source.itemsPath) || '').trim(),
|
||||
value: current.value !== undefined ? current.value : ''
|
||||
};
|
||||
}
|
||||
|
||||
function substituteVariables(html, item, options) {
|
||||
function substituteVariables(html, item, options, items) {
|
||||
var source = String(html || '');
|
||||
return source.replace(/\{\{\s*([^{}]+?)\s*\}\}/g, function (_match, expression) {
|
||||
if (!item || typeof item !== 'object') {
|
||||
var indexedMatch = String(expression || '').match(/^\s*(\d+)\.(.+)$/);
|
||||
var resultIndex = indexedMatch ? Number(indexedMatch[1]) : 0;
|
||||
var expressionItem = indexedMatch ? (Array.isArray(items) ? items[resultIndex] : null) : item;
|
||||
var resolvedExpression = indexedMatch ? indexedMatch[2] : expression;
|
||||
if (!expressionItem || typeof expressionItem !== 'object') {
|
||||
return '';
|
||||
}
|
||||
|
||||
@@ -82,16 +89,16 @@
|
||||
return '';
|
||||
}
|
||||
|
||||
var resolved = placeholderUtils.resolvePlaceholderExpression(item, expression);
|
||||
if (typeof placeholderUtils.isProgressPlaceholderExpression === 'function' && placeholderUtils.isProgressPlaceholderExpression(expression)) {
|
||||
return placeholderUtils.renderProgressPlaceholder(item, expression);
|
||||
var resolved = placeholderUtils.resolvePlaceholderExpression(expressionItem, resolvedExpression);
|
||||
if (typeof placeholderUtils.isProgressPlaceholderExpression === 'function' && placeholderUtils.isProgressPlaceholderExpression(resolvedExpression)) {
|
||||
return placeholderUtils.renderProgressPlaceholder(expressionItem, resolvedExpression);
|
||||
}
|
||||
if (typeof placeholderUtils.isImagePlaceholderExpression === 'function' && placeholderUtils.isImagePlaceholderExpression(expression)) {
|
||||
if (typeof placeholderUtils.isImagePlaceholderExpression === 'function' && placeholderUtils.isImagePlaceholderExpression(resolvedExpression)) {
|
||||
var imageSource = placeholderUtils.formatPlaceholderValue(resolved);
|
||||
if (!/^(?:https?:\/\/|\/media\/|\/assets\/|\/[^/])/i.test(imageSource)) {
|
||||
return '';
|
||||
}
|
||||
var imageConfig = typeof placeholderUtils.getImagePlaceholderConfig === 'function' ? placeholderUtils.getImagePlaceholderConfig(expression) : {};
|
||||
var imageConfig = typeof placeholderUtils.getImagePlaceholderConfig === 'function' ? placeholderUtils.getImagePlaceholderConfig(resolvedExpression) : {};
|
||||
var imageStyle = options && options.preview && imageConfig.width && imageConfig.height
|
||||
? 'display:block;width:100%;height:100%;object-fit:contain;'
|
||||
: 'display:block;width:auto;height:auto;' + (imageConfig.width ? 'max-width:' + imageConfig.width + 'px;' : '') + (imageConfig.height ? 'max-height:' + imageConfig.height + 'px;' : '');
|
||||
@@ -99,13 +106,14 @@
|
||||
var hasPreviewBounds = options && options.preview && imageConfig.width && imageConfig.height;
|
||||
if (hasPreviewBounds || imageConfig.verticalAlign) {
|
||||
var wrapperStyle = 'display:inline-flex;align-items:center;justify-content:center;';
|
||||
var wrapperClass = hasPreviewBounds ? ' class="api-image-placeholder-bounds"' : '';
|
||||
if (hasPreviewBounds) {
|
||||
wrapperStyle += 'box-sizing:border-box;width:' + imageConfig.width + 'px;height:' + imageConfig.height + 'px;border:1px dashed rgba(120,120,120,.75);';
|
||||
}
|
||||
if (imageConfig.verticalAlign) {
|
||||
wrapperStyle += 'vertical-align:' + imageConfig.verticalAlign + ';';
|
||||
}
|
||||
return '<span style="' + wrapperStyle + '">' + image + '</span>';
|
||||
return '<span' + wrapperClass + ' style="' + wrapperStyle + '">' + image + '</span>';
|
||||
}
|
||||
return image;
|
||||
}
|
||||
@@ -113,8 +121,8 @@
|
||||
});
|
||||
}
|
||||
|
||||
function getItem(sourceId, itemNumber, sources, itemsPathOverride) {
|
||||
var items = getItems(sourceId, sources, itemsPathOverride);
|
||||
function getItem(sourceId, itemNumber, sources, itemsPathOverride, sortBy, sortDirection) {
|
||||
var items = getItems(sourceId, sources, itemsPathOverride, sortBy, sortDirection);
|
||||
var parsedItemNumber = Math.max(1, Number(itemNumber || 1));
|
||||
var index = Number.isFinite(parsedItemNumber) && parsedItemNumber > 0 ? parsedItemNumber - 1 : 0;
|
||||
return items[index] || null;
|
||||
@@ -149,8 +157,8 @@
|
||||
'<h2 class="offcanvas-title fs-5" id="' + offcanvasId + '-label">API placeholder transforms</h2>' +
|
||||
'<button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>' +
|
||||
'</div>' +
|
||||
'<div class="offcanvas-body">' +
|
||||
'<p class="small text-body-secondary">Placeholders read values from the selected API item. Nested fields use dots.</p>' +
|
||||
'<div class="offcanvas-body">' +
|
||||
'<p class="small text-body-secondary">Use placeholders such as <code>{{name}}</code> for the selected result, or <code>{{0.name}}</code> and <code>{{1.name}}</code> to read sorted results by index. Indices start at 0. Nested fields use dots.</p>' +
|
||||
(window.placeholderInfo ? window.placeholderInfo.renderTextTransforms() : '') +
|
||||
(window.placeholderInfo ? window.placeholderInfo.renderMathTransforms() : '') +
|
||||
(window.placeholderInfo ? window.placeholderInfo.renderDateFormatTokens() : '') +
|
||||
@@ -189,14 +197,15 @@
|
||||
var sourceId = regionContent && regionContent.source_id !== undefined ? regionContent.source_id : config.source_id;
|
||||
var itemNumber = regionContent && regionContent.item_number !== undefined ? regionContent.item_number : config.item_number;
|
||||
var itemsPath = regionContent && regionContent.items_path !== undefined ? regionContent.items_path : (config.items_path !== undefined ? config.items_path : config.default_items_path);
|
||||
var itemCount = getItemCount(sourceId, sources, itemsPath);
|
||||
var itemNumberMax = Math.max(1, Number(itemCount || 1));
|
||||
var fontFamily = sanitizeFontFamily(regionContent.font_family || region.fontFamily);
|
||||
var fontSize = sanitizeFontSize(regionContent.font_size || region.fontSize);
|
||||
var fontColor = sanitizeTextColor(regionContent.font_color || region.fontColor);
|
||||
var item = getItem(sourceId, itemNumber, sources, itemsPath);
|
||||
var items = getItems(sourceId, sources, itemsPath, regionContent.sort_by, regionContent.sort_direction);
|
||||
var parsedItemNumber = Math.max(1, Number(itemNumber || 1));
|
||||
var itemIndex = Number.isFinite(parsedItemNumber) && parsedItemNumber > 0 ? parsedItemNumber - 1 : 0;
|
||||
var item = items[itemIndex] || null;
|
||||
var hasSource = String(sourceId === undefined || sourceId === null ? '' : sourceId).trim() !== '';
|
||||
var body = hasSource ? (item ? substituteVariables(content, item, { preview: true }) : '') : content;
|
||||
var body = hasSource ? (item || items.length ? substituteVariables(content, item, { preview: true }, items) : '') : content;
|
||||
|
||||
body = String(body || '')
|
||||
.replace(/<pre[^>]*class="[^"]*api-region-sample-preview[^"]*"[^>]*>[\s\S]*?<\/pre>/gi, '')
|
||||
@@ -239,17 +248,13 @@
|
||||
'<textarea class="editor-source" rows="10">' + escapeHtml(current.value !== undefined ? current.value : '') + '</textarea>' +
|
||||
'</div>' +
|
||||
'<div class="row g-3 align-items-end">' +
|
||||
'<div class="col-12 col-lg-5">' +
|
||||
'<div class="col-12 col-lg-4">' +
|
||||
'<label class="form-label" for="region_api_source_id_' + region.id + '">API source</label>' +
|
||||
'<select id="region_api_source_id_' + region.id + '" name="region_api_source_id_' + region.id + '" class="form-select">' +
|
||||
'<option value="">Select a source</option>' +
|
||||
sourceOptions +
|
||||
'</select>' +
|
||||
'</div>' +
|
||||
'<div class="col-6 col-lg-2">' +
|
||||
'<label class="form-label" for="region_api_item_number_' + region.id + '">Item number</label>' +
|
||||
'<input id="region_api_item_number_' + region.id + '" type="number" min="1" step="1" name="region_api_item_number_' + region.id + '" class="form-control" value="' + escapeHtml(config.item_number) + '" />' +
|
||||
'</div>' +
|
||||
'<div class="col-12 col-lg-5">' +
|
||||
'<label class="form-label" for="region_api_items_path_' + region.id + '">Items path override</label>' +
|
||||
'<div class="input-group flex-nowrap">' +
|
||||
@@ -257,17 +262,36 @@
|
||||
'<button type="button" class="btn btn-outline-secondary text-nowrap" data-api-items-path-reset data-api-default-items-path="' + escapeHtml(config.default_items_path || '') + '">Reset</button>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'<div class="col-12 col-lg-3 d-flex align-items-end">' +
|
||||
'<button type="button" class="btn btn-outline-secondary w-100" data-api-advanced-toggle aria-expanded="false" aria-controls="api-region-advanced-' + region.id + '"><i class="bi bi-sliders me-2" aria-hidden="true"></i>Advanced options</button>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'<div id="api-region-advanced-' + region.id + '" class="row g-3 align-items-end api-region-advanced-options" data-api-advanced-options hidden>' +
|
||||
'<div class="col-12 col-md-4">' +
|
||||
'<label class="form-label" for="region_api_sort_mode_' + region.id + '">Order results</label>' +
|
||||
'<select id="region_api_sort_mode_' + region.id + '" name="region_api_sort_mode_' + region.id + '" class="form-select"><option value="original"' + (config.sort_by ? '' : ' selected') + '>API order</option><option value="field"' + (config.sort_by ? ' selected' : '') + '>Sort by field</option></select>' +
|
||||
'</div>' +
|
||||
'<div class="col-12 col-md-5" data-api-sort-field-wrap' + (config.sort_by ? '' : ' hidden') + '>' +
|
||||
'<label class="form-label" for="region_api_sort_by_' + region.id + '">Sort field</label>' +
|
||||
'<input id="region_api_sort_by_' + region.id + '" type="text" name="region_api_sort_by_' + region.id + '" class="form-control" value="' + escapeHtml(config.sort_by || '') + '" placeholder="Enter a field path" />' +
|
||||
'</div>' +
|
||||
'<div class="col-12 col-md-3" data-api-sort-direction-wrap' + (config.sort_by ? '' : ' hidden') + '>' +
|
||||
'<label class="form-label" for="region_api_sort_direction_' + region.id + '">Direction</label>' +
|
||||
'<select id="region_api_sort_direction_' + region.id + '" name="region_api_sort_direction_' + region.id + '" class="form-select"><option value="asc"' + (config.sort_direction === 'asc' ? ' selected' : '') + '>Ascending</option><option value="desc"' + (config.sort_direction !== 'asc' ? ' selected' : '') + '>Descending</option></select>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'<input type="hidden" name="region_font_size_' + region.id + '" value="' + escapeHtml(context.fontSize || '') + '" />' +
|
||||
'<input type="hidden" name="region_text_' + region.id + '" value="' + escapeHtml(current.value !== undefined ? current.value : '') + '" />' +
|
||||
'<div class="api-region-placeholder-section">' +
|
||||
'<div class="api-region-placeholder-title api-region-placeholder-title-help d-flex align-items-center gap-2">Available placeholders ' + renderTransformInfo(region.id) + '</div>' +
|
||||
'<div class="api-region-placeholder-title api-region-placeholder-title-help d-flex align-items-center gap-2">Available fields ' + renderTransformInfo(region.id) + '</div>' +
|
||||
'<div class="d-flex flex-wrap gap-2" data-placeholder-chips>' + ((placeholderFields.length && window.placeholderChips && typeof window.placeholderChips.renderChips === 'function') ? window.placeholderChips.renderChips(placeholderFields) : placeholderChips || '<span class="muted slide-image-file">No JSON fields available.</span>') + '</div>' +
|
||||
'</div>' +
|
||||
'<details class="api-region-sample-accordion" data-api-sample-data-accordion>' +
|
||||
'<summary>Data</summary>' +
|
||||
'<div class="api-region-sample-body" data-api-sample-data-panel>' + sampleDataPreview + '</div>' +
|
||||
'</details>' +
|
||||
'<div class="api-region-sample-accordion" data-api-sample-data-accordion>' +
|
||||
'<div class="api-region-sample-header">' +
|
||||
'<button type="button" class="btn btn-outline-primary api-region-sample-toggle" data-api-sample-toggle aria-expanded="false" aria-controls="api-region-sample-panel-' + region.id + '"><span><i class="bi bi-eye me-2" aria-hidden="true"></i>View results</span><i class="bi bi-chevron-down api-region-sample-chevron" aria-hidden="true"></i></button>' +
|
||||
'</div>' +
|
||||
'<div id="api-region-sample-panel-' + region.id + '" class="api-region-sample-body" data-api-sample-data-panel hidden>' + sampleDataPreview + '</div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
}
|
||||
@@ -314,7 +338,9 @@
|
||||
}())),
|
||||
source_id: card.querySelector('select[name="region_api_source_id_' + region.id + '"]') ? card.querySelector('select[name="region_api_source_id_' + region.id + '"]').value : current.source_id,
|
||||
item_number: (card.querySelector('input[name="region_api_item_number_' + region.id + '"]') || {}).value || current.item_number,
|
||||
items_path: card.querySelector('input[name="region_api_items_path_' + region.id + '"]') ? (card.querySelector('input[name="region_api_items_path_' + region.id + '"]') || {}).value : current.items_path
|
||||
items_path: card.querySelector('input[name="region_api_items_path_' + region.id + '"]') ? (card.querySelector('input[name="region_api_items_path_' + region.id + '"]') || {}).value : current.items_path,
|
||||
sort_by: card.querySelector('select[name="region_api_sort_mode_' + region.id + '"]') && card.querySelector('select[name="region_api_sort_mode_' + region.id + '"]').value === 'field' ? (card.querySelector('input[name="region_api_sort_by_' + region.id + '"]') || {}).value || '' : '',
|
||||
sort_direction: (card.querySelector('select[name="region_api_sort_direction_' + region.id + '"]') || {}).value || current.sort_direction
|
||||
} : current;
|
||||
|
||||
return {
|
||||
@@ -322,6 +348,8 @@
|
||||
source_id: content.source_id,
|
||||
item_number: content.item_number,
|
||||
items_path: content.items_path,
|
||||
sort_by: content.sort_by,
|
||||
sort_direction: content.sort_direction,
|
||||
existingContent: existingContent || {},
|
||||
sources: Array.isArray(sources) ? sources : []
|
||||
};
|
||||
|
||||
@@ -67,6 +67,44 @@
|
||||
return value && typeof value === 'object' ? [value] : [];
|
||||
}
|
||||
|
||||
function sortApiItems(items, sortBy, direction) {
|
||||
var path = String(sortBy || '').trim().replace(/\[([0-9]+)\]/g, '.$1');
|
||||
if (!Array.isArray(items)) {
|
||||
return [];
|
||||
}
|
||||
if (!path) {
|
||||
return items.slice();
|
||||
}
|
||||
|
||||
var descending = String(direction || '').toLowerCase() === 'desc';
|
||||
function valueFor(item) {
|
||||
return resolvePath(item, path);
|
||||
}
|
||||
function isMissing(value) {
|
||||
return value === undefined || value === null || value === '';
|
||||
}
|
||||
function compare(left, right) {
|
||||
if (isMissing(left)) return isMissing(right) ? 0 : 1;
|
||||
if (isMissing(right)) return -1;
|
||||
var leftNumber = typeof left === 'number' ? left : (typeof left === 'string' && left.trim() !== '' ? Number(left) : NaN);
|
||||
var rightNumber = typeof right === 'number' ? right : (typeof right === 'string' && right.trim() !== '' ? Number(right) : NaN);
|
||||
if (Number.isFinite(leftNumber) && Number.isFinite(rightNumber)) {
|
||||
return leftNumber < rightNumber ? -1 : leftNumber > rightNumber ? 1 : 0;
|
||||
}
|
||||
return String(left).localeCompare(String(right), undefined, { numeric: true, sensitivity: 'base' });
|
||||
}
|
||||
|
||||
return items.map(function (item, index) {
|
||||
return { item: item, index: index, value: valueFor(item) };
|
||||
}).sort(function (left, right) {
|
||||
var result = compare(left.value, right.value);
|
||||
if (result && descending && !isMissing(left.value) && !isMissing(right.value)) return -result;
|
||||
return result || left.index - right.index;
|
||||
}).map(function (entry) {
|
||||
return entry.item;
|
||||
});
|
||||
}
|
||||
|
||||
function parsePlaceholderExpression(expression) {
|
||||
var raw = String(expression || '').trim();
|
||||
var segments = raw ? splitExpressionSegments(raw) : [];
|
||||
@@ -604,6 +642,7 @@
|
||||
return {
|
||||
resolvePath: resolvePath,
|
||||
resolveApiItems: resolveApiItems,
|
||||
sortApiItems: sortApiItems,
|
||||
parsePlaceholderExpression: parsePlaceholderExpression,
|
||||
resolvePlaceholderExpression: resolvePlaceholderExpression,
|
||||
isImagePlaceholderExpression: isImagePlaceholderExpression,
|
||||
|
||||
@@ -178,18 +178,39 @@ export function createSlideFormRegionHelpers(options) {
|
||||
return text.slice(0, limit).replace(/\s+$/, '') + '\n...';
|
||||
}
|
||||
|
||||
function buildApiSampleDataMarkup(sourceId, itemNumber, itemsPathOverride) {
|
||||
function buildApiSampleDataMarkup(sourceId, itemsPathOverride, sortBy, sortDirection) {
|
||||
var source = getApiSourceById(sourceId);
|
||||
if (!source) {
|
||||
return '<div class="api-region-sample-meta">Select an API source to preview sample data.</div>';
|
||||
}
|
||||
|
||||
var item = getApiSourceItems(sourceId, itemsPathOverride)[Math.max(0, Math.max(1, Number(itemNumber || 1)) - 1)] || null;
|
||||
if (!item) {
|
||||
var items = getApiSourceItems(sourceId, itemsPathOverride, sortBy, sortDirection);
|
||||
if (!items.length) {
|
||||
return '<div class="api-region-sample-meta">No sample item is available for the current selection.</div>';
|
||||
}
|
||||
|
||||
return '<pre class="api-region-sample-preview" data-api-sample-data-output>' + escapeHtml(truncateJsonPreview(item, 1100)) + '</pre>';
|
||||
var firstItemJson = '';
|
||||
try {
|
||||
firstItemJson = JSON.stringify(items[0], null, 2);
|
||||
} catch (_error) {
|
||||
firstItemJson = String(items[0] === undefined || items[0] === null ? '' : items[0]);
|
||||
}
|
||||
var label = apiItemsPathIsArray(source, itemsPathOverride) ? 'Example result (first item)' : 'Example result';
|
||||
var jsonSource = JSON.stringify(firstItemJson).replace(/</g, '\\u003c').replace(/>/g, '\\u003e').replace(/&/g, '\\u0026');
|
||||
return '' +
|
||||
'<div class="api-region-sample-example">' +
|
||||
'<div class="d-flex align-items-center justify-content-between flex-wrap gap-2 mb-1">' +
|
||||
'<div class="api-region-sample-meta">' + label + '</div>' +
|
||||
'<div class="btn-group btn-group-sm" role="group" aria-label="Example JSON controls">' +
|
||||
'<button type="button" class="btn btn-outline-secondary" data-json-toggle-collapse-all><i class="bi bi-arrows-collapse me-1" aria-hidden="true"></i>Collapse all</button>' +
|
||||
'<button type="button" class="btn btn-outline-secondary" data-json-toggle-expand-all><i class="bi bi-arrows-expand me-1" aria-hidden="true"></i>Expand all</button>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'<div data-json-toggle-panel>' +
|
||||
'<script type="application/json" data-json-toggle-source>' + jsonSource + '</script>' +
|
||||
'<div class="api-region-sample-preview font-monospace" data-json-toggle-output data-api-sample-data-output>' + escapeHtml(firstItemJson) + '</div>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
}
|
||||
|
||||
function updatePlaceholderChipList(card, fieldList, emptyLabel) {
|
||||
@@ -356,25 +377,31 @@ export function createSlideFormRegionHelpers(options) {
|
||||
return String(overridePath || '').trim();
|
||||
}
|
||||
|
||||
function getApiSourceItems(sourceId, itemsPathOverride) {
|
||||
function getApiSourceItems(sourceId, itemsPathOverride, sortBy, sortDirection) {
|
||||
var source = getApiSourceById(sourceId);
|
||||
var module = getRegionTypeModule('api');
|
||||
if (module && typeof module.getItems === 'function') {
|
||||
return module.getItems(sourceId, apiSources, itemsPathOverride);
|
||||
return module.getItems(sourceId, apiSources, itemsPathOverride, sortBy, sortDirection);
|
||||
}
|
||||
|
||||
var responseJson = source && source.responseJson && typeof source.responseJson === 'object' ? source.responseJson : null;
|
||||
var itemsPath = getApiSourceItemsPath(source, itemsPathOverride);
|
||||
return window.placeholderUtils.resolveApiItems(responseJson, itemsPath);
|
||||
var items = window.placeholderUtils.resolveApiItems(responseJson, itemsPath);
|
||||
return typeof window.placeholderUtils.sortApiItems === 'function' ? window.placeholderUtils.sortApiItems(items, sortBy, sortDirection) : items;
|
||||
}
|
||||
|
||||
function getApiItemCount(sourceId, itemsPathOverride) {
|
||||
var module = getRegionTypeModule('api');
|
||||
if (module && typeof module.getItemCount === 'function') {
|
||||
return module.getItemCount(sourceId, apiSources, itemsPathOverride);
|
||||
function apiItemsPathIsArray(source, itemsPathOverride) {
|
||||
var response = source && source.responseJson;
|
||||
var itemsPath = getApiSourceItemsPath(source, itemsPathOverride);
|
||||
if (itemsPath) {
|
||||
return Array.isArray(window.placeholderUtils.resolvePath(response, itemsPath));
|
||||
}
|
||||
|
||||
return getApiSourceItems(sourceId, itemsPathOverride).length;
|
||||
if (Array.isArray(response)) {
|
||||
return true;
|
||||
}
|
||||
return Boolean(response && ['items', 'results', 'data'].some(function (key) {
|
||||
return Array.isArray(response[key]);
|
||||
}));
|
||||
}
|
||||
|
||||
function getApiFieldList(sourceId, itemsPathOverride) {
|
||||
@@ -399,7 +426,18 @@ export function createSlideFormRegionHelpers(options) {
|
||||
container.innerHTML = buildLimitedPlaceholderChipMarkup(getApiFieldList(sourceId, itemsPathOverride), 'No JSON fields available.', false);
|
||||
}
|
||||
|
||||
function updateApiSampleDataPanel(regionId, sourceId, itemNumber, itemsPathOverride) {
|
||||
function updateApiItemsPathReset(regionId, sourceId) {
|
||||
var card = templateFields ? templateFields.querySelector('[data-region-id="' + regionId + '"]') : null;
|
||||
var button = card ? card.querySelector('[data-api-items-path-reset]') : null;
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
|
||||
var source = getApiSourceById(sourceId);
|
||||
button.dataset.apiDefaultItemsPath = String(source && (source.items_path || source.itemsPath) || '').trim();
|
||||
}
|
||||
|
||||
function updateApiSampleDataPanel(regionId, sourceId, itemsPathOverride, sortBy, sortDirection) {
|
||||
var card = templateFields ? templateFields.querySelector('[data-region-id="' + regionId + '"]') : null;
|
||||
if (!card) {
|
||||
return;
|
||||
@@ -410,44 +448,10 @@ export function createSlideFormRegionHelpers(options) {
|
||||
return;
|
||||
}
|
||||
|
||||
container.innerHTML = buildApiSampleDataMarkup(sourceId, itemNumber, itemsPathOverride);
|
||||
}
|
||||
|
||||
function updateApiItemNumberLimit(regionId, sourceId, itemsPathOverride) {
|
||||
var card = templateFields ? templateFields.querySelector('[data-region-id="' + regionId + '"]') : null;
|
||||
if (!card) {
|
||||
return;
|
||||
container.innerHTML = buildApiSampleDataMarkup(sourceId, itemsPathOverride, sortBy, sortDirection);
|
||||
if (typeof window.initJsonTogglePanels === 'function') {
|
||||
window.initJsonTogglePanels(container);
|
||||
}
|
||||
|
||||
var input = card.querySelector('input[name="region_api_item_number_' + regionId + '"]');
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
|
||||
var itemCount = Math.max(1, Number(getApiItemCount(sourceId, itemsPathOverride) || 1));
|
||||
input.setAttribute('max', String(itemCount));
|
||||
if (Number(input.value || 0) > itemCount) {
|
||||
input.value = String(itemCount);
|
||||
}
|
||||
}
|
||||
|
||||
function clampApiItemNumber(regionId, sourceId, itemNumber, itemsPathOverride) {
|
||||
var card = templateFields ? templateFields.querySelector('[data-region-id="' + regionId + '"]') : null;
|
||||
if (!card) {
|
||||
return '';
|
||||
}
|
||||
|
||||
var input = card.querySelector('input[name="region_api_item_number_' + regionId + '"]');
|
||||
if (!input) {
|
||||
return '';
|
||||
}
|
||||
|
||||
var itemCount = Math.max(1, Number(getApiItemCount(sourceId, itemsPathOverride) || 1));
|
||||
var parsedValue = Math.max(1, Number(itemNumber || 1));
|
||||
var clampedValue = Math.min(itemCount, Number.isFinite(parsedValue) && parsedValue > 0 ? parsedValue : 1);
|
||||
input.setAttribute('max', String(itemCount));
|
||||
input.value = String(clampedValue);
|
||||
return String(clampedValue);
|
||||
}
|
||||
|
||||
function getCurrentApiConfig(region) {
|
||||
@@ -546,7 +550,7 @@ export function createSlideFormRegionHelpers(options) {
|
||||
: region.region_type === 'rss'
|
||||
? getRssFieldList(getCurrentRssConfig(region).feed_id)
|
||||
: [],
|
||||
sampleDataPreview: buildApiSampleDataMarkup(getCurrentApiConfig(region).source_id, getCurrentApiConfig(region).item_number, getCurrentApiConfig(region).items_path),
|
||||
sampleDataPreview: buildApiSampleDataMarkup(getCurrentApiConfig(region).source_id, getCurrentApiConfig(region).items_path, getCurrentApiConfig(region).sort_by, getCurrentApiConfig(region).sort_direction),
|
||||
timetableGroups: timetableGroups,
|
||||
weatherLocations: weatherLocations,
|
||||
mediaAssets: mediaAssets
|
||||
@@ -589,7 +593,7 @@ export function createSlideFormRegionHelpers(options) {
|
||||
: region.region_type === 'rss'
|
||||
? getRssFieldList(rssConfig.feed_id)
|
||||
: [],
|
||||
sampleDataPreview: buildApiSampleDataMarkup(apiConfig.source_id, apiConfig.item_number, apiItemsPath),
|
||||
sampleDataPreview: buildApiSampleDataMarkup(apiConfig.source_id, apiItemsPath, apiConfig.sort_by, apiConfig.sort_direction),
|
||||
timetableGroups: timetableGroups,
|
||||
weatherLocations: weatherLocations,
|
||||
mediaAssets: mediaAssets
|
||||
@@ -754,7 +758,6 @@ export function createSlideFormRegionHelpers(options) {
|
||||
var rssFeedInput = card.querySelector('select[name="region_rss_feed_id_' + region.id + '"]');
|
||||
var rssItemInput = card.querySelector('input[name="region_rss_item_number_' + region.id + '"]');
|
||||
var apiSourceInput = card.querySelector('select[name="region_api_source_id_' + region.id + '"]');
|
||||
var apiItemInput = card.querySelector('input[name="region_api_item_number_' + region.id + '"]');
|
||||
var apiItemsPathInput = card.querySelector('input[name="region_api_items_path_' + region.id + '"]');
|
||||
|
||||
if (region.region_type === 'image') {
|
||||
@@ -779,8 +782,12 @@ export function createSlideFormRegionHelpers(options) {
|
||||
} else if (region.region_type === 'api') {
|
||||
content.value = hiddenInput ? hiddenInput.value : (content.value || '');
|
||||
content.source_id = apiSourceInput ? apiSourceInput.value : content.source_id;
|
||||
content.item_number = apiItemInput ? apiItemInput.value : content.item_number;
|
||||
content.items_path = apiItemsPathInput ? apiItemsPathInput.value : content.items_path;
|
||||
var apiSortModeInput = card.querySelector('select[name="region_api_sort_mode_' + region.id + '"]');
|
||||
var apiSortByInput = card.querySelector('input[name="region_api_sort_by_' + region.id + '"]');
|
||||
var apiSortDirectionInput = card.querySelector('select[name="region_api_sort_direction_' + region.id + '"]');
|
||||
content.sort_by = apiSortModeInput && apiSortModeInput.value === 'field' && apiSortByInput ? apiSortByInput.value : '';
|
||||
content.sort_direction = apiSortDirectionInput ? apiSortDirectionInput.value : content.sort_direction;
|
||||
} else if (region.region_type === 'timetable') {
|
||||
var timetableGroupInput = card.querySelector('select[name="region_timetable_group_id_' + region.id + '"]');
|
||||
var timetableDisplayModeInput = card.querySelector('select[name="region_timetable_display_mode_' + region.id + '"]');
|
||||
@@ -835,9 +842,10 @@ export function createSlideFormRegionHelpers(options) {
|
||||
updateRssPlaceholderChips: updateRssPlaceholderChips,
|
||||
getCurrentRssConfig: getCurrentRssConfig,
|
||||
getApiFieldList: getApiFieldList,
|
||||
buildApiSampleDataMarkup: buildApiSampleDataMarkup,
|
||||
updateApiPlaceholderChips: updateApiPlaceholderChips,
|
||||
updateApiItemsPathReset: updateApiItemsPathReset,
|
||||
updateApiSampleDataPanel: updateApiSampleDataPanel,
|
||||
updateApiItemNumberLimit: updateApiItemNumberLimit,
|
||||
updateRssItemNumberLimit: updateRssItemNumberLimit,
|
||||
getCurrentApiConfig: getCurrentApiConfig,
|
||||
reduceAspectRatio: reduceAspectRatio,
|
||||
|
||||
@@ -748,8 +748,8 @@ import { createSlideAnimationEditor } from '/assets/js/slides/slide-animation-ed
|
||||
var getCurrentRssConfig = slideRegionHelpers.getCurrentRssConfig;
|
||||
var getApiFieldList = slideRegionHelpers.getApiFieldList;
|
||||
var updateApiPlaceholderChips = slideRegionHelpers.updateApiPlaceholderChips;
|
||||
var updateApiItemsPathReset = slideRegionHelpers.updateApiItemsPathReset;
|
||||
var updateApiSampleDataPanel = slideRegionHelpers.updateApiSampleDataPanel;
|
||||
var updateApiItemNumberLimit = slideRegionHelpers.updateApiItemNumberLimit;
|
||||
var getCurrentApiConfig = slideRegionHelpers.getCurrentApiConfig;
|
||||
var updateRssItemNumberLimit = slideRegionHelpers.updateRssItemNumberLimit;
|
||||
|
||||
@@ -768,6 +768,9 @@ import { createSlideAnimationEditor } from '/assets/js/slides/slide-animation-ed
|
||||
templateFields.innerHTML = template.regions.length ? template.regions.map(function (region) {
|
||||
return getRegionEditorCardHtml(region) || '<div class="muted">Region editor unavailable.</div>';
|
||||
}).join('') : '<div class="muted">This template has no regions.</div>';
|
||||
if (typeof window.initJsonTogglePanels === 'function') {
|
||||
window.initJsonTogglePanels(templateFields);
|
||||
}
|
||||
|
||||
if (window.adminlte && typeof window.adminlte.CardWidget === 'function') {
|
||||
templateFields.querySelectorAll('.card-widget[data-region-id]').forEach(function (card) {
|
||||
@@ -787,14 +790,6 @@ import { createSlideAnimationEditor } from '/assets/js/slides/slide-animation-ed
|
||||
window.requestAnimationFrame(function () {
|
||||
bindRegionCards();
|
||||
});
|
||||
templateFields.querySelectorAll('input[name^="region_api_item_number_"]').forEach(function (input) {
|
||||
var regionId = input.name.replace(/^region_api_item_number_/, '');
|
||||
var sourceInput = templateFields.querySelector('select[name="region_api_source_id_' + regionId + '"]');
|
||||
var pathInput = templateFields.querySelector('input[name="region_api_items_path_' + regionId + '"]');
|
||||
if (sourceInput) {
|
||||
updateApiItemNumberLimit(regionId, sourceInput.value, pathInput ? pathInput.value : '');
|
||||
}
|
||||
});
|
||||
templateFields.querySelectorAll('input[name^="region_rss_item_number_"]').forEach(function (input) {
|
||||
var regionId = input.name.replace(/^region_rss_item_number_/, '');
|
||||
var feedInput = templateFields.querySelector('select[name="region_rss_feed_id_' + regionId + '"]');
|
||||
@@ -852,39 +847,59 @@ import { createSlideAnimationEditor } from '/assets/js/slides/slide-animation-ed
|
||||
}
|
||||
});
|
||||
}
|
||||
templateFields.querySelectorAll('select[name^="region_rss_feed_id_"], input[name^="region_rss_item_number_"], select[name^="region_api_source_id_"], input[name^="region_api_item_number_"], input[name^="region_api_items_path_"]').forEach(function (input) {
|
||||
templateFields.querySelectorAll('select[name^="region_rss_feed_id_"], input[name^="region_rss_item_number_"], select[name^="region_api_source_id_"], input[name^="region_api_items_path_"], select[name^="region_api_sort_mode_"], input[name^="region_api_sort_by_"], select[name^="region_api_sort_direction_"]').forEach(function (input) {
|
||||
input.addEventListener('input', function () {
|
||||
var regionId = input.name.replace(/^region_(?:rss_feed_id|rss_item_number|api_source_id|api_item_number|api_items_path)_/, '');
|
||||
var regionId = input.name.replace(/^region_(?:rss_feed_id|rss_item_number|api_source_id|api_items_path|api_sort_mode|api_sort_by|api_sort_direction)_/, '');
|
||||
if (input.name.indexOf('region_rss_') === 0) {
|
||||
var rssFeed = input.name.indexOf('region_rss_feed_id_') === 0 ? input.value : (templateFields.querySelector('select[name="region_rss_feed_id_' + regionId + '"]') || {}).value;
|
||||
updateRssPlaceholderChips(regionId, rssFeed);
|
||||
updateRssItemNumberLimit(regionId, rssFeed);
|
||||
}
|
||||
if (input.name.indexOf('region_api_') === 0) {
|
||||
var apiSortMode = templateFields.querySelector('select[name="region_api_sort_mode_' + regionId + '"]');
|
||||
var apiSortByInput = templateFields.querySelector('input[name="region_api_sort_by_' + regionId + '"]');
|
||||
var apiSortFieldWrap = apiSortByInput && apiSortByInput.closest('[data-api-sort-field-wrap]');
|
||||
var apiSortDirection = templateFields.querySelector('select[name="region_api_sort_direction_' + regionId + '"]');
|
||||
var apiSortDirectionWrap = apiSortDirection && apiSortDirection.closest('[data-api-sort-direction-wrap]');
|
||||
var apiSortEnabled = apiSortMode && apiSortMode.value === 'field';
|
||||
if (apiSortFieldWrap) apiSortFieldWrap.hidden = !apiSortEnabled;
|
||||
if (apiSortDirectionWrap) apiSortDirectionWrap.hidden = !apiSortEnabled;
|
||||
if (apiSortMode && !apiSortEnabled && apiSortByInput) apiSortByInput.value = '';
|
||||
var apiSource = input.name.indexOf('region_api_source_id_') === 0 ? input.value : (templateFields.querySelector('select[name="region_api_source_id_' + regionId + '"]') || {}).value;
|
||||
var apiItemNumber = input.name.indexOf('region_api_item_number_') === 0 ? input.value : (templateFields.querySelector('input[name="region_api_item_number_' + regionId + '"]') || {}).value;
|
||||
var apiItemsPath = input.name.indexOf('region_api_items_path_') === 0 ? input.value : (templateFields.querySelector('input[name="region_api_items_path_' + regionId + '"]') || {}).value;
|
||||
updateApiItemNumberLimit(regionId, apiSource, apiItemsPath);
|
||||
var apiSortBy = apiSortEnabled && apiSortByInput ? apiSortByInput.value : '';
|
||||
var apiSortDirectionValue = apiSortDirection ? apiSortDirection.value : 'asc';
|
||||
updateApiItemsPathReset(regionId, apiSource);
|
||||
updateApiPlaceholderChips(regionId, apiSource, apiItemsPath);
|
||||
updateApiSampleDataPanel(regionId, apiSource, apiItemNumber, apiItemsPath);
|
||||
updateApiSampleDataPanel(regionId, apiSource, apiItemsPath, apiSortBy, apiSortDirectionValue);
|
||||
}
|
||||
templateSelectorLock.markEdited();
|
||||
requestPreviewRender();
|
||||
});
|
||||
input.addEventListener('change', function () {
|
||||
var regionId = input.name.replace(/^region_(?:rss_feed_id|rss_item_number|api_source_id|api_item_number|api_items_path)_/, '');
|
||||
var regionId = input.name.replace(/^region_(?:rss_feed_id|rss_item_number|api_source_id|api_items_path|api_sort_mode|api_sort_by|api_sort_direction)_/, '');
|
||||
if (input.name.indexOf('region_rss_') === 0) {
|
||||
var rssFeed = input.name.indexOf('region_rss_feed_id_') === 0 ? input.value : (templateFields.querySelector('select[name="region_rss_feed_id_' + regionId + '"]') || {}).value;
|
||||
updateRssPlaceholderChips(regionId, rssFeed);
|
||||
updateRssItemNumberLimit(regionId, rssFeed);
|
||||
}
|
||||
if (input.name.indexOf('region_api_') === 0) {
|
||||
var apiSortMode = templateFields.querySelector('select[name="region_api_sort_mode_' + regionId + '"]');
|
||||
var apiSortByInput = templateFields.querySelector('input[name="region_api_sort_by_' + regionId + '"]');
|
||||
var apiSortFieldWrap = apiSortByInput && apiSortByInput.closest('[data-api-sort-field-wrap]');
|
||||
var apiSortDirection = templateFields.querySelector('select[name="region_api_sort_direction_' + regionId + '"]');
|
||||
var apiSortDirectionWrap = apiSortDirection && apiSortDirection.closest('[data-api-sort-direction-wrap]');
|
||||
var apiSortEnabled = apiSortMode && apiSortMode.value === 'field';
|
||||
if (apiSortFieldWrap) apiSortFieldWrap.hidden = !apiSortEnabled;
|
||||
if (apiSortDirectionWrap) apiSortDirectionWrap.hidden = !apiSortEnabled;
|
||||
if (apiSortMode && !apiSortEnabled && apiSortByInput) apiSortByInput.value = '';
|
||||
var apiSource = input.name.indexOf('region_api_source_id_') === 0 ? input.value : (templateFields.querySelector('select[name="region_api_source_id_' + regionId + '"]') || {}).value;
|
||||
var apiItemNumber = input.name.indexOf('region_api_item_number_') === 0 ? input.value : (templateFields.querySelector('input[name="region_api_item_number_' + regionId + '"]') || {}).value;
|
||||
var apiItemsPath = input.name.indexOf('region_api_items_path_') === 0 ? input.value : (templateFields.querySelector('input[name="region_api_items_path_' + regionId + '"]') || {}).value;
|
||||
updateApiItemNumberLimit(regionId, apiSource, apiItemsPath);
|
||||
var apiSortBy = apiSortEnabled && apiSortByInput ? apiSortByInput.value : '';
|
||||
var apiSortDirectionValue = apiSortDirection ? apiSortDirection.value : 'asc';
|
||||
updateApiItemsPathReset(regionId, apiSource);
|
||||
updateApiPlaceholderChips(regionId, apiSource, apiItemsPath);
|
||||
updateApiSampleDataPanel(regionId, apiSource, apiItemNumber, apiItemsPath);
|
||||
updateApiSampleDataPanel(regionId, apiSource, apiItemsPath, apiSortBy, apiSortDirectionValue);
|
||||
}
|
||||
templateSelectorLock.markEdited();
|
||||
requestPreviewRender();
|
||||
@@ -989,6 +1004,30 @@ import { createSlideAnimationEditor } from '/assets/js/slides/slide-animation-ed
|
||||
requestPreviewRender();
|
||||
});
|
||||
templateFields.addEventListener('click', function (event) {
|
||||
var advancedToggle = event.target && typeof event.target.closest === 'function' ? event.target.closest('[data-api-advanced-toggle]') : null;
|
||||
if (advancedToggle) {
|
||||
var advancedPanel = templateFields.querySelector('#' + advancedToggle.getAttribute('aria-controls'));
|
||||
if (advancedPanel) {
|
||||
var isExpanded = advancedToggle.getAttribute('aria-expanded') === 'true';
|
||||
advancedToggle.setAttribute('aria-expanded', isExpanded ? 'false' : 'true');
|
||||
advancedPanel.hidden = isExpanded;
|
||||
advancedToggle.classList.toggle('btn-outline-secondary', isExpanded);
|
||||
advancedToggle.classList.toggle('btn-secondary', !isExpanded);
|
||||
}
|
||||
return;
|
||||
}
|
||||
var sampleToggle = event.target && typeof event.target.closest === 'function' ? event.target.closest('[data-api-sample-toggle]') : null;
|
||||
if (sampleToggle) {
|
||||
var sampleAccordion = sampleToggle.closest('[data-api-sample-data-accordion]');
|
||||
var samplePanel = sampleAccordion && sampleAccordion.querySelector('[data-api-sample-data-panel]');
|
||||
if (sampleAccordion && samplePanel) {
|
||||
var isExpanded = sampleToggle.getAttribute('aria-expanded') === 'true';
|
||||
sampleToggle.setAttribute('aria-expanded', isExpanded ? 'false' : 'true');
|
||||
sampleAccordion.classList.toggle('is-open', !isExpanded);
|
||||
samplePanel.hidden = isExpanded;
|
||||
}
|
||||
return;
|
||||
}
|
||||
var button = event.target && typeof event.target.closest === 'function' ? event.target.closest('[data-api-items-path-reset]') : null;
|
||||
var webpageUpdateButton = event.target && typeof event.target.closest === 'function' ? event.target.closest('[data-webpage-preview-update]') : null;
|
||||
if (!button) {
|
||||
|
||||
Reference in new issue
Block a user