History: PageBanner
Source of version: 2 (current)
Copy to clipboard
{HTML(wiki="0")}
<style>
#community-promotion-carousel {
--promotion-control-width: 2.75rem;
}
#community-promotion-carousel .carousel-control-prev,
#community-promotion-carousel .carousel-control-next {
width: var(--promotion-control-width);
}
#evoludata-promotion-panel {
background-color: var(--bs-body-bg);
color: var(--bs-body-color);
border-color: var(--bs-border-color);
box-sizing: border-box;
padding: .75rem 3.25rem;
}
#evoludata-promotion-layout {
display: flex;
align-items: center;
gap: 1.5rem;
width: 100%;
min-width: 0;
}
#evoludata-promotion-logo {
flex: 0 0 110px;
width: 110px;
height: 100px;
padding: .5rem;
}
#evoludata-promotion-logo img {
display: block;
width: 100%;
height: 100%;
object-fit: contain;
}
#evoludata-promotion-copy {
min-width: 0;
}
#evoludata-promotion-title {
margin: 0 0 .25rem;
font-size: clamp(1.25rem, 2.2vw, 1.6rem);
line-height: 1.1;
}
#evoludata-promotion-description {
margin: 0 0 .25rem;
font-size: .95rem;
line-height: 1.2;
}
#evoludata-promotion-products {
margin: 0 0 .35rem;
}
#evoludata-promotion-actions .btn {
padding: .25rem .6rem;
}
@media (max-width: 575.98px) {
#evoludata-promotion-panel {
padding: .75rem 2.75rem;
}
#evoludata-promotion-layout {
gap: .75rem;
}
#evoludata-promotion-logo {
flex-basis: 72px;
width: 72px;
height: 72px;
padding: .25rem;
}
#evoludata-promotion-title {
font-size: 1.05rem;
}
#evoludata-promotion-description,
#evoludata-promotion-products {
font-size: .78rem;
line-height: 1.15;
}
#evoludata-promotion-actions {
gap: .3rem !important;
}
#evoludata-promotion-actions .btn {
padding: .2rem .4rem;
font-size: .72rem;
}
}
@media (prefers-reduced-motion: reduce) {
#community-promotion-carousel .carousel-item {
transition: none !important;
}
}
</style>
<div
id="community-promotion-carousel"
class="carousel slide mb-3"
data-bs-ride="carousel"
data-bs-interval="8000"
data-bs-pause="hover"
role="region"
aria-roledescription="carousel"
aria-label="Upcoming event and EvoluData promotion"
>
<div class="carousel-inner" aria-live="polite">
<div
id="calendar-event-slide"
class="carousel-item active"
role="group"
aria-roledescription="slide"
aria-label="1 of 2"
>
{HTML}
{rss url="https://tiki.org/tiki-calendars_rss.php" max="1" date="1" desc="1" author="1" showtitle="1" ticker="1" sortBy="publication_date" sortOrder="ASC" tplWiki="rss_gabarit" refresh="360"}
{HTML(wiki="0")}
</div>
<div
id="evoludata-promotion-slide"
class="carousel-item"
role="group"
aria-roledescription="slide"
aria-label="2 of 2"
>
<section
id="evoludata-promotion-panel"
class="alert alert-light bg-white border overflow-hidden d-flex align-items-center"
aria-labelledby="evoludata-promotion-title"
>
<div id="evoludata-promotion-layout">
<a
id="evoludata-promotion-logo"
href="https://evoludata.com/?utm_source=dev-tiki&utm_medium=carousel&utm_campaign=open-source-sites"
target="_blank"
rel="noopener noreferrer"
class="d-flex align-items-center justify-content-center rounded bg-light"
aria-label="Visit EvoluData"
>
<img
src="https://evoludata.com/display22"
alt="EvoluData"
width="110"
height="100"
decoding="async"
>
</a>
<div
id="evoludata-promotion-copy"
class="flex-grow-1 text-start"
>
<h2
id="evoludata-promotion-title"
class="text-primary fw-bold"
>
Open Source solutions
</h2>
<p id="evoludata-promotion-description">
Custom development, consulting, and reliable support for critical Open Source platforms
</p>
<p
id="evoludata-promotion-products"
class="fw-semibold"
>
TikiWiki · Cypht · Dolibarr
</p>
<div
id="evoludata-promotion-actions"
class="d-flex flex-wrap gap-2"
>
<a
class="btn btn-primary"
href="https://evoludata.com/en/Solutions?utm_source=dev-tiki&utm_medium=carousel&utm_campaign=open-source-sites&utm_content=solutions"
target="_blank"
rel="noopener noreferrer"
>
Explore our solutions
</a>
<a
class="btn btn-outline-primary"
href="https://evoludata.com/en/Contact-Us?utm_source=dev-tiki&utm_medium=carousel&utm_campaign=open-source-sites&utm_content=contact"
target="_blank"
rel="noopener noreferrer"
>
Contact us
</a>
</div>
</div>
</div>
</section>
</div>
</div>
<button
class="carousel-control-prev"
type="button"
data-bs-target="#community-promotion-carousel"
data-bs-slide="prev"
aria-label="Previous slide"
>
<span
class="carousel-control-prev-icon btn btn-dark"
aria-hidden="true"
></span>
</button>
<button
class="carousel-control-next "
type="button"
data-bs-target="#community-promotion-carousel"
data-bs-slide="next"
aria-label="Next slide"
>
<span
class="carousel-control-next-icon btn btn-dark"
aria-hidden="true"
></span>
</button>
</div>
{HTML}
{JQ()}
var $scope = $('#calendar-event-slide').find(
'.upcoming-event-banner, .rsslist'
);
function extractCalItemId(url) {
if (!url) return null;
try {
url = decodeURIComponent(url);
} catch (e) {}
var match = url.match(
/(?:^|[?&])calitemId=([^&#]+)/i
);
return match ? match[1] : null;
}
$scope.find('a:not([target="_blank"])').each(function () {
var $link = $(this);
var href = $link.attr('href');
if (
!href
|| /tiki-calendar_export_ical\.php/i.test(href)
) {
return;
}
var id = extractCalItemId(href)
|| extractCalItemId(
$link.attr('data-href')
);
if (id) {
$link.attr(
'href',
'https://tiki.org/tiki-calendar_export_ical.php'
+ '?export=y&calendarItem='
+ encodeURIComponent(id)
);
}
});
$scope.find('a[target="_blank"]').each(function () {
var $link = $(this);
var href = $link.attr('href');
if (
!href
|| !/%3F|%3D|%26|%2F/i.test(href)
) {
return;
}
try {
$link.attr(
'href',
decodeURIComponent(href)
);
} catch (e) {}
});
var carousel = document.getElementById(
'community-promotion-carousel'
);
var inner = carousel
&& carousel.querySelector('.carousel-inner');
var eventSlide = document.getElementById(
'calendar-event-slide'
);
var promotionSlide = document.getElementById(
'evoludata-promotion-slide'
);
var promotion = document.getElementById(
'evoludata-promotion-panel'
);
var controls = carousel
&& carousel.querySelectorAll(
'.carousel-control-prev, .carousel-control-next'
);
var frame = 0;
function findEventCard(scope) {
return scope.querySelector(
'.upcoming-event-banner, .rsslist > .alert'
) || scope.firstElementChild;
}
function measureCard(card) {
if (!card) return null;
var height = Math.ceil(
card.getBoundingClientRect().height
);
if (!height) return null;
var style = window.getComputedStyle(card);
return {
card: height,
total: height
+ parseFloat(style.marginTop || 0)
+ parseFloat(style.marginBottom || 0)
};
}
function eventMeasurements() {
var card = findEventCard(eventSlide);
var measurements = measureCard(card);
if (measurements) {
return measurements;
}
var clone = eventSlide.cloneNode(true);
clone.removeAttribute('id');
clone.className = 'carousel-item active';
clone.setAttribute('aria-hidden', 'true');
$(clone).css({
position: 'absolute',
visibility: 'hidden',
pointerEvents: 'none',
display: 'block',
width: inner.clientWidth + 'px',
height: 'auto'
});
inner.appendChild(clone);
card = findEventCard(clone);
measurements = measureCard(card);
clone.remove();
return measurements;
}
function syncPromotionHeight() {
cancelAnimationFrame(frame);
frame = requestAnimationFrame(function () {
var measurements = eventMeasurements();
if (!measurements) {
return;
}
promotion.style.height =
measurements.card + 'px';
inner.style.height =
measurements.total + 'px';
});
}
if (
carousel
&& inner
&& eventSlide
&& promotionSlide
&& promotion
) {
if (!eventSlide.querySelector('.rssitem')) {
eventSlide.classList.remove('active');
promotionSlide.classList.add('active');
$(controls).addClass('d-none');
carousel.removeAttribute(
'data-bs-ride'
);
if (window.bootstrap) {
bootstrap.Carousel.getOrCreateInstance(
carousel,
{interval: false}
).pause();
}
} else {
$(window).on(
'load resize',
syncPromotionHeight
);
$(carousel).on(
'slide.bs.carousel slid.bs.carousel',
syncPromotionHeight
);
$(eventSlide).find('img').on(
'load',
syncPromotionHeight
);
if (window.ResizeObserver) {
new ResizeObserver(
syncPromotionHeight
).observe(
findEventCard(eventSlide)
);
}
if (
document.fonts
&& document.fonts.ready
) {
document.fonts.ready.then(
syncPromotionHeight
);
}
if (
window.matchMedia(
'(prefers-reduced-motion: reduce)'
).matches
&& window.bootstrap
) {
bootstrap.Carousel.getOrCreateInstance(
carousel,
{interval: false}
).pause();
}
syncPromotionHeight();
}
}
{JQ}