Lỗi typeerror o.pagerel.on is not a function năm 2024

This code is written in jquery and you might haven't called jquery in your theme.liquid file or you have called jquery after the theme.js file

For that, navigate to theme.liqudi and add add below script under </head> tag or before theme.js file in theme.liquid.

<script src="https://code.jquery.com/jquery-3.6.0.min.js" async></script>

just like the below example.

<head>
/* other script and codes... */
<script src="https://code.jquery.com/jquery-3.6.0.min.js" async></script>
</head>

If you still facing trouble then just drop a mail at [email protected]. our dev team will help you to resolve this query.

// the float attribute is a reserved word in compressors like YUI compressor and need to be quoted

48 'float': slider.settings.mode \=== 'horizontal' ? 'left' : 'none', listStyle: 'none', position: 'relative' }); // apply the calculated width after the float is applied to prevent scrollbar interference slider.children.css('width', getSlideWidth()); // if slideMargin is supplied, add the css if (slider.settings.mode \=== 'horizontal' && slider.settings.slideMargin \> 0) { slider.children.css('marginRight', slider.settings.slideMargin); } if (slider.settings.mode \=== 'vertical' && slider.settings.slideMargin \> 0) { slider.children.css('marginBottom', slider.settings.slideMargin); } // if "fade" mode, add positioning and z-index CSS if (slider.settings.mode \=== 'fade') { slider.children.css({ position: 'absolute', zIndex: 0, display: 'none' }); // prepare the z-index on the showing element slider.children.eq(slider.settings.startSlide).css({zIndex: slider.settings.slideZIndex, display: 'block'}); } // create an element to contain all slider controls (pager, start / stop, etc) slider.controls.el \= $('<div class="bx-controls" />'); // if captions are requested, add them if (slider.settings.captions) { appendCaptions(); } // check if startSlide is last slide slider.active.last \= slider.settings.startSlide \=== getPagerQty() - 1; // if video is true, set up the fitVids plugin if (slider.settings.video) { el.fitVids(); } //preloadImages if (slider.settings.preloadImages \=== 'none') { preloadSelector \= null; } else if (slider.settings.preloadImages \=== 'all' || slider.settings.ticker) { preloadSelector \= slider.children; } // only check for control addition if not in "ticker" mode if (!slider.settings.ticker) { // if controls are requested, add them if (slider.settings.controls) { appendControls(); } // if auto is true, and auto controls are requested, add them if (slider.settings.auto && slider.settings.autoControls) { appendControlsAuto(); } // if pager is requested, add it if (slider.settings.pager) { appendPager(); } // if any control option is requested, add the controls wrapper if (slider.settings.controls || slider.settings.autoControls || slider.settings.pager) { slider.viewport.after(slider.controls.el); } // if ticker mode, do not allow a pager } else { slider.settings.pager \= false; } if (preloadSelector \=== null) { start(); } else { loadElements(preloadSelector, start); } }; var loadElements \= function(selector, callback) { var total \= selector.find('img:not([src=""]), iframe').length, count \= 0; if (total \=== 0) { callback(); return; } selector.find('img:not([src=""]), iframe').each(function() { $(this).one('load error', function() { if (count \=== total) { callback(); } }).each(function() { if (this.complete || this.src \== '') { $(this).trigger('load'); } }); }); }; /** * Start the slider */ var start \= function() { // if infinite loop, prepare additional slides if (slider.settings.infiniteLoop && slider.settings.mode !== 'fade' && !slider.settings.ticker) { var slice \= slider.settings.mode \=== 'vertical' ? slider.settings.minSlides : slider.settings.maxSlides, sliceAppend \= slider.children.slice(0, slice).clone(true).addClass('bx-clone'), slicePrepend \= slider.children.slice(-slice).clone(true).addClass('bx-clone'); if (slider.settings.ariaHidden) { sliceAppend.attr('aria-hidden', true); slicePrepend.attr('aria-hidden', true); } el.append(sliceAppend).prepend(slicePrepend); } // remove the loading DOM element slider.loader.remove(); // set the left / top position of "el" setSlidePosition(); // if "vertical" mode, always use adaptiveHeight to prevent odd behavior if (slider.settings.mode \=== 'vertical') { slider.settings.adaptiveHeight \= true; } // set the viewport height slider.viewport.height(getViewportHeight()); // make sure everything is positioned just right (same as a window resize) el.redrawSlider(); // onSliderLoad callback slider.settings.onSliderLoad.call(el, slider.active.index); // slider has been fully initialized slider.initialized \= true; // add the resize call to the window if (slider.settings.responsive) { $(window).on('resize', resizeWindow); } // if auto is true and has more than 1 page, start the show if (slider.settings.auto && slider.settings.autoStart && (getPagerQty() \> 1 || slider.settings.autoSlideForOnePage)) { initAuto(); } // if ticker is true, start the ticker if (slider.settings.ticker) { initTicker(); } // if pager is requested, make the appropriate pager link active if (slider.settings.pager) { updatePagerActive(slider.settings.startSlide); } // check for any updates to the controls (like hideControlOnEnd updates) if (slider.settings.controls) { updateDirectionControls(); } // if touchEnabled is true, setup the touch events if (navigator.maxTouchPoints \> 1) { initTouch(); } // if keyboardEnabled is true, setup the keyboard events if (slider.settings.keyboardEnabled && !slider.settings.ticker) { $(document).keydown(keyPress); } }; /** * Returns the calculated height of the viewport, used to determine either adaptiveHeight or the maxHeight value */ var getViewportHeight \= function() { var height \= 0; // first determine which children (slides) should be used in our height calculation var children \= $(); // if mode is not "vertical" and adaptiveHeight is false, include all children if (slider.settings.mode !== 'vertical' && !slider.settings.adaptiveHeight) { children \= slider.children; } else { // if not carousel, return the single active child if (!slider.carousel) { children \= slider.children.eq(slider.active.index); // if carousel, return a slice of children } else { // get the individual slide index var currentIndex \= slider.settings.moveSlides \=== 1 ? slider.active.index : slider.active.index * getMoveBy(); // add the current slide to the children children \= slider.children.eq(currentIndex); // cycle through the remaining "showing" slides for (i \= 1; i <= slider.settings.maxSlides - 1; i) { // if looped back to the start if (currentIndex + i \>= slider.children.length) { children \= children.add(slider.children.eq(i - 1)); } else { children \= children.add(slider.children.eq(currentIndex + i)); } } } } // if "vertical" mode, calculate the sum of the heights of the children if (slider.settings.mode \=== 'vertical') { children.each(function(index) { height += $(this).outerHeight(); }); // add user-supplied margins if (slider.settings.slideMargin \> 0) { height += slider.settings.slideMargin * (slider.settings.minSlides - 1); } // if not "vertical" mode, calculate the max height of the children } else { height \= Math.max.apply(Math, children.map(function() { return $(this).outerHeight(false); }).get()); } if (slider.viewport.css('box-sizing') \=== 'border-box') { height += parseFloat(slider.viewport.css('padding-top')) + parseFloat(slider.viewport.css('padding-bottom')) + parseFloat(slider.viewport.css('border-top-width')) + parseFloat(slider.viewport.css('border-bottom-width')); } else if (slider.viewport.css('box-sizing') \=== 'padding-box') { height += parseFloat(slider.viewport.css('padding-top')) + parseFloat(slider.viewport.css('padding-bottom')); } return height; }; /** * Returns the calculated width to be used for the outer wrapper / viewport */ var getViewportMaxWidth \= function() { var width \= '100%'; if (slider.settings.slideWidth \> 0) { if (slider.settings.mode \=== 'horizontal') { width \= (slider.settings.maxSlides * slider.settings.slideWidth) + ((slider.settings.maxSlides - 1) * slider.settings.slideMargin); } else { width \= slider.settings.slideWidth; } } return width; }; /** * Returns the calculated width to be applied to each slide */ var getSlideWidth \= function() { var newElWidth \= slider.settings.slideWidth, // start with any user-supplied slide width wrapWidth \= slider.viewport.width(); // get the current viewport width // if slide width was not supplied, or is larger than the viewport use the viewport width if (slider.settings.slideWidth \=== 0 || (slider.settings.slideWidth \> wrapWidth && !slider.carousel) || slider.settings.mode \=== 'vertical') { newElWidth \= wrapWidth; // if carousel, use the thresholds to determine the width } else if (slider.settings.maxSlides \> 1 && slider.settings.mode \=== 'horizontal') { if (wrapWidth \> slider.maxThreshold) { return newElWidth; } else if (wrapWidth < slider.minThreshold) { newElWidth \= (wrapWidth - (slider.settings.slideMargin * (slider.settings.minSlides - 1))) / slider.settings.minSlides; } else if (slider.settings.shrinkItems) { newElWidth \= Math.floor((wrapWidth + slider.settings.slideMargin) / (Math.ceil((wrapWidth + slider.settings.slideMargin) / (newElWidth + slider.settings.slideMargin))) - slider.settings.slideMargin); } } return newElWidth; }; /** * Returns the number of slides currently visible in the viewport (includes partially visible slides) */ var getNumberSlidesShowing \= function() { var slidesShowing \= 1, childWidth \= null; if (slider.settings.mode \=== 'horizontal' && slider.settings.slideWidth \> 0) { // if viewport is smaller than minThreshold, return minSlides if (slider.viewport.width() < slider.minThreshold) { slidesShowing \= slider.settings.minSlides; // if viewport is larger than maxThreshold, return maxSlides } else if (slider.viewport.width() \> slider.maxThreshold) { slidesShowing \= slider.settings.maxSlides; // if viewport is between min / max thresholds, divide viewport width by first child width } else { childWidth \= slider.children.first().width() + slider.settings.slideMargin; slidesShowing \= Math.floor((slider.viewport.width() + slider.settings.slideMargin) / childWidth) || 1; } // if "vertical" mode, slides showing will always be minSlides } else if (slider.settings.mode \=== 'vertical') { slidesShowing \= slider.settings.minSlides; } return slidesShowing; }; /** * Returns the number of pages (one full viewport of slides is one "page") */ var getPagerQty \= function() { var pagerQty \= 0, breakPoint \= 0, counter \= 0; // if moveSlides is specified by the user if (slider.settings.moveSlides \> 0) { if (slider.settings.infiniteLoop) { pagerQty \= Math.ceil(slider.children.length / getMoveBy()); } else { // when breakpoint goes above children length, counter is the number of pages while (breakPoint < slider.children.length) { pagerQty; breakPoint \= counter + getNumberSlidesShowing(); counter += slider.settings.moveSlides <= getNumberSlidesShowing() ? slider.settings.moveSlides : getNumberSlidesShowing(); } return counter; } // if moveSlides is 0 (auto) divide children length by sides showing, then round up } else { pagerQty \= Math.ceil(slider.children.length / getNumberSlidesShowing()); } return pagerQty; }; /** * Returns the number of individual slides by which to shift the slider */ var getMoveBy \= function() { // if moveSlides was set by the user and moveSlides is less than number of slides showing if (slider.settings.moveSlides \> 0 && slider.settings.moveSlides <= getNumberSlidesShowing()) { return slider.settings.moveSlides; } // if moveSlides is 0 (auto) return getNumberSlidesShowing(); }; /** * Sets the slider's (el) left or top position */ var setSlidePosition \= function() { var position, lastChild, lastShowingIndex; // if last slide, not infinite loop, and number of children is larger than specified maxSlides if (slider.children.length \> slider.settings.maxSlides && slider.active.last && !slider.settings.infiniteLoop) { if (slider.settings.mode \=== 'horizontal') { // get the last child's position lastChild \= slider.children.last(); position \= lastChild.position(); // set the left position setPositionProperty(-(position.left - (slider.viewport.width() - lastChild.outerWidth())), 'reset', 0); } else if (slider.settings.mode \=== 'vertical') { // get the last showing index's position lastShowingIndex \= slider.children.length - slider.settings.minSlides; position \= slider.children.eq(lastShowingIndex).position(); // set the top position setPositionProperty(-position.top, 'reset', 0); } // if not last slide } else { // get the position of the first showing slide position \= slider.children.eq(slider.active.index * getMoveBy()).position(); // check for last slide if (slider.active.index \=== getPagerQty() - 1) { slider.active.last \= true; } // set the respective position if (position !== undefined) { if (slider.settings.mode \=== 'horizontal') { setPositionProperty(-position.left, 'reset', 0); } else if (slider.settings.mode \=== 'vertical') { setPositionProperty(-position.top, 'reset', 0); } } } }; /** * Sets the el's animating property position (which in turn will sometimes animate el). * If using CSS, sets the transform property. If not using CSS, sets the top / left property. * * @param value (int) * - the animating property's value * * @param type (string) 'slide', 'reset', 'ticker' * - the type of instance for which the function is being * * @param duration (int) * - the amount of time (in ms) the transition should occupy * * @param params (array) optional * - an optional parameter containing any variables that need to be passed in */ var setPositionProperty \= function(value, type, duration, params) { var animateObj, propValue; // use CSS transform if (slider.usingCSS) { // determine the translate3d value propValue \= slider.settings.mode \=== 'vertical' ? 'translate3d(0, ' + value + 'px, 0)' : 'translate3d(' + value + 'px, 0, 0)'; // add the CSS transition-duration el.css('-' + slider.cssPrefix + '-transition-duration', duration / 1000 + 's'); if (type \=== 'slide') { // set the property value el.css(slider.animProp, propValue); if (duration !== 0) { // add a callback method - executes when CSS transition completes el.on('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function(e) { //make sure it's the correct one if (!$(e.target).is(el)) { return; } // remove the callback el.off('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd'); updateAfterSlideTransition(); }); } else { //duration = 0 updateAfterSlideTransition(); } } else if (type \=== 'reset') { el.css(slider.animProp, propValue); } else if (type \=== 'ticker') { // make the transition use 'linear' el.css('-' + slider.cssPrefix + '-transition-timing-function', 'linear'); el.css(slider.animProp, propValue); if (duration !== 0) { el.on('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function(e) { //make sure it's the correct one if (!$(e.target).is(el)) { return; } // remove the callback el.off('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd'); // reset the position setPositionProperty(params.resetValue, 'reset', 0); // start the loop again tickerLoop(); }); } else { //duration = 0 setPositionProperty(params.resetValue, 'reset', 0); tickerLoop(); } } // use JS animate } else { animateObj \= {}; animateObj[slider.animProp] \= value; if (type \=== 'slide') { el.animate(animateObj, duration, slider.settings.easing, function() { updateAfterSlideTransition(); }); } else if (type \=== 'reset') { el.css(slider.animProp, value); } else if (type \=== 'ticker') { el.animate(animateObj, duration, 'linear', function() { setPositionProperty(params.resetValue, 'reset', 0); // run the recursive loop after animation tickerLoop(); }); } } }; /** * Populates the pager with proper amount of pages */ var populatePager \= function() { var pagerHtml \= '', linkContent \= '', pagerQty \= getPagerQty(); // loop through each pager item for (var i \= 0; i < pagerQty; i) { linkContent \= ''; // if a buildPager function is supplied, use it to get pager link value, else use index + 1 if (slider.settings.buildPager && $.isFunction(slider.settings.buildPager) || slider.settings.pagerCustom) { linkContent \= slider.settings.buildPager(i); slider.pagerEl.addClass('bx-custom-pager'); } else { linkContent \= i + 1; slider.pagerEl.addClass('bx-default-pager'); } // var linkContent = slider.settings.buildPager && $.isFunction(slider.settings.buildPager) ? slider.settings.buildPager(i) : i + 1; // add the markup to the string pagerHtml += '<div class="bx-pager-item"><a href="" data-slide-index="' + i + '" class="bx-pager-link">' + linkContent + '</a></div>'; } // populate the pager element with pager links slider.pagerEl.html(pagerHtml); }; /** * Appends the pager to the controls element */ var appendPager \= function() { if (!slider.settings.pagerCustom) { // create the pager DOM element slider.pagerEl \= $('<div class="bx-pager" />'); // if a pager selector was supplied, populate it with the pager if (slider.settings.pagerSelector) { $(slider.settings.pagerSelector).html(slider.pagerEl); // if no pager selector was supplied, add it after the wrapper } else { slider.controls.el.addClass('bx-has-pager').append(slider.pagerEl); } // populate the pager populatePager(); } else { slider.pagerEl \= $(slider.settings.pagerCustom); } // assign the pager click binding slider.pagerEl.on('click touchend', 'a', clickPagerBind); }; /** * Appends prev / next controls to the controls element */ var appendControls \= function() { slider.controls.next \= $('<a class="bx-next" href="">' + slider.settings.nextText + '</a>'); slider.controls.prev \= $('<a class="bx-prev" href="">' + slider.settings.prevText + '</a>'); // add click actions to the controls slider.controls.next.on('click touchend', clickNextBind); slider.controls.prev.on('click touchend', clickPrevBind); // if nextSelector was supplied, populate it if (slider.settings.nextSelector) { $(slider.settings.nextSelector).append(slider.controls.next); } // if prevSelector was supplied, populate it if (slider.settings.prevSelector) { $(slider.settings.prevSelector).append(slider.controls.prev); } // if no custom selectors were supplied if (!slider.settings.nextSelector && !slider.settings.prevSelector) { // add the controls to the DOM slider.controls.directionEl \= $('<div class="bx-controls-direction" />'); // add the control elements to the directionEl slider.controls.directionEl.append(slider.controls.prev).append(slider.controls.next); // slider.viewport.append(slider.controls.directionEl); slider.controls.el.addClass('bx-has-controls-direction').append(slider.controls.directionEl); } }; /** * Appends start / stop auto controls to the controls element */ var appendControlsAuto \= function() { slider.controls.start \= $('<div class="bx-controls-auto-item"><a class="bx-start" href="">' + slider.settings.startText + '</a></div>'); slider.controls.stop \= $('<div class="bx-controls-auto-item"><a class="bx-stop" href="">' + slider.settings.stopText + '</a></div>'); // add the controls to the DOM slider.controls.autoEl \= $('<div class="bx-controls-auto" />'); // on click actions to the controls slider.controls.autoEl.on('click', '.bx-start', clickStartBind); slider.controls.autoEl.on('click', '.bx-stop', clickStopBind); // if autoControlsCombine, insert only the "start" control if (slider.settings.autoControlsCombine) { slider.controls.autoEl.append(slider.controls.start); // if autoControlsCombine is false, insert both controls } else { slider.controls.autoEl.append(slider.controls.start).append(slider.controls.stop); } // if auto controls selector was supplied, populate it with the controls if (slider.settings.autoControlsSelector) { $(slider.settings.autoControlsSelector).html(slider.controls.autoEl); // if auto controls selector was not supplied, add it after the wrapper } else { slider.controls.el.addClass('bx-has-controls-auto').append(slider.controls.autoEl); } // update the auto controls updateAutoControls(slider.settings.autoStart ? 'stop' : 'start'); }; /** * Appends image captions to the DOM */ var appendCaptions \= function() { // cycle through each child slider.children.each(function(index) { // get the image title attribute var title \= $(this).find('img:first').attr('title'); // append the caption if (title !== undefined && ('' + title).length) { $(this).append('<div class="bx-caption"><span>' + title + '</span></div>'); } }); }; /** * Click next binding * * @param e (event) * - DOM event object */ var clickNextBind \= function(e) { e.preventDefault(); if (slider.controls.el.hasClass('disabled')) { return; } // if auto show is running, stop it if (slider.settings.auto && slider.settings.stopAutoOnClick) { el.stopAuto(); } el.goToNextSlide(); }; /** * Click prev binding * * @param e (event) * - DOM event object */ var clickPrevBind \= function(e) { e.preventDefault(); if (slider.controls.el.hasClass('disabled')) { return; } // if auto show is running, stop it if (slider.settings.auto && slider.settings.stopAutoOnClick) { el.stopAuto(); } el.goToPrevSlide(); }; /** * Click start binding * * @param e (event) * - DOM event object */ var clickStartBind \= function(e) { el.startAuto(); e.preventDefault(); }; /** * Click stop binding * * @param e (event) * - DOM event object */ var clickStopBind \= function(e) { el.stopAuto(); e.preventDefault(); }; /** * Click pager binding * * @param e (event) * - DOM event object */ var clickPagerBind \= function(e) { var pagerLink, pagerIndex; e.preventDefault(); if (slider.controls.el.hasClass('disabled')) { return; } // if auto show is running, stop it if (slider.settings.auto && slider.settings.stopAutoOnClick) { el.stopAuto(); } pagerLink \= $(e.currentTarget); if (pagerLink.attr('data-slide-index') !== undefined) { pagerIndex \= parseInt(pagerLink.attr('data-slide-index')); // if clicked pager link is not active, continue with the goToSlide call if (pagerIndex !== slider.active.index) { el.goToSlide(pagerIndex); } } }; /** * Updates the pager links with an active class * * @param slideIndex (int) * - index of slide to make active */ var updatePagerActive \= function(slideIndex) { // if "short" pager type var len \= slider.children.length; // nb of children if (slider.settings.pagerType \=== 'short') { if (slider.settings.maxSlides \> 1) { len \= Math.ceil(slider.children.length / slider.settings.maxSlides); } slider.pagerEl.html((slideIndex + 1) + slider.settings.pagerShortSeparator + len); return; } // remove all pager active classes slider.pagerEl.find('a').removeClass('active'); // apply the active class for all pagers slider.pagerEl.each(function(i, el) { $(el).find('a').eq(slideIndex).addClass('active'); }); }; /** * Performs needed actions after a slide transition */ var updateAfterSlideTransition \= function() { // if infinite loop is true if (slider.settings.infiniteLoop) { var position \= ''; // first slide if (slider.active.index \=== 0) { // set the new position position \= slider.children.eq(0).position(); // carousel, last slide } else if (slider.active.index \=== getPagerQty() - 1 && slider.carousel) { position \= slider.children.eq((getPagerQty() - 1) * getMoveBy()).position(); // last slide } else if (slider.active.index \=== slider.children.length - 1) { position \= slider.children.eq(slider.children.length - 1).position(); } if (position) { if (slider.settings.mode \=== 'horizontal') { setPositionProperty(-position.left, 'reset', 0); } else if (slider.settings.mode \=== 'vertical') { setPositionProperty(-position.top, 'reset', 0); } } } // declare that the transition is complete slider.working \= false; // onSlideAfter callback slider.settings.onSlideAfter.call(el, slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index); }; /** * Updates the auto controls state (either active, or combined switch) * * @param state (string) "start", "stop" * - the new state of the auto show */ var updateAutoControls \= function(state) { // if autoControlsCombine is true, replace the current control with the new state if (slider.settings.autoControlsCombine) { slider.controls.autoEl.html(slider.controls[state]); // if autoControlsCombine is false, apply the "active" class to the appropriate control } else { slider.controls.autoEl.find('a').removeClass('active'); slider.controls.autoEl.find('a:not(.bx-' + state + ')').addClass('active'); } }; /** * Updates the direction controls (checks if either should be hidden) */ var updateDirectionControls \= function() { if (getPagerQty() \=== 1) { slider.controls.prev.addClass('disabled'); slider.controls.next.addClass('disabled'); } else if (!slider.settings.infiniteLoop && slider.settings.hideControlOnEnd) { // if first slide if (slider.active.index \=== 0) { slider.controls.prev.addClass('disabled'); slider.controls.next.removeClass('disabled'); // if last slide } else if (slider.active.index \=== getPagerQty() - 1) { slider.controls.next.addClass('disabled'); slider.controls.prev.removeClass('disabled'); // if any slide in the middle } else { slider.controls.prev.removeClass('disabled'); slider.controls.next.removeClass('disabled'); } } }; /* auto start and stop functions */ var windowFocusHandler \= function() { el.startAuto(); }; var windowBlurHandler \= function() { el.stopAuto(); }; /** * Initializes the auto process */ var initAuto \= function() { // if autoDelay was supplied, launch the auto show using a setTimeout() call if (slider.settings.autoDelay \> 0) { setTimeout(el.startAuto, slider.settings.autoDelay); // if autoDelay was not supplied, start the auto show normally } else { el.startAuto(); //add focus and blur events to ensure its running if timeout gets paused $(window).focus(windowFocusHandler).blur(windowBlurHandler); } // if autoHover is requested if (slider.settings.autoHover) { // on el hover el.hover(function() { // if the auto show is currently playing (has an active interval) if (slider.interval) { // stop the auto show and pass true argument which will prevent control update el.stopAuto(true); // create a new autoPaused value which will be used by the relative "mouseout" event slider.autoPaused \= true; } }, function() { // if the autoPaused value was created be the prior "mouseover" event if (slider.autoPaused) { // start the auto show and pass true argument which will prevent control update el.startAuto(true); // reset the autoPaused value slider.autoPaused \= null; } }); } }; /** * Initializes the ticker process */ var initTicker \= function() { var startPosition \= 0, position, transform, value, idx, ratio, property, newSpeed, totalDimens; // if autoDirection is "next", append a clone of the entire slider if (slider.settings.autoDirection \=== 'next') { el.append(slider.children.clone().addClass('bx-clone')); // if autoDirection is "prev", prepend a clone of the entire slider, and set the left position } else { el.prepend(slider.children.clone().addClass('bx-clone')); position \= slider.children.first().position(); startPosition \= slider.settings.mode \=== 'horizontal' ? -position.left : -position.top; } setPositionProperty(startPosition, 'reset', 0); // do not allow controls in ticker mode slider.settings.pager \= false; slider.settings.controls \= false; slider.settings.autoControls \= false; // if autoHover is requested if (slider.settings.tickerHover) { if (slider.usingCSS) { idx \= slider.settings.mode \=== 'horizontal' ? 4 : 5; slider.viewport.hover(function() { transform \= el.css('-' + slider.cssPrefix + '-transform'); value \= parseFloat(transform.split(',')[idx]); setPositionProperty(value, 'reset', 0); }, function() { totalDimens \= 0; slider.children.each(function(index) { totalDimens += slider.settings.mode \=== 'horizontal' ? $(this).outerWidth(true) : $(this).outerHeight(true); }); // calculate the speed ratio (used to determine the new speed to finish the paused animation) ratio \= slider.settings.speed / totalDimens; // determine which property to use property \= slider.settings.mode \=== 'horizontal' ? 'left' : 'top'; // calculate the new speed newSpeed \= ratio * (totalDimens - (Math.abs(parseInt(value)))); tickerLoop(newSpeed); }); } else { // on el hover slider.viewport.hover(function() { el.stop(); }, function() { // calculate the total width of children (used to calculate the speed ratio) totalDimens \= 0; slider.children.each(function(index) { totalDimens += slider.settings.mode \=== 'horizontal' ? $(this).outerWidth(true) : $(this).outerHeight(true); }); // calculate the speed ratio (used to determine the new speed to finish the paused animation) ratio \= slider.settings.speed / totalDimens; // determine which property to use property \= slider.settings.mode \=== 'horizontal' ? 'left' : 'top'; // calculate the new speed newSpeed \= ratio * (totalDimens - (Math.abs(parseInt(el.css(property))))); tickerLoop(newSpeed); }); } } // start the ticker loop tickerLoop(); }; /** * Runs a continuous loop, news ticker-style */ var tickerLoop \= function(resumeSpeed) { var speed \= resumeSpeed ? resumeSpeed : slider.settings.speed, position \= {left: 0, top: 0}, reset \= {left: 0, top: 0}, animateProperty, resetValue, params; // if "next" animate left position to last child, then reset left to 0 if (slider.settings.autoDirection \=== 'next') { position \= el.find('.bx-clone').first().position(); // if "prev" animate left position to 0, then reset left to first non-clone child } else { reset \= slider.children.first().position(); } animateProperty \= slider.settings.mode \=== 'horizontal' ? -position.left : -position.top; resetValue \= slider.settings.mode \=== 'horizontal' ? -reset.left : -reset.top; params \= {resetValue: resetValue}; setPositionProperty(animateProperty, 'ticker', speed, params); }; /** * Check if el is on screen */ var isOnScreen \= function(el) { var win \= $(window), viewport \= { top: win.scrollTop(), left: win.scrollLeft() }, bounds \= el.offset(); viewport.right \= viewport.left + win.width(); viewport.bottom \= viewport.top + win.height(); bounds.right \= bounds.left + el.outerWidth(); bounds.bottom \= bounds.top + el.outerHeight(); return (!(viewport.right < bounds.left || viewport.left \> bounds.right || viewport.bottom < bounds.top || viewport.top \> bounds.bottom)); }; /** * Initializes keyboard events */ var keyPress \= function(e) { var activeElementTag \= document.activeElement.tagName.toLowerCase(), tagFilters \= 'input|textarea', p \= new RegExp(activeElementTag,['i']), result \= p.exec(tagFilters); if (result \== null && isOnScreen(el)) { if (e.keyCode \=== 39) { clickNextBind(e); return false; } else if (e.keyCode \=== 37) { clickPrevBind(e); return false; } } }; /** * Initializes touch events */ var initTouch \= function() { // initialize object to contain all touch values slider.touch \= { start: {x: 0, y: 0}, end: {x: 0, y: 0} }; slider.viewport.on('touchstart MSPointerDown pointerdown', onTouchStart); //for browsers that have implemented pointer events and fire a click after //every pointerup regardless of whether pointerup is on same screen location as pointerdown or not slider.viewport.on('click', '.bxslider a', function(e) { if (slider.viewport.hasClass('click-disabled')) { e.preventDefault(); slider.viewport.removeClass('click-disabled'); } }); }; /** * Event handler for "touchstart" * * @param e (event) * - DOM event object */ var onTouchStart \= function(e) { // watch only for left mouse, touch contact and pen contact // touchstart event object doesn`t have button property if (e.type !== 'touchstart' && e.button !== 0) { return; } if (slider.pointerId \=== undefined){ return; } // Enable once the BxSlider library fixes this issue and it is to fix the touch for Android devices. if( ! e.target.href ) { e.preventDefault(); } // e.preventDefault(); //disable slider controls while user is interacting with slides to avoid slider freeze that happens on touch devices when a slide swipe happens immediately after interacting with slider controls slider.controls.el.addClass('disabled'); if (slider.working) { slider.controls.el.removeClass('disabled'); } else { // record the original position when touch starts slider.touch.originalPos \= el.position(); var orig \= e.originalEvent, touchPoints \= (typeof orig.changedTouches !== 'undefined') ? orig.changedTouches : [orig]; var chromePointerEvents \= typeof PointerEvent \=== 'function'; if (chromePointerEvents) { if (orig.pointerId \=== undefined) { return; } } // record the starting touch x, y coordinates slider.touch.start.x \= touchPoints[0].pageX; slider.touch.start.y \= touchPoints[0].pageY; if (slider.viewport.get(0).setPointerCapture) { slider.pointerId \= orig.pointerId; slider.viewport.get(0).setPointerCapture(slider.pointerId); } // store original event data for click fixation slider.originalClickTarget \= orig.originalTarget || orig.target; slider.originalClickButton \= orig.button; slider.originalClickButtons \= orig.buttons; slider.originalEventType \= orig.type; // at this moment we don`t know what it is click or swipe slider.hasMove \= false; // on a "touchmove" event to the viewport slider.viewport.on('touchmove MSPointerMove pointermove', onTouchMove); // on a "touchend" event to the viewport slider.viewport.on('touchend MSPointerUp pointerup', onTouchEnd); slider.viewport.on('MSPointerCancel pointercancel', onPointerCancel); } }; /** * Cancel Pointer for Windows Phone * * @param e (event) * - DOM event object */ var onPointerCancel \= function(e) { e.preventDefault(); /* onPointerCancel handler is needed to deal with situations when a touchend doesn't fire after a touchstart (this happens on windows phones only) */ setPositionProperty(slider.touch.originalPos.left, 'reset', 0); //remove handlers slider.controls.el.removeClass('disabled'); slider.viewport.off('MSPointerCancel pointercancel', onPointerCancel); slider.viewport.off('touchmove MSPointerMove pointermove', onTouchMove); slider.viewport.off('touchend MSPointerUp pointerup', onTouchEnd); if (slider.viewport.get(0).releasePointerCapture) { slider.viewport.get(0).releasePointerCapture(slider.pointerId); } }; /** * Event handler for "touchmove" * * @param e (event) * - DOM event object */ var onTouchMove \= function(e) { var orig \= e.originalEvent, touchPoints \= (typeof orig.changedTouches !== 'undefined') ? orig.changedTouches : [orig], // if scrolling on y axis, do not prevent default xMovement \= Math.abs(touchPoints[0].pageX - slider.touch.start.x), yMovement \= Math.abs(touchPoints[0].pageY - slider.touch.start.y), value \= 0, change \= 0; // this is swipe slider.hasMove \= true; // x axis swipe if ((xMovement * 3) \> yMovement && slider.settings.preventDefaultSwipeX) { e.preventDefault(); // y axis swipe } else if ((yMovement * 3) \> xMovement && slider.settings.preventDefaultSwipeY) { e.preventDefault(); } if (e.type !== 'touchmove') { e.preventDefault(); } if (slider.settings.mode !== 'fade' && slider.settings.oneToOneTouch) { // if horizontal, drag along x axis if (slider.settings.mode \=== 'horizontal') { change \= touchPoints[0].pageX - slider.touch.start.x; value \= slider.touch.originalPos.left + change; // if vertical, drag along y axis } else { change \= touchPoints[0].pageY - slider.touch.start.y; value \= slider.touch.originalPos.top + change; } setPositionProperty(value, 'reset', 0); } }; /** * Event handler for "touchend" * * @param e (event) * - DOM event object */ var onTouchEnd \= function(e) { e.preventDefault(); slider.viewport.off('touchmove MSPointerMove pointermove', onTouchMove); //enable slider controls as soon as user stops interacing with slides slider.controls.el.removeClass('disabled'); var orig \= e.originalEvent, touchPoints \= (typeof orig.changedTouches !== 'undefined') ? orig.changedTouches : [orig], value \= 0, distance \= 0; // record end x, y positions slider.touch.end.x \= touchPoints[0].pageX; slider.touch.end.y \= touchPoints[0].pageY; // if fade mode, check if absolute x distance clears the threshold if (slider.settings.mode \=== 'fade') { distance \= Math.abs(slider.touch.start.x - slider.touch.end.x); if (distance \>= slider.settings.swipeThreshold) { if (slider.touch.start.x \> slider.touch.end.x) { el.goToNextSlide(); } else { el.goToPrevSlide(); } el.stopAuto(); } // not fade mode } else { // calculate distance and el's animate property if (slider.settings.mode \=== 'horizontal') { distance \= slider.touch.end.x - slider.touch.start.x; value \= slider.touch.originalPos.left; } else { distance \= slider.touch.end.y - slider.touch.start.y; value \= slider.touch.originalPos.top; } // if not infinite loop and first / last slide, do not attempt a slide transition if (!slider.settings.infiniteLoop && ((slider.active.index \=== 0 && distance \> 0) || (slider.active.last && distance < 0))) { setPositionProperty(value, 'reset', 200); } else { // check if distance clears threshold if (Math.abs(distance) \>= slider.settings.swipeThreshold) { if (distance < 0) { el.goToNextSlide(); } else { el.goToPrevSlide(); } el.stopAuto(); } else { // el.animate(property, 200); setPositionProperty(value, 'reset', 200); } } } slider.viewport.off('touchend MSPointerUp pointerup', onTouchEnd); if (slider.viewport.get(0).releasePointerCapture) { slider.viewport.get(0).releasePointerCapture(slider.pointerId); } // if slider had swipe with left mouse, touch contact and pen contact if (slider.hasMove \=== false && (slider.originalClickButton \=== 0 || slider.originalEventType \=== 'touchstart')) { // trigger click event (fix for Firefox59 and PointerEvent standard compatibility) $(slider.originalClickTarget).trigger({ type: 'click', button: slider.originalClickButton, buttons: slider.originalClickButtons }); } }; /** * Window resize event callback */ var resizeWindow \= function(e) { // don't do anything if slider isn't initialized. if (!slider.initialized) { return; } // Delay if slider working. if (slider.working) { window.setTimeout(resizeWindow, 10); } else { // get the new window dimens (again, thank you IE) var windowWidthNew \= $(window).width(), windowHeightNew \= $(window).height(); // make sure that it is a true window resize // *we must check this because our dinosaur friend IE fires a window resize event when certain DOM elements // are resized. Can you just die already?* if (windowWidth !== windowWidthNew || windowHeight !== windowHeightNew) { // set the new window dimens windowWidth \= windowWidthNew; windowHeight \= windowHeightNew; // update all dynamic elements el.redrawSlider(); // Call user resize handler slider.settings.onSliderResize.call(el, slider.active.index); } } }; /** * Adds an aria-hidden=true attribute to each element * * @param startVisibleIndex (int) * - the first visible element's index */ var applyAriaHiddenAttributes \= function(startVisibleIndex) { var numberOfSlidesShowing \= getNumberSlidesShowing(); // only apply attributes if the setting is enabled and not in ticker mode if (slider.settings.ariaHidden && !slider.settings.ticker) { // add aria-hidden=true to all elements slider.children.attr('aria-hidden', 'true'); // get the visible elements and change to aria-hidden=false slider.children.slice(startVisibleIndex, startVisibleIndex + numberOfSlidesShowing).attr('aria-hidden', 'false'); } }; /** * Returns index according to present page range * * @param slideOndex (int) * - the desired slide index */ var setSlideIndex \= function(slideIndex) { if (slideIndex < 0) { if (slider.settings.infiniteLoop) { return getPagerQty() - 1; }else { //we don't go to undefined slides return slider.active.index; } // if slideIndex is greater than children length, set active index to 0 (this happens during infinite loop) } else if (slideIndex \>= getPagerQty()) { if (slider.settings.infiniteLoop) { return 0; } else { //we don't move to undefined pages return slider.active.index; } // set active index to requested slide } else { return slideIndex; } }; /** * =================================================================================== * = PUBLIC FUNCTIONS * =================================================================================== */ /** * Performs slide transition to the specified slide * * @param slideIndex (int) * - the destination slide's index (zero-based) * * @param direction (string) * - INTERNAL USE ONLY - the direction of travel ("prev" / "next") */ el.goToSlide \= function(slideIndex, direction) { // onSlideBefore, onSlideNext, onSlidePrev callbacks // Allow transition canceling based on returned value var performTransition \= true, moveBy \= 0, position \= {left: 0, top: 0}, lastChild \= null, lastShowingIndex, eq, value, requestEl; // store the old index slider.oldIndex \= slider.active.index; //set new index slider.active.index \= setSlideIndex(slideIndex); // if plugin is currently in motion, ignore request if (slider.working || slider.active.index \=== slider.oldIndex) { return; } // declare that plugin is in motion slider.working \= true; performTransition \= slider.settings.onSlideBefore.call(el, slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index); // If transitions canceled, reset and return if (typeof (performTransition) !== 'undefined' && !performTransition) { slider.active.index \= slider.oldIndex; // restore old index slider.working \= false; // is not in motion return; } if (direction \=== 'next') { // Prevent canceling in future functions or lack there-of from negating previous commands to cancel if (!slider.settings.onSlideNext.call(el, slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index)) { performTransition \= false; } } else if (direction \=== 'prev') { // Prevent canceling in future functions or lack there-of from negating previous commands to cancel if (!slider.settings.onSlidePrev.call(el, slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index)) { performTransition \= false; } } // check if last slide slider.active.last \= slider.active.index \>= getPagerQty() - 1; // update the pager with active class if (slider.settings.pager || slider.settings.pagerCustom) { updatePagerActive(slider.active.index); } // // check for direction control update if (slider.settings.controls) { updateDirectionControls(); } // if slider is set to mode: "fade" if (slider.settings.mode \=== 'fade') { // if adaptiveHeight is true and next height is different from current height, animate to the new height