fix(user): rebuild badge modal ajax flow
This commit is contained in:
1 parent
029df27b1d
commit
9c827ff493
14 files changed
+243
-591
No files matched your search
@@ -5,7 +5,6 @@ export const frontendModalRolloutSchema = {
|
||||
description: '按领域控制前台弹窗新流程的分阶段发布。',
|
||||
defaults: {
|
||||
frontend_modal_rollout_identity: true,
|
||||
frontend_modal_rollout_badge: true,
|
||||
frontend_modal_rollout_order: true,
|
||||
frontend_modal_rollout_vip: true,
|
||||
},
|
||||
@@ -21,12 +20,6 @@ export const frontendModalRolloutSchema = {
|
||||
type: 'switch',
|
||||
help: '启用统一弹窗运行时与认证快照流程。',
|
||||
},
|
||||
{
|
||||
key: 'frontend_modal_rollout_badge',
|
||||
label: '徽章新流程',
|
||||
type: 'switch',
|
||||
help: '启用统一 JSON 徽章流程和短缓存。',
|
||||
},
|
||||
{
|
||||
key: 'frontend_modal_rollout_order',
|
||||
label: '订单新流程',
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
/* ============================================================
|
||||
* 徽章弹窗(zibll medal 1:1 风格)
|
||||
* ------------------------------------------------------------
|
||||
* 共享于两个入口:
|
||||
* 1. 用户中心「我的徽章」弹窗(.uc-badges-modal,JS 渲染)
|
||||
* 2. 远程弹窗徽章明细/单卡(.medal-modal,PHP 渲染)
|
||||
* 加载条件与 user-badges.js 一致(badge surface 页面)。
|
||||
* 共享于用户中心与公开主页的服务端 HTML 徽章弹窗。
|
||||
* ============================================================ */
|
||||
|
||||
/* ---------- 顶部资料卡入口(zibll user-medal-info parity) ---------- */
|
||||
@@ -109,6 +106,11 @@
|
||||
gap: 8px 4px;
|
||||
}
|
||||
|
||||
.medal-list-box--grant { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
||||
.medal-grant-item { min-width: 0; }
|
||||
.medal-grant-item .medal-card { height: 100%; }
|
||||
.medal-grant-item > .but { display: block; width: 100%; }
|
||||
|
||||
.medal-list {
|
||||
display: block;
|
||||
min-width: 0;
|
||||
@@ -304,104 +306,6 @@
|
||||
}
|
||||
.medal-modal__back:hover { color: var(--focus-color); }
|
||||
|
||||
/* ---------- 用户中心「我的徽章」弹窗 ---------- */
|
||||
.uc-badges-dialog {
|
||||
max-width: 560px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.uc-badges-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 16px 46px 12px 18px;
|
||||
border-bottom: 1px solid var(--main-border-color, var(--color-line));
|
||||
}
|
||||
.uc-badges-head__icon {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
flex: none;
|
||||
font-size: 16px;
|
||||
color: var(--focus-color);
|
||||
background: var(--focus-color-opacity1);
|
||||
border-radius: 10px;
|
||||
}
|
||||
.uc-badges-head__title {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
}
|
||||
.uc-badges-head__count {
|
||||
margin-left: 6px;
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
color: var(--muted-2-color, var(--color-ink-4));
|
||||
}
|
||||
.uc-badges-head__wear { flex: none; }
|
||||
.uc-badges-head__wear-tag {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
max-width: 140px;
|
||||
padding: 3px 10px;
|
||||
font-size: 12px;
|
||||
color: var(--focus-color);
|
||||
background: var(--focus-color-opacity1);
|
||||
border-radius: 100px;
|
||||
}
|
||||
.uc-badges-head__wear-tag .medal-icon {
|
||||
width: auto;
|
||||
height: 18px;
|
||||
object-fit: contain;
|
||||
}
|
||||
.uc-badges-head__wear-name {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.uc-badges-body {
|
||||
max-height: 56vh;
|
||||
max-height: 56dvh;
|
||||
overflow-y: auto;
|
||||
padding: 16px 14px 18px;
|
||||
}
|
||||
.uc-badges-loading,
|
||||
.uc-badges-error {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
padding: 32px 0;
|
||||
}
|
||||
|
||||
/* 详情视图 */
|
||||
.uc-badges-view--detail { padding: 8px 16px 18px; }
|
||||
.uc-badges-detail__head { margin-bottom: 6px; }
|
||||
.uc-badges-back {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding: 4px 10px 4px 6px;
|
||||
border: 0;
|
||||
background: none;
|
||||
font: inherit;
|
||||
font-size: 13px;
|
||||
color: var(--muted-2-color, var(--color-ink-4));
|
||||
cursor: pointer;
|
||||
border-radius: var(--mini-radius, 6px);
|
||||
transition: color 0.15s ease, background-color 0.15s ease;
|
||||
}
|
||||
.uc-badges-back:hover {
|
||||
color: var(--focus-color);
|
||||
background: var(--focus-color-opacity1);
|
||||
}
|
||||
|
||||
/* ---------- 细滚动条(zibll .mini-scrollbar) ---------- */
|
||||
.mini-scrollbar { scrollbar-width: thin; scrollbar-color: var(--muted-border-color, rgba(136, 136, 136, 0.3)) transparent; }
|
||||
.mini-scrollbar::-webkit-scrollbar { width: 5px; height: 5px; }
|
||||
@@ -411,11 +315,10 @@
|
||||
/* ---------- 响应式(zibll: 桌面 5 列 / 移动 4 列) ---------- */
|
||||
@media (max-width: 768px) {
|
||||
.medal-list-box { grid-template-columns: repeat(4, 1fr); }
|
||||
.medal-list-box--grant { grid-template-columns: 1fr; }
|
||||
.medal-card .medal-icon { height: 55px; }
|
||||
.medal-card .medal-icon--fa { width: 44px; height: 55px; font-size: 26px; }
|
||||
.medal-single-card .medal-icon { height: 96px; }
|
||||
.uc-badges-dialog { max-width: 100%; }
|
||||
.uc-badges-body { max-height: 62vh; max-height: 62dvh; }
|
||||
}
|
||||
|
||||
@media (max-width: 400px) {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
if (!url || url === "#") return;
|
||||
|
||||
var ttl = parseInt(element.getAttribute("data-aksrt-modal-cache-ttl") || "15000", 10);
|
||||
var cache = element.getAttribute("data-aksrt-modal-cache") !== "false";
|
||||
var tags = (element.getAttribute("data-aksrt-modal-cache-tags") || "").split(",").map(function (tag) {
|
||||
return tag.trim();
|
||||
}).filter(Boolean);
|
||||
@@ -28,6 +29,7 @@
|
||||
bottom: element.getAttribute("data-aksrt-modal-bottom") === "true",
|
||||
kind: element.getAttribute("data-aksrt-modal-kind") || "generic",
|
||||
cacheKey: element.getAttribute("data-aksrt-modal-cache-key") || "",
|
||||
cache: cache,
|
||||
cacheTtl: ttl > 0 ? ttl : 15000,
|
||||
cacheTags: tags,
|
||||
});
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Server-rendered user medal actions.
|
||||
*
|
||||
* Mirrors the Zibll admin-ajax lifecycle: mutate, close the dialog, then
|
||||
* reload the page so every server-rendered medal surface is in sync.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
(function (window, document) {
|
||||
'use strict';
|
||||
|
||||
var actions = {
|
||||
wear: 'aksrt_user_medal_wear',
|
||||
grant: 'aksrt_user_medal_manually_add',
|
||||
revoke: 'aksrt_user_medal_manually_remove'
|
||||
};
|
||||
|
||||
function notice(message, type) {
|
||||
if (typeof window.notyf === 'function') window.notyf(message, type);
|
||||
}
|
||||
|
||||
document.addEventListener('click', function (event) {
|
||||
var button = event.target.closest('[data-aksrt-badge-action]');
|
||||
if (!button || button.classList.contains('is-loading')) return;
|
||||
|
||||
var type = button.getAttribute('data-aksrt-badge-action') || '';
|
||||
var action = actions[type];
|
||||
var slug = button.getAttribute('data-slug') || '';
|
||||
var nonce = (window.aksrtData && window.aksrtData.nonce) || '';
|
||||
if (!action || !slug || !nonce) return;
|
||||
|
||||
event.preventDefault();
|
||||
button.classList.add('is-loading');
|
||||
button.setAttribute('aria-busy', 'true');
|
||||
|
||||
var form = new URLSearchParams();
|
||||
form.set('action', action);
|
||||
form.set('nonce', nonce);
|
||||
form.set('slug', slug);
|
||||
if (type !== 'wear') form.set('id', button.getAttribute('data-user-id') || '0');
|
||||
|
||||
window.fetch((window.aksrtData && window.aksrtData.ajaxUrl) || '/wp-admin/admin-ajax.php', {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
|
||||
body: form.toString()
|
||||
}).then(function (response) {
|
||||
return response.json();
|
||||
}).then(function (json) {
|
||||
if (!json || !json.success) throw new Error((json && json.data && json.data.message) || '操作失败');
|
||||
notice((json.data && json.data.message) || '操作成功', 'success');
|
||||
window.AksrtModalRuntime.close('badge-action');
|
||||
window.setTimeout(function () { window.location.reload(); }, 120);
|
||||
}).catch(function (error) {
|
||||
button.classList.remove('is-loading');
|
||||
button.removeAttribute('aria-busy');
|
||||
notice(error.message || '网络错误', 'danger');
|
||||
});
|
||||
});
|
||||
})(window, document);
|
||||
@@ -1,291 +0,0 @@
|
||||
/**
|
||||
* AKSRT user badges — canonical JSON/runtime path.
|
||||
*
|
||||
* User-center and public-author triggers share one privacy-aware REST DTO,
|
||||
* short user-scoped runtime cache, and one in-modal list/detail renderer.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
(function (window, document) {
|
||||
'use strict';
|
||||
|
||||
var activeState = null;
|
||||
|
||||
function escapeHtml(value) {
|
||||
return String(value == null ? '' : value)
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''');
|
||||
}
|
||||
|
||||
function api(path, options) {
|
||||
return window.AksrtRequest.request(path, options || {}).then(function (response) {
|
||||
return {
|
||||
ok: response.ok,
|
||||
status: response.status,
|
||||
json: response.json || {},
|
||||
};
|
||||
}).catch(function (error) {
|
||||
var response = error && error.response ? error.response : {};
|
||||
return {
|
||||
ok: false,
|
||||
status: error && error.status ? error.status : (response.status || 0),
|
||||
json: error && error.json ? error.json : (response.json || { message: error && error.message }),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function iconHtml(item, className) {
|
||||
var icon = item && item.icon_url ? String(item.icon_url) : '';
|
||||
var label = item && item.label ? String(item.label) : '';
|
||||
if (icon) {
|
||||
return '<img' + window.aksrtGetLazyImageAttr('lazy_other', icon, 'medal-icon img-icon' + (className ? ' ' + className : '')) + ' alt="' + escapeHtml(label) + '" title="' + escapeHtml(label) + '" decoding="async">';
|
||||
}
|
||||
return '<span class="medal-icon medal-icon--fa' + (className ? ' ' + className : '') + '"><i class="fa fas fa-trophy" aria-hidden="true"></i></span>';
|
||||
}
|
||||
|
||||
function emptyHtml() {
|
||||
return '<div class="empty-state empty-state--sm">' +
|
||||
'<div class="empty-state__icon"><i class="fa fas fa-trophy" aria-hidden="true"></i></div>' +
|
||||
'<div class="empty-state__title">暂无徽章</div>' +
|
||||
'<div class="empty-state__desc">积极参与社区互动即可获得徽章</div>' +
|
||||
'</div>';
|
||||
}
|
||||
|
||||
function findItem(state, slug) {
|
||||
var categories = state.data && Array.isArray(state.data.categories) ? state.data.categories : [];
|
||||
for (var i = 0; i < categories.length; i += 1) {
|
||||
var items = Array.isArray(categories[i].items) ? categories[i].items : [];
|
||||
for (var j = 0; j < items.length; j += 1) {
|
||||
if (String(items[j].slug || '') === String(slug || '')) return items[j];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function wornItem(state) {
|
||||
var wear = state.data && state.data.wear ? state.data.wear : '';
|
||||
return wear ? findItem(state, wear) : null;
|
||||
}
|
||||
|
||||
function cardHtml(item) {
|
||||
var classes = 'medal-card' + (item.owned ? ' is-has' : ' no-has') + (item.wear ? ' is-wear' : '');
|
||||
return '<div class="' + classes + '">' +
|
||||
iconHtml(item) +
|
||||
'<div class="medal-card__name">' + escapeHtml(item.label) + '</div>' +
|
||||
(item.wear ? '<div class="medal-card__wear">佩戴中</div>' : '') +
|
||||
'</div>';
|
||||
}
|
||||
|
||||
function listHtml(state) {
|
||||
var data = state.data || {};
|
||||
var categories = Array.isArray(data.categories) ? data.categories : [];
|
||||
var worn = wornItem(state);
|
||||
var title = data.is_self ? '我的徽章' : '徽章明细';
|
||||
var wearHtml = worn
|
||||
? '<span class="uc-badges-head__wear-tag" title="当前佩戴:' + escapeHtml(worn.label) + '">' + iconHtml(worn) + '<span class="uc-badges-head__wear-name">' + escapeHtml(worn.label) + '</span></span>'
|
||||
: '';
|
||||
var html = '<div class="medal-modal">' +
|
||||
'<div class="uc-badges-head">' +
|
||||
'<span class="uc-badges-head__icon" aria-hidden="true"><i class="fa fas fa-trophy"></i></span>' +
|
||||
'<div class="uc-badges-head__title">' + escapeHtml(title) + '<span class="uc-badges-head__count">' + (Number(data.count || 0) > 0 ? '共 ' + Number(data.count) + ' 枚' : '') + '</span></div>' +
|
||||
'<div class="uc-badges-head__wear">' + wearHtml + '</div>' +
|
||||
'</div>';
|
||||
|
||||
if (!categories.length) return html + '<div class="medal-modal__scroll mini-scrollbar">' + emptyHtml() + '</div></div>';
|
||||
|
||||
html += '<div class="medal-modal__scroll mini-scrollbar">';
|
||||
categories.forEach(function (category) {
|
||||
var items = Array.isArray(category.items) ? category.items : [];
|
||||
var cards = items.map(function (item) {
|
||||
return '<button type="button" class="medal-list" data-aksrt-badge-detail="' + escapeHtml(item.slug) + '" aria-label="' + escapeHtml(item.label) + '">' + cardHtml(item) + '</button>';
|
||||
}).join('');
|
||||
html += '<div class="medal-cat-box"><div class="medal-cat-head"><b class="medal-cat-name">' + escapeHtml(category.cat_name || '') + '</b></div><div class="medal-list-box">' + cards + '</div></div>';
|
||||
});
|
||||
return html + '</div></div>';
|
||||
}
|
||||
|
||||
function detailHtml(state) {
|
||||
var item = findItem(state, state.detailSlug);
|
||||
if (!item) return listHtml(state);
|
||||
|
||||
var stateLine = '';
|
||||
if (item.owned && item.time) {
|
||||
stateLine = '<div class="medal-single-state c-blue">' + escapeHtml(item.time + ' 获得') + '</div>';
|
||||
} else if (!item.owned) {
|
||||
stateLine = '<div class="medal-single-state c-yellow">暂未获得</div>';
|
||||
}
|
||||
|
||||
var action = '';
|
||||
if (state.canWear && item.owned && !item.wear) {
|
||||
action = '<button type="button" class="but jb-blue btn-block radius" data-aksrt-badge-wear="' + escapeHtml(item.slug) + '">佩戴此徽章</button>';
|
||||
} else if (item.wear) {
|
||||
action = '<span class="badg btn-block c-blue">当前佩戴此徽章</span>';
|
||||
}
|
||||
|
||||
return '<div class="medal-modal medal-modal--single">' +
|
||||
'<div class="uc-badges-detail__head"><button type="button" class="uc-badges-back" data-aksrt-badges-back><i class="fa fas fa-angle-left" aria-hidden="true"></i> 返回列表</button></div>' +
|
||||
'<div class="medal-single-card"><div class="medal-single-bg"><img' + window.aksrtGetLazyImageAttr('lazy_other', (window.aksrtData && window.aksrtData.themeUri ? window.aksrtData.themeUri : '') + '/assets/img/medal/medal-background.svg', 'fit-cover') + ' alt=""></div><div class="medal-single-main">' +
|
||||
iconHtml(item) + '<div class="medal-single-name">' + escapeHtml(item.label) + '</div>' +
|
||||
(item.desc ? '<div class="medal-single-desc muted-2-color">' + escapeHtml(item.desc) + '</div>' : '') + stateLine +
|
||||
'</div></div>' + (action ? '<div class="medal-modal__actions">' + action + '</div>' : '') +
|
||||
'</div>';
|
||||
}
|
||||
|
||||
function renderState(state) {
|
||||
return state.detailSlug ? detailHtml(state) : listHtml(state);
|
||||
}
|
||||
|
||||
function rehydrate(content) {
|
||||
window.AksrtFrontend.rehydrate(content, 'modal');
|
||||
}
|
||||
|
||||
function renderInto(state) {
|
||||
if (!state.session || state.session.closed || !state.session.content) return;
|
||||
state.session.content.innerHTML = renderState(state);
|
||||
rehydrate(state.session.content);
|
||||
bindContent(state);
|
||||
}
|
||||
|
||||
function syncHeaderIcon(state) {
|
||||
var worn = wornItem(state);
|
||||
if (!worn || !worn.icon_url) return;
|
||||
document.querySelectorAll('.aksrt-identity-medal.is-wear').forEach(function (node) {
|
||||
if (node.tagName === 'IMG') {
|
||||
node.src = worn.icon_url;
|
||||
node.alt = worn.label;
|
||||
node.title = worn.label;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function wear(state, slug, button) {
|
||||
if (!state.canWear || state.wearing || !slug) return;
|
||||
state.wearing = true;
|
||||
state.wearController = window.AbortController ? new window.AbortController() : null;
|
||||
if (button) button.disabled = true;
|
||||
api('/users/me/badges/wear', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ slug: slug }),
|
||||
signal: state.wearController ? state.wearController.signal : undefined,
|
||||
}).then(function (result) {
|
||||
if (state.session && state.session.closed) return;
|
||||
if (!result.ok) {
|
||||
notyf((result.json && (result.json.message || (result.json.data && result.json.data.message))) || '佩戴失败', 'danger');
|
||||
if (button) button.disabled = false;
|
||||
return;
|
||||
}
|
||||
if (result.json && result.json.data) state.data = result.json.data;
|
||||
state.detailSlug = slug;
|
||||
window.AksrtModalRuntime.invalidate(['badges', 'identity', 'badges:user:' + state.userId]);
|
||||
notyf((result.json && result.json.message) || '已佩戴徽章', 'success');
|
||||
renderInto(state);
|
||||
syncHeaderIcon(state);
|
||||
}).catch(function (error) {
|
||||
if (error && error.name === 'AbortError') return;
|
||||
notyf('网络错误', 'danger');
|
||||
if (button) button.disabled = false;
|
||||
}).finally(function () {
|
||||
state.wearing = false;
|
||||
state.wearController = null;
|
||||
});
|
||||
}
|
||||
|
||||
function bindContent(state) {
|
||||
if (!state.session || !state.session.content || state.session.content.dataset.aksrtBadgesBound === '1') return;
|
||||
state.session.content.dataset.aksrtBadgesBound = '1';
|
||||
state.session.content.addEventListener('click', function (event) {
|
||||
var back = event.target.closest('[data-aksrt-badges-back]');
|
||||
if (back) {
|
||||
event.preventDefault();
|
||||
state.detailSlug = '';
|
||||
renderInto(state);
|
||||
return;
|
||||
}
|
||||
var detail = event.target.closest('[data-aksrt-badge-detail]');
|
||||
if (detail) {
|
||||
event.preventDefault();
|
||||
state.detailSlug = detail.getAttribute('data-aksrt-badge-detail') || '';
|
||||
renderInto(state);
|
||||
return;
|
||||
}
|
||||
var wearButton = event.target.closest('[data-aksrt-badge-wear]');
|
||||
if (wearButton) {
|
||||
event.preventDefault();
|
||||
wear(state, wearButton.getAttribute('data-aksrt-badge-wear') || '', wearButton);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function openBadges(trigger) {
|
||||
var runtime = window.AksrtModalRuntime;
|
||||
if (!runtime.isRolloutEnabled("badge")) return;
|
||||
var userId = parseInt(trigger.getAttribute('data-aksrt-badges-user-id') || '0', 10);
|
||||
if (!userId) return;
|
||||
if (activeState && activeState.wearController) {
|
||||
try { activeState.wearController.abort(); } catch (_) {}
|
||||
}
|
||||
|
||||
var state = {
|
||||
userId: userId,
|
||||
canWear: trigger.getAttribute('data-aksrt-badges-can-wear') === '1',
|
||||
data: null,
|
||||
detailSlug: '',
|
||||
session: null,
|
||||
wearing: false,
|
||||
wearController: null,
|
||||
};
|
||||
activeState = state;
|
||||
runtime.openRemote({
|
||||
url: '/users/' + userId + '/badges',
|
||||
kind: 'badges',
|
||||
title: '徽章',
|
||||
className: 'modal-mini full-sm aksrt-badges-modal-shell',
|
||||
mobileBottom: true,
|
||||
skeleton: '<div class="medal-modal"><div class="uc-badges-head"><span class="aksrt-modal-runtime__skeleton-line is-short"></span><span class="aksrt-modal-runtime__skeleton-line is-wide"></span></div><div class="medal-list-box aksrt-modal-runtime__skeleton"><span class="aksrt-modal-runtime__skeleton-block"></span><span class="aksrt-modal-runtime__skeleton-block"></span><span class="aksrt-modal-runtime__skeleton-block"></span></div></div>',
|
||||
cacheTtl: 12000,
|
||||
cacheTags: ['badges', 'identity', 'badges:user:' + userId],
|
||||
responseType: 'json',
|
||||
renderData: function (data, session) {
|
||||
state.session = session;
|
||||
state.data = data || {};
|
||||
state.canWear = state.canWear && state.data.can_wear === true;
|
||||
session.content.innerHTML = renderState(state);
|
||||
},
|
||||
onData: function (data, session) {
|
||||
state.session = session;
|
||||
state.data = data || state.data;
|
||||
state.canWear = state.canWear && state.data.can_wear === true;
|
||||
bindContent(state);
|
||||
syncHeaderIcon(state);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('aksrt:modal:close', function (event) {
|
||||
if (!activeState || !event.detail || event.detail.session !== activeState.session) return;
|
||||
if (activeState.wearController) {
|
||||
try { activeState.wearController.abort(); } catch (_) {}
|
||||
}
|
||||
activeState = null;
|
||||
});
|
||||
|
||||
function bindOnce() {
|
||||
if (window.__aksrtBadgesBound) return;
|
||||
window.__aksrtBadgesBound = true;
|
||||
document.addEventListener('click', function (event) {
|
||||
var trigger = event.target.closest('[data-aksrt-badges-open]');
|
||||
if (!trigger) return;
|
||||
event.preventDefault();
|
||||
openBadges(trigger);
|
||||
});
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', bindOnce, { once: true });
|
||||
} else {
|
||||
bindOnce();
|
||||
}
|
||||
})(window, document);
|
||||
Reference in new issue
Block a user