Skip to content

Instantly share code, notes, and snippets.

@philwilliammee
Created March 1, 2019 18:06
Show Gist options
  • Save philwilliammee/a058bb8851922bc3440e4b864315efe5 to your computer and use it in GitHub Desktop.
Save philwilliammee/a058bb8851922bc3440e4b864315efe5 to your computer and use it in GitHub Desktop.
/* CWD Card Slider (ama39, last update: 9/6/18)
Cutom Card slider to use with timeline (psw58, updated 3/1/19)
-
- Accessibility Notes:
- --
- Future Plans:
- -- Possible improvements in focus detection, ensuring that items are optimally visible when accessed by keyboard or screen reader
- -- Free Scroll Mode (disabling screen-by-screen locking, to allow the element to be freely scrolled with mouse or touch gesture)
------------------------------------------------------------------------- */
jQuery(document).ready(function ($) {
// Apply touch-action polyfill (requires pep.js)
$('.card-slider .cards').attr('touch-action', 'pan-y');
// Set-up markup
$('.card-slider').each(function () {
// psw58 define timeline variable
var doTimeline = $(this).hasClass('card-slider-timeline'); //psw
$(this).addClass('scripted'); // This tells the CSS that JavaScript is present, so we can safely override natural overflow scrolling
// detect prefs
if ($(this).hasClass('side-padding')) {
$(this).wrap('<div class="card-slider-padded"></div>')
}
// detect viewer width
var viewer = $(this);
var viewer_band = $(this).find('.cards').first();
var card_count = $(this).find('.card').length;
var card_width = $(this).find('.card').first().outerWidth();
var viewer_width = $(viewer_band).width();
var viewer_scroll_limit = $(viewer_band)[0].scrollWidth - viewer_width;
var cards_per_screen = Math.round(viewer_width / card_width);
var scroll_target = 0;
$(window).resize(function () {
viewer_width = $(viewer_band).width();
viewer_scroll_limit = $(viewer_band)[0].scrollWidth - viewer_width;
card_width = $(viewer_band).find('.card').first().outerWidth();
cards_per_screen = Math.round(viewer_width / card_width);
// recalibrate
var current_first_card = Math.round($(viewer_band).scrollLeft() / card_width);
if (current_first_card % cards_per_screen != 0) { // lock to slide set
current_first_card = cards_per_screen * (Math.floor(current_first_card / card_count) * cards_per_screen);
}
scroll_target = current_first_card * card_width;
if (scroll_target < 10) {
scroll_target = 0;
} else if (scroll_target > viewer_scroll_limit || viewer_scroll_limit - scroll_target < 10) {
scroll_target = viewer_scroll_limit;
}
$(viewer_band).scrollLeft(scroll_target);
// refresh buttons
updateButtons(viewer, viewer_scroll_limit, scroll_target);
// ********************** psw58 **************************/
if (doTimeline && timeline != 'undefined') {
timeline.renderButtons( cards_per_screen );
}
// ***************** end psw58 **************************/
});
// build buttons
var nextprev_html = '';
if (card_count > 1) {
$(viewer_band).before('<div class="pips"></div>').wrap('<div class="mask"></div>');
nextprev_html = '<div class="next-prev"><button class="prev"><span class="sr-only">Previous Slide Set</span><span class="fa fa-angle-left"></span></button><button class="next"><span class="sr-only">Next Slide Set</span><span class="fa fa-angle-right"></span></button></div>';
$(this).append(nextprev_html);
$(this).find('.next, .prev').click(function (e) {
if ($(this).hasClass('prev')) {
scroll_target -= viewer_width;
} else {
scroll_target += viewer_width;
}
if (scroll_target < 10) {
scroll_target = 0;
} else if (scroll_target > viewer_scroll_limit || viewer_scroll_limit - scroll_target < 10) {
scroll_target = viewer_scroll_limit;
}
updateButtons(viewer, viewer_scroll_limit, scroll_target); // refresh buttons
$(viewer_band).stop().animate({
scrollLeft: scroll_target
}, 500, 'easeOutQuad');
});
}
updateButtons(viewer, viewer_scroll_limit, scroll_target); // refresh buttons
// ********************* start psw58 ***************************** */
var timeline;
if (doTimeline && Timeline != 'undefined') {
//requires Timeline
timeline = new Timeline( viewer, viewer_band, cards_per_screen, jQuery );
}else{
console.log('timeline not found');
}
// ************************ end psw58 ***************************** */
});
// Wesley Swipes (Touch Screen Logic)
// -- if pep.js is loaded, vertical page scroll will be locked after horizontal panning begins
$('.card-slider .cards').on('touchstart', function (e) {
var this_viewer_band = $(this);
var drag_detected = false;
var start_x = e.originalEvent.touches[0].pageX;
var start_y = e.originalEvent.touches[0].pageY;
var start_drag = $(this).scrollLeft();
$(this).on('touchmove', function (e) {
// If the swipe intent seems more horizontal than vertical...
if (Math.abs(e.originalEvent.touches[0].pageX - start_x) > (Math.abs(e.originalEvent.touches[0].pageY - start_y))) {
drag_detected = true;
}
// ...start dragging, synced to any further touchmoves
if (drag_detected) {
$(this_viewer_band).scrollLeft(start_drag + (start_x - e.originalEvent.touches[0].pageX));
}
}).on('touchend', function (e) {
if (drag_detected) {
if (start_x - e.originalEvent.changedTouches[0].pageX > 80) {
$(this).parent().next('.next-prev').find('.next').trigger('click'); // swipe left
$(this).off('touchmove touchend');
} else if (e.originalEvent.changedTouches[0].pageX - start_x > 80) {
$(this).parent().next('.next-prev').find('.prev').trigger('click'); // swipe right
$(this).off('touchmove touchend');
} else {
$(this_viewer_band).stop().animate({
scrollLeft: start_drag
}, 500, 'easeOutQuad');
}
}
});
});
function updateButtons(viewer, viewer_scroll_limit, scroll_target) {
// update enabled/disabled
$(viewer).find('.next-prev button').prop('disabled', false);
if (scroll_target == 0) {
$(viewer).find('.prev').prop('disabled', true);
}
if (scroll_target == viewer_scroll_limit) {
$(viewer).find('.next').prop('disabled', true);
}
// Indicator Pips
var viewer_width_natural = 0;
viewer_width_natural = $(viewer).find('.cards').first()[0].scrollWidth;
var pip_count = Math.ceil(viewer_width_natural / $(viewer).find('.cards').first().outerWidth() - 0.1);
var pips_html = '';
if (pip_count > 1) {
for (i = 0; i < pip_count; i++) {
pips_html += '<button class="pip"><span class="sr-only">Slide Set ' + (i + 1) + '</span></button>';
}
$(viewer).find('.next-prev button').show(); // also show Next and Prev buttons
} else {
$(viewer).find('.next-prev button').hide(); // only a single slide set is visible, so also hide Next and Prev buttons
}
$(viewer).find('.pips').html(pips_html);
var active_pip = 0;
if (scroll_target > 0) {
active_pip = Math.ceil((scroll_target / viewer_scroll_limit) * pip_count) - 1;
}
$(viewer).find('.pip').eq(active_pip).addClass('active');
$(viewer).find('.pip').click(function (e) {
var this_pip = $(this).index();
var pip_change = 0;
var change_direction = 'next';
if (this_pip > active_pip) {
pip_change = this_pip - active_pip;
} else if (this_pip < active_pip) {
pip_change = active_pip - this_pip;
change_direction = 'prev';
}
var trigger_clicks = []; // a generic array used below to direct forEach() to call the jQuery trigger() function multiple times
for (i = 0; i < pip_change; i++) {
trigger_clicks.push(0);
}
trigger_clicks.forEach(function (i) {
$(viewer).find('.' + change_direction).trigger('click');
});
});
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment