Created
June 21, 2018 17:42
-
-
Save acdha/10fe15b1486e12875f9104cd30ab3bb4 to your computer and use it in GitHub Desktop.
WDL Homepage Carousel: minimal source extraction
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div id="featured-items-container" class="well"> | |
<div id="featured-items" class="multi-carousel" data-json-url="{% url 'featured-items-json' %}"> | |
<ul class="items list-unstyled list-inline"> | |
{% for wdl_id, thumbnail_ts, title in featured_items|slice:":5" %} | |
<li class="item" data-wdl-id="{{ wdl_id|unlocalize }}"> | |
<a href="{% url 'item-detail' wdl_id=wdl_id %}" title="{{ title }}"> | |
<img class="img-rounded" width="308" height="255" src="{% media_url 'item-thumbnail' wdl_id=wdl_id height=255 width=308 timestamp=thumbnail_ts %}" alt="{{ title }}"> | |
<span class="caption">{{ title }}</span> | |
</a> | |
</li> | |
{% endfor %} | |
</ul> | |
{% for wdl_id, thumbnail_ts, title in featured_items|slice:"5:" %} | |
<span class="pending-item" data-wdl-id="{{ wdl_id|unlocalize }}" data-url="{% url 'item-detail' wdl_id=wdl_id %}" data-title="{{ title }}" data-thumbnail="{% media_url 'item-thumbnail' wdl_id=wdl_id height=255 width=308 timestamp=thumbnail_ts %}"></span> | |
{% endfor %} | |
<a hidden class="left carousel-control" href="#featured-items" data-slide="prev"> | |
<span class="fa fa-lg fa-chevron-left"></span> | |
</a> | |
<a hidden class="right carousel-control" href="#featured-items" data-slide="next"> | |
<span class="fa fa-lg fa-chevron-right"></span> | |
</a> | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function($) { | |
'use strict'; | |
if (!$(document.body).hasClass('homepage')) { | |
return; | |
} | |
var featuredItemContainer = document.getElementById('featured-items'), | |
featuredItems = featuredItemContainer.querySelector('.items'); | |
// Remove all child nodes which aren't display items: | |
for (var i = 0; i < featuredItems.childNodes.length; i++) { | |
var n = featuredItems.childNodes[i]; | |
if (n.nodeType != 1 || n.className.indexOf('item') < 0) { | |
featuredItems.removeChild(n); | |
} | |
} | |
var $featuredItemContainer = $(featuredItemContainer); | |
$featuredItemContainer.on('click', '.carousel-control', function() { | |
if (this.className.indexOf('left') > -1) { | |
featuredItems.insertBefore(featuredItems.lastElementChild, featuredItems.firstElementChild); | |
} else { | |
featuredItems.insertBefore(featuredItems.firstElementChild, null); | |
} | |
return false; | |
}); | |
if (featuredItemContainer.addEventListener) { | |
featuredItemContainer.addEventListener( | |
'wheel', | |
$.throttle(250, true, function(evt) { | |
var deltaX = evt.deltaX, | |
deltaY = evt.deltaY; | |
if (Math.abs(deltaY) > Math.abs(deltaX)) { | |
return; | |
} | |
if (deltaX > 0) { | |
$('.carousel-control.right').trigger('click'); | |
} else { | |
$('.carousel-control.left').trigger('click'); | |
} | |
evt.preventDefault(); | |
return false; | |
}), | |
{passive: true} | |
); | |
} | |
$(window).on('keydown', function(evt) { | |
switch (evt.which) { | |
case 37: // left arrow | |
$('.carousel-control.left').trigger('click'); | |
return false; | |
case 39: // right arrow | |
$('.carousel-control.right').trigger('click'); | |
return false; | |
} | |
}); | |
$featuredItemContainer.find('.carousel-control').removeAttr('hidden'); | |
var pendingItems = [], | |
$itemTemplate = $featuredItemContainer.find('.item[data-wdl-id]').first(), | |
existingItems = $featuredItemContainer.find('.item[data-wdl-id]').map(function(idx, elem) { | |
return parseInt($(elem).data('wdl-id'), 10); | |
}).get(); | |
function animateCarousel() { | |
if (featuredItemContainer.querySelector(':hover') !== null) { | |
return; | |
} | |
var newFirstItem; | |
if (pendingItems.length > 0) { | |
newFirstItem = pendingItems.pop(); | |
} else { | |
newFirstItem = featuredItems.lastElementChild; | |
} | |
featuredItems.insertBefore(newFirstItem, featuredItems.firstElementChild); | |
} | |
window.setInterval(animateCarousel, 8000); | |
function loadMoreFeaturedItems() { | |
var jsonURL = $featuredItemContainer.data('json-url'); | |
if (!jsonURL) { | |
return; | |
} | |
$.getJSON(jsonURL, { | |
count: existingItems.length * 3 | |
}).success(function(items) { | |
// Add new items to the queue in random order: | |
WDL.arrayShuffle(items); | |
for (var i = 0; i < items.length; i++) { | |
var item = items[i]; | |
addFeaturedItem(item['wdl-id'], item.url, item.thumbnail, item.title); | |
} | |
}); | |
} | |
function addFeaturedItem(itemId, itemUrl, thumbnailUrl, title) { | |
if (existingItems.indexOf(itemId) >= 0) { | |
return; | |
} | |
var $item = $itemTemplate.clone(); | |
$item.data('wdl-id', itemId).attr('data-wdl-id', itemId); | |
$item.find('a').attr({ | |
href: itemUrl, | |
title: title | |
}); | |
// Note: seemingly-useless src='' toggle is required for IE8 support: | |
$item.find('img').attr('src', '').attr({ | |
src: thumbnailUrl, | |
alt: title | |
}); | |
$item.find('.caption').text(title); | |
// Delay adding the item to the list until the thumbnail has loaded: | |
$item.find('img').on('load', function() { | |
pendingItems.push($item.get(0)); | |
}); | |
} | |
$featuredItemContainer.find('.pending-item').each(function(idx, elem) { | |
var $elem = $(elem), | |
data = $elem.data(); | |
addFeaturedItem(data.wdlId, data.url, data.thumbnail, data.title); | |
$elem.remove(); | |
}); | |
$(window).on('load', function() { | |
window.setTimeout(loadMoreFeaturedItems, 20 * 1000); | |
}); | |
})(jQuery); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#featured-items-container { | |
padding-right: 8px; | |
padding-bottom: 2px; | |
padding-left: 8px; | |
} | |
#featured-items { | |
position: relative; | |
height: $featured-items-height; | |
.items { | |
position: relative; | |
overflow: hidden; | |
height: 100%; | |
margin: 0 1.5em; | |
} | |
.item { | |
$image-border-width: 1px; | |
@include transition(all 0.4s ease-out); | |
// Attempt to request hardware acceleration: | |
@include backface-visibility(hidden); | |
position: absolute; | |
top: 0; | |
left: 0; | |
width: #{308px + 2 * $image-border-width}; | |
padding: 0; | |
will-change: transform; | |
&:lang(ar) { | |
right: 0; | |
left: auto; | |
} | |
&:first-child { | |
padding-left: 0; | |
} | |
// We'll slide all of the items off the screen and backfill the first few to be visible: | |
@include translateX(900%); | |
&:nth-child(1) { @include translateX(0%); } | |
&:nth-child(2) { @include translateX(100%); } | |
&:nth-child(3) { @include translateX(200%); } | |
&:nth-child(4) { @include translateX(300%); } | |
&:nth-child(5) { @include translateX(400%); } | |
&:nth-child(6) { @include translateX(500%); } | |
&:nth-child(7) { @include translateX(600%); } | |
&:nth-child(8) { @include translateX(700%); } | |
&:nth-child(9) { @include translateX(800%); } | |
&:lang(ar) { | |
@include translateX(-900%); | |
&:nth-child(1) { @include translateX(0%); } | |
&:nth-child(2) { @include translateX(-100%); } | |
&:nth-child(3) { @include translateX(-200%); } | |
&:nth-child(4) { @include translateX(-300%); } | |
&:nth-child(5) { @include translateX(-400%); } | |
&:nth-child(6) { @include translateX(-500%); } | |
&:nth-child(7) { @include translateX(-600%); } | |
&:nth-child(8) { @include translateX(-700%); } | |
&:nth-child(9) { @include translateX(-800%); } | |
} | |
a { | |
display: block; | |
color: $text-color; | |
&:hover img { | |
border-color: $btn-default-border; | |
} | |
img { | |
display: block; // Prevent inline display of errored images in Firefox | |
width: #{308px + 2 * $image-border-width}; | |
height: #{255px + 2 * $image-border-width}; | |
border: solid transparent $image-border-width; | |
} | |
.caption { | |
display: block; | |
overflow: hidden; | |
max-width: 96%; | |
margin: auto; | |
text-align: center; | |
white-space: nowrap; | |
text-overflow: ellipsis; | |
font-weight: bold; | |
} | |
} | |
} | |
.carousel-control { | |
width: 25px; | |
color: #000; | |
background: none !important; | |
filter: none; | |
&:hover { | |
@include opacity(1); | |
color: $btn-primary-bg; | |
} | |
.fa { | |
position: absolute; | |
top: floor(($featured-items-height / 2) - ($line-height-computed / 2)); | |
top: calc(50% - #{$line-height-computed / 2}); | |
} | |
&.left .fa { | |
left: 0; | |
// Intentionally override this because bootstrap-rtl already flips the element: | |
&.fa-chevron-left:lang(ar)::before { | |
content: $fa-var-chevron-left; | |
} | |
} | |
&.right .fa { | |
right: 0; | |
// Intentionally override this because bootstrap-rtl already flips the element: | |
&.fa-chevron-right:lang(ar)::before { | |
content: $fa-var-chevron-right; | |
} | |
} | |
} | |
.no-csstransforms & { | |
// Since IE8 supports neither CSS transforms nor nth-child selectors, we'll just use a | |
// basic inline list display: | |
.items { | |
text-align: center; | |
} | |
.item { | |
position: relative; | |
display: inline-block; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment