From d48100d386d16f611968f147c84fb03be45ed9d7 Mon Sep 17 00:00:00 2001 From: Marko Jevtic Date: Mon, 12 Jun 2017 13:34:24 +0000 Subject: [PATCH] [LEARNER-1367] Move Program Marketing page from private themes repo to edx platform repo [LEARNER-311] Enable a purchase button on the Program page - platform (WL) --- lms/djangoapps/courseware/tests/test_views.py | 6 +- lms/djangoapps/courseware/views/views.py | 12 +- lms/static/js/leanModal.js | 136 ++ lms/static/js/program_marketing.js | 172 ++ lms/static/js/slick.min.js | 18 + lms/static/sass/_build-lms-v2.scss | 3 + .../sass/views/_program-marketing-page.scss | 1739 +++++++++++++++++ .../courseware/program_marketing.html | 423 +++- .../djangoapps/programs/tests/test_utils.py | 12 + openedx/core/djangoapps/programs/utils.py | 4 +- 10 files changed, 2517 insertions(+), 8 deletions(-) create mode 100644 lms/static/js/leanModal.js create mode 100644 lms/static/js/program_marketing.js create mode 100644 lms/static/js/slick.min.js create mode 100644 lms/static/sass/views/_program-marketing-page.scss diff --git a/lms/djangoapps/courseware/tests/test_views.py b/lms/djangoapps/courseware/tests/test_views.py index 426b85cdb3..bf04cd62e8 100644 --- a/lms/djangoapps/courseware/tests/test_views.py +++ b/lms/djangoapps/courseware/tests/test_views.py @@ -1001,7 +1001,11 @@ class TestProgramMarketingView(SharedModuleStoreTestCase): course_run = CourseRunFactory(key=unicode(modulestore_course.id)) # pylint: disable=no-member course = CatalogCourseFactory(course_runs=[course_run]) - cls.data = ProgramFactory(uuid=cls.program_uuid, courses=[course]) + cls.data = ProgramFactory( + courses=[course], + is_program_eligible_for_one_click_purchase=False, + uuid=cls.program_uuid, + ) def test_404_if_no_data(self, mock_cache): """ diff --git a/lms/djangoapps/courseware/views/views.py b/lms/djangoapps/courseware/views/views.py index 9529b8f415..be6c3b19bd 100644 --- a/lms/djangoapps/courseware/views/views.py +++ b/lms/djangoapps/courseware/views/views.py @@ -20,6 +20,7 @@ from django.db.models import Q from django.http import Http404, HttpResponse, HttpResponseBadRequest, HttpResponseForbidden, QueryDict from django.shortcuts import redirect from django.utils.decorators import method_decorator +from django.utils.text import slugify from django.utils.timezone import UTC from django.utils.translation import ugettext as _ from django.views.decorators.cache import cache_control @@ -832,13 +833,16 @@ def program_marketing(request, program_uuid): raise Http404 program = ProgramMarketingDataExtender(program_data, request.user).extend() + program['type_slug'] = slugify(program['type']) skus = program.get('skus') ecommerce_service = EcommerceService() - return render_to_response('courseware/program_marketing.html', { - 'buy_button_href': ecommerce_service.get_checkout_page_url(*skus) if skus else '#courses', - 'program': program, - }) + context = {'program': program} + + if program.get('is_learner_eligible_for_one_click_purchase') and skus: + context['buy_button_href'] = ecommerce_service.get_checkout_page_url(*skus) + + return render_to_response('courseware/program_marketing.html', context) @transaction.non_atomic_requests diff --git a/lms/static/js/leanModal.js b/lms/static/js/leanModal.js new file mode 100644 index 0000000000..45b4779de7 --- /dev/null +++ b/lms/static/js/leanModal.js @@ -0,0 +1,136 @@ +(function($) { // eslint-disable-line wrap-iife + 'use strict'; + $.fn.extend({ + /* + * leanModal prepares an element to be a modal dialog. Call it once on the + * element that launches the dialog, when the page is ready. This function + * will add a .click() handler that properly opens the dialog. + * + * The launching element must: + * - be an element, not a button, + * - have an href= attribute identifying the id of the dialog element, + * - have rel='leanModal'. + */ + leanModal: function(options) { + var defaults = { + top: 100, + overlay: 0.5, + closeButton: null, + position: 'fixed' + }; + + options = $.extend(defaults, options); // eslint-disable-line no-param-reassign + + function closeModal(modalId, e) { + $('#lean_overlay').fadeOut(200); + $('iframe', modalId).attr('src', ''); + $(modalId).css({display: 'none'}); + if (modalId === '#modal_clone') { + $(modalId).remove(); + } + e.preventDefault(); + $(document).off('keydown.leanModal'); + } + + return this.each(function() { + var o = options; + + $(this).click(function(e) { + var modalId = $(this).attr('href'), + modalClone, modalCloneHtml, notice, $notice; + + $('.modal').hide(); + + if ($(modalId).hasClass('video-modal')) { + // Video modals need to be cloned before being presented as a modal + // This is because actions on the video get recorded in the history. + // Deleting the video (clone) prevents the odd back button behavior. + modalClone = $(modalId).clone(true, true); + modalClone.attr('id', 'modal_clone'); + modalCloneHtml = edx.HtmlUtils.template(modalClone); + $(modalId).after( + edx.HtmlUtils.ensureHtml(modalCloneHtml).toString() + ); + modalId = '#modal_clone'; + } + + $(document).on('keydown.leanModal', function(event) { + if (event.which === 27) { + closeModal(modalId, event); + } + }); + + $('#lean_overlay').click(function(ev) { + closeModal(modalId, ev); + }); + + $(o.closeButton).click(function(ev) { + closeModal(modalId, ev); + }); + + // To enable closing of email modal when copy button hit + $(o.copyEmailButton).click(function(ev) { + closeModal(modalId, ev); + }); + + $('#lean_overlay').css({display: 'block', opacity: 0}); + $('#lean_overlay').fadeTo(200, o.overlay); + + $('iframe', modalId).attr('src', $('iframe', modalId).data('src')); + if ($(modalId).hasClass('email-modal')) { + $(modalId).css({ + width: 80 + '%', + height: 80 + '%', + position: o.position, + opacity: 0, + 'z-index': 11000, + left: 10 + '%', + top: 10 + '%' + }); + } else { + $(modalId).css({ + position: o.position, + opacity: 0, + 'z-index': 11000, + left: 50 + '%', + 'margin-left': -($(modalId).outerWidth() / 2) + 'px', + top: o.top + 'px' + }); + } + + $(modalId).show().fadeTo(200, 1); + $(modalId).find('.notice').hide() + .html(''); + notice = $(this).data('notice'); + if (notice !== undefined) { + $notice = $(modalId).find('.notice'); + $notice.show().text(notice); + // This is for activating leanModal links that were in the notice. + // We should have a cleaner way of allowing all dynamically added leanmodal links to work. + $notice.find('a[rel*=leanModal]').leanModal({ + top: 120, + overlay: 1, + closeButton: '.close-modal', + position: 'absolute' + }); + } + e.preventDefault(); + }); + }); + } + }); + + $(document).ready(function($) { // eslint-disable-line no-shadow + $('button[rel*=leanModal]').each(function() { + var sep, embed; + + $(this).leanModal({top: 120, overlay: 1, closeButton: '.close-modal', position: 'absolute'}); + embed = $($(this).attr('href')).find('iframe'); + if (embed.length > 0 && embed.attr('src')) { + sep = (embed.attr('src').indexOf('?') > 0) ? '&' : '?'; + embed.data('src', embed.attr('src') + sep + 'autoplay=1&rel=0'); + embed.attr('src', ''); + } + }); + }); +})(jQuery); diff --git a/lms/static/js/program_marketing.js b/lms/static/js/program_marketing.js new file mode 100644 index 0000000000..955fb51a71 --- /dev/null +++ b/lms/static/js/program_marketing.js @@ -0,0 +1,172 @@ +function initializeCourseSlider() { + 'use strict'; + var isMobileResolution = $(window).width() <= 767, + sliderExists = $('.course-slider-xs').hasClass('slick-slider'); + $('.course-card').toggleClass('slidable', isMobileResolution); + if (isMobileResolution) { // Second condition will avoid the multiple calls from resize + $('.copy-meta-mobile').show(); + $('.copy-meta').hide(); + if (!sliderExists) { + $('.course-slider-xs').slick({ + arrows: false, + centerMode: true, + centerPadding: '40px', + slidesToShow: 1 + }); + } + } else { + $('.copy-meta').show(); + $('.copy-meta-mobile').hide(); + if (sliderExists) { + $('.course-slider-xs').slick('unslick'); + $('.course-slider-xs').html(); + $('.slick-arrow, .pageInfo').hide(); + } + } +} + +function paginate(page, size, total) { + 'use strict'; + var start = size * page, + end = (start + size - 1) >= total ? total - 1 : (start + size - 1); + $('.profile-item-desktop').each(function(index, item) { + if (index >= start && index <= end) { + $(item).css('display', 'block'); + } else { + $(item).css('display', 'none'); + } + }); + $('.pagination-start').text(start + 1); + $('.pagination-end').text(end + 1); +} + +$.fn.getFocusableChildren = function() { + 'use strict'; + return $(this) + /* eslint max-len: 0 */ + .find('a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object:not([disabled]), embed, *[tabindex], *[contenteditable]') + .filter(':visible'); +}; + +$(document).ready(function() { + 'use strict'; + // Create MutationObserver which prevents the body of + // the page from scrolling when a modal window is displayed + var observer = new MutationObserver(function(mutations) { + mutations.forEach(function(mutation) { + if ($(mutation.target).css('display') === 'block') { + $('body').css('overflow', 'hidden'); + } else { + $('body').css('overflow', 'auto'); + } + }); + }); + + // Custom function showing current slide + var $status = $('.pagingInfo'); + var $slickElement = $('.course-slider-xs'); + + // Instructor pagination + var page = 0, + size = 4, + total = parseInt($('.instructor-size').text(), 10), + maxPages = Math.ceil(total / size) - 1; + + paginate(page, size, total); + + initializeCourseSlider(); + + // In order to restrict focus, we added two pseudo elements, one before the instructor modal and one after. + // When reaching the first , we focus the last element in the dialog. + // If there is no focusable element, we focus the close button. + // When focusing the last , we focus the first control in the dialog. + $('.focusKeeper:even').on('focus', function(event) { + event.preventDefault(); + if ($(this).parent().find('.modal-body') + .getFocusableChildren().length) { + $(this).parent().find('.modal-body') + .getFocusableChildren() + .filter(':last') + .focus(); + } else { + $(this).parent().find('.modal_close a') + .focus(); + } + }); + + $('.focusKeeper:odd').on('focus', function(event) { + event.preventDefault(); + $(this).parent().find('.modal_close a') + .focus(); + }); + + $(window).resize(function() { + initializeCourseSlider(); + }); + + // Initialize instructor bio modals + $('.instructor-image, .instructor-label').leanModal({closeButton: '.modal_close', top: '10%'}); + + $('.modal').each(function(index, element) { + observer.observe(element, {attributes: true, attributeFilter: ['style']}); + }); + + $slickElement.on('init reInit afterChange', function(event, slick, currentSlide) { + // currentSlide is undefined on init -- set it to 0 in this case (currentSlide is 0 based) + var i = currentSlide || 1; + $status.text(i + ' of ' + slick.slideCount); + }); + + // Initialize FAQ + $('ul.faq-links-list li.item').click(function() { + if ($(this).find('.answer').hasClass('hidden')) { + $(this).find('.answer').removeClass('hidden'); + $(this).addClass('expanded'); + } else { + $(this).find('.answer').addClass('hidden'); + $(this).removeClass('expanded'); + } + }); + + if (page < maxPages) { + $('#pagination-next').addClass('active'); + $('#pagination-next > span.sr').attr('aria-hidden', 'false'); + } + + $('#pagination-next').click(function() { + if (page === maxPages) { + return false; + } + if (page + 1 === maxPages) { + $(this).removeClass('active'); + $(this).children('span.sr').attr('aria-hidden', 'true'); + } + page = page + 1; + paginate(page, size, total); + $('#pagination-previous').addClass('active'); + $('#pagination-previous > span.sr').attr('aria-hidden', 'false'); + return false; + }); + + $('#pagination-previous').click(function() { + if (page === 0) { + return false; + } + if (page - 1 === 0) { + $(this).removeClass('active'); + $(this).children('span.sr').attr('aria-hidden', 'true'); + } + page = page - 1; + paginate(page, size, total); + $('#pagination-next').addClass('active'); + $('#pagination-next > span.sr').attr('aria-hidden', 'false'); + return false; + }); + + $('#accordion-group').accordion({ + header: '> .accordion-item > .accordion-head', + collapsible: true, + active: false, + heightStyle: 'content' + }); +}); diff --git a/lms/static/js/slick.min.js b/lms/static/js/slick.min.js new file mode 100644 index 0000000000..afc9482480 --- /dev/null +++ b/lms/static/js/slick.min.js @@ -0,0 +1,18 @@ +/* + _ _ _ _ + ___| (_) ___| | __ (_)___ +/ __| | |/ __| |/ / | / __| +\__ \ | | (__| < _ | \__ \ +|___/_|_|\___|_|\_(_)/ |___/ + |__/ + + Version: 1.5.9 + Author: Ken Wheeler + Website: http://kenwheeler.github.io + Docs: http://kenwheeler.github.io/slick + Repo: http://github.com/kenwheeler/slick + Issues: http://github.com/kenwheeler/slick/issues + + */ +!function(a){"use strict";"function"==typeof define&&define.amd?define(["jquery"],a):"undefined"!=typeof exports?module.exports=a(require("jquery")):a(jQuery)}(function(a){"use strict";var b=window.Slick||{};b=function(){function c(c,d){var f,e=this;e.defaults={accessibility:!0,adaptiveHeight:!1,appendArrows:a(c),appendDots:a(c),arrows:!0,asNavFor:null,prevArrow:'',nextArrow:'',autoplay:!1,autoplaySpeed:3e3,centerMode:!1,centerPadding:"50px",cssEase:"ease",customPaging:function(a,b){return'"},dots:!1,dotsClass:"slick-dots",draggable:!0,easing:"linear",edgeFriction:.35,fade:!1,focusOnSelect:!1,infinite:!0,initialSlide:0,lazyLoad:"ondemand",mobileFirst:!1,pauseOnHover:!0,pauseOnDotsHover:!1,respondTo:"window",responsive:null,rows:1,rtl:!1,slide:"",slidesPerRow:1,slidesToShow:1,slidesToScroll:1,speed:500,swipe:!0,swipeToSlide:!1,touchMove:!0,touchThreshold:5,useCSS:!0,useTransform:!1,variableWidth:!1,vertical:!1,verticalSwiping:!1,waitForAnimate:!0,zIndex:1e3},e.initials={animating:!1,dragging:!1,autoPlayTimer:null,currentDirection:0,currentLeft:null,currentSlide:0,direction:1,$dots:null,listWidth:null,listHeight:null,loadIndex:0,$nextArrow:null,$prevArrow:null,slideCount:null,slideWidth:null,$slideTrack:null,$slides:null,sliding:!1,slideOffset:0,swipeLeft:null,$list:null,touchObject:{},transformsEnabled:!1,unslicked:!1},a.extend(e,e.initials),e.activeBreakpoint=null,e.animType=null,e.animProp=null,e.breakpoints=[],e.breakpointSettings=[],e.cssTransitions=!1,e.hidden="hidden",e.paused=!1,e.positionProp=null,e.respondTo=null,e.rowCount=1,e.shouldClick=!0,e.$slider=a(c),e.$slidesCache=null,e.transformType=null,e.transitionType=null,e.visibilityChange="visibilitychange",e.windowWidth=0,e.windowTimer=null,f=a(c).data("slick")||{},e.options=a.extend({},e.defaults,f,d),e.currentSlide=e.options.initialSlide,e.originalSettings=e.options,"undefined"!=typeof document.mozHidden?(e.hidden="mozHidden",e.visibilityChange="mozvisibilitychange"):"undefined"!=typeof document.webkitHidden&&(e.hidden="webkitHidden",e.visibilityChange="webkitvisibilitychange"),e.autoPlay=a.proxy(e.autoPlay,e),e.autoPlayClear=a.proxy(e.autoPlayClear,e),e.changeSlide=a.proxy(e.changeSlide,e),e.clickHandler=a.proxy(e.clickHandler,e),e.selectHandler=a.proxy(e.selectHandler,e),e.setPosition=a.proxy(e.setPosition,e),e.swipeHandler=a.proxy(e.swipeHandler,e),e.dragHandler=a.proxy(e.dragHandler,e),e.keyHandler=a.proxy(e.keyHandler,e),e.autoPlayIterator=a.proxy(e.autoPlayIterator,e),e.instanceUid=b++,e.htmlExpr=/^(?:\s*(<[\w\W]+>)[^>]*)$/,e.registerBreakpoints(),e.init(!0),e.checkResponsive(!0)}var b=0;return c}(),b.prototype.addSlide=b.prototype.slickAdd=function(b,c,d){var e=this;if("boolean"==typeof c)d=c,c=null;else if(0>c||c>=e.slideCount)return!1;e.unload(),"number"==typeof c?0===c&&0===e.$slides.length?a(b).appendTo(e.$slideTrack):d?a(b).insertBefore(e.$slides.eq(c)):a(b).insertAfter(e.$slides.eq(c)):d===!0?a(b).prependTo(e.$slideTrack):a(b).appendTo(e.$slideTrack),e.$slides=e.$slideTrack.children(this.options.slide),e.$slideTrack.children(this.options.slide).detach(),e.$slideTrack.append(e.$slides),e.$slides.each(function(b,c){a(c).attr("data-slick-index",b)}),e.$slidesCache=e.$slides,e.reinit()},b.prototype.animateHeight=function(){var a=this;if(1===a.options.slidesToShow&&a.options.adaptiveHeight===!0&&a.options.vertical===!1){var b=a.$slides.eq(a.currentSlide).outerHeight(!0);a.$list.animate({height:b},a.options.speed)}},b.prototype.animateSlide=function(b,c){var d={},e=this;e.animateHeight(),e.options.rtl===!0&&e.options.vertical===!1&&(b=-b),e.transformsEnabled===!1?e.options.vertical===!1?e.$slideTrack.animate({left:b},e.options.speed,e.options.easing,c):e.$slideTrack.animate({top:b},e.options.speed,e.options.easing,c):e.cssTransitions===!1?(e.options.rtl===!0&&(e.currentLeft=-e.currentLeft),a({animStart:e.currentLeft}).animate({animStart:b},{duration:e.options.speed,easing:e.options.easing,step:function(a){a=Math.ceil(a),e.options.vertical===!1?(d[e.animType]="translate("+a+"px, 0px)",e.$slideTrack.css(d)):(d[e.animType]="translate(0px,"+a+"px)",e.$slideTrack.css(d))},complete:function(){c&&c.call()}})):(e.applyTransition(),b=Math.ceil(b),e.options.vertical===!1?d[e.animType]="translate3d("+b+"px, 0px, 0px)":d[e.animType]="translate3d(0px,"+b+"px, 0px)",e.$slideTrack.css(d),c&&setTimeout(function(){e.disableTransition(),c.call()},e.options.speed))},b.prototype.asNavFor=function(b){var c=this,d=c.options.asNavFor;d&&null!==d&&(d=a(d).not(c.$slider)),null!==d&&"object"==typeof d&&d.each(function(){var c=a(this).slick("getSlick");c.unslicked||c.slideHandler(b,!0)})},b.prototype.applyTransition=function(a){var b=this,c={};b.options.fade===!1?c[b.transitionType]=b.transformType+" "+b.options.speed+"ms "+b.options.cssEase:c[b.transitionType]="opacity "+b.options.speed+"ms "+b.options.cssEase,b.options.fade===!1?b.$slideTrack.css(c):b.$slides.eq(a).css(c)},b.prototype.autoPlay=function(){var a=this;a.autoPlayTimer&&clearInterval(a.autoPlayTimer),a.slideCount>a.options.slidesToShow&&a.paused!==!0&&(a.autoPlayTimer=setInterval(a.autoPlayIterator,a.options.autoplaySpeed))},b.prototype.autoPlayClear=function(){var a=this;a.autoPlayTimer&&clearInterval(a.autoPlayTimer)},b.prototype.autoPlayIterator=function(){var a=this;a.options.infinite===!1?1===a.direction?(a.currentSlide+1===a.slideCount-1&&(a.direction=0),a.slideHandler(a.currentSlide+a.options.slidesToScroll)):(a.currentSlide-1===0&&(a.direction=1),a.slideHandler(a.currentSlide-a.options.slidesToScroll)):a.slideHandler(a.currentSlide+a.options.slidesToScroll)},b.prototype.buildArrows=function(){var b=this;b.options.arrows===!0&&(b.$prevArrow=a(b.options.prevArrow).addClass("slick-arrow"),b.$nextArrow=a(b.options.nextArrow).addClass("slick-arrow"),b.slideCount>b.options.slidesToShow?(b.$prevArrow.removeClass("slick-hidden").removeAttr("aria-hidden tabindex"),b.$nextArrow.removeClass("slick-hidden").removeAttr("aria-hidden tabindex"),b.htmlExpr.test(b.options.prevArrow)&&b.$prevArrow.prependTo(b.options.appendArrows),b.htmlExpr.test(b.options.nextArrow)&&b.$nextArrow.appendTo(b.options.appendArrows),b.options.infinite!==!0&&b.$prevArrow.addClass("slick-disabled").attr("aria-disabled","true")):b.$prevArrow.add(b.$nextArrow).addClass("slick-hidden").attr({"aria-disabled":"true",tabindex:"-1"}))},b.prototype.buildDots=function(){var c,d,b=this;if(b.options.dots===!0&&b.slideCount>b.options.slidesToShow){for(d='",b.$dots=a(d).appendTo(b.options.appendDots),b.$dots.find("li").first().addClass("slick-active").attr("aria-hidden","false")}},b.prototype.buildOut=function(){var b=this;b.$slides=b.$slider.children(b.options.slide+":not(.slick-cloned)").addClass("slick-slide"),b.slideCount=b.$slides.length,b.$slides.each(function(b,c){a(c).attr("data-slick-index",b).data("originalStyling",a(c).attr("style")||"")}),b.$slider.addClass("slick-slider"),b.$slideTrack=0===b.slideCount?a('
').appendTo(b.$slider):b.$slides.wrapAll('
').parent(),b.$list=b.$slideTrack.wrap('
').parent(),b.$slideTrack.css("opacity",0),(b.options.centerMode===!0||b.options.swipeToSlide===!0)&&(b.options.slidesToScroll=1),a("img[data-lazy]",b.$slider).not("[src]").addClass("slick-loading"),b.setupInfinite(),b.buildArrows(),b.buildDots(),b.updateDots(),b.setSlideClasses("number"==typeof b.currentSlide?b.currentSlide:0),b.options.draggable===!0&&b.$list.addClass("draggable")},b.prototype.buildRows=function(){var b,c,d,e,f,g,h,a=this;if(e=document.createDocumentFragment(),g=a.$slider.children(),a.options.rows>1){for(h=a.options.slidesPerRow*a.options.rows,f=Math.ceil(g.length/h),b=0;f>b;b++){var i=document.createElement("div");for(c=0;cd.breakpoints[e]&&(f=d.breakpoints[e]));null!==f?null!==d.activeBreakpoint?(f!==d.activeBreakpoint||c)&&(d.activeBreakpoint=f,"unslick"===d.breakpointSettings[f]?d.unslick(f):(d.options=a.extend({},d.originalSettings,d.breakpointSettings[f]),b===!0&&(d.currentSlide=d.options.initialSlide),d.refresh(b)),h=f):(d.activeBreakpoint=f,"unslick"===d.breakpointSettings[f]?d.unslick(f):(d.options=a.extend({},d.originalSettings,d.breakpointSettings[f]),b===!0&&(d.currentSlide=d.options.initialSlide),d.refresh(b)),h=f):null!==d.activeBreakpoint&&(d.activeBreakpoint=null,d.options=d.originalSettings,b===!0&&(d.currentSlide=d.options.initialSlide),d.refresh(b),h=f),b||h===!1||d.$slider.trigger("breakpoint",[d,h])}},b.prototype.changeSlide=function(b,c){var f,g,h,d=this,e=a(b.target);switch(e.is("a")&&b.preventDefault(),e.is("li")||(e=e.closest("li")),h=d.slideCount%d.options.slidesToScroll!==0,f=h?0:(d.slideCount-d.currentSlide)%d.options.slidesToScroll,b.data.message){case"previous":g=0===f?d.options.slidesToScroll:d.options.slidesToShow-f,d.slideCount>d.options.slidesToShow&&d.slideHandler(d.currentSlide-g,!1,c);break;case"next":g=0===f?d.options.slidesToScroll:f,d.slideCount>d.options.slidesToShow&&d.slideHandler(d.currentSlide+g,!1,c);break;case"index":var i=0===b.data.index?0:b.data.index||e.index()*d.options.slidesToScroll;d.slideHandler(d.checkNavigable(i),!1,c),e.children().trigger("focus");break;default:return}},b.prototype.checkNavigable=function(a){var c,d,b=this;if(c=b.getNavigableIndexes(),d=0,a>c[c.length-1])a=c[c.length-1];else for(var e in c){if(ab.options.slidesToShow&&(b.$prevArrow&&b.$prevArrow.off("click.slick",b.changeSlide),b.$nextArrow&&b.$nextArrow.off("click.slick",b.changeSlide)),b.$list.off("touchstart.slick mousedown.slick",b.swipeHandler),b.$list.off("touchmove.slick mousemove.slick",b.swipeHandler),b.$list.off("touchend.slick mouseup.slick",b.swipeHandler),b.$list.off("touchcancel.slick mouseleave.slick",b.swipeHandler),b.$list.off("click.slick",b.clickHandler),a(document).off(b.visibilityChange,b.visibility),b.$list.off("mouseenter.slick",a.proxy(b.setPaused,b,!0)),b.$list.off("mouseleave.slick",a.proxy(b.setPaused,b,!1)),b.options.accessibility===!0&&b.$list.off("keydown.slick",b.keyHandler),b.options.focusOnSelect===!0&&a(b.$slideTrack).children().off("click.slick",b.selectHandler),a(window).off("orientationchange.slick.slick-"+b.instanceUid,b.orientationChange),a(window).off("resize.slick.slick-"+b.instanceUid,b.resize),a("[draggable!=true]",b.$slideTrack).off("dragstart",b.preventDefault),a(window).off("load.slick.slick-"+b.instanceUid,b.setPosition),a(document).off("ready.slick.slick-"+b.instanceUid,b.setPosition)},b.prototype.cleanUpRows=function(){var b,a=this;a.options.rows>1&&(b=a.$slides.children().children(),b.removeAttr("style"),a.$slider.html(b))},b.prototype.clickHandler=function(a){var b=this;b.shouldClick===!1&&(a.stopImmediatePropagation(),a.stopPropagation(),a.preventDefault())},b.prototype.destroy=function(b){var c=this;c.autoPlayClear(),c.touchObject={},c.cleanUpEvents(),a(".slick-cloned",c.$slider).detach(),c.$dots&&c.$dots.remove(),c.$prevArrow&&c.$prevArrow.length&&(c.$prevArrow.removeClass("slick-disabled slick-arrow slick-hidden").removeAttr("aria-hidden aria-disabled tabindex").css("display",""),c.htmlExpr.test(c.options.prevArrow)&&c.$prevArrow.remove()),c.$nextArrow&&c.$nextArrow.length&&(c.$nextArrow.removeClass("slick-disabled slick-arrow slick-hidden").removeAttr("aria-hidden aria-disabled tabindex").css("display",""),c.htmlExpr.test(c.options.nextArrow)&&c.$nextArrow.remove()),c.$slides&&(c.$slides.removeClass("slick-slide slick-active slick-center slick-visible slick-current").removeAttr("aria-hidden").removeAttr("data-slick-index").each(function(){a(this).attr("style",a(this).data("originalStyling"))}),c.$slideTrack.children(this.options.slide).detach(),c.$slideTrack.detach(),c.$list.detach(),c.$slider.append(c.$slides)),c.cleanUpRows(),c.$slider.removeClass("slick-slider"),c.$slider.removeClass("slick-initialized"),c.unslicked=!0,b||c.$slider.trigger("destroy",[c])},b.prototype.disableTransition=function(a){var b=this,c={};c[b.transitionType]="",b.options.fade===!1?b.$slideTrack.css(c):b.$slides.eq(a).css(c)},b.prototype.fadeSlide=function(a,b){var c=this;c.cssTransitions===!1?(c.$slides.eq(a).css({zIndex:c.options.zIndex}),c.$slides.eq(a).animate({opacity:1},c.options.speed,c.options.easing,b)):(c.applyTransition(a),c.$slides.eq(a).css({opacity:1,zIndex:c.options.zIndex}),b&&setTimeout(function(){c.disableTransition(a),b.call()},c.options.speed))},b.prototype.fadeSlideOut=function(a){var b=this;b.cssTransitions===!1?b.$slides.eq(a).animate({opacity:0,zIndex:b.options.zIndex-2},b.options.speed,b.options.easing):(b.applyTransition(a),b.$slides.eq(a).css({opacity:0,zIndex:b.options.zIndex-2}))},b.prototype.filterSlides=b.prototype.slickFilter=function(a){var b=this;null!==a&&(b.$slidesCache=b.$slides,b.unload(),b.$slideTrack.children(this.options.slide).detach(),b.$slidesCache.filter(a).appendTo(b.$slideTrack),b.reinit())},b.prototype.getCurrent=b.prototype.slickCurrentSlide=function(){var a=this;return a.currentSlide},b.prototype.getDotCount=function(){var a=this,b=0,c=0,d=0;if(a.options.infinite===!0)for(;bb.options.slidesToShow&&(b.slideOffset=b.slideWidth*b.options.slidesToShow*-1,e=d*b.options.slidesToShow*-1),b.slideCount%b.options.slidesToScroll!==0&&a+b.options.slidesToScroll>b.slideCount&&b.slideCount>b.options.slidesToShow&&(a>b.slideCount?(b.slideOffset=(b.options.slidesToShow-(a-b.slideCount))*b.slideWidth*-1,e=(b.options.slidesToShow-(a-b.slideCount))*d*-1):(b.slideOffset=b.slideCount%b.options.slidesToScroll*b.slideWidth*-1,e=b.slideCount%b.options.slidesToScroll*d*-1))):a+b.options.slidesToShow>b.slideCount&&(b.slideOffset=(a+b.options.slidesToShow-b.slideCount)*b.slideWidth,e=(a+b.options.slidesToShow-b.slideCount)*d),b.slideCount<=b.options.slidesToShow&&(b.slideOffset=0,e=0),b.options.centerMode===!0&&b.options.infinite===!0?b.slideOffset+=b.slideWidth*Math.floor(b.options.slidesToShow/2)-b.slideWidth:b.options.centerMode===!0&&(b.slideOffset=0,b.slideOffset+=b.slideWidth*Math.floor(b.options.slidesToShow/2)),c=b.options.vertical===!1?a*b.slideWidth*-1+b.slideOffset:a*d*-1+e,b.options.variableWidth===!0&&(f=b.slideCount<=b.options.slidesToShow||b.options.infinite===!1?b.$slideTrack.children(".slick-slide").eq(a):b.$slideTrack.children(".slick-slide").eq(a+b.options.slidesToShow),c=b.options.rtl===!0?f[0]?-1*(b.$slideTrack.width()-f[0].offsetLeft-f.width()):0:f[0]?-1*f[0].offsetLeft:0,b.options.centerMode===!0&&(f=b.slideCount<=b.options.slidesToShow||b.options.infinite===!1?b.$slideTrack.children(".slick-slide").eq(a):b.$slideTrack.children(".slick-slide").eq(a+b.options.slidesToShow+1),c=b.options.rtl===!0?f[0]?-1*(b.$slideTrack.width()-f[0].offsetLeft-f.width()):0:f[0]?-1*f[0].offsetLeft:0,c+=(b.$list.width()-f.outerWidth())/2)),c},b.prototype.getOption=b.prototype.slickGetOption=function(a){var b=this;return b.options[a]},b.prototype.getNavigableIndexes=function(){var e,a=this,b=0,c=0,d=[];for(a.options.infinite===!1?e=a.slideCount:(b=-1*a.options.slidesToScroll,c=-1*a.options.slidesToScroll,e=2*a.slideCount);e>b;)d.push(b),b=c+a.options.slidesToScroll,c+=a.options.slidesToScroll<=a.options.slidesToShow?a.options.slidesToScroll:a.options.slidesToShow;return d},b.prototype.getSlick=function(){return this},b.prototype.getSlideCount=function(){var c,d,e,b=this;return e=b.options.centerMode===!0?b.slideWidth*Math.floor(b.options.slidesToShow/2):0,b.options.swipeToSlide===!0?(b.$slideTrack.find(".slick-slide").each(function(c,f){return f.offsetLeft-e+a(f).outerWidth()/2>-1*b.swipeLeft?(d=f,!1):void 0}),c=Math.abs(a(d).attr("data-slick-index")-b.currentSlide)||1):b.options.slidesToScroll},b.prototype.goTo=b.prototype.slickGoTo=function(a,b){var c=this;c.changeSlide({data:{message:"index",index:parseInt(a)}},b)},b.prototype.init=function(b){var c=this;a(c.$slider).hasClass("slick-initialized")||(a(c.$slider).addClass("slick-initialized"),c.buildRows(),c.buildOut(),c.setProps(),c.startLoad(),c.loadSlider(),c.initializeEvents(),c.updateArrows(),c.updateDots()),b&&c.$slider.trigger("init",[c]),c.options.accessibility===!0&&c.initADA()},b.prototype.initArrowEvents=function(){var a=this;a.options.arrows===!0&&a.slideCount>a.options.slidesToShow&&(a.$prevArrow.on("click.slick",{message:"previous"},a.changeSlide),a.$nextArrow.on("click.slick",{message:"next"},a.changeSlide))},b.prototype.initDotEvents=function(){var b=this;b.options.dots===!0&&b.slideCount>b.options.slidesToShow&&a("li",b.$dots).on("click.slick",{message:"index"},b.changeSlide),b.options.dots===!0&&b.options.pauseOnDotsHover===!0&&b.options.autoplay===!0&&a("li",b.$dots).on("mouseenter.slick",a.proxy(b.setPaused,b,!0)).on("mouseleave.slick",a.proxy(b.setPaused,b,!1))},b.prototype.initializeEvents=function(){var b=this;b.initArrowEvents(),b.initDotEvents(),b.$list.on("touchstart.slick mousedown.slick",{action:"start"},b.swipeHandler),b.$list.on("touchmove.slick mousemove.slick",{action:"move"},b.swipeHandler),b.$list.on("touchend.slick mouseup.slick",{action:"end"},b.swipeHandler),b.$list.on("touchcancel.slick mouseleave.slick",{action:"end"},b.swipeHandler),b.$list.on("click.slick",b.clickHandler),a(document).on(b.visibilityChange,a.proxy(b.visibility,b)),b.$list.on("mouseenter.slick",a.proxy(b.setPaused,b,!0)),b.$list.on("mouseleave.slick",a.proxy(b.setPaused,b,!1)),b.options.accessibility===!0&&b.$list.on("keydown.slick",b.keyHandler),b.options.focusOnSelect===!0&&a(b.$slideTrack).children().on("click.slick",b.selectHandler),a(window).on("orientationchange.slick.slick-"+b.instanceUid,a.proxy(b.orientationChange,b)),a(window).on("resize.slick.slick-"+b.instanceUid,a.proxy(b.resize,b)),a("[draggable!=true]",b.$slideTrack).on("dragstart",b.preventDefault),a(window).on("load.slick.slick-"+b.instanceUid,b.setPosition),a(document).on("ready.slick.slick-"+b.instanceUid,b.setPosition)},b.prototype.initUI=function(){var a=this;a.options.arrows===!0&&a.slideCount>a.options.slidesToShow&&(a.$prevArrow.show(),a.$nextArrow.show()),a.options.dots===!0&&a.slideCount>a.options.slidesToShow&&a.$dots.show(),a.options.autoplay===!0&&a.autoPlay()},b.prototype.keyHandler=function(a){var b=this;a.target.tagName.match("TEXTAREA|INPUT|SELECT")||(37===a.keyCode&&b.options.accessibility===!0?b.changeSlide({data:{message:"previous"}}):39===a.keyCode&&b.options.accessibility===!0&&b.changeSlide({data:{message:"next"}}))},b.prototype.lazyLoad=function(){function g(b){a("img[data-lazy]",b).each(function(){var b=a(this),c=a(this).attr("data-lazy"),d=document.createElement("img");d.onload=function(){b.animate({opacity:0},100,function(){b.attr("src",c).animate({opacity:1},200,function(){b.removeAttr("data-lazy").removeClass("slick-loading")})})},d.src=c})}var c,d,e,f,b=this;b.options.centerMode===!0?b.options.infinite===!0?(e=b.currentSlide+(b.options.slidesToShow/2+1),f=e+b.options.slidesToShow+2):(e=Math.max(0,b.currentSlide-(b.options.slidesToShow/2+1)),f=2+(b.options.slidesToShow/2+1)+b.currentSlide):(e=b.options.infinite?b.options.slidesToShow+b.currentSlide:b.currentSlide,f=e+b.options.slidesToShow,b.options.fade===!0&&(e>0&&e--,f<=b.slideCount&&f++)),c=b.$slider.find(".slick-slide").slice(e,f),g(c),b.slideCount<=b.options.slidesToShow?(d=b.$slider.find(".slick-slide"),g(d)):b.currentSlide>=b.slideCount-b.options.slidesToShow?(d=b.$slider.find(".slick-cloned").slice(0,b.options.slidesToShow),g(d)):0===b.currentSlide&&(d=b.$slider.find(".slick-cloned").slice(-1*b.options.slidesToShow),g(d))},b.prototype.loadSlider=function(){var a=this;a.setPosition(),a.$slideTrack.css({opacity:1}),a.$slider.removeClass("slick-loading"),a.initUI(),"progressive"===a.options.lazyLoad&&a.progressiveLazyLoad()},b.prototype.next=b.prototype.slickNext=function(){var a=this;a.changeSlide({data:{message:"next"}})},b.prototype.orientationChange=function(){var a=this;a.checkResponsive(),a.setPosition()},b.prototype.pause=b.prototype.slickPause=function(){var a=this;a.autoPlayClear(),a.paused=!0},b.prototype.play=b.prototype.slickPlay=function(){var a=this;a.paused=!1,a.autoPlay()},b.prototype.postSlide=function(a){var b=this;b.$slider.trigger("afterChange",[b,a]),b.animating=!1,b.setPosition(),b.swipeLeft=null,b.options.autoplay===!0&&b.paused===!1&&b.autoPlay(),b.options.accessibility===!0&&b.initADA()},b.prototype.prev=b.prototype.slickPrev=function(){var a=this;a.changeSlide({data:{message:"previous"}})},b.prototype.preventDefault=function(a){a.preventDefault()},b.prototype.progressiveLazyLoad=function(){var c,d,b=this;c=a("img[data-lazy]",b.$slider).length,c>0&&(d=a("img[data-lazy]",b.$slider).first(),d.attr("src",null),d.attr("src",d.attr("data-lazy")).removeClass("slick-loading").load(function(){d.removeAttr("data-lazy"),b.progressiveLazyLoad(),b.options.adaptiveHeight===!0&&b.setPosition()}).error(function(){d.removeAttr("data-lazy"),b.progressiveLazyLoad()}))},b.prototype.refresh=function(b){var d,e,c=this;e=c.slideCount-c.options.slidesToShow,c.options.infinite||(c.slideCount<=c.options.slidesToShow?c.currentSlide=0:c.currentSlide>e&&(c.currentSlide=e)),d=c.currentSlide,c.destroy(!0),a.extend(c,c.initials,{currentSlide:d}),c.init(),b||c.changeSlide({data:{message:"index",index:d}},!1)},b.prototype.registerBreakpoints=function(){var c,d,e,b=this,f=b.options.responsive||null;if("array"===a.type(f)&&f.length){b.respondTo=b.options.respondTo||"window";for(c in f)if(e=b.breakpoints.length-1,d=f[c].breakpoint,f.hasOwnProperty(c)){for(;e>=0;)b.breakpoints[e]&&b.breakpoints[e]===d&&b.breakpoints.splice(e,1),e--;b.breakpoints.push(d),b.breakpointSettings[d]=f[c].settings}b.breakpoints.sort(function(a,c){return b.options.mobileFirst?a-c:c-a})}},b.prototype.reinit=function(){var b=this;b.$slides=b.$slideTrack.children(b.options.slide).addClass("slick-slide"),b.slideCount=b.$slides.length,b.currentSlide>=b.slideCount&&0!==b.currentSlide&&(b.currentSlide=b.currentSlide-b.options.slidesToScroll),b.slideCount<=b.options.slidesToShow&&(b.currentSlide=0),b.registerBreakpoints(),b.setProps(),b.setupInfinite(),b.buildArrows(),b.updateArrows(),b.initArrowEvents(),b.buildDots(),b.updateDots(),b.initDotEvents(),b.checkResponsive(!1,!0),b.options.focusOnSelect===!0&&a(b.$slideTrack).children().on("click.slick",b.selectHandler),b.setSlideClasses(0),b.setPosition(),b.$slider.trigger("reInit",[b]),b.options.autoplay===!0&&b.focusHandler()},b.prototype.resize=function(){var b=this;a(window).width()!==b.windowWidth&&(clearTimeout(b.windowDelay),b.windowDelay=window.setTimeout(function(){b.windowWidth=a(window).width(),b.checkResponsive(),b.unslicked||b.setPosition()},50))},b.prototype.removeSlide=b.prototype.slickRemove=function(a,b,c){var d=this;return"boolean"==typeof a?(b=a,a=b===!0?0:d.slideCount-1):a=b===!0?--a:a,d.slideCount<1||0>a||a>d.slideCount-1?!1:(d.unload(),c===!0?d.$slideTrack.children().remove():d.$slideTrack.children(this.options.slide).eq(a).remove(),d.$slides=d.$slideTrack.children(this.options.slide),d.$slideTrack.children(this.options.slide).detach(),d.$slideTrack.append(d.$slides),d.$slidesCache=d.$slides,void d.reinit())},b.prototype.setCSS=function(a){var d,e,b=this,c={};b.options.rtl===!0&&(a=-a),d="left"==b.positionProp?Math.ceil(a)+"px":"0px",e="top"==b.positionProp?Math.ceil(a)+"px":"0px",c[b.positionProp]=a,b.transformsEnabled===!1?b.$slideTrack.css(c):(c={},b.cssTransitions===!1?(c[b.animType]="translate("+d+", "+e+")",b.$slideTrack.css(c)):(c[b.animType]="translate3d("+d+", "+e+", 0px)",b.$slideTrack.css(c)))},b.prototype.setDimensions=function(){var a=this;a.options.vertical===!1?a.options.centerMode===!0&&a.$list.css({padding:"0px "+a.options.centerPadding}):(a.$list.height(a.$slides.first().outerHeight(!0)*a.options.slidesToShow),a.options.centerMode===!0&&a.$list.css({padding:a.options.centerPadding+" 0px"})),a.listWidth=a.$list.width(),a.listHeight=a.$list.height(),a.options.vertical===!1&&a.options.variableWidth===!1?(a.slideWidth=Math.ceil(a.listWidth/a.options.slidesToShow),a.$slideTrack.width(Math.ceil(a.slideWidth*a.$slideTrack.children(".slick-slide").length))):a.options.variableWidth===!0?a.$slideTrack.width(5e3*a.slideCount):(a.slideWidth=Math.ceil(a.listWidth),a.$slideTrack.height(Math.ceil(a.$slides.first().outerHeight(!0)*a.$slideTrack.children(".slick-slide").length)));var b=a.$slides.first().outerWidth(!0)-a.$slides.first().width();a.options.variableWidth===!1&&a.$slideTrack.children(".slick-slide").width(a.slideWidth-b)},b.prototype.setFade=function(){var c,b=this;b.$slides.each(function(d,e){c=b.slideWidth*d*-1,b.options.rtl===!0?a(e).css({position:"relative",right:c,top:0,zIndex:b.options.zIndex-2,opacity:0}):a(e).css({position:"relative",left:c,top:0,zIndex:b.options.zIndex-2,opacity:0})}),b.$slides.eq(b.currentSlide).css({zIndex:b.options.zIndex-1,opacity:1})},b.prototype.setHeight=function(){var a=this;if(1===a.options.slidesToShow&&a.options.adaptiveHeight===!0&&a.options.vertical===!1){var b=a.$slides.eq(a.currentSlide).outerHeight(!0);a.$list.css("height",b)}},b.prototype.setOption=b.prototype.slickSetOption=function(b,c,d){var f,g,e=this;if("responsive"===b&&"array"===a.type(c))for(g in c)if("array"!==a.type(e.options.responsive))e.options.responsive=[c[g]];else{for(f=e.options.responsive.length-1;f>=0;)e.options.responsive[f].breakpoint===c[g].breakpoint&&e.options.responsive.splice(f,1),f--;e.options.responsive.push(c[g])}else e.options[b]=c;d===!0&&(e.unload(),e.reinit())},b.prototype.setPosition=function(){var a=this;a.setDimensions(),a.setHeight(),a.options.fade===!1?a.setCSS(a.getLeft(a.currentSlide)):a.setFade(),a.$slider.trigger("setPosition",[a])},b.prototype.setProps=function(){var a=this,b=document.body.style;a.positionProp=a.options.vertical===!0?"top":"left","top"===a.positionProp?a.$slider.addClass("slick-vertical"):a.$slider.removeClass("slick-vertical"),(void 0!==b.WebkitTransition||void 0!==b.MozTransition||void 0!==b.msTransition)&&a.options.useCSS===!0&&(a.cssTransitions=!0),a.options.fade&&("number"==typeof a.options.zIndex?a.options.zIndex<3&&(a.options.zIndex=3):a.options.zIndex=a.defaults.zIndex),void 0!==b.OTransform&&(a.animType="OTransform",a.transformType="-o-transform",a.transitionType="OTransition",void 0===b.perspectiveProperty&&void 0===b.webkitPerspective&&(a.animType=!1)),void 0!==b.MozTransform&&(a.animType="MozTransform",a.transformType="-moz-transform",a.transitionType="MozTransition",void 0===b.perspectiveProperty&&void 0===b.MozPerspective&&(a.animType=!1)),void 0!==b.webkitTransform&&(a.animType="webkitTransform",a.transformType="-webkit-transform",a.transitionType="webkitTransition",void 0===b.perspectiveProperty&&void 0===b.webkitPerspective&&(a.animType=!1)),void 0!==b.msTransform&&(a.animType="msTransform",a.transformType="-ms-transform",a.transitionType="msTransition",void 0===b.msTransform&&(a.animType=!1)),void 0!==b.transform&&a.animType!==!1&&(a.animType="transform",a.transformType="transform",a.transitionType="transition"),a.transformsEnabled=a.options.useTransform&&null!==a.animType&&a.animType!==!1},b.prototype.setSlideClasses=function(a){var c,d,e,f,b=this;d=b.$slider.find(".slick-slide").removeClass("slick-active slick-center slick-current").attr("aria-hidden","true"),b.$slides.eq(a).addClass("slick-current"),b.options.centerMode===!0?(c=Math.floor(b.options.slidesToShow/2),b.options.infinite===!0&&(a>=c&&a<=b.slideCount-1-c?b.$slides.slice(a-c,a+c+1).addClass("slick-active").attr("aria-hidden","false"):(e=b.options.slidesToShow+a,d.slice(e-c+1,e+c+2).addClass("slick-active").attr("aria-hidden","false")),0===a?d.eq(d.length-1-b.options.slidesToShow).addClass("slick-center"):a===b.slideCount-1&&d.eq(b.options.slidesToShow).addClass("slick-center")),b.$slides.eq(a).addClass("slick-center")):a>=0&&a<=b.slideCount-b.options.slidesToShow?b.$slides.slice(a,a+b.options.slidesToShow).addClass("slick-active").attr("aria-hidden","false"):d.length<=b.options.slidesToShow?d.addClass("slick-active").attr("aria-hidden","false"):(f=b.slideCount%b.options.slidesToShow,e=b.options.infinite===!0?b.options.slidesToShow+a:a,b.options.slidesToShow==b.options.slidesToScroll&&b.slideCount-ab.options.slidesToShow)){for(e=b.options.centerMode===!0?b.options.slidesToShow+1:b.options.slidesToShow,c=b.slideCount;c>b.slideCount-e;c-=1)d=c-1,a(b.$slides[d]).clone(!0).attr("id","").attr("data-slick-index",d-b.slideCount).prependTo(b.$slideTrack).addClass("slick-cloned");for(c=0;e>c;c+=1)d=c,a(b.$slides[d]).clone(!0).attr("id","").attr("data-slick-index",d+b.slideCount).appendTo(b.$slideTrack).addClass("slick-cloned");b.$slideTrack.find(".slick-cloned").find("[id]").each(function(){a(this).attr("id","")})}},b.prototype.setPaused=function(a){var b=this;b.options.autoplay===!0&&b.options.pauseOnHover===!0&&(b.paused=a,a?b.autoPlayClear():b.autoPlay())},b.prototype.selectHandler=function(b){var c=this,d=a(b.target).is(".slick-slide")?a(b.target):a(b.target).parents(".slick-slide"),e=parseInt(d.attr("data-slick-index"));return e||(e=0),c.slideCount<=c.options.slidesToShow?(c.setSlideClasses(e),void c.asNavFor(e)):void c.slideHandler(e)},b.prototype.slideHandler=function(a,b,c){var d,e,f,g,h=null,i=this;return b=b||!1,i.animating===!0&&i.options.waitForAnimate===!0||i.options.fade===!0&&i.currentSlide===a||i.slideCount<=i.options.slidesToShow?void 0:(b===!1&&i.asNavFor(a),d=a,h=i.getLeft(d),g=i.getLeft(i.currentSlide),i.currentLeft=null===i.swipeLeft?g:i.swipeLeft,i.options.infinite===!1&&i.options.centerMode===!1&&(0>a||a>i.getDotCount()*i.options.slidesToScroll)?void(i.options.fade===!1&&(d=i.currentSlide,c!==!0?i.animateSlide(g,function(){i.postSlide(d); +}):i.postSlide(d))):i.options.infinite===!1&&i.options.centerMode===!0&&(0>a||a>i.slideCount-i.options.slidesToScroll)?void(i.options.fade===!1&&(d=i.currentSlide,c!==!0?i.animateSlide(g,function(){i.postSlide(d)}):i.postSlide(d))):(i.options.autoplay===!0&&clearInterval(i.autoPlayTimer),e=0>d?i.slideCount%i.options.slidesToScroll!==0?i.slideCount-i.slideCount%i.options.slidesToScroll:i.slideCount+d:d>=i.slideCount?i.slideCount%i.options.slidesToScroll!==0?0:d-i.slideCount:d,i.animating=!0,i.$slider.trigger("beforeChange",[i,i.currentSlide,e]),f=i.currentSlide,i.currentSlide=e,i.setSlideClasses(i.currentSlide),i.updateDots(),i.updateArrows(),i.options.fade===!0?(c!==!0?(i.fadeSlideOut(f),i.fadeSlide(e,function(){i.postSlide(e)})):i.postSlide(e),void i.animateHeight()):void(c!==!0?i.animateSlide(h,function(){i.postSlide(e)}):i.postSlide(e))))},b.prototype.startLoad=function(){var a=this;a.options.arrows===!0&&a.slideCount>a.options.slidesToShow&&(a.$prevArrow.hide(),a.$nextArrow.hide()),a.options.dots===!0&&a.slideCount>a.options.slidesToShow&&a.$dots.hide(),a.$slider.addClass("slick-loading")},b.prototype.swipeDirection=function(){var a,b,c,d,e=this;return a=e.touchObject.startX-e.touchObject.curX,b=e.touchObject.startY-e.touchObject.curY,c=Math.atan2(b,a),d=Math.round(180*c/Math.PI),0>d&&(d=360-Math.abs(d)),45>=d&&d>=0?e.options.rtl===!1?"left":"right":360>=d&&d>=315?e.options.rtl===!1?"left":"right":d>=135&&225>=d?e.options.rtl===!1?"right":"left":e.options.verticalSwiping===!0?d>=35&&135>=d?"left":"right":"vertical"},b.prototype.swipeEnd=function(a){var c,b=this;if(b.dragging=!1,b.shouldClick=b.touchObject.swipeLength>10?!1:!0,void 0===b.touchObject.curX)return!1;if(b.touchObject.edgeHit===!0&&b.$slider.trigger("edge",[b,b.swipeDirection()]),b.touchObject.swipeLength>=b.touchObject.minSwipe)switch(b.swipeDirection()){case"left":c=b.options.swipeToSlide?b.checkNavigable(b.currentSlide+b.getSlideCount()):b.currentSlide+b.getSlideCount(),b.slideHandler(c),b.currentDirection=0,b.touchObject={},b.$slider.trigger("swipe",[b,"left"]);break;case"right":c=b.options.swipeToSlide?b.checkNavigable(b.currentSlide-b.getSlideCount()):b.currentSlide-b.getSlideCount(),b.slideHandler(c),b.currentDirection=1,b.touchObject={},b.$slider.trigger("swipe",[b,"right"])}else b.touchObject.startX!==b.touchObject.curX&&(b.slideHandler(b.currentSlide),b.touchObject={})},b.prototype.swipeHandler=function(a){var b=this;if(!(b.options.swipe===!1||"ontouchend"in document&&b.options.swipe===!1||b.options.draggable===!1&&-1!==a.type.indexOf("mouse")))switch(b.touchObject.fingerCount=a.originalEvent&&void 0!==a.originalEvent.touches?a.originalEvent.touches.length:1,b.touchObject.minSwipe=b.listWidth/b.options.touchThreshold,b.options.verticalSwiping===!0&&(b.touchObject.minSwipe=b.listHeight/b.options.touchThreshold),a.data.action){case"start":b.swipeStart(a);break;case"move":b.swipeMove(a);break;case"end":b.swipeEnd(a)}},b.prototype.swipeMove=function(a){var d,e,f,g,h,b=this;return h=void 0!==a.originalEvent?a.originalEvent.touches:null,!b.dragging||h&&1!==h.length?!1:(d=b.getLeft(b.currentSlide),b.touchObject.curX=void 0!==h?h[0].pageX:a.clientX,b.touchObject.curY=void 0!==h?h[0].pageY:a.clientY,b.touchObject.swipeLength=Math.round(Math.sqrt(Math.pow(b.touchObject.curX-b.touchObject.startX,2))),b.options.verticalSwiping===!0&&(b.touchObject.swipeLength=Math.round(Math.sqrt(Math.pow(b.touchObject.curY-b.touchObject.startY,2)))),e=b.swipeDirection(),"vertical"!==e?(void 0!==a.originalEvent&&b.touchObject.swipeLength>4&&a.preventDefault(),g=(b.options.rtl===!1?1:-1)*(b.touchObject.curX>b.touchObject.startX?1:-1),b.options.verticalSwiping===!0&&(g=b.touchObject.curY>b.touchObject.startY?1:-1),f=b.touchObject.swipeLength,b.touchObject.edgeHit=!1,b.options.infinite===!1&&(0===b.currentSlide&&"right"===e||b.currentSlide>=b.getDotCount()&&"left"===e)&&(f=b.touchObject.swipeLength*b.options.edgeFriction,b.touchObject.edgeHit=!0),b.options.vertical===!1?b.swipeLeft=d+f*g:b.swipeLeft=d+f*(b.$list.height()/b.listWidth)*g,b.options.verticalSwiping===!0&&(b.swipeLeft=d+f*g),b.options.fade===!0||b.options.touchMove===!1?!1:b.animating===!0?(b.swipeLeft=null,!1):void b.setCSS(b.swipeLeft)):void 0)},b.prototype.swipeStart=function(a){var c,b=this;return 1!==b.touchObject.fingerCount||b.slideCount<=b.options.slidesToShow?(b.touchObject={},!1):(void 0!==a.originalEvent&&void 0!==a.originalEvent.touches&&(c=a.originalEvent.touches[0]),b.touchObject.startX=b.touchObject.curX=void 0!==c?c.pageX:a.clientX,b.touchObject.startY=b.touchObject.curY=void 0!==c?c.pageY:a.clientY,void(b.dragging=!0))},b.prototype.unfilterSlides=b.prototype.slickUnfilter=function(){var a=this;null!==a.$slidesCache&&(a.unload(),a.$slideTrack.children(this.options.slide).detach(),a.$slidesCache.appendTo(a.$slideTrack),a.reinit())},b.prototype.unload=function(){var b=this;a(".slick-cloned",b.$slider).remove(),b.$dots&&b.$dots.remove(),b.$prevArrow&&b.htmlExpr.test(b.options.prevArrow)&&b.$prevArrow.remove(),b.$nextArrow&&b.htmlExpr.test(b.options.nextArrow)&&b.$nextArrow.remove(),b.$slides.removeClass("slick-slide slick-active slick-visible slick-current").attr("aria-hidden","true").css("width","")},b.prototype.unslick=function(a){var b=this;b.$slider.trigger("unslick",[b,a]),b.destroy()},b.prototype.updateArrows=function(){var b,a=this;b=Math.floor(a.options.slidesToShow/2),a.options.arrows===!0&&a.slideCount>a.options.slidesToShow&&!a.options.infinite&&(a.$prevArrow.removeClass("slick-disabled").attr("aria-disabled","false"),a.$nextArrow.removeClass("slick-disabled").attr("aria-disabled","false"),0===a.currentSlide?(a.$prevArrow.addClass("slick-disabled").attr("aria-disabled","true"),a.$nextArrow.removeClass("slick-disabled").attr("aria-disabled","false")):a.currentSlide>=a.slideCount-a.options.slidesToShow&&a.options.centerMode===!1?(a.$nextArrow.addClass("slick-disabled").attr("aria-disabled","true"),a.$prevArrow.removeClass("slick-disabled").attr("aria-disabled","false")):a.currentSlide>=a.slideCount-1&&a.options.centerMode===!0&&(a.$nextArrow.addClass("slick-disabled").attr("aria-disabled","true"),a.$prevArrow.removeClass("slick-disabled").attr("aria-disabled","false")))},b.prototype.updateDots=function(){var a=this;null!==a.$dots&&(a.$dots.find("li").removeClass("slick-active").attr("aria-hidden","true"),a.$dots.find("li").eq(Math.floor(a.currentSlide/a.options.slidesToScroll)).addClass("slick-active").attr("aria-hidden","false"))},b.prototype.visibility=function(){var a=this;document[a.hidden]?(a.paused=!0,a.autoPlayClear()):a.options.autoplay===!0&&(a.paused=!1,a.autoPlay())},b.prototype.initADA=function(){var b=this;b.$slides.add(b.$slideTrack.find(".slick-cloned")).attr({"aria-hidden":"true",tabindex:"-1"}).find("a, input, button, select").attr({tabindex:"-1"}),b.$slideTrack.attr("role","listbox"),b.$slides.not(b.$slideTrack.find(".slick-cloned")).each(function(c){a(this).attr({role:"option","aria-describedby":"slick-slide"+b.instanceUid+c})}),null!==b.$dots&&b.$dots.attr("role","tablist").find("li").each(function(c){a(this).attr({role:"presentation","aria-selected":"false","aria-controls":"navigation"+b.instanceUid+c,id:"slick-slide"+b.instanceUid+c})}).first().attr("aria-selected","true").end().find("button").attr("role","button").end().closest("div").attr("role","toolbar"),b.activateADA()},b.prototype.activateADA=function(){var a=this;a.$slideTrack.find(".slick-active").attr({"aria-hidden":"false"}).find("a, input, button, select").attr({tabindex:"0"})},b.prototype.focusHandler=function(){var b=this;b.$slider.on("focus.slick blur.slick","*",function(c){c.stopImmediatePropagation();var d=a(this);setTimeout(function(){b.isPlay&&(d.is(":focus")?(b.autoPlayClear(),b.paused=!0):(b.paused=!1,b.autoPlay()))},0)})},a.fn.slick=function(){var f,g,a=this,c=arguments[0],d=Array.prototype.slice.call(arguments,1),e=a.length;for(f=0;e>f;f++)if("object"==typeof c||"undefined"==typeof c?a[f].slick=new b(a[f],c):g=a[f].slick[c].apply(a[f].slick,d),"undefined"!=typeof g)return g;return a}}); diff --git a/lms/static/sass/_build-lms-v2.scss b/lms/static/sass/_build-lms-v2.scss index 595cfd3542..9ea180bcb5 100644 --- a/lms/static/sass/_build-lms-v2.scss +++ b/lms/static/sass/_build-lms-v2.scss @@ -28,3 +28,6 @@ @import 'features/course-experience'; @import 'features/course-search'; @import 'features/course-sock'; + +// Views +@import "views/program-marketing-page"; diff --git a/lms/static/sass/views/_program-marketing-page.scss b/lms/static/sass/views/_program-marketing-page.scss new file mode 100644 index 0000000000..e0d57ff8eb --- /dev/null +++ b/lms/static/sass/views/_program-marketing-page.scss @@ -0,0 +1,1739 @@ +/* Box shadow mixin */ +// example: @include box-shadow( 2px, 3px, 6px, rgba(0, 0, 0, 0.3) ); +@mixin box-shadow($x, $y, $blur, $color, $inset: false) { + @if $inset { + -webkit-box-shadow: inset $x $y $blur $color; + -moz-box-shadow: inset $x $y $blur $color; + box-shadow: inset $x $y $blur $color; + } @else { + -webkit-box-shadow: $x $y $blur $color; + -moz-box-shadow: $x $y $blur $color; + box-shadow: $x $y $blur $color; + } +} + +#program-details-page { + .main-banner { + height: 260px; + background: palette(primary, dark); + margin-bottom: 20px; + position: relative; + @media(max-width: 767px){ + padding: 0 12px 25px; + height: auto; + } + @media (min-width: 768px) { + height: 333px; + margin-bottom: 20px; + } + @media (min-width: 1024px) { + margin-bottom: 50px + } + + .btn-play { + background-image: none; + background-color: transparent; + box-shadow: none; + padding: 0; + margin-left: -moz-calc((100% - 74px) / 2); + margin-left: -webkit-calc((100% - 74px) / 2); + margin-left: calc((100% - 74px) / 2); + margin-top: 125px; + margin-bottom: 94px; + height: 74px; + width: 74px; + color: #fff; + background: none; + border: 4px solid #fff; + border-radius: 50%; + + .icon { + padding-left: 8px; + } + + &:hover { + opacity: 0.7; + outline: none; + } + } + + .org-logo { + display: inline-block; + position: relative; + overflow: hidden; + margin-bottom: 8px; + background: rgba(255, 255, 255, .8); + @include box-shadow(0, 3px, 4px, rgba(0, 0, 0, 0.5)); + @media (max-width: 767px) { + margin-bottom: 12px; + max-width: 120px; + box-shadow: none; + } + @media (min-width: 768px) { + max-width: 150px; + position: absolute; + top: 0; + } + @media (min-width: 1024px) { + max-width: 200px; + } + + img { + max-width: 100%; + max-height: 95px; + } + &:after{ + content: ""; + position: absolute; + top: 0; + left: -2px; + right: -2px; + box-shadow: 0px 1px 3px #333; + height: 1px; + background: #a1a5a5; + z-index: 1; + } + } + + .banner-title, + .banner-description { + color: $white; + } + + .banner-title { + font-size: 1.5em; + font-weight: 600; + text-align: left; + letter-spacing: inherit; + margin-bottom: 10px; + @media (min-width: 768px) { + margin-top: 105px; + font-size: 1.9em; + } + @media (min-width: 1024px) { + font-size: 2em; + } + @media (min-width: 1280px) { + font-size: 2.25em; + } + } + + .banner-description { + min-height: 60px; + font-size: 1.06em; + font-weight: 600; + line-height: 1.35em; + @media (max-width: 767px) { + margin-bottom: 14px; + font-weight: normal; + } + @media (min-width: 768px) { + font-size: 1.1em; + } + @media (min-width: 1024px) { + font-size: 1.25em; + } + } + .grid-manual, .row{ + @media(max-width: 767px){ + display: block; + } + } + .grid-manual{ + .btn-start{ + min-width: 300px; + padding: 0.75rem 2rem; + font-size: 1.25rem; + text-decoration: none; + text-align: center; + font-weight: 600; + border-radius: 0; + background: #008100; + background: -moz-linear-gradient(top, #008100 0%, #0a570a 100%); + background: -webkit-linear-gradient(top, #008100 0%,#0a570a 100%); + background: linear-gradient(to bottom, #008100 0%,#0a570a 100%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#008100', endColorstr='#0a570a',GradientType=0 ); + border: 0; + } + } + } + + .left-col, + .right-col { + @media (min-width: 768px) { + padding: 0 0 15px; + } + @media (min-width: 1024px) { + padding: 15px 0; + } + } + + .left-col { + @media (min-width: 768px) { + border-right: 1px solid #979797; + padding-right: 20px; + } + @media (min-width: 1024px) { + padding-right: 50px; + } + } + + .right-col { + @media (min-width: 768px) { + padding-left: 0; + } + @media (min-width: 1024px) { + padding-left: 30px; + } + } + + .courses-in-program .course-card .tbl-view .tbl-col:first-child{ + width: 70% !important; + @media (max-width: 768px) { + width: 95% !important; + } + } + + .courses-in-program .course-card { + background: $white; + padding: 10px; + margin-bottom: 30px; + border: 1px solid palette(grayscale, back); + @include box-shadow(0, 1px, 5px, rgba(0, 0, 0, 0.4)); + border-radius: 4px; + @media (min-width: 768px) { + padding: 20px; + border: 1px solid #979797; + box-shadow: none; + border-radius: 0; + } + + .title { + margin-bottom: 10px; + font-size: 18px; + text-decoration: underline; + a{ + color: #005686; + } + + small { + display: block; + font-size: 0; + margin-top: 5px; + + > span { + display: inline-block; + text-decoration: none; + font-size: 1rem !important; + &:first-child { + border-right: 1px solid #4a4a4a; + padding-right: 6px; + margin-right: 6px; + @media (min-width: 768px) { + padding-right: 10px; + margin-right: 10px; + } + } + } + } + } + + p { + margin-bottom: 0; + font-weight: normal; + font-size: 1rem; + } + + &:last-child { + margin-bottom: 0; + } + } + + .courses-in-program.container { + display: block; + padding: 20px 0; + background: #ececec; + margin-top: 15px; + @media (min-width: 768px) { + margin-top: 0; + background: $white; + padding: 20px; + } + + .course-cards { + padding-top: 5px; + @media (min-width: 768px) { + width: 100% !important; + transform: none !important; + } + } + + > .hd { + padding: 0 1.25rem !important; + margin-bottom: 15px; + @media (min-width: 768px) { + padding: 0; + font-size: 18px !important; + } + @media (min-width: 1024px) { + font-size: 22px !important; + } + } + + .course-card { + margin-bottom: 20px; + min-height: 283px; + position: relative; + @media (max-width: 767px) { + min-height: 300px; + margin-left: 5px; + margin-right: 5px; + padding-bottom: 50px; + overflow: hidden; + position: relative; + } + + .tbl-view { + .tbl-col { + .btn-enroll-now { + position: absolute; + left: 0; + right: 0; + bottom: 0; + width: 100%; + border-radius: 0; + line-height: 22px; + background: #0f8012; + @media (min-width: 768px) { + position: relative; + border: 1px solid #ccc; + max-width: 200px; + } + } + + &:first-child { + @media (min-width: 768px) { + width: 75%; + } + + p { + @media (min-width: 768px) { + max-width: 700px; + } + } + } + } + } + .btn-enroll-now{ + width: 100% !important; + max-width: 300px !important; + min-height: 50px; + font-size: 1.33rem; + font-weight: bold; + } + } + + .pagingInfo { + display: block; + text-align: center; + @media (min-width: 768px) { + display: none; + } + } + } + + .copy-meta-mobile{ + font-size: 0.875rem; + line-height: 1.6em; + } + + //Helper Classes + .pull-left{ + float: left !important; + } + + .pull-right{ + float: right !important; + } + + .block{ + display: block; + } + + a{ + text-decoration: none; + &:hover{ + opacity: 0.8; + text-decoration: none; + } + &:focus{ + text-decoration: none; + } + } + .no-padding{ + padding: 0 !important; + } + #success-message{ + padding: 0; + .alert { + min-width: 0; + border-left-width: 0; + border-right-width: 0; + border-bottom-width: 0; + box-shadow: none; + } + } + .window-wrap{ + background-color: transparent; + } + .content-wrapper{ + max-width: none; + padding-top: 0; + padding-bottom: 0; + .container { + border: none; + } + } + .grid-container{ + padding: 0 1rem; + } + .show-user-menu{ + display: block !important; + right: -16px !important; + } + + .hidden-mobile{ + display: none; + } + .visible-mobile{ + display: block; + } + .btn-success{ + background-color: palette(success, text) !important; + color: $white !important; + border-color: palette(success, text); + &:hover{ + background-color: palette(success, accent) !important; + } + } + .btn-block{ + width: 100% !important; + } + .bookmark-button:hover { + color: #0071bb !important; + border-color: transparent !important; + } + .inner-container{ + @include grid-container(); + @include span(12); + padding: 0 1.25rem; + } + h2{ + font-size: 1.5rem; + font-family: "Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif; + margin: 1.25rem 0; + text-transform: none; + } + h1, h2, h3, h4, h5, h6{ + font-family: "Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif; + } + .col-centered{ + float: none !important; + margin-left: auto !important; + margin-right: auto !important; + } + .input-group{ + margin-bottom: 1.25rem; + } + .input-lg{ + line-height: 55px !important; + height: 55px !important; + padding: 0 1.25rem !important; + } + .form-block{ + label, input, select, button, textarea{ + display: block; + width: 100%; + font-family: "Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif; + font-style: normal; + margin-bottom: 0.5rem !important; + &.has-error{ + border-color: palette(error, text); + border-radius: 4px 4px 0 0; + margin-bottom: 0 !important; + + .field-message{ + border-radius: 0 0 4px 4px; + width: 100%; + } + } + } + input{ + box-shadow: none; + border: 1px solid palette(grayscale, back); + border-radius: 4px; + font-size: 1rem; + width: 100%; + &:focus, &:active{ + box-shadow: none; + border-color: palette(grayscale, base); + } + } + select{ + -webkit-appearance: none; + -moz-appearance: none; + border-color: palette(grayscale, back); + appearance: none; + &::-ms-expand{ + display: none; + } + } + textarea{ + height: 280px; + border-color: palette(grayscale, back); + box-shadow: none; + resize: none; + padding: 1rem; + } + button{ + margin-top: 2.5rem; + padding: 1.25rem; + } + } + + .list-bulleted{ + li{ + margin-bottom: 0.2rem !important; + padding-left: 0.5rem !important; + line-height: 1.5rem; + color: palette(grayscale, base); + .brand-link{ + display: inline; + } + } + } + + .btn-enroll-mobile{ + margin-bottom: 2rem; + .btn-enroll{ + max-width: 95%; + margin: auto; + border-radius: 3px; + } + } + + #course-trailer { + .trailer-link { + color: $white; + font-weight: bold; + + span { + text-decoration: underline; + } + + &:hover { + cursor: pointer; + } + } + } + + #accordion-group { + font-family: "Open Sans", Arial, Helvetica, sans-serif; + + .accordion-item { + border-bottom: 1px solid palette(primary, dark); + .accordion-head { + background: #004165; + padding: 18px 18px 18px 84px; + color: $white; + border-radius: 0; + border: none; + margin: 0; + font-size: 1.13em; + position: relative; + + &:hover, + &.active, + &:focus{ + cursor: pointer; + } + + &:before { + content: "\f054"; + font-family: FontAwesome; + position: absolute; + left: 44px; + top: 20px; + width: 18px; + height: 22px; + } + + &.ui-state-active { + + &:before { + content: "\f078"; + left: 40px; + } + } + } + + .accordion-content { + display: none; + padding: 15px; + background: #f6f6f6; + border: none; + + p, + ul { + color: #4a4a4a; + font-size: .85em; + line-height: 1.5em; + margin-bottom: 15px; + + &:last-child { + margin-bottom: 0; + } + } + + p { + + &:last-child { + margin: 0; + } + } + + ul { + + li { + padding-left: 0 !important; + color: #4a4a4a; + } + } + } + + &.show { + .accordion-content { + display: block; + } + } + + &:nth-of-type(2) .accordion-head { + background: #004a74; + } + &:nth-of-type(3) .accordion-head { + background: #00527f; + } + &:nth-of-type(4) .accordion-head { + background: #005d91; + } + &:nth-of-type(5) .accordion-head { + background: #016fad; + } + &:nth-of-type(6) .accordion-head { + background: #1878ad; + } + + &.instructors-mobile-list { + @extend .visible-sm; + + .accordion-content { + background: $white; + padding: 0; + + .instructor-profiles { + margin: 0; + + .profile-item { + padding: 15px 25px; + margin: 0; + + .details { + padding-left: 10px; + + .name { + font-size: .8em; + } + .dept { + font-size: .7em; + } + } + + &:nth-child(even) { + background: #f0f0f0; + } + } + } + } + } + } + } + + // Program marketing page + .main-banner { + &:before { + content: ''; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + background: #000; + opacity: 0.35; + } + + .grid-manual { + z-index: 1; + position: relative; + + .btn-start { + color: #ffffff !important; + } + } + } + + #courses { + .btn-enroll { + text-align: center; + font-size: 1.3em; + font-weight: bold; + } + } + + // Program catalog listing + + .program-list { + .programs-listing-item { + box-sizing: border-box; + box-shadow: 1px 2px 5px #ccc; + position: relative; + height: 360px; + overflow: visible; + min-height: 0; + border: none; + display: block; + margin: 0 auto 40px; + background: $white; + border-radius: 0; + + .program-image { + height: 142px; + position: relative; + overflow: hidden; + + .cover-image { + height: 142px; + + img { + width: 100%; + height: auto; + } + + &:before { + content: ''; + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + margin: auto; + background: black; + opacity: 0; + transition: all 0.2s ease-out; + } + .learn-more { + left: calc(50% - 100px); + box-sizing: border-box; + position: absolute; + z-index: 100; + top: 62px; + padding: 0 20px; + width: 200px; + height: 50px; + border-color: #0074b4; + border-radius: 3px; + background: #0074b4; + color: #fff; + line-height: 50px; + text-align: center; + opacity: 0; + text-transform: none; + transition: all 0.25s ease; + } + } + } + + .banner { + background: #065784; + color: $white; + padding-right: 15px; + line-height: 18px; + font-weight: bold; + font-size: 0.7em; + text-align: right; + text-transform: uppercase; + } + + .program-info { + padding: 12px 15px 5px; + + .program-org { + font-weight: normal; + font-size: 0.9em; + color: #3d3e3f; + margin: 0; + line-height: 16px; + } + + .program-title { + max-height: 55px; + overflow: hidden; + color: #222; + font-size: 1.25em; + line-height: 1.333em; + margin-bottom: 5px; + } + + .program-subtitle { + font-size: 1em; + margin-bottom: 33px; + line-height: 1.25em; + height: 40px; + color: palette(primary, dark); + overflow: hidden; + } + } + + .program-footer { + display: table; + width: 100%; + padding: 0 15px 15px; + position: absolute; + bottom: 0; + + .availability, + .program-logo { + display: table-cell; + } + + .availability { + text-align: left; + font-size: 0.9em; + line-height: 20px; + color: palette(primary, dark); + } + + .program-logo { + text-align: right; + width: 75px; + } + } + + &:before, + &:after { + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.2); + content: ''; + position: absolute; + width: 100%; + height: 100%; + background: #d5d5d5; + border: 1px solid #b5b5b5; + } + + &:before { + left: -5px; + top: -5px; + z-index: -1; + } + + &:after { + left: -10px; + top: -10px; + z-index: -2; + } + + &:hover { + opacity: 1; + + .program-image { + .cover-image { + .learn-more { + opacity: 1; + } + &:before { + opacity: .6; + } + } + } + } + } + } + + .container { + min-width: auto; + border: none; + max-width: 73.125rem; + padding: 20px 1rem; + } + + > .grid-manual { + > .row { + align-items: stretch; + + [class*='col'] { + @media (max-width: 767px) { + margin: 0 auto; + width: 100%; + padding: 0; + } + } + } + } + + .instructors-title { + color: palette(primary, dark); + font-family: $sans-serif; + text-transform: none; + letter-spacing: 0px; + @media (min-width: 768px) { + margin-top: 5px; + font-size: 18px !important; + } + @media (min-width: 1024px) { + font-size: 22px !important; + } + } + + .instructor-profiles { + margin-bottom: 30px; + + .profile-item { + @extend .tbl-view; + margin-bottom: 25px; + + .avatar, + .details { + @extend .tbl-col; + display: table-cell; + } + + .avatar { + width: 54px; + @media (min-width: 768px) { + width: 60px; + } + + .img-holder { + width: 70px; + height: 70px; + border-radius: 50%; + border: 2px solid palette(primary, dark); + overflow: hidden; + img { + max-width: 100%; + } + } + } + + .details { + padding-left: 15px; + + .name { + color: palette(primary, dark); + font-size: 1em; + margin-bottom: 0; + a{ + font-weight: 600; + text-decoration: underline; + } + } + .dept { + font-size: 1em; + line-height: 1.5em; + } + } + + &:last-child { + margin-bottom: 0; + } + } + } + + .visible-sm { + @media (min-width: 768px) { + display: none !important; + } + } + + .hidden-sm { + @media (max-width: 767px) { + display: none !important; + } + } + + .pagination { + margin: 10px 0 50px; + width: 100%; + display: block; + .pages{ + width: calc(100% - 120px); + text-align: right; + display: inline-block; + font-size: 14px; + } + .controls{ + text-align: center; + display: inline-block; + width: 115px; + a{ + display: inline-block; + width: 50px; + &:first-child{ + border-right: 1px solid $light-gray2; + } + .fa{ + font-size: 1.75rem; + color: $border-color; + } + &.active{ + .fa{ + color: palette(primary, dark); + } + } + } + } + } + + .program-desc-tbl { + margin-bottom: 20px; + + @extend .tbl-view; + border: 1px solid #e3e3e3; + border-radius: 6px; + @media (min-width: 768px) { + border: 2px solid palette(primary, base); + border-radius: 0; + padding: 5px 15px; + } + @media (min-width: 1024px) { + padding: 8px 15px; + } + + .item { + padding: 10px 10px 12px !important; + font-size: .9em; + border-color: #d0d0d0; + margin: 0; + @media (min-width: 768px) { + font-size: 1em; + padding: 15px 0 !important; + } + @media (min-width: 1024px) { + font-size: 1em; + padding: 15px !important; + } + span { + font-size: 1em !important; + + a{ + font-weight: 600; + font-size: 1em !important; + text-decoration: underline; + } + } + + > span { + @extend .tbl-col; + display: block; + width: 100%; + color: palette(primary, dark); + line-height: 1.4em; + + @media (min-width: 768px) { + display: inline-block; + width: 50%; + } + + .fa { + display: none; + margin-right: 30px; + margin-left: 20px; + font-size: 1.4em !important; + @media (min-width: 1024px) { + display: inline-block; + } + } + + + a { + @media (max-width: 767px) { + color: palette(primary, dark); + } + } + + &:first-child { + color: palette(primary, dark); + margin-bottom: 5px; + @media (max-width: 767px) { + margin-bottom: 0; + } + font-size: .85em; + @media (max-width: 767px) { + text-transform: uppercase; + } + @media (min-width: 768px) { + width: 48%; + color: palette(primary, dark); + margin-bottom: 0; + font-size: 1.024em; + } + } + } + } + } + + .data-table{ + @media(max-width: 767px){ + padding: 0 20px; + } + .list-divided{ + @media(min-width: 767px){ + padding: 0 12px !important; + } + + .item{ + margin-top: 0.625rem; + line-height: 1.4em; + padding: 15px 15px 19px 25px !important; + border-bottom: 1px solid $m-gray-l3 !important; + @media (min-width: 768px) { + padding: 15px 0px 19px 0 !important; + } + @media(max-width: 767px){ + margin: 0 !important; + } + &:last-child{ + border-bottom: 0 !important; + } + } + } + } + + .program-quote { + margin-left: 0; + margin-right: 0; + margin-bottom: 0; + line-height: 1.4; + font-size: .8em; + @media (min-width: 768px) { + line-height: 1.8; + font-size: 1em; + } + + span { + display: block; + margin-bottom: 10px; + @media (min-width: 768px) { + display: inline; + } + + &.writer { + font-weight: 600; + padding-left: 50px; + @media (min-width: 768px) { + padding-left: 0; + } + + &:before { + @media (min-width: 768px) { + //content: '—'; + content: '\2014'; + margin-right: 3px; + margin-left: 5px; + } + } + } + img{ + height: auto; + margin-left: 6px; + width: 100%; + } + } + + &.visible-mobile { + font-size: 1em; + line-height: 1.5; + } + } + + .faq-links-list { + + li { + margin-bottom: 15px; + + a { + display: block; + position: relative; + color: $blue; + padding-left: 30px; + + &:before { + font-family: "FontAwesome"; + content: "\f105"; + position: absolute; + left: 5px; + top: 1px; + } + & + div { + padding: 10px 30px; + font-size: 1rem; + color: $black; + } + } + &.expanded { + a:before { + content: "\f107"; + } + } + } + + } + + .ui-state-default .ui-icon { + display: none; + } + + //Modals + .modal { + border-radius: 0px !important; + background: #FFFFFF !important; + + .inner-wrapper { + padding: 0px !important; + border: none !important; + } + } + .modal-custom { + width: 320px; + background-color: $white; + padding: 30px 30px; + position: fixed !important; + overflow: auto; + overflow-x: hidden; + top: 10%; + bottom: 10%; + left: calc(50% - 160px) !important; + margin-left: 0 !important; + z-index: 999; + .btn-close { + position: absolute !important; + right: 20px !important; + top: 20px !important; + cursor: pointer; + .fa { + font-size: 1.75em; + color: black; + } + } + &.custom-video-modal { + padding: 10px; + max-height: 360px; + .inner-wrapper, iframe { + height: 100%; + width: 100%; + } + } + .modal-body{ + overflow: hidden !important; + position: relative !important; + width: 100%; + .modal-header{ + display: block; + width: 100%; + margin-bottom: 2rem !important; + margin-left: 0 !important; + margin-right: 0 !important; + .instructor-data{ + display: block; + .thumbnail{ + display: block; + width: 100%; + padding-bottom: 0; + img{ + border-radius: 50%; + border: 5px solid palette(grayscale, back); + margin-bottom: 1rem; + } + } + h3{ + display: block; + width: 100%; + vertical-align: middle; + font-size: 1.5em; + line-height: normal; + color: black; + margin-bottom: 0; + span{ + display: block; + font-size: 1rem; + line-height: 1.1rem; + color: black; + &:last-child{ + color: black; + font-size: .8rem; + line-height: 1.1rem; + margin-top: 5px; + } + } + } + } + } + .instructor-bio{ + line-height: 1.5rem; + margin-bottom: 2rem; + color: black; + margin: 0 !important; + font-size: 1rem; + } + .links{ + a{ + margin-right: 0; + display: block; + margin-bottom: 0.5rem; + } + } + } + } + + //Media Queries + + @media screen and (min-width: 30em){ + .hero{ + .tint-dark { + .grid-manual { + .text-tint { + .btn-neutral { + padding: 0.8em 2em; + } + } + } + } + } + .courses-section { + .courses-container { + .highlighted-courses { + .courses { + .course-info{ + height: 165px; + } + .course-list{ + .courses-listing-item{ + padding: 0; + } + } + + } + } + } + } + .footer-main{ + .footer-logo{ + text-align: center; + } + } + .visible-mobile{ + display: none; + } + .hidden-mobile{ + display: block; + } + .testimonial-main{ + p{ + text-align: left; + } + img{ + margin-bottom: 0; + } + } + } + + @media screen and (min-width: 48em){ + .btn-enroll-mobile{ + display: none; + } + header.header-main{ + .logo a img { + height: 44px; + } + .collapsed-button{ + display: none; + } + .nav-collapse{ + ul{ + display: block; + transition: all .2s; + position: relative; + top: inherit; + right: inherit; + left: inherit; + border-top: 0; + background-color: transparent; + box-shadow: none; + padding: 0; + li{ + width: auto; + text-align: left; + line-height: 100px; + padding: 0 0.5rem; + a{ + &.btn-neutral{ + padding: 0.625rem 1.25rem; + } + } + &.user-account{ + ul{ + position: absolute; + right: 1rem; + top: 100%; + width: 100%; + margin-top: -1.5rem; + li{ + display: block; + float: none; + line-height: normal; + a{ + padding: 0.5rem; + display: inline-block; + } + } + } + } + } + } + } + } + .footer-main{ + .footer-logo{ + text-align: left; + } + .open-edx-logo{ + ul{ + li{ + text-align: right; + img{ + max-width: 80%; + } + } + } + } + } + .hero { + .tint-dark { + max-height: 350px; + .grid-manual { + .text-tint { + p { + font-size: 40px; + span { + display: block; + font-size: 1.5rem; + } + } + } + } + } + &.hero-video{ + background: rgba(0,0,0,0.6); + .hero-image { + display: block; + background-size: cover !important; + } + .tint-dark { + background: -moz-linear-gradient(left, rgba(0, 0, 0, 0.65) 0%, rgba(0, 0, 0, 0) 100%); /* FF3.6-15 */ + background: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.65) 0%, rgba(0, 0, 0, 0) 100%); /* Chrome10-25,Safari5.1-6 */ + background: linear-gradient(to right, rgba(0, 0, 0, 0.65) 0%, rgba(0, 0, 0, 0) 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */ + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#a6000000', endColorstr='#00000000', GradientType=1); /* IE6-9 */ + } + .grid-container{ + padding: 0 1rem; + .row{ + height: 22rem; + .description{ + .data{ + padding: 11.5% 2% 0 0; + h1{ + color: $white; + font-size: 2.2rem; + } + p{ + color: $white; + font-size: 1.3rem; + } + } + } + .video{ + float: right; + padding-left: 1.04167%; + padding-right: 1.04167%; + .video-data{ + line-height: 352px; + max-width: 95%; + img{ + border: 3px solid $white; + width: auto; + } + } + } + } + } + &.no-video .grid-container .row .description .data{ + margin: 0; + } + } + } + .course-info { + .course-detail { + [class*="col"] { + margin-bottom: 0; + } + .btn-enroll{ + margin-top: 0; + } + } + .description-container{ + .expandable{ + max-height: 224px; + } + } + } + .modal-custom{ + display:none; + width: 540px; + padding: 30px 30px; + left: calc(50% - 270px) !important; + .focusKeeper { + width: 0; + height: 0; + overflow: hidden; + } + .modal-body{ + .modal-header{ + display: table; + width: 100%; + .instructor-data{ + display: table-row; + .thumbnail{ + display: table-cell; + width: 25%; + padding-bottom: 0; + img{ + margin-bottom: 0; + } + } + h3{ + display: table-cell; + width: 65%; + padding: 1rem; + } + } + } + + .links{ + a{ + margin-right: 1.5rem; + display: inline-block; + margin-bottom: 0; + } + } + } + } + .rtl .hero.hero-video .tint-dark .grid-container .row .description{ + padding-right: 1.04167%; + } + .course-card{ + .title{ + small{ + > span{ + font-size: 0.8rem !important; + } + } + } + } + } + + @media screen and (min-width: 64em){ /* 980px */ + header.header-main { + .nav-collapse { + ul { + li { + padding: 0 0.9rem; + } + } + } + } + .hero{ + &.hero-video .grid-container .row .description .data h1 { + font-size: 2.5rem; + } + } + .footer-main { + .footer-logo { + text-align: left; + } + } + .course-card{ + .title{ + small{ + > span{ + font-size: 1rem !important; + } + } + } + } + } + + @media screen and (min-width: 80em){ + .footer-main { + .footer-logo { + text-align: left; + } + } + } + + // For RTL + .rtl { + header{ + &.header-main{ + .list-inline li{ + float: left; + } + .nav-collapse .collapsed-button{ + left: 20px; + right: auto; + } + } + } + .hero.hero-video .grid-container .row { + .description{ + padding-right: 2%; + .data { + h1 { + text-align: right; + } + } + } + .video{ + float: left; + } + } + .footer-main ul li:last-child{ + text-align: right; + } + .course-index .accordion .course-navigation .button-chapter .group-heading { + padding: 15px 40px 15px 20px; + } + .ui-state-default.slick-header-column { + float: right !important; + left: inherit !important; + width: 84px !important; + height: 25px; + padding: 5px; + } + .grid-canvas { + width: 1097px !important; + } + .instructor-dashboard-content-2 { + .slickgrid .slick-cell { + float: right; + right: 0; + left: inherit; + position: relative !important; + width: 84px; + + &.l0.r0 { + border-right: 1px dotted silver; + } + &.l12.r12 { + border-right: 0; + } + } + .content-history-table-inner .slickgrid .slick-cell { + width: 219px; + } + .report-downloads-table .slickgrid .slick-cell { + width: 100%; + } + } + .slick-header-columns { + right: 0 !important; + left: inherit !important; + width: 1097px !important; + } + .content-history-table-inner .ui-state-default.slick-header-column { + width: 219px !important; + } + } + + @media(min-width: 768px) { + header.header-main .list-inline li.user-account ul:before { + right: 0.4rem; + } + .course-card{ + display: inline-block; + margin: 0 calc(0.5 * 2.6rem) 30px calc(0.5 * 1rem) !important; + width: calc(50% - 22px); + vertical-align: top; + position: absolute; + height: 283px; + max-height: 283px; + overflow: hidden; + &:nth-child(even){ + margin-right: 0 !important; + } + .title{ + a{ + height: auto; + max-height: 50px; + overflow: hidden; + display: block; + color: #005686; + text-decoration: underline; + } + small{ + margin-top: 10px; + > span{ + font-size: 0.9rem; + } + } + } + p{ + margin-bottom: 30px; + min-height: 75px; + max-height: 75px; + overflow: hidden; + position: absolute; + bottom: 66px; + left: 20px; + right: 20px; + } + .btn-enroll{ + display: inline-block; + background-color: $green !important; + min-width: 220px; + padding: 10px 30px; + font-size: 16px !important; + font-weight: 600 !important; + text-decoration: none; + position: absolute; + bottom: 20px; + left: 20px; + } + } + } + + img{ + max-width: 100%; + } + + @media(min-width: 1024px) { + header.header-main .list-inline li.user-account ul:before { + right: 0.72rem; + } + } +} diff --git a/lms/templates/courseware/program_marketing.html b/lms/templates/courseware/program_marketing.html index f146cfe02e..b9eb161ed0 100644 --- a/lms/templates/courseware/program_marketing.html +++ b/lms/templates/courseware/program_marketing.html @@ -1,3 +1,424 @@ <%page expression_filter="h"/> +<%inherit file="../main.html"/> +<%! +from datetime import datetime -## This page is intentionally left blank. You can add your own program marketing page using comprehensive theming (http://edx.readthedocs.io/projects/edx-installing-configuring-and-running/en/latest/configuration/changing_appearance/theming/enable_themes.html?highlight=theming). +from django.core.urlresolvers import reverse +from django.utils.translation import ugettext as _ +from mako import exceptions + +from openedx.core.djangolib.markup import HTML, Text +%> + +<%namespace name='static' file='../static_content.html'/> + +<% +faq = program['faq'] +program_type = program['type'] +program_type_slug = program['type_slug'] +title = program['title'] +status = program['status'] +courses = program['courses'] +subtitle = program['subtitle'] +overview = program['overview'] +instructors = program['instructors'] +job_outlook_items = program['job_outlook_items'] +weeks_to_complete = program['weeks_to_complete'] +full_program_price_format = '{0:.0f}' if program['full_program_price'].is_integer() else '{0:.2f}' +full_program_price = full_program_price_format.format(program['full_program_price']) +endorsement = program['individual_endorsements'][0] if program['individual_endorsements'] else {} +endorsement_quote = endorsement.get('quote', '') +endorser = endorsement.get('endorser', {}) +endorsement_image = endorser.get('profile_image', {}).get('medium', {}).get('url', '') +endorsement_name = endorser.get('given_name', '') +endorsement_position = (endorser.get('position') or {}).get('title', '') +endorsement_organization = (endorser.get('position') or {}).get('organization_name', '') +expected_learning_items = program['expected_learning_items'] +authoring_organizations = program['authoring_organizations'] +min_hours_effort_per_week = program['min_hours_effort_per_week'] +max_hours_effort_per_week = program['max_hours_effort_per_week'] +video_url = (program.get('video', {}) or {}).get('src', '') +banner_image = program.get('banner_image', {}).get('large', {}).get('url', '') +description_max_length = 250 +%> + +<%static:css group='style-main-v2'/> +<%static:css group='style-learner-dashboard'/> + +<%block name="js_extra"> + + + + + +<%block name="pagetitle">${program['title']} + +
+ + +
+
+
+
    +
  • + + + ${_('Number of Courses')} + + + ${Text(_('{number_of_courses} courses in program')).format( + number_of_courses=len(courses) + )} + +
  • +
  • + + + ${_('Average Length')} + + + ${Text(_('{weeks_to_complete} weeks per course')).format( + weeks_to_complete=weeks_to_complete + )} + +
  • +
  • + + + ${_('Effort')} + + + ${Text(_('{min_hours_effort_per_week}-{max_hours_effort_per_week} hours per week, per course')).format( + max_hours_effort_per_week=max_hours_effort_per_week, + min_hours_effort_per_week=min_hours_effort_per_week + )} + +
  • +
  • + + + ${_('Price (USD)')} + + + ${Text(_('${full_program_price} for entire program')).format( + full_program_price=full_program_price + )} + +
  • +
+
+
+
${_('Overview')}
+
+

${overview}

+
+
+
+
${_('Job Outlook')}
+
+
    + % for item in job_outlook_items: +
  • ${item}
  • + % endfor +
+
+
+
+
${_("What You'll Learn")}
+
+
    + % for item in expected_learning_items: +
  • ${item}
  • + % endfor +
+
+
+
+
${_("Instructors")}
+
+
+ <% index = 0 %> + % for instructor in instructors: + <% index += 1 %> +
+
+
+ + ${instructor.get('name')} + +
+
+
+ + % if instructor.get('position'): +
${instructor['position'].get('organization_name')}
+ % endif +
+ +
+ %endfor +
+
+
+ + % try: + <%include file="_${program_type_slug}_faq.html" args="program_type=program_type" /> + % except exceptions.TemplateLookupException: + ## pass + % endtry + +
+
${_("FAQ")}
+
+ +
+
+
+
+
+ % if endorsement: + "${endorsement_quote}" + % if endorser and endorsement_image: + ${_('Endorser Image')} + + ${endorsement_name}, + ${endorsement_position}, + ${endorsement_organization} + + % endif + % endif +
+
+
+ + +
+
+ +
+

+ ${Text(_('Courses in the {program_type}')).format( + program_type=program_type + )} +

+
+ % for course in courses: + % if course.get('course_runs'): +
+
+
+

+ ${course['title']} + + + + ${Text(_('Starts {course_start_datetime}')).format( + course_start_datetime=datetime.strptime(course['course_runs'][0]['start'], '%Y-%m-%dT%H:%M:%SZ').strftime('%B %-d, %Y') + )} + + + % if course['course_runs'][0]['pacing_type'] == "instructor_paced": + ${_('Instructor - Paced')} + % else: + ${_('Self - Paced')} + % endif + +

+

+ % if course['course_runs'][0]['short_description']: + ${course['course_runs'][0]['short_description']} + % endif +

+

+ % if course['course_runs'][0]['short_description']: + ${course['course_runs'][0]['short_description'][:description_max_length]} + % if len(course['course_runs'][0]['short_description']) > description_max_length: + ... + % endif + % endif +

+
+
+
+ % endif + % endfor +
+ +
+ + +
diff --git a/openedx/core/djangoapps/programs/tests/test_utils.py b/openedx/core/djangoapps/programs/tests/test_utils.py index f3cd99ed1a..59dfd28cb5 100644 --- a/openedx/core/djangoapps/programs/tests/test_utils.py +++ b/openedx/core/djangoapps/programs/tests/test_utils.py @@ -886,6 +886,18 @@ class TestProgramMarketingDataExtender(ModuleStoreTestCase): self.assertEqual(data['full_program_price'], program_full_price) self.assertEqual(data['avg_price_per_course'], program_full_price / self.number_of_courses) + def test_course_pricing_when_all_course_runs_have_no_seats(self): + course = ModuleStoreCourseFactory() + course = self.update_course(course, self.user.id) + course_run = CourseRunFactory(key=unicode(course.id), seats=[]) + program = ProgramFactory(courses=[CourseFactory(course_runs=[course_run])]) + + data = ProgramMarketingDataExtender(program, self.user).extend() + + self.assertEqual(data['number_of_courses'], len(program['courses'])) + self.assertEqual(data['full_program_price'], 0.0) + self.assertEqual(data['avg_price_per_course'], 0.0) + @ddt.data(True, False) @mock.patch(UTILS_MODULE + '.has_access') def test_can_enroll(self, can_enroll, mock_has_access): diff --git a/openedx/core/djangoapps/programs/utils.py b/openedx/core/djangoapps/programs/utils.py index f962141aae..a5a1fc6cf1 100644 --- a/openedx/core/djangoapps/programs/utils.py +++ b/openedx/core/djangoapps/programs/utils.py @@ -504,9 +504,9 @@ class ProgramMarketingDataExtender(ProgramDataExtender): self.instructors = {} # Values for programs' price calculation. - self.data['avg_price_per_course'] = 0 + self.data['avg_price_per_course'] = 0.0 self.data['number_of_courses'] = 0 - self.data['full_program_price'] = 0 + self.data['full_program_price'] = 0.0 def _extend_program(self): """Aggregates data from the program data structure."""