310 lines
9.7 KiB
JavaScript
310 lines
9.7 KiB
JavaScript
/**
|
|
* AKSRT Post Share
|
|
*
|
|
* Handles share dropdowns, social share targets, copy link,
|
|
* and WeChat bridge handoff with QR fallback.
|
|
*
|
|
* @package AKSRT
|
|
*/
|
|
|
|
(function () {
|
|
'use strict';
|
|
|
|
function notify(message, type) {
|
|
if (!message) return;
|
|
if (typeof window.AksrtToast === 'function') {
|
|
window.AksrtToast(message, type || 'info');
|
|
return;
|
|
}
|
|
if (typeof window.showToast === 'function') {
|
|
window.showToast(message, type || 'info');
|
|
return;
|
|
}
|
|
if (typeof window.aksrtToast === 'function') {
|
|
window.aksrtToast(message, type || 'info');
|
|
return;
|
|
}
|
|
window.alert(message);
|
|
}
|
|
|
|
function getMetaContent(selectors) {
|
|
for (var i = 0; i < selectors.length; i += 1) {
|
|
var node = document.querySelector(selectors[i]);
|
|
var content = node ? node.getAttribute('content') : '';
|
|
if (content) return content;
|
|
}
|
|
return '';
|
|
}
|
|
|
|
function getPlatform(node) {
|
|
if (!node) return '';
|
|
return node.getAttribute('data-share-platform') || node.getAttribute('data-platform') || '';
|
|
}
|
|
|
|
function resolvePayload(node) {
|
|
// Unified payload via the shared builder; fall back to local resolution
|
|
// only if the builder script is unavailable.
|
|
if (window.AksrtShareData && typeof window.AksrtShareData.resolve === 'function') {
|
|
return window.AksrtShareData.resolve(node);
|
|
}
|
|
|
|
var dropdown = document.getElementById('share-dropdown');
|
|
var source = node && typeof node.closest === 'function'
|
|
? node.closest('[data-share-url], [data-share-title], [data-share-desc], [data-share-image]')
|
|
: null;
|
|
var context = source || dropdown;
|
|
|
|
function readAttr(name) {
|
|
return (node && node.getAttribute(name)) || (context && context.getAttribute(name)) || '';
|
|
}
|
|
|
|
return {
|
|
title: readAttr('data-share-title') || document.title,
|
|
url: readAttr('data-share-url') || window.location.href,
|
|
desc: readAttr('data-share-desc') || getMetaContent(['meta[property="og:description"]', 'meta[name="description"]']),
|
|
text: readAttr('data-share-text') || '',
|
|
image: readAttr('data-share-image') || getMetaContent(['meta[property="og:image"]']),
|
|
qrcode: readAttr('data-share-qrcode') || ''
|
|
};
|
|
}
|
|
|
|
function openWindow(url) {
|
|
if (!url) return;
|
|
window.open(url, '_blank', 'width=640,height=560,scrollbars=yes,resizable=yes');
|
|
}
|
|
|
|
function buildShareUrl(platform, payload) {
|
|
switch (platform) {
|
|
case 'weibo':
|
|
return 'https://service.weibo.com/share/share.php?url=' + encodeURIComponent(payload.url) + '&title=' + encodeURIComponent(payload.title + (payload.text ? ' ' + payload.text : ''));
|
|
case 'qq':
|
|
return 'https://connect.qq.com/widget/shareqq/index.html?url=' + encodeURIComponent(payload.url) + '&title=' + encodeURIComponent(payload.title) + '&desc=' + encodeURIComponent(payload.desc || payload.text || '');
|
|
case 'twitter':
|
|
return 'https://x.com/intent/tweet?url=' + encodeURIComponent(payload.url) + '&text=' + encodeURIComponent(payload.title);
|
|
case 'telegram':
|
|
return 'https://t.me/share/url?url=' + encodeURIComponent(payload.url) + '&text=' + encodeURIComponent(payload.title);
|
|
case 'linkedin':
|
|
return 'https://www.linkedin.com/sharing/share-offsite/?url=' + encodeURIComponent(payload.url);
|
|
default:
|
|
return '';
|
|
}
|
|
}
|
|
|
|
function fallbackCopy(text) {
|
|
var textarea = document.createElement('textarea');
|
|
textarea.value = text;
|
|
textarea.style.cssText = 'position:fixed;left:-9999px;top:-9999px;opacity:0;';
|
|
textarea.setAttribute('readonly', '');
|
|
document.body.appendChild(textarea);
|
|
try {
|
|
textarea.select();
|
|
textarea.setSelectionRange(0, textarea.value.length);
|
|
if (!document.execCommand('copy')) {
|
|
throw new Error('copy command failed');
|
|
}
|
|
} finally {
|
|
document.body.removeChild(textarea);
|
|
}
|
|
}
|
|
|
|
function copyLink(text) {
|
|
if (navigator.clipboard && navigator.clipboard.writeText) {
|
|
return navigator.clipboard.writeText(text).catch(function () {
|
|
fallbackCopy(text);
|
|
});
|
|
}
|
|
|
|
try {
|
|
fallbackCopy(text);
|
|
return Promise.resolve();
|
|
} catch (error) {
|
|
return Promise.reject(error);
|
|
}
|
|
}
|
|
|
|
function initShareDropdown() {
|
|
var trigger = document.getElementById('action-share-trigger');
|
|
var dropdown = document.getElementById('share-dropdown');
|
|
if (!trigger || !dropdown || dropdown.dataset.aksrtShareBound === '1') return;
|
|
|
|
dropdown.dataset.aksrtShareBound = '1';
|
|
|
|
var qrBox = document.getElementById('share-qrcode-box');
|
|
var qrImage = document.getElementById('share-qrcode-image');
|
|
|
|
function closeDropdown() {
|
|
dropdown.setAttribute('aria-hidden', 'true');
|
|
trigger.setAttribute('aria-expanded', 'false');
|
|
if (window.AksrtShare && typeof window.AksrtShare.hideQrFallback === 'function') {
|
|
window.AksrtShare.hideQrFallback(qrBox);
|
|
} else if (qrBox) {
|
|
qrBox.classList.remove('is-visible');
|
|
qrBox.setAttribute('aria-hidden', 'true');
|
|
}
|
|
}
|
|
|
|
function toggleDropdown() {
|
|
var isOpen = dropdown.getAttribute('aria-hidden') === 'false';
|
|
if (isOpen) {
|
|
closeDropdown();
|
|
return;
|
|
}
|
|
|
|
dropdown.setAttribute('aria-hidden', 'false');
|
|
trigger.setAttribute('aria-expanded', 'true');
|
|
}
|
|
|
|
trigger.addEventListener('click', function (event) {
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
toggleDropdown();
|
|
});
|
|
|
|
document.addEventListener('click', function (event) {
|
|
if (!trigger.contains(event.target) && !dropdown.contains(event.target)) {
|
|
closeDropdown();
|
|
}
|
|
});
|
|
|
|
document.addEventListener('keydown', function (event) {
|
|
if (event.key === 'Escape') {
|
|
closeDropdown();
|
|
}
|
|
});
|
|
|
|
dropdown.addEventListener('click', function (event) {
|
|
var item = event.target.closest('.share-item');
|
|
if (!item) return;
|
|
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
|
|
handleShareAction(item, {
|
|
qrBox: qrBox,
|
|
qrImage: qrImage,
|
|
closeDropdown: closeDropdown,
|
|
withinDropdown: true
|
|
});
|
|
});
|
|
}
|
|
|
|
function handleWeixinShare(node, payload, options) {
|
|
options = options || {};
|
|
|
|
var share = window.AksrtShare;
|
|
if (!share || typeof share.openWeixinShare !== 'function') {
|
|
notify('微信分享模块未加载', 'error');
|
|
return Promise.resolve({ mode: 'error' });
|
|
}
|
|
|
|
if (
|
|
options.qrBox &&
|
|
options.qrBox.classList.contains('is-visible') &&
|
|
(!share.isWeixinEnv || !share.isWeixinEnv())
|
|
) {
|
|
share.hideQrFallback(options.qrBox);
|
|
return Promise.resolve({ mode: 'closed' });
|
|
}
|
|
|
|
return share.openWeixinShare({
|
|
title: payload.title,
|
|
url: payload.url,
|
|
desc: payload.desc || payload.text || '',
|
|
image: payload.image,
|
|
qrBox: options.qrBox || null,
|
|
qrImage: options.qrImage || null
|
|
}).then(function (result) {
|
|
if (result && result.message) {
|
|
notify(result.message, result.mode === 'error' ? 'error' : (result.mode === 'bridge' ? 'success' : 'info'));
|
|
}
|
|
return result;
|
|
});
|
|
}
|
|
|
|
function handleShareAction(node, options) {
|
|
var platform = getPlatform(node);
|
|
if (!platform) return Promise.resolve({ mode: 'noop' });
|
|
|
|
var payload = resolvePayload(node);
|
|
if (!payload.url) return Promise.resolve({ mode: 'noop' });
|
|
|
|
if (platform === 'copy') {
|
|
return copyLink(payload.url).then(function () {
|
|
notify('链接已复制', 'success');
|
|
if (options && typeof options.closeDropdown === 'function') {
|
|
options.closeDropdown();
|
|
}
|
|
return { mode: 'copy' };
|
|
}).catch(function () {
|
|
notify('复制失败,请手动复制链接', 'error');
|
|
return { mode: 'error' };
|
|
});
|
|
}
|
|
|
|
if (platform === 'wechat') {
|
|
return handleWeixinShare(node, payload, options).then(function (result) {
|
|
if (result && result.mode !== 'qr' && result.mode !== 'error' && options && typeof options.closeDropdown === 'function') {
|
|
options.closeDropdown();
|
|
}
|
|
return result;
|
|
});
|
|
}
|
|
|
|
if (platform === 'poster') {
|
|
if (window.AksrtPosterShare && typeof window.AksrtPosterShare.open === 'function') {
|
|
window.AksrtPosterShare.open(payload);
|
|
if (options && typeof options.closeDropdown === 'function') options.closeDropdown();
|
|
return Promise.resolve({ mode: 'poster' });
|
|
}
|
|
notify('海报模块未加载', 'error');
|
|
return Promise.resolve({ mode: 'error' });
|
|
}
|
|
|
|
var shareUrl = buildShareUrl(platform, payload);
|
|
if (!shareUrl) {
|
|
return Promise.resolve({ mode: 'noop' });
|
|
}
|
|
|
|
openWindow(shareUrl);
|
|
if (options && typeof options.closeDropdown === 'function') {
|
|
options.closeDropdown();
|
|
}
|
|
|
|
return Promise.resolve({ mode: 'window' });
|
|
}
|
|
|
|
function bindGenericShareButtons() {
|
|
document.addEventListener('click', function (event) {
|
|
var node = event.target.closest('[data-share-platform]');
|
|
if (!node || node.closest('#share-dropdown')) return;
|
|
|
|
event.preventDefault();
|
|
handleShareAction(node, {});
|
|
});
|
|
|
|
document.addEventListener('click', function (event) {
|
|
var node = event.target.closest('[data-share-copy]');
|
|
if (!node) return;
|
|
|
|
event.preventDefault();
|
|
var url = node.getAttribute('data-share-url') || window.location.href;
|
|
copyLink(url).then(function () {
|
|
notify('链接已复制', 'success');
|
|
}).catch(function () {
|
|
notify('复制失败,请手动复制链接', 'error');
|
|
});
|
|
});
|
|
}
|
|
|
|
function init() {
|
|
initShareDropdown();
|
|
bindGenericShareButtons();
|
|
}
|
|
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', init);
|
|
} else {
|
|
init();
|
|
}
|
|
})();
|