<section class="section logo-module ">
</section>
{% if (data.isGrid) %}
{% set sectionContent %}
<div class="grid">
{% for logo in data.logos %}
<div class="grid__col grid__col--xs-2 grid__col--sm-1 grid__col--lg-4">
<div class="logo-module__logo-wrapper">
{% include '@image' with { data: logo|srcset('280x155'), class: 'logo-module__logo', noCaption: true } %}
{% if logo.customPermalink %}
<a class="logo-module__link" href="{{ logo.customPermalink }}" aria-title="{{ logo.title }}" target="_blank"></a>
{% endif %}
</div>
</div>
{% endfor %}
</div>
{% endset %}
{% else %}
{% set sectionWideContent %}
<div class="logo-module__scroller-wrapper">
<div class="logo-module__scroller">
{% for logo in data.logos %}
<div class="logo-module__logo-wrapper">
{% include '@image' with { data: logo|srcset('280x155'), class: 'logo-module__logo', noCaption: true } %}
{% if logo.customPermalink %}
<a class="logo-module__link" href="{{ logo.customPermalink }}" aria-title="{{ logo.title }}" target="_blank"></a>
{% endif %}
</div>
{% endfor %}
</div>
</div>
{% endset %}
{% endif %}
{% include '@section' with { class: 'logo-module' } %}
{
"language": "en-US",
"data": {
"logos": [
true,
true,
true,
true,
true,
true
]
}
}
.logo-module__logo {
height: 48px;
.image__img {
height: 100%;
width: auto;
margin: 0 auto;
}
}
.logo-module__logo-wrapper {
position: relative;
padding: 12px 24px;
background-color: $L-background-medium;
@include bp(md-min) {
padding: 24px 42px;
}
}
.logo-module__scroller-wrapper {
width: 100%;
overflow-x: auto;
overflow-style: none;
scrollbar-width: none;
&::-webkit-scrollbar {
display: none;
}
&.is-scrolling {
display: flex;
}
}
.logo-module__scroller {
display: flex;
justify-content: center;
& > * + * {
margin-left: 24px;
}
& + & {
margin-left: 24px;
}
.logo-module__scroller-wrapper.is-scrolling & {
justify-content: flex-start;
}
}
.logo-module__link {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
import { debounce } from 'throttle-debounce';
import Component from '../../components/component/component';
import Helpers from '../../components/helpers/helpers';
import './logo-module.scss';
export default class LogoModule extends Component {
static initSelector: string = '.logo-module__scroller-wrapper';
readonly scroller: JQuery;
readonly scrollTime: number;
readonly debounceUpdate: debounce<() => void>;
readonly debounceLoad: debounce<() => void>;
readonly debounceScrollForward: debounce<() => void>;
private scrollNeed: number;
private duplicate: JQuery;
constructor(element: HTMLElement) {
super(element);
this.scroller = this.element.find('.logo-module__scroller');
this.scrollTime = (this.element.find('.logo-module__logo-wrapper').length * 750) * 2;
this.scrollForward = this.scrollForward.bind(this);
this.pauseScrolling = this.pauseScrolling.bind(this);
this.maybeStartScrolling = this.maybeStartScrolling.bind(this);
this.debounceUpdate = debounce(500, this.maybeStartScrolling);
this.debounceLoad = debounce(500, this.maybeStartScrolling);
this.debounceScrollForward = debounce(500, this.scrollForward);
$(window).on('resize', this.debounceUpdate);
$(window).on('scroll', this.debounceUpdate);
this.element.on('mouseenter', this.pauseScrolling);
this.element.on('mouseleave', this.maybeStartScrolling);
this.element.find('img').on('load', this.debounceLoad);
this.maybeStartScrolling();
}
stopScrolling(): void {
this.element.stop();
}
scrollForward(): void {
this.scrollNeed = (this.element[0].scrollWidth / 2) + 12; // +12px is half of the margin between two scrollers
const currentScroll: number = this.element.scrollLeft();
const timeMultiplier: number = (this.scrollNeed - currentScroll) / this.scrollNeed;
this.element.stop();
this.element.animate({ scrollLeft: this.scrollNeed }, this.scrollTime * timeMultiplier, 'linear', this.scrollBack.bind(this));
}
scrollBack(): void {
this.element.scrollLeft(0);
this.debounceScrollForward();
}
createDuplicateElements(): void {
this.element.addClass('is-scrolling');
if (!this.duplicate) {
this.duplicate = this.scroller.clone();
const images: JQuery = this.duplicate.find('.lazyautosizes');
images.removeClass('.lazyloading');
images.removeClass('.lazyautosizes');
images.addClass('lazyload');
images.addClass('lazypreload');
this.duplicate.appendTo(this.element);
this.duplicate.find('img').on('load', this.debounceLoad);
}
}
clearDuplicateElements(): void {
this.element.removeClass('is-scrolling');
if (this.duplicate) {
this.duplicate.detach();
this.duplicate = null;
}
}
pauseScrolling(): void {
this.element.stop();
}
get isOverflowing(): boolean {
return this.scroller[0].scrollWidth > this.element.innerWidth();
}
maybeStartScrolling(): void {
if (this.element.find('img').length > 0) {
if (this.isOverflowing) {
this.createDuplicateElements();
if (Helpers.isOnScreen(this.element)) {
this.debounceScrollForward();
} else {
this.pauseScrolling();
}
} else {
this.stopScrolling();
this.clearDuplicateElements();
}
}
}
}
<section class="section logo-module ">
<div class="grid">
<div class="grid__col grid__col--xs-2 grid__col--sm-1 grid__col--lg-4">
<div class="logo-module__logo-wrapper">
<figure class="image logo-module__logo">
<img loading="lazy" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20280%20155%22%3E%3C%2Fsvg%3E" data-srcset="//via.placeholder.com/280x155 280w, //via.placeholder.com/560x310 560w, //via.placeholder.com/840x465 840w, //via.placeholder.com/1120x620 1120w, //via.placeholder.com/1400x775 1400w, //via.placeholder.com/1680x930 1680w, //via.placeholder.com/1960x1085 1960w, //via.placeholder.com/2240x1240 2240w" data-sizes="auto" alt="" class="image__img lazyload">
</figure>
</div>
</div>
<div class="grid__col grid__col--xs-2 grid__col--sm-1 grid__col--lg-4">
<div class="logo-module__logo-wrapper">
<figure class="image logo-module__logo">
<img loading="lazy" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20280%20155%22%3E%3C%2Fsvg%3E" data-srcset="//via.placeholder.com/280x155 280w, //via.placeholder.com/560x310 560w, //via.placeholder.com/840x465 840w, //via.placeholder.com/1120x620 1120w, //via.placeholder.com/1400x775 1400w, //via.placeholder.com/1680x930 1680w, //via.placeholder.com/1960x1085 1960w, //via.placeholder.com/2240x1240 2240w" data-sizes="auto" alt="" class="image__img lazyload">
</figure>
</div>
</div>
<div class="grid__col grid__col--xs-2 grid__col--sm-1 grid__col--lg-4">
<div class="logo-module__logo-wrapper">
<figure class="image logo-module__logo">
<img loading="lazy" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20280%20155%22%3E%3C%2Fsvg%3E" data-srcset="//via.placeholder.com/280x155 280w, //via.placeholder.com/560x310 560w, //via.placeholder.com/840x465 840w, //via.placeholder.com/1120x620 1120w, //via.placeholder.com/1400x775 1400w, //via.placeholder.com/1680x930 1680w, //via.placeholder.com/1960x1085 1960w, //via.placeholder.com/2240x1240 2240w" data-sizes="auto" alt="" class="image__img lazyload">
</figure>
</div>
</div>
<div class="grid__col grid__col--xs-2 grid__col--sm-1 grid__col--lg-4">
<div class="logo-module__logo-wrapper">
<figure class="image logo-module__logo">
<img loading="lazy" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20280%20155%22%3E%3C%2Fsvg%3E" data-srcset="//via.placeholder.com/280x155 280w, //via.placeholder.com/560x310 560w, //via.placeholder.com/840x465 840w, //via.placeholder.com/1120x620 1120w, //via.placeholder.com/1400x775 1400w, //via.placeholder.com/1680x930 1680w, //via.placeholder.com/1960x1085 1960w, //via.placeholder.com/2240x1240 2240w" data-sizes="auto" alt="" class="image__img lazyload">
</figure>
</div>
</div>
<div class="grid__col grid__col--xs-2 grid__col--sm-1 grid__col--lg-4">
<div class="logo-module__logo-wrapper">
<figure class="image logo-module__logo">
<img loading="lazy" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20280%20155%22%3E%3C%2Fsvg%3E" data-srcset="//via.placeholder.com/280x155 280w, //via.placeholder.com/560x310 560w, //via.placeholder.com/840x465 840w, //via.placeholder.com/1120x620 1120w, //via.placeholder.com/1400x775 1400w, //via.placeholder.com/1680x930 1680w, //via.placeholder.com/1960x1085 1960w, //via.placeholder.com/2240x1240 2240w" data-sizes="auto" alt="" class="image__img lazyload">
</figure>
</div>
</div>
<div class="grid__col grid__col--xs-2 grid__col--sm-1 grid__col--lg-4">
<div class="logo-module__logo-wrapper">
<figure class="image logo-module__logo">
<img loading="lazy" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20280%20155%22%3E%3C%2Fsvg%3E" data-srcset="//via.placeholder.com/280x155 280w, //via.placeholder.com/560x310 560w, //via.placeholder.com/840x465 840w, //via.placeholder.com/1120x620 1120w, //via.placeholder.com/1400x775 1400w, //via.placeholder.com/1680x930 1680w, //via.placeholder.com/1960x1085 1960w, //via.placeholder.com/2240x1240 2240w" data-sizes="auto" alt="" class="image__img lazyload">
</figure>
</div>
</div>
</div>
</section>
{% if (data.isGrid) %}
{% set sectionContent %}
<div class="grid">
{% for logo in data.logos %}
<div class="grid__col grid__col--xs-2 grid__col--sm-1 grid__col--lg-4">
<div class="logo-module__logo-wrapper">
{% include '@image' with { data: logo|srcset('280x155'), class: 'logo-module__logo', noCaption: true } %}
{% if logo.customPermalink %}
<a class="logo-module__link" href="{{ logo.customPermalink }}" aria-title="{{ logo.title }}" target="_blank"></a>
{% endif %}
</div>
</div>
{% endfor %}
</div>
{% endset %}
{% else %}
{% set sectionWideContent %}
<div class="logo-module__scroller-wrapper">
<div class="logo-module__scroller">
{% for logo in data.logos %}
<div class="logo-module__logo-wrapper">
{% include '@image' with { data: logo|srcset('280x155'), class: 'logo-module__logo', noCaption: true } %}
{% if logo.customPermalink %}
<a class="logo-module__link" href="{{ logo.customPermalink }}" aria-title="{{ logo.title }}" target="_blank"></a>
{% endif %}
</div>
{% endfor %}
</div>
</div>
{% endset %}
{% endif %}
{% include '@section' with { class: 'logo-module' } %}
{
"language": "en-US",
"data": {
"logos": [
true,
true,
true,
true,
true,
true
],
"isGrid": true
}
}
.logo-module__logo {
height: 48px;
.image__img {
height: 100%;
width: auto;
margin: 0 auto;
}
}
.logo-module__logo-wrapper {
position: relative;
padding: 12px 24px;
background-color: $L-background-medium;
@include bp(md-min) {
padding: 24px 42px;
}
}
.logo-module__scroller-wrapper {
width: 100%;
overflow-x: auto;
overflow-style: none;
scrollbar-width: none;
&::-webkit-scrollbar {
display: none;
}
&.is-scrolling {
display: flex;
}
}
.logo-module__scroller {
display: flex;
justify-content: center;
& > * + * {
margin-left: 24px;
}
& + & {
margin-left: 24px;
}
.logo-module__scroller-wrapper.is-scrolling & {
justify-content: flex-start;
}
}
.logo-module__link {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
import { debounce } from 'throttle-debounce';
import Component from '../../components/component/component';
import Helpers from '../../components/helpers/helpers';
import './logo-module.scss';
export default class LogoModule extends Component {
static initSelector: string = '.logo-module__scroller-wrapper';
readonly scroller: JQuery;
readonly scrollTime: number;
readonly debounceUpdate: debounce<() => void>;
readonly debounceLoad: debounce<() => void>;
readonly debounceScrollForward: debounce<() => void>;
private scrollNeed: number;
private duplicate: JQuery;
constructor(element: HTMLElement) {
super(element);
this.scroller = this.element.find('.logo-module__scroller');
this.scrollTime = (this.element.find('.logo-module__logo-wrapper').length * 750) * 2;
this.scrollForward = this.scrollForward.bind(this);
this.pauseScrolling = this.pauseScrolling.bind(this);
this.maybeStartScrolling = this.maybeStartScrolling.bind(this);
this.debounceUpdate = debounce(500, this.maybeStartScrolling);
this.debounceLoad = debounce(500, this.maybeStartScrolling);
this.debounceScrollForward = debounce(500, this.scrollForward);
$(window).on('resize', this.debounceUpdate);
$(window).on('scroll', this.debounceUpdate);
this.element.on('mouseenter', this.pauseScrolling);
this.element.on('mouseleave', this.maybeStartScrolling);
this.element.find('img').on('load', this.debounceLoad);
this.maybeStartScrolling();
}
stopScrolling(): void {
this.element.stop();
}
scrollForward(): void {
this.scrollNeed = (this.element[0].scrollWidth / 2) + 12; // +12px is half of the margin between two scrollers
const currentScroll: number = this.element.scrollLeft();
const timeMultiplier: number = (this.scrollNeed - currentScroll) / this.scrollNeed;
this.element.stop();
this.element.animate({ scrollLeft: this.scrollNeed }, this.scrollTime * timeMultiplier, 'linear', this.scrollBack.bind(this));
}
scrollBack(): void {
this.element.scrollLeft(0);
this.debounceScrollForward();
}
createDuplicateElements(): void {
this.element.addClass('is-scrolling');
if (!this.duplicate) {
this.duplicate = this.scroller.clone();
const images: JQuery = this.duplicate.find('.lazyautosizes');
images.removeClass('.lazyloading');
images.removeClass('.lazyautosizes');
images.addClass('lazyload');
images.addClass('lazypreload');
this.duplicate.appendTo(this.element);
this.duplicate.find('img').on('load', this.debounceLoad);
}
}
clearDuplicateElements(): void {
this.element.removeClass('is-scrolling');
if (this.duplicate) {
this.duplicate.detach();
this.duplicate = null;
}
}
pauseScrolling(): void {
this.element.stop();
}
get isOverflowing(): boolean {
return this.scroller[0].scrollWidth > this.element.innerWidth();
}
maybeStartScrolling(): void {
if (this.element.find('img').length > 0) {
if (this.isOverflowing) {
this.createDuplicateElements();
if (Helpers.isOnScreen(this.element)) {
this.debounceScrollForward();
} else {
this.pauseScrolling();
}
} else {
this.stopScrolling();
this.clearDuplicateElements();
}
}
}
}