feat: add support for global and element-specific custom HTML attributes across editor plugins and page templates
This commit is contained in:
@@ -349,7 +349,8 @@
|
||||
<!-- 15. Grid / Columns Block -->
|
||||
<th:block th:if="${block['type'] == 'grid'}">
|
||||
<div th:id="${block.data['globalId'] != null and !#strings.isEmpty(block.data['globalId']) ? block.data['globalId'] : null}"
|
||||
th:class="${block.data['globalClass'] != null and !#strings.isEmpty(block.data['globalClass']) ? block.data['globalClass'] : null}">
|
||||
th:class="${block.data['globalClass'] != null and !#strings.isEmpty(block.data['globalClass']) ? block.data['globalClass'] : null}"
|
||||
th:data-custom-attrs="${block.data['globalAttributes'] != null and !#strings.isEmpty(block.data['globalAttributes']) ? block.data['globalAttributes'] : (block.data['attributes'] != null and !#strings.isEmpty(block.data['attributes']) ? block.data['attributes'] : null)}">
|
||||
<div class="container py-4">
|
||||
<div class="row">
|
||||
<th:block th:each="i : ${#numbers.sequence(1, block.data['cols'])}">
|
||||
@@ -357,6 +358,7 @@
|
||||
th:id="${block.data['id' + i] != null and !#strings.isEmpty(block.data['id' + i]) ? block.data['id' + i] : null}"
|
||||
th:class="${(block.data['width' + i] != null and block.data['width' + i] gt 0) ? ('col-lg-' + block.data['width' + i] + ' col-md-6 col-12 mb-4') : (block.data['cols'] == 1 ? 'col-12 mb-4' : (block.data['cols'] == 2 ? 'col-md-6 col-12 mb-4' : (block.data['cols'] == 3 ? 'col-lg-4 col-md-6 col-12 mb-4' : (block.data['cols'] == 4 ? 'col-lg-3 col-md-6 col-12 mb-4' : 'col-lg col-md-6 col-12 mb-4'))))}"
|
||||
th:classappend="${block.data['class' + i] != null and !#strings.isEmpty(block.data['class' + i]) ? block.data['class' + i] : ''}"
|
||||
th:data-custom-attrs="${block.data['attr' + i] != null and !#strings.isEmpty(block.data['attr' + i]) ? block.data['attr' + i] : null}"
|
||||
>
|
||||
<div th:replace=":: renderCell(type=${block.data['type' + i]}, i=${i}, blockData=${block.data})"></div>
|
||||
</div>
|
||||
@@ -369,7 +371,8 @@
|
||||
<!-- 16. Flex Layout Block -->
|
||||
<th:block th:if="${block['type'] == 'flex'}">
|
||||
<div th:id="${block.data['globalId'] != null and !#strings.isEmpty(block.data['globalId']) ? block.data['globalId'] : null}"
|
||||
th:class="${block.data['globalClass'] != null and !#strings.isEmpty(block.data['globalClass']) ? block.data['globalClass'] : null}">
|
||||
th:class="${block.data['globalClass'] != null and !#strings.isEmpty(block.data['globalClass']) ? block.data['globalClass'] : null}"
|
||||
th:data-custom-attrs="${block.data['globalAttributes'] != null and !#strings.isEmpty(block.data['globalAttributes']) ? block.data['globalAttributes'] : (block.data['attributes'] != null and !#strings.isEmpty(block.data['attributes']) ? block.data['attributes'] : null)}">
|
||||
<div class="container py-4">
|
||||
<div
|
||||
style="display: flex; flex-wrap: wrap;"
|
||||
@@ -380,6 +383,7 @@
|
||||
th:id="${block.data['id' + i] != null and !#strings.isEmpty(block.data['id' + i]) ? block.data['id' + i] : null}"
|
||||
th:class="${(block.data['width' + i] != null and block.data['width' + i] gt 0) ? ('col-lg-' + block.data['width' + i] + ' col-md-6 col-12 mb-4') : (block.data['cols'] == 1 ? 'col-12 mb-4' : (block.data['cols'] == 2 ? 'col-md-6 col-12 mb-4' : (block.data['cols'] == 3 ? 'col-lg-4 col-md-6 col-12 mb-4' : (block.data['cols'] == 4 ? 'col-lg-3 col-md-6 col-12 mb-4' : 'col-lg col-md-6 col-12 mb-4'))))}"
|
||||
th:classappend="${block.data['class' + i] != null and !#strings.isEmpty(block.data['class' + i]) ? block.data['class' + i] : ''}"
|
||||
th:data-custom-attrs="${block.data['attr' + i] != null and !#strings.isEmpty(block.data['attr' + i]) ? block.data['attr' + i] : null}"
|
||||
>
|
||||
<div th:replace=":: renderCell(type=${block.data['type' + i]}, i=${i}, blockData=${block.data})"></div>
|
||||
</div>
|
||||
@@ -392,12 +396,14 @@
|
||||
<!-- 17. Dedicated Hover Cards Block -->
|
||||
<th:block th:if="${block['type'] == 'hovercard' or block['type'] == 'hover-card' or block['type'] == 'hoverCard'}">
|
||||
<div th:id="${block.data['globalId'] != null and !#strings.isEmpty(block.data['globalId']) ? block.data['globalId'] : null}"
|
||||
th:class="${(block.data['styleVariant'] == 'v2' or (block.data['globalClass'] != null and block.data['globalClass'].contains('v2'))) ? ('sis-hover-card-v2-section ' + (block.data['globalClass'] != null ? block.data['globalClass'] : '')) : ('sis-hover-card-section ' + (block.data['globalClass'] != null ? block.data['globalClass'] : ''))}">
|
||||
th:class="${(block.data['styleVariant'] == 'v2' or (block.data['globalClass'] != null and block.data['globalClass'].contains('v2'))) ? ('sis-hover-card-v2-section ' + (block.data['globalClass'] != null ? block.data['globalClass'] : '')) : ('sis-hover-card-section ' + (block.data['globalClass'] != null ? block.data['globalClass'] : ''))}"
|
||||
th:data-custom-attrs="${block.data['globalAttributes'] != null and !#strings.isEmpty(block.data['globalAttributes']) ? block.data['globalAttributes'] : (block.data['attributes'] != null and !#strings.isEmpty(block.data['attributes']) ? block.data['attributes'] : null)}">
|
||||
<div class="container py-4">
|
||||
<div class="row align-items-center">
|
||||
<th:block th:each="item, iterStat : ${block.data['items']}">
|
||||
<div th:class="${block.data['cols'] == 1 ? 'col-12 mb-4' : (block.data['cols'] == 2 ? 'col-md-6 col-12 mb-4' : (block.data['cols'] == 3 ? 'col-lg-4 col-md-6 col-12 mb-4' : (block.data['cols'] == 6 ? 'col-lg-2 col-md-4 col-6 mb-4' : 'col-lg-3 col-md-6 col-12 mb-4')))}">
|
||||
<div th:class="${(block.data['styleVariant'] == 'v2' or (block.data['globalClass'] != null and block.data['globalClass'].contains('v2'))) ? ('sis-hover-card sis-hover-card-v2 ' + ((item['active'] == true or (item['active'] == null and iterStat.first)) ? 'active' : '')) : ('sis-hover-card ' + ((item['active'] == true or (item['active'] == null and iterStat.first)) ? 'active' : ''))}">
|
||||
<div th:class="${(block.data['styleVariant'] == 'v2' or (block.data['globalClass'] != null and block.data['globalClass'].contains('v2'))) ? ('sis-hover-card sis-hover-card-v2 ' + ((item['active'] == true or (item['active'] == null and iterStat.first)) ? 'active' : '')) : ('sis-hover-card ' + ((item['active'] == true or (item['active'] == null and iterStat.first)) ? 'active' : ''))}"
|
||||
th:data-custom-attrs="${item['attributes'] != null and !#strings.isEmpty(item['attributes']) ? item['attributes'] : null}">
|
||||
<div class="w-full flex flex-col items-center justify-center transition-all duration-500">
|
||||
<div class="sis-hover-card__icon" th:if="${item['imageUrl'] != null and !#strings.isEmpty(item['imageUrl'])}">
|
||||
<img th:src="${item['imageUrl']}" class="sis-hover-card__img-main" th:alt="${item['title']}" />
|
||||
@@ -692,17 +698,42 @@
|
||||
}
|
||||
});
|
||||
|
||||
// Interactive Hover Cards — Mouseenter transfers active class to hovered card
|
||||
document.querySelectorAll('.sis-hover-card').forEach(function (card) {
|
||||
card.addEventListener('mouseenter', function () {
|
||||
var parentRow = card.closest('.row');
|
||||
// Interactive Hover Cards — Mouseover event delegation to apply active class dynamically
|
||||
document.addEventListener('mouseover', function (e) {
|
||||
var card = e.target.closest('.sis-hover-card, .sis-hover-card-v2');
|
||||
if (card && !card.classList.contains('active')) {
|
||||
var parentRow = card.closest('.row') || card.parentElement;
|
||||
if (parentRow) {
|
||||
parentRow.querySelectorAll('.sis-hover-card').forEach(function (c) {
|
||||
parentRow.querySelectorAll('.sis-hover-card, .sis-hover-card-v2').forEach(function (c) {
|
||||
c.classList.remove('active');
|
||||
});
|
||||
}
|
||||
card.classList.add('active');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Apply Custom Attributes (e.g. data-aos="fade-up" style="background:#fff") dynamically
|
||||
document.querySelectorAll('[data-custom-attrs]').forEach(function (el) {
|
||||
var attrStr = el.getAttribute('data-custom-attrs');
|
||||
if (attrStr && attrStr.trim() !== '') {
|
||||
var tempDiv = document.createElement('div');
|
||||
tempDiv.innerHTML = '<div ' + attrStr + '></div>';
|
||||
var tempEl = tempDiv.firstElementChild;
|
||||
if (tempEl) {
|
||||
Array.from(tempEl.attributes).forEach(function (attr) {
|
||||
if (attr.name === 'class') {
|
||||
attr.value.split(/\s+/).filter(Boolean).forEach(function (c) {
|
||||
el.classList.add(c);
|
||||
});
|
||||
} else if (attr.name === 'style') {
|
||||
el.style.cssText += ';' + attr.value;
|
||||
} else {
|
||||
el.setAttribute(attr.name, attr.value);
|
||||
}
|
||||
});
|
||||
}
|
||||
el.removeAttribute('data-custom-attrs');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user