| 1 |
/* Tag Cloud — frontend */ |
| 2 |
(function () { |
| 3 |
function colorAt(index, multiColors, primary) { |
| 4 |
if (!multiColors) { return primary; } |
| 5 |
var cols = multiColors.split(',').map(function (c) { return c.trim(); }).filter(Boolean); |
| 6 |
return cols[index % cols.length] || primary; |
| 7 |
} |
| 8 |
|
| 9 |
function buildTagElement(label, url, fontSize, bg, textColor, border, paddingX, paddingY, borderRadius, fontWeight, lineHeight) { |
| 10 |
var a = document.createElement('a'); |
| 11 |
a.className = 'bktagcl-tag'; |
| 12 |
a.href = url || '#'; |
| 13 |
a.textContent = label; |
| 14 |
a.style.cssText = [ |
| 15 |
'font-size:' + fontSize + 'px', |
| 16 |
'padding:' + paddingY + 'px ' + paddingX + 'px', |
| 17 |
'border-radius:' + borderRadius + 'px', |
| 18 |
'background:' + bg, |
| 19 |
'color:' + textColor, |
| 20 |
'border:' + border, |
| 21 |
'display:inline-block', |
| 22 |
].join(';'); |
| 23 |
return a; |
| 24 |
} |
| 25 |
|
| 26 |
function getTagParams(wrap) { |
| 27 |
var cs = getComputedStyle(wrap); |
| 28 |
return { |
| 29 |
source: wrap.getAttribute('data-source') || 'custom', |
| 30 |
max: parseInt(wrap.getAttribute('data-max'), 10) || 20, |
| 31 |
sort: wrap.getAttribute('data-sort') || 'input', |
| 32 |
showCount: wrap.getAttribute('data-count') === '1', |
| 33 |
hoverBg: wrap.getAttribute('data-hover-bg') || '', |
| 34 |
hoverText: wrap.getAttribute('data-hover-text') || '', |
| 35 |
animate: wrap.getAttribute('data-animate') === '1', |
| 36 |
tagStyle: wrap.getAttribute('data-tag-style') || 'rounded', |
| 37 |
colorMode: wrap.getAttribute('data-color-mode') || 'single', |
| 38 |
primary: wrap.getAttribute('data-primary') || '#6c3fb5', |
| 39 |
secondary: wrap.getAttribute('data-secondary') || '#a855f7', |
| 40 |
multiColors: wrap.getAttribute('data-multi-colors') || '', |
| 41 |
textColor: wrap.getAttribute('data-text-color') || '#ffffff', |
| 42 |
borderColor: wrap.getAttribute('data-border-color') || '#6c3fb5', |
| 43 |
borderWidth: parseInt(wrap.getAttribute('data-border-width'), 10) || 1, |
| 44 |
fontSizeMin: parseInt(wrap.getAttribute('data-fs-min'), 10) || 13, |
| 45 |
fontSizeMax: parseInt(wrap.getAttribute('data-fs-max'), 10) || 22, |
| 46 |
fontWeight: wrap.getAttribute('data-font-weight') || '500', |
| 47 |
lineHeight: parseFloat(wrap.getAttribute('data-line-height')) || 1.4, |
| 48 |
paddingX: parseInt(wrap.getAttribute('data-px'), 10) || 14, |
| 49 |
paddingY: parseInt(wrap.getAttribute('data-py'), 10) || 7, |
| 50 |
bdRadius: parseInt(wrap.getAttribute('data-br'), 10) || 6, |
| 51 |
}; |
| 52 |
} |
| 53 |
|
| 54 |
function renderTags(wrap, rawTags, params) { |
| 55 |
wrap.innerHTML = ''; |
| 56 |
var tags = rawTags.slice(0, params.max); |
| 57 |
|
| 58 |
// sort |
| 59 |
if (params.sort === 'alpha') { |
| 60 |
tags.sort(function (a, b) { return a.label.localeCompare(b.label); }); |
| 61 |
} else if (params.sort === 'size') { |
| 62 |
tags.sort(function (a, b) { return b.weight - a.weight; }); |
| 63 |
} |
| 64 |
|
| 65 |
tags.forEach(function (tag, idx) { |
| 66 |
var weight = tag.weight || 1; |
| 67 |
var fs = Math.round(params.fontSizeMin + ((weight - 1) / 4) * (params.fontSizeMax - params.fontSizeMin)); |
| 68 |
var isGrad = params.colorMode === 'gradient'; |
| 69 |
var col = params.colorMode === 'multi' ? colorAt(idx, params.multiColors, params.primary) : params.primary; |
| 70 |
var br = params.tagStyle === 'pill' ? 9999 : params.bdRadius; |
| 71 |
|
| 72 |
var bg, textCol, border; |
| 73 |
if (params.tagStyle === 'flat') { |
| 74 |
bg = 'none'; textCol = col; border = 'none'; |
| 75 |
} else if (params.tagStyle === 'outlined') { |
| 76 |
bg = 'transparent'; textCol = col; border = params.borderWidth + 'px solid ' + col; |
| 77 |
} else { |
| 78 |
bg = isGrad ? ('linear-gradient(135deg,' + params.primary + ',' + params.secondary + ')') : col; |
| 79 |
textCol = params.textColor; |
| 80 |
border = 'none'; |
| 81 |
} |
| 82 |
|
| 83 |
var a = buildTagElement( |
| 84 |
params.showCount && tag.count !== undefined ? tag.label + ' (' + tag.count + ')' : tag.label, |
| 85 |
tag.url, fs, bg, textCol, border, |
| 86 |
params.paddingX, params.paddingY, br, params.fontWeight, params.lineHeight |
| 87 |
); |
| 88 |
|
| 89 |
wrap.appendChild(a); |
| 90 |
}); |
| 91 |
|
| 92 |
// write CSS vars for hover |
| 93 |
if (params.hoverBg) { |
| 94 |
wrap.style.setProperty('--bktagcl-hover-bg', params.hoverBg); |
| 95 |
wrap.style.setProperty('--bktagcl-hover-text', params.hoverText); |
| 96 |
} |
| 97 |
} |
| 98 |
|
| 99 |
function init() { |
| 100 |
document.querySelectorAll('.bktagcl-wrap').forEach(function (wrap) { |
| 101 |
if (wrap._bktagclInit) { return; } |
| 102 |
wrap._bktagclInit = true; |
| 103 |
|
| 104 |
var source = wrap.getAttribute('data-source') || 'custom'; |
| 105 |
var params = getTagParams(wrap); |
| 106 |
|
| 107 |
if (source === 'wp-tags') { |
| 108 |
var max = params.max; |
| 109 |
var apiBase = (window.wpApiSettings && window.wpApiSettings.root) |
| 110 |
? window.wpApiSettings.root.replace(/\/$/, '') |
| 111 |
: '/wp-json'; |
| 112 |
var url = apiBase + '/wp/v2/tags?per_page=' + max + '&orderby=count&order=desc&_fields=id,name,count,link'; |
| 113 |
|
| 114 |
fetch(url) |
| 115 |
.then(function (r) { return r.json(); }) |
| 116 |
.then(function (data) { |
| 117 |
var maxCount = data.reduce(function (m, t) { return Math.max(m, t.count || 1); }, 1); |
| 118 |
var minCount = data.reduce(function (m, t) { return Math.min(m, t.count || 1); }, maxCount); |
| 119 |
|
| 120 |
var tags = data.map(function (t) { |
| 121 |
// map count → weight 1-5 |
| 122 |
var range = maxCount - minCount || 1; |
| 123 |
var weight = Math.round(((t.count - minCount) / range) * 4) + 1; |
| 124 |
return { label: t.name, url: t.link, weight: weight, count: t.count }; |
| 125 |
}); |
| 126 |
|
| 127 |
renderTags(wrap, tags, params); |
| 128 |
}) |
| 129 |
.catch(function () { |
| 130 |
wrap.textContent = 'Could not load tags.'; |
| 131 |
}); |
| 132 |
} else { |
| 133 |
// custom: inline styles already set by save(), just apply CSS vars |
| 134 |
if (params.hoverBg) { |
| 135 |
wrap.style.setProperty('--bktagcl-hover-bg', params.hoverBg); |
| 136 |
wrap.style.setProperty('--bktagcl-hover-text', params.hoverText); |
| 137 |
} |
| 138 |
} |
| 139 |
}); |
| 140 |
} |
| 141 |
|
| 142 |
if (document.readyState === 'loading') { |
| 143 |
document.addEventListener('DOMContentLoaded', init); |
| 144 |
} else { |
| 145 |
init(); |
| 146 |
} |
| 147 |
}()); |
| 148 |
|