diff --git a/dist/scroll.carousel.css b/dist/scroll.carousel.css index 5b992a8..fa15919 100644 --- a/dist/scroll.carousel.css +++ b/dist/scroll.carousel.css @@ -1,9 +1,9 @@ /*! * - * scroll-carousel - 0.5.0 + * scroll-carousel - 1.1.0 * Responsive scroll slider * - * https://asif-jalil.github.io/scroll-carousel + * https://asif-jalil.github.io/scroll-carousel-website * */ /*!*********************************************************************************************************************************************************************!*\ diff --git a/dist/scroll.carousel.js b/dist/scroll.carousel.js index 7114950..d342b5a 100644 --- a/dist/scroll.carousel.js +++ b/dist/scroll.carousel.js @@ -1,9 +1,9 @@ /*! * - * scroll-carousel - 0.5.0 + * scroll-carousel - 1.1.0 * Responsive scroll slider * - * https://asif-jalil.github.io/scroll-carousel + * https://asif-jalil.github.io/scroll-carousel-website * */ (function webpackUniversalModuleDefinition(root, factory) { @@ -20,6 +20,22 @@ return /******/ (function() { // webpackBootstrap /******/ "use strict"; /******/ var __webpack_modules__ = ({ +/***/ "./src/js/scroll.carousel.const.js": +/*!*****************************************!*\ + !*** ./src/js/scroll.carousel.const.js ***! + \*****************************************/ +/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ "LTR": function() { return /* binding */ LTR; }, +/* harmony export */ "RTL": function() { return /* binding */ RTL; } +/* harmony export */ }); +var RTL = 'rtl'; +var LTR = 'ltr'; + +/***/ }), + /***/ "./src/js/util.js": /*!************************!*\ !*** ./src/js/util.js ***! @@ -38,6 +54,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony export */ "sanitizer": function() { return /* binding */ sanitizer; }, /* harmony export */ "toDashed": function() { return /* binding */ toDashed; } /* harmony export */ }); +/* harmony import */ var _scroll_carousel_const__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./scroll.carousel.const */ "./src/js/scroll.carousel.const.js"); function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); } function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } @@ -45,6 +62,8 @@ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o = function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } + + /** * check an element, node, array, object is into view or not * @@ -190,6 +209,10 @@ function sanitizer(options) { if (Object.keys(options).includes('speed') && !Number(options.speed)) options.speed = 7; if (Number(options.speed) <= 0) options.speed = 1; if (Object.keys(options).includes('margin') && !Number(options.margin) && Number(options.margin) !== 0) options.margin = 10; + if (Object.keys(options).includes('direction')) options.direction = options.direction.toLowerCase(); + if (Object.keys(options).includes('direction') && options.direction !== _scroll_carousel_const__WEBPACK_IMPORTED_MODULE_0__.RTL && options.direction !== _scroll_carousel_const__WEBPACK_IMPORTED_MODULE_0__.LTR) options.direction = _scroll_carousel_const__WEBPACK_IMPORTED_MODULE_0__.RTL; + if (Object.keys(options).includes('autoplaySpeed') && !Number(options.autoplaySpeed)) options.autoplaySpeed = 5; + if (Number(options.autoplaySpeed) <= 0) options.autoplaySpeed = 1; return options; } @@ -271,7 +294,8 @@ var __webpack_exports__ = {}; \***********************************/ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _scss_main_scss__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../scss/main.scss */ "./src/scss/main.scss"); -/* harmony import */ var _util__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./util */ "./src/js/util.js"); +/* harmony import */ var _scroll_carousel_const__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./scroll.carousel.const */ "./src/js/scroll.carousel.const.js"); +/* harmony import */ var _util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./util */ "./src/js/util.js"); function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } @@ -284,6 +308,7 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope + // globally unique identifiers var GUID = 0; // internal store of all ScrollCarousel instances @@ -297,7 +322,7 @@ var instances = {}; */ function ScrollCarousel(element) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - var queryElement = (0,_util__WEBPACK_IMPORTED_MODULE_1__.getQueryElement)(element); + var queryElement = (0,_util__WEBPACK_IMPORTED_MODULE_2__.getQueryElement)(element); if (!queryElement) { if (console) console.error("Bad element for Scroll Carousel: ".concat(queryElement || element)); return; @@ -311,12 +336,12 @@ function ScrollCarousel(element) { return instance; } - // baseOption will be used for destroy method + // baseOption will be used for destroy method and reinit method this.baseOption = options; // options this.options = _objectSpread({}, this.constructor.defaults); // validated options - var sanitizedOptions = (0,_util__WEBPACK_IMPORTED_MODULE_1__.sanitizer)(options); + var sanitizedOptions = (0,_util__WEBPACK_IMPORTED_MODULE_2__.sanitizer)(options); // merge options with prototype this.option(sanitizedOptions); @@ -334,9 +359,13 @@ ScrollCarousel.defaults = { margin: 10, // slide will play auto autoplay: false, + // speed control for autoplay + autoplaySpeed: 5, // select slide with class name which you want to select for carousel. // other element will behave as simple - slideSelector: null + slideSelector: null, + // moving direction of the slides + direction: _scroll_carousel_const__WEBPACK_IMPORTED_MODULE_1__.RTL }; var proto = ScrollCarousel.prototype; @@ -368,25 +397,35 @@ proto.activate = function () { _this = this; if (this.isActive) return; this.isActive = true; - this._translate = 0; + this.translate = 0; this.displacement = 0; this.isScrolling = true; this.prevPosition = document.body.scrollTop || document.documentElement.scrollTop; // baseElems will be used for destroy method - this.baseElems = (0,_util__WEBPACK_IMPORTED_MODULE_1__.makeArray)(this.element.children); + this.baseElems = (0,_util__WEBPACK_IMPORTED_MODULE_2__.makeArray)(this.element.children); // move initial slide elements so they can be loaded as slides var slideElems = this._filterFindSlideElements(this.element.children); this.slideElems = this._makeSlides(slideElems); + // for ltr direction reverse the elements like rtl mode + if (this.options.direction === _scroll_carousel_const__WEBPACK_IMPORTED_MODULE_1__.LTR) { + this.slideElems = this.slideElems.reverse(); + } + // duplicate the slide array - var duplicateSlideElems = (0,_util__WEBPACK_IMPORTED_MODULE_1__.duplicateElems)(this.slideElems); + var duplicateSlideElems = (0,_util__WEBPACK_IMPORTED_MODULE_2__.duplicateElems)(this.slideElems); (_this$slider = this.slider).append.apply(_this$slider, _toConsumableArray(this.slideElems).concat(_toConsumableArray(duplicateSlideElems))); this.viewport.append(this.slider); this.element.append(this.viewport); + + // kick for ltr support + if (this.options.direction === _scroll_carousel_const__WEBPACK_IMPORTED_MODULE_1__.LTR) { + this._supportLtr(); + } if (this.options.autoplay) { - this.autoplay(); + this._autoplay(); } // transform function call on scroll @@ -396,19 +435,19 @@ proto.activate = function () { }; // run interval for autoplay -proto.autoplay = function () { +proto._autoplay = function () { var _this2 = this; // autoplay will set an interval. in every interval, // we transform the slider. the interval // will be removed when destroy method fired this.interval = setInterval(function () { _this2._transform(); - }, 20); + }, 10); }; // transform the slider proto._transform = function () { - if (!(0,_util__WEBPACK_IMPORTED_MODULE_1__.isScrolledIntoView)(this.element)) return; + if (!(0,_util__WEBPACK_IMPORTED_MODULE_2__.isScrolledIntoView)(this.element)) return; if (this.options.autoplay) { this._setIsScrolling(); } @@ -422,21 +461,46 @@ proto._transform = function () { // calculate speed without smart speed proto._calcRegularSpeed = function () { var rect = this.slider.getBoundingClientRect(); - this.slider.style.transform = "translateX(".concat(this._translate, "px)"); - this.isScrolling ? this._translate -= this.options.speed : this._translate -= 1.2; - if (this._translate <= -rect.width / 2) this._translate = 0; + this.slider.style.transform = "translateX(".concat(this.translate, "px)"); + var speed = this.isScrolling ? this.options.speed : 1.2; + if (this.options.direction === _scroll_carousel_const__WEBPACK_IMPORTED_MODULE_1__.RTL) this.translate -= speed; + if (this.options.direction === _scroll_carousel_const__WEBPACK_IMPORTED_MODULE_1__.LTR) this.translate += speed; + if (this.options.direction === _scroll_carousel_const__WEBPACK_IMPORTED_MODULE_1__.RTL && this.translate <= -rect.width / 2) this.translate = 0; + if (this.options.direction === _scroll_carousel_const__WEBPACK_IMPORTED_MODULE_1__.LTR && this.translate >= 0) this.translate = -rect.width / 2; }; // calculate smart speed proto._calcSmartSpeed = function () { var documentScrollTop = document.body.scrollTop || document.documentElement.scrollTop; - var displacementAmount = this.isScrolling ? Math.abs(this.prevPosition - documentScrollTop) : 1.5; - this.displacement -= displacementAmount; - var translateAmount = this.displacement / 5.5e3 * (this.options.speed * 10) % 50; - this.slider.style.transform = "translateX(".concat(translateAmount, "%)"); + this.displacement -= this.isScrolling ? Math.abs(this.prevPosition - documentScrollTop) : 1.2; + if (this.options.direction === _scroll_carousel_const__WEBPACK_IMPORTED_MODULE_1__.LTR && this.displacement < 0) { + this.displacement = 50 / (this.options.speed * 10 / 5.5e3 % 50); + } + var translateBasic = this.displacement / 5.5e3 * (this.options.speed * 10) % 50; + var translate; + if (this.options.direction === _scroll_carousel_const__WEBPACK_IMPORTED_MODULE_1__.RTL) translate = translateBasic; + if (this.options.direction === _scroll_carousel_const__WEBPACK_IMPORTED_MODULE_1__.LTR) translate = -translateBasic; + this.slider.style.transform = "translateX(".concat(translate, "%)"); this.prevPosition = documentScrollTop; }; +// initial kick for ltr direction +proto._supportLtr = function () { + var rect = this.slider.getBoundingClientRect(); + + // calculate initial translate for regular speed + this.translate = -rect.width + Math.min(document.documentElement.clientWidth, window.innerWidth); + + // calculate initial displacement for smartSpeed + var translateInPercent = 100 * this.translate / rect.width; + this.displacement = -translateInPercent / (this.options.speed * 10 / 5.5e3 % 50); + if (this.options.smartSpeed) { + this.slider.style.transform = "translateX(".concat(translateInPercent, "%)"); + } else { + this.slider.style.transform = "translateX(".concat(this.translate, "px)"); + } +}; + // check if the document is scrolling or not proto._setIsScrolling = function () { var top = document.body.scrollTop || document.documentElement.scrollTop; @@ -484,8 +548,11 @@ proto._createViewport = function () { // filtering elements if the element child structure is too much complex (specially for slideSelector option) proto._filterFindSlideElements = function (elems) { - return (0,_util__WEBPACK_IMPORTED_MODULE_1__.filterFindElements)(elems, this.options.slideSelector); + return (0,_util__WEBPACK_IMPORTED_MODULE_2__.filterFindElements)(elems, this.options.slideSelector); }; + +// ============================== METHOD ============================== + proto.destroy = function () { var _this$element; if (!this.isActive) return; @@ -501,18 +568,25 @@ proto.destroy = function () { delete instances[this.guid]; }; +// Re initialize the carousel after destroy +proto.reinit = function () { + return new ScrollCarousel(this.element, this.baseOption); +}; + +// ============================== DATA ATTRIBUTE ============================== + /** * get Scroll Carousel instance from element * @param {[Node, Element, String]} elem - element or selector string * @returns {ScrollCarousel} - Scroll Carousel instance */ ScrollCarousel.data = function (elem) { - elem = (0,_util__WEBPACK_IMPORTED_MODULE_1__.getQueryElement)(elem); + elem = (0,_util__WEBPACK_IMPORTED_MODULE_2__.getQueryElement)(elem); if (elem) return instances[elem.scrollCarouselGUID]; }; // initialize with data attribute from here -(0,_util__WEBPACK_IMPORTED_MODULE_1__.htmlInit)(ScrollCarousel, 'carousel'); +(0,_util__WEBPACK_IMPORTED_MODULE_2__.htmlInit)(ScrollCarousel, 'carousel'); /* harmony default export */ __webpack_exports__["default"] = (ScrollCarousel); }(); __webpack_exports__ = __webpack_exports__["default"]; diff --git a/dist/scroll.carousel.min.js b/dist/scroll.carousel.min.js index 2c2d2a8..00ca7de 100644 --- a/dist/scroll.carousel.min.js +++ b/dist/scroll.carousel.min.js @@ -1,2 +1,2 @@ -!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define("ScrollCarousel",[],e):"object"==typeof exports?exports.ScrollCarousel=e():t.ScrollCarousel=e()}(this,(function(){return function(){"use strict";var t={d:function(e,r){for(var n in r)t.o(r,n)&&!t.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:r[n]})},o:function(t,e){return Object.prototype.hasOwnProperty.call(t,e)}},e={};function r(t){return r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},r(t)}function n(t){return function(t){if(Array.isArray(t))return o(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||function(t,e){if(!t)return;if("string"==typeof t)return o(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);"Object"===r&&t.constructor&&(r=t.constructor.name);if("Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return o(t,e)}(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function o(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);rt.length)&&(e=t.length);for(var r=0,n=new Array(e);r1&&void 0!==arguments[1]?arguments[1]:{},r=i(t);if(r){if(this.element=r,this.element.scrollCarouselGUID){var n=m[this.element.scrollCarouselGUID];return n&&n.option(e),n}this.baseOption=e,this.options=p({},this.constructor.defaults);var o=l(e);this.option(o),this._create()}else console&&console.error("Bad element for Scroll Carousel: ".concat(r||t))}h.defaults={speed:7,smartSpeed:!1,margin:10,autoplay:!1,slideSelector:null};var y,v,b,g,S=h.prototype;S._create=function(){var t=this.guid=++f;this.element.scrollCarouselGUID=t,m[t]=this,this._createViewport(),this._createSlider(),this.activate()},S.option=function(t){Object.assign(this.options,t)},S.activate=function(){var t,e=this;if(!this.isActive){this.isActive=!0,this._translate=0,this.displacement=0,this.isScrolling=!0,this.prevPosition=document.body.scrollTop||document.documentElement.scrollTop,this.baseElems=s(this.element.children);var r=this._filterFindSlideElements(this.element.children);this.slideElems=this._makeSlides(r);var n=this.slideElems.map((function(t){return t.cloneNode(!0)}));(t=this.slider).append.apply(t,c(this.slideElems).concat(c(n))),this.viewport.append(this.slider),this.element.append(this.viewport),this.options.autoplay&&this.autoplay(),window.addEventListener("scroll",(function(){return e._transform()}))}},S.autoplay=function(){var t=this;this.interval=setInterval((function(){t._transform()}),20)},S._transform=function(){(function(t){if(!t)return!1;var e=t.getBoundingClientRect(),r=window.innerHeight||document.documentElement.clientHeight,n=window.innerWidth||document.documentElement.clientWidth,o=e.top<=r&&e.top+e.height>=0,i=e.left<=n&&e.left+e.width>=0;return o&&i})(this.element)&&(this.options.autoplay&&this._setIsScrolling(),this.options.smartSpeed?this._calcSmartSpeed():this._calcRegularSpeed())},S._calcRegularSpeed=function(){var t=this.slider.getBoundingClientRect();this.slider.style.transform="translateX(".concat(this._translate,"px)"),this.isScrolling?this._translate-=this.options.speed:this._translate-=1.2,this._translate<=-t.width/2&&(this._translate=0)},S._calcSmartSpeed=function(){var t=document.body.scrollTop||document.documentElement.scrollTop,e=this.isScrolling?Math.abs(this.prevPosition-t):1.5;this.displacement-=e;var r=this.displacement/5500*(10*this.options.speed)%50;this.slider.style.transform="translateX(".concat(r,"%)"),this.prevPosition=t},S._setIsScrolling=function(){var t=document.body.scrollTop||document.documentElement.scrollTop;this.isScrolling=!0,this.prevPosition!==t?this.options.smartSpeed||(this.prevPosition=t):this.isScrolling=!1},S._makeSlide=function(t){var e=document.createElement("div");return e.style.marginRight=this.options.margin+"px",e.className="sc-slide",this.slideElem=e,this.slideElem.append(t),this.slideElem},S._makeSlides=function(t){var e=this;return t.map((function(t){return e._makeSlide(t)}))},S._createSlider=function(){var t=document.createElement("div");t.className="scroll-carousel-slider",this.slider=t},S._createViewport=function(){this.viewport=document.createElement("div"),this.viewport.className="scroll-carousel-viewport"},S._filterFindSlideElements=function(t){return function(t,e){return(t=s(t)).filter((function(t){return t instanceof HTMLElement})).reduce((function(t,r){var o;if(!e)return t.push(r),t;r.matches(e)&&t.push(r);var i=r.querySelectorAll(e);return(o=t).concat.apply(o,n(i))}),[])}(t,this.options.slideSelector)},S.destroy=function(){var t;this.isActive&&(this.viewport.remove(),(t=this.element).append.apply(t,c(this.baseElems)),this.isActive=!1,clearInterval(this.interval),window.removeEventListener("scroll",this),delete this.element.scrollCarouselGUID,delete m[this.guid])},h.data=function(t){if(t=i(t))return m[t.scrollCarouselGUID]},y=h,v="carousel",b=function(){var t="data-"+v.replace(/(.)([A-Z])/g,(function(t,e,r){return e+"-"+r})).toLowerCase();n(document.querySelectorAll("[".concat(t,"]"))).forEach((function(e){var r,n=e.getAttribute(t);try{r=n&&JSON.parse(n)}catch(r){return void(console&&console.error("Error parsing ".concat(t," on ").concat(e.className,": ").concat(r)))}new y(e,r)}))},"complete"==(g=document.readyState)||"interactive"==g?setTimeout(b):document.addEventListener("DOMContentLoaded",b);var w=h;return e=e.default}()})); +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define("ScrollCarousel",[],e):"object"==typeof exports?exports.ScrollCarousel=e():t.ScrollCarousel=e()}(this,(function(){return function(){"use strict";var t={d:function(e,r){for(var n in r)t.o(r,n)&&!t.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:r[n]})},o:function(t,e){return Object.prototype.hasOwnProperty.call(t,e)}},e={};t.d(e,{default:function(){return E}});var r="rtl",n="ltr";function i(t){return i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},i(t)}function o(t){return function(t){if(Array.isArray(t))return s(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||function(t,e){if(!t)return;if("string"==typeof t)return s(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);"Object"===r&&t.constructor&&(r=t.constructor.name);if("Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return s(t,e)}(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function s(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);rt.length)&&(e=t.length);for(var r=0,n=new Array(e);r1&&void 0!==arguments[1]?arguments[1]:{},r=l(t);if(r){if(this.element=r,this.element.scrollCarouselGUID){var n=y[this.element.scrollCarouselGUID];return n&&n.option(e),n}this.baseOption=e,this.options=h({},this.constructor.defaults);var i=c(e);this.option(i),this._create()}else console&&console.error("Bad element for Scroll Carousel: ".concat(r||t))}v.defaults={speed:7,smartSpeed:!1,margin:10,autoplay:!1,autoplaySpeed:5,slideSelector:null,direction:r};var b,S,g,w,O=v.prototype;O._create=function(){var t=this.guid=++f;this.element.scrollCarouselGUID=t,y[t]=this,this._createViewport(),this._createSlider(),this.activate()},O.option=function(t){Object.assign(this.options,t)},O.activate=function(){var t,e=this;if(!this.isActive){this.isActive=!0,this.translate=0,this.displacement=0,this.isScrolling=!0,this.prevPosition=document.body.scrollTop||document.documentElement.scrollTop,this.baseElems=a(this.element.children);var r=this._filterFindSlideElements(this.element.children);this.slideElems=this._makeSlides(r),this.options.direction===n&&(this.slideElems=this.slideElems.reverse());var i=this.slideElems.map((function(t){return t.cloneNode(!0)}));(t=this.slider).append.apply(t,u(this.slideElems).concat(u(i))),this.viewport.append(this.slider),this.element.append(this.viewport),this.options.direction===n&&this._supportLtr(),this.options.autoplay&&this._autoplay(),window.addEventListener("scroll",(function(){return e._transform()}))}},O._autoplay=function(){var t=this;this.interval=setInterval((function(){t._transform()}),10)},O._transform=function(){(function(t){if(!t)return!1;var e=t.getBoundingClientRect(),r=window.innerHeight||document.documentElement.clientHeight,n=window.innerWidth||document.documentElement.clientWidth,i=e.top<=r&&e.top+e.height>=0,o=e.left<=n&&e.left+e.width>=0;return i&&o})(this.element)&&(this.options.autoplay&&this._setIsScrolling(),this.options.smartSpeed?this._calcSmartSpeed():this._calcRegularSpeed())},O._calcRegularSpeed=function(){var t=this.slider.getBoundingClientRect();this.slider.style.transform="translateX(".concat(this.translate,"px)");var e=this.isScrolling?this.options.speed:1.2;this.options.direction===r&&(this.translate-=e),this.options.direction===n&&(this.translate+=e),this.options.direction===r&&this.translate<=-t.width/2&&(this.translate=0),this.options.direction===n&&this.translate>=0&&(this.translate=-t.width/2)},O._calcSmartSpeed=function(){var t=document.body.scrollTop||document.documentElement.scrollTop;this.displacement-=this.isScrolling?Math.abs(this.prevPosition-t):1.2,this.options.direction===n&&this.displacement<0&&(this.displacement=50/(10*this.options.speed/5500%50));var e,i=this.displacement/5500*(10*this.options.speed)%50;this.options.direction===r&&(e=i),this.options.direction===n&&(e=-i),this.slider.style.transform="translateX(".concat(e,"%)"),this.prevPosition=t},O._supportLtr=function(){var t=this.slider.getBoundingClientRect();this.translate=-t.width+Math.min(document.documentElement.clientWidth,window.innerWidth);var e=100*this.translate/t.width;this.displacement=-e/(10*this.options.speed/5500%50),this.options.smartSpeed?this.slider.style.transform="translateX(".concat(e,"%)"):this.slider.style.transform="translateX(".concat(this.translate,"px)")},O._setIsScrolling=function(){var t=document.body.scrollTop||document.documentElement.scrollTop;this.isScrolling=!0,this.prevPosition!==t?this.options.smartSpeed||(this.prevPosition=t):this.isScrolling=!1},O._makeSlide=function(t){var e=document.createElement("div");return e.style.marginRight=this.options.margin+"px",e.className="sc-slide",this.slideElem=e,this.slideElem.append(t),this.slideElem},O._makeSlides=function(t){var e=this;return t.map((function(t){return e._makeSlide(t)}))},O._createSlider=function(){var t=document.createElement("div");t.className="scroll-carousel-slider",this.slider=t},O._createViewport=function(){this.viewport=document.createElement("div"),this.viewport.className="scroll-carousel-viewport"},O._filterFindSlideElements=function(t){return function(t,e){return(t=a(t)).filter((function(t){return t instanceof HTMLElement})).reduce((function(t,r){var n;if(!e)return t.push(r),t;r.matches(e)&&t.push(r);var i=r.querySelectorAll(e);return(n=t).concat.apply(n,o(i))}),[])}(t,this.options.slideSelector)},O.destroy=function(){var t;this.isActive&&(this.viewport.remove(),(t=this.element).append.apply(t,u(this.baseElems)),this.isActive=!1,clearInterval(this.interval),window.removeEventListener("scroll",this),delete this.element.scrollCarouselGUID,delete y[this.guid])},O.reinit=function(){return new v(this.element,this.baseOption)},v.data=function(t){if(t=l(t))return y[t.scrollCarouselGUID]},b=v,S="carousel",g=function(){var t="data-"+S.replace(/(.)([A-Z])/g,(function(t,e,r){return e+"-"+r})).toLowerCase();o(document.querySelectorAll("[".concat(t,"]"))).forEach((function(e){var r,n=e.getAttribute(t);try{r=n&&JSON.parse(n)}catch(r){return void(console&&console.error("Error parsing ".concat(t," on ").concat(e.className,": ").concat(r)))}new b(e,r)}))},"complete"==(w=document.readyState)||"interactive"==w?setTimeout(g):document.addEventListener("DOMContentLoaded",g);var E=v;return e=e.default}()})); //# sourceMappingURL=scroll.carousel.min.js.map \ No newline at end of file diff --git a/dist/scroll.carousel.min.js.map b/dist/scroll.carousel.min.js.map index 32838b3..0a805da 100644 --- a/dist/scroll.carousel.min.js.map +++ b/dist/scroll.carousel.min.js.map @@ -1 +1 @@ -{"version":3,"file":"scroll.carousel.min.js","mappings":"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","sources":["webpack://ScrollCarousel/webpack/universalModuleDefinition","webpack://ScrollCarousel/webpack/bootstrap","webpack://ScrollCarousel/webpack/runtime/define property getters","webpack://ScrollCarousel/webpack/runtime/hasOwnProperty shorthand","webpack://ScrollCarousel/./src/js/util.js","webpack://ScrollCarousel/./src/js/scroll.carousel.js"],"sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"ScrollCarousel\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"ScrollCarousel\"] = factory();\n\telse\n\t\troot[\"ScrollCarousel\"] = factory();\n})(this, function() {\nreturn ","// The require scope\nvar __webpack_require__ = {};\n\n","// define getter functions for harmony exports\n__webpack_require__.d = function(exports, definition) {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }","/**\n * check an element, node, array, object is into view or not\n *\n * @param {[Node, Element]} el\n * - single element, selected node, an array or a object\n *\n * @return {Boolean} - Boolean\n */\nexport function isScrolledIntoView(el) {\n if (!el) {\n return false;\n }\n const rect = el.getBoundingClientRect();\n const windowHeight = window.innerHeight || document.documentElement.clientHeight;\n const windowWidth = window.innerWidth || document.documentElement.clientWidth;\n const vertInView = rect.top <= windowHeight && rect.top + rect.height >= 0;\n const horInView = rect.left <= windowWidth && rect.left + rect.width >= 0;\n return vertInView && horInView;\n}\n\n// ----- getQueryElement ----- //\n\n// use element as selector string\nexport function getQueryElement(elem) {\n if (typeof elem == 'string') {\n return document.querySelector(elem);\n }\n return elem;\n}\n\n// ----- filterFindElements ----- //\nexport function filterFindElements(elems, selector) {\n // make array of elems\n elems = makeArray(elems);\n\n return (\n elems\n // check that elem is an actual element\n .filter(elem => elem instanceof HTMLElement)\n .reduce((scElems, elem) => {\n // add elem of no selector\n if (!selector) {\n scElems.push(elem);\n return scElems;\n }\n // filter & find items if we have a selector\n // filter\n if (elem.matches(selector)) {\n scElems.push(elem);\n }\n // find children\n let childElems = elem.querySelectorAll(selector);\n // concat childElems to filterFound array\n scElems = scElems.concat(...childElems);\n return scElems;\n }, [])\n );\n}\n\n// ----- makeArray ----- //\n\n// turn element or NodeList into an array\nexport function makeArray(obj) {\n // use object if already an array\n if (Array.isArray(obj)) return obj;\n\n // return empty array if undefined or null\n if (obj === null || obj === undefined) return [];\n\n let isArrayLike = typeof obj == 'object' && typeof obj.length == 'number';\n // convert nodeList to array\n if (isArrayLike) return [...obj];\n\n // array of single index\n return [obj];\n}\n\n// ----- docReady ----- //\n\nexport function docReady(onDocReady) {\n let readyState = document.readyState;\n if (readyState == 'complete' || readyState == 'interactive') {\n // do async to allow for other scripts to run.\n setTimeout(onDocReady);\n } else {\n document.addEventListener('DOMContentLoaded', onDocReady);\n }\n}\n\n// ----- htmlInit ----- //\n\n// source: http://bit.ly/3oYLusc\nexport function toDashed(str) {\n return str\n .replace(/(.)([A-Z])/g, function (match, $1, $2) {\n return $1 + '-' + $2;\n })\n .toLowerCase();\n}\n\n// allow user to initialize classes via [data-namespace] or .js-namespace class\n// htmlInit( Widget, 'widgetName' )\n// options are parsed from data-namespace-options\nexport function htmlInit(WidgetClass, namespace) {\n docReady(function () {\n let dashedNamespace = toDashed(namespace);\n let dataAttr = 'data-' + dashedNamespace;\n let dataAttrElems = document.querySelectorAll(`[${dataAttr}]`);\n\n [...dataAttrElems].forEach(elem => {\n let attr = elem.getAttribute(dataAttr);\n let options;\n try {\n options = attr && JSON.parse(attr);\n } catch (error) {\n // log error, do not initialize\n if (console) {\n console.error(`Error parsing ${dataAttr} on ${elem.className}: ${error}`);\n }\n return;\n }\n // initialize\n new WidgetClass(elem, options);\n });\n });\n}\n\n/**\n * Duplicate a node\n *\n * @param {Array} elems\n * @return {Array} array of element\n *\n */\nexport function duplicateElems(elems) {\n return elems.map(node => node.cloneNode(true));\n}\n\n// option validation\n/**\n *\n * @param {Object} options\n * @returns {Object} Same object of param with sanitization\n */\nexport function sanitizer(options) {\n if (Object.keys(options).includes('speed') && !Number(options.speed)) options.speed = 7;\n if (Number(options.speed) <= 0) options.speed = 1;\n if (Object.keys(options).includes('margin') && !Number(options.margin) && Number(options.margin) !== 0)\n options.margin = 10;\n\n return options;\n}\n\n","import '../scss/main.scss';\nimport {\n duplicateElems,\n filterFindElements,\n getQueryElement,\n htmlInit,\n isScrolledIntoView,\n makeArray,\n sanitizer\n} from './util';\n\n// globally unique identifiers\nlet GUID = 0;\n// internal store of all ScrollCarousel instances\nlet instances = {};\n\n/**\n * Representing the Scroll Carousel\n * @constructor\n * @param {[Node, Element, string]} element - Target element where\n * @param {ScrollCarousel.defaults} options - Configuration options of the carousel\n */\nfunction ScrollCarousel(element, options = {}) {\n let queryElement = getQueryElement(element);\n if (!queryElement) {\n if (console) console.error(`Bad element for Scroll Carousel: ${queryElement || element}`);\n return;\n }\n this.element = queryElement;\n\n // do not initialize twice on same element\n if (this.element.scrollCarouselGUID) {\n let instance = instances[this.element.scrollCarouselGUID];\n if (instance) instance.option(options);\n return instance;\n }\n\n // baseOption will be used for destroy method\n this.baseOption = options;\n // options\n this.options = { ...this.constructor.defaults };\n // validated options\n const sanitizedOptions = sanitizer(options);\n // merge options with prototype\n this.option(sanitizedOptions);\n\n // kick things off\n this._create();\n}\n\n// default options\nScrollCarousel.defaults = {\n // movement speed of the carousel\n speed: 7,\n // handle the speed according to acceleration\n smartSpeed: false,\n // margin between two slides\n margin: 10,\n // slide will play auto\n autoplay: false,\n // select slide with class name which you want to select for carousel.\n // other element will behave as simple\n slideSelector: null\n};\n\nlet proto = ScrollCarousel.prototype;\n\n// start creating the carousel\nproto._create = function () {\n // add id for ScrollCarousel.data\n let id = (this.guid = ++GUID);\n this.element.scrollCarouselGUID = id; // expando\n instances[id] = this; // associate via id\n\n // create viewport\n this._createViewport();\n\n // create slider\n this._createSlider();\n\n // add listeners from on option\n this.activate();\n};\n\n// assign default option with user input option\nproto.option = function (opts) {\n Object.assign(this.options, opts);\n};\n\n// main mechanism of Scroll Carousel\nproto.activate = function () {\n if (this.isActive) return;\n\n this.isActive = true;\n this._translate = 0;\n this.displacement = 0;\n this.isScrolling = true;\n this.prevPosition = document.body.scrollTop || document.documentElement.scrollTop;\n\n // baseElems will be used for destroy method\n this.baseElems = makeArray(this.element.children);\n\n // move initial slide elements so they can be loaded as slides\n let slideElems = this._filterFindSlideElements(this.element.children);\n this.slideElems = this._makeSlides(slideElems);\n\n // duplicate the slide array\n let duplicateSlideElems = duplicateElems(this.slideElems);\n\n this.slider.append(...this.slideElems, ...duplicateSlideElems);\n this.viewport.append(this.slider);\n this.element.append(this.viewport);\n\n if (this.options.autoplay) {\n this.autoplay();\n }\n\n // transform function call on scroll\n window.addEventListener('scroll', () => this._transform());\n};\n\n// run interval for autoplay\nproto.autoplay = function () {\n // autoplay will set an interval. in every interval,\n // we transform the slider. the interval\n // will be removed when destroy method fired\n this.interval = setInterval(() => {\n this._transform();\n }, 20);\n};\n\n// transform the slider\nproto._transform = function () {\n if (!isScrolledIntoView(this.element)) return;\n\n if (this.options.autoplay) {\n this._setIsScrolling();\n }\n\n if (!this.options.smartSpeed) {\n this._calcRegularSpeed();\n } else {\n this._calcSmartSpeed();\n }\n};\n\n// calculate speed without smart speed\nproto._calcRegularSpeed = function () {\n const rect = this.slider.getBoundingClientRect();\n\n this.slider.style.transform = `translateX(${this._translate}px)`;\n this.isScrolling ? (this._translate -= this.options.speed) : (this._translate -= 1.2);\n if (this._translate <= -rect.width / 2) this._translate = 0;\n};\n\n// calculate smart speed\nproto._calcSmartSpeed = function () {\n const documentScrollTop = document.body.scrollTop || document.documentElement.scrollTop;\n const displacementAmount = this.isScrolling ? Math.abs(this.prevPosition - documentScrollTop) : 1.5;\n this.displacement -= displacementAmount;\n\n const translateAmount = ((this.displacement / 5.5e3) * (this.options.speed * 10)) % 50;\n this.slider.style.transform = `translateX(${translateAmount}%)`;\n this.prevPosition = documentScrollTop;\n};\n\n// check if the document is scrolling or not\nproto._setIsScrolling = function () {\n const top = document.body.scrollTop || document.documentElement.scrollTop;\n\n this.isScrolling = true;\n if (this.prevPosition === top) {\n this.isScrolling = false;\n return;\n }\n\n // for smartSpeed the prevPosition will be set from _calcSmartSpeed function\n if (!this.options.smartSpeed) this.prevPosition = top;\n};\n\n// every node will be in sc-slide\nproto._makeSlide = function (elem) {\n let slideElem = document.createElement('div');\n slideElem.style.marginRight = this.options.margin + 'px';\n slideElem.className = 'sc-slide';\n this.slideElem = slideElem;\n this.slideElem.append(elem);\n return this.slideElem;\n};\n\n// full array of node\nproto._makeSlides = function (elems) {\n return elems.map(elem => this._makeSlide(elem));\n};\n\n// slider positions the slide\nproto._createSlider = function () {\n // slider element does all the positioning\n let slider = document.createElement('div');\n slider.className = 'scroll-carousel-slider';\n this.slider = slider;\n};\n\n// slider will be in a viewport and it will transform\nproto._createViewport = function () {\n this.viewport = document.createElement('div');\n this.viewport.className = 'scroll-carousel-viewport';\n};\n\n// filtering elements if the element child structure is too much complex (specially for slideSelector option)\nproto._filterFindSlideElements = function (elems) {\n return filterFindElements(elems, this.options.slideSelector);\n};\n\nproto.destroy = function () {\n if (!this.isActive) return;\n\n this.viewport.remove();\n this.element.append(...this.baseElems);\n\n // set flags\n this.isActive = false;\n // clear the interval\n clearInterval(this.interval);\n\n window.removeEventListener('scroll', this);\n delete this.element.scrollCarouselGUID;\n delete instances[this.guid];\n};\n\n/**\n * get Scroll Carousel instance from element\n * @param {[Node, Element, String]} elem - element or selector string\n * @returns {ScrollCarousel} - Scroll Carousel instance\n */\nScrollCarousel.data = function (elem) {\n elem = getQueryElement(elem);\n if (elem) return instances[elem.scrollCarouselGUID];\n};\n\n// initialize with data attribute from here\nhtmlInit(ScrollCarousel, 'carousel');\n\nexport default ScrollCarousel;\n\n"],"names":["root","factory","exports","module","define","amd","this","__webpack_require__","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","getQueryElement","elem","document","querySelector","makeArray","Array","isArray","length","sanitizer","options","keys","includes","Number","speed","margin","GUID","instances","ScrollCarousel","element","queryElement","scrollCarouselGUID","instance","option","baseOption","constructor","defaults","sanitizedOptions","_create","console","error","smartSpeed","autoplay","slideSelector","WidgetClass","namespace","onDocReady","readyState","proto","id","guid","_createViewport","_createSlider","activate","opts","assign","isActive","_translate","displacement","isScrolling","prevPosition","body","scrollTop","documentElement","baseElems","children","slideElems","_filterFindSlideElements","_makeSlides","duplicateSlideElems","map","node","cloneNode","slider","append","viewport","window","addEventListener","_transform","interval","setInterval","el","rect","getBoundingClientRect","windowHeight","innerHeight","clientHeight","windowWidth","innerWidth","clientWidth","vertInView","top","height","horInView","left","width","isScrolledIntoView","_setIsScrolling","_calcSmartSpeed","_calcRegularSpeed","style","transform","documentScrollTop","displacementAmount","Math","abs","translateAmount","_makeSlide","slideElem","createElement","marginRight","className","elems","selector","filter","HTMLElement","reduce","scElems","push","matches","childElems","querySelectorAll","concat","filterFindElements","destroy","remove","clearInterval","removeEventListener","data","dataAttr","replace","match","$1","$2","toLowerCase","forEach","attr","getAttribute","JSON","parse","setTimeout"],"sourceRoot":""} \ No newline at end of file +{"version":3,"file":"scroll.carousel.min.js","mappings":"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","sources":["webpack://ScrollCarousel/webpack/universalModuleDefinition","webpack://ScrollCarousel/webpack/bootstrap","webpack://ScrollCarousel/webpack/runtime/define property getters","webpack://ScrollCarousel/webpack/runtime/hasOwnProperty shorthand","webpack://ScrollCarousel/./src/js/scroll.carousel.const.js","webpack://ScrollCarousel/./src/js/util.js","webpack://ScrollCarousel/./src/js/scroll.carousel.js"],"sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"ScrollCarousel\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"ScrollCarousel\"] = factory();\n\telse\n\t\troot[\"ScrollCarousel\"] = factory();\n})(this, function() {\nreturn ","// The require scope\nvar __webpack_require__ = {};\n\n","// define getter functions for harmony exports\n__webpack_require__.d = function(exports, definition) {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }","export const RTL = 'rtl';\nexport const LTR = 'ltr';\n","import { LTR, RTL } from './scroll.carousel.const';\n\n/**\n * check an element, node, array, object is into view or not\n *\n * @param {[Node, Element]} el\n * - single element, selected node, an array or a object\n *\n * @return {Boolean} - Boolean\n */\nexport function isScrolledIntoView(el) {\n if (!el) {\n return false;\n }\n const rect = el.getBoundingClientRect();\n const windowHeight = window.innerHeight || document.documentElement.clientHeight;\n const windowWidth = window.innerWidth || document.documentElement.clientWidth;\n const vertInView = rect.top <= windowHeight && rect.top + rect.height >= 0;\n const horInView = rect.left <= windowWidth && rect.left + rect.width >= 0;\n return vertInView && horInView;\n}\n\n// ----- getQueryElement ----- //\n\n// use element as selector string\nexport function getQueryElement(elem) {\n if (typeof elem == 'string') {\n return document.querySelector(elem);\n }\n return elem;\n}\n\n// ----- filterFindElements ----- //\nexport function filterFindElements(elems, selector) {\n // make array of elems\n elems = makeArray(elems);\n\n return (\n elems\n // check that elem is an actual element\n .filter(elem => elem instanceof HTMLElement)\n .reduce((scElems, elem) => {\n // add elem of no selector\n if (!selector) {\n scElems.push(elem);\n return scElems;\n }\n // filter & find items if we have a selector\n // filter\n if (elem.matches(selector)) {\n scElems.push(elem);\n }\n // find children\n let childElems = elem.querySelectorAll(selector);\n // concat childElems to filterFound array\n scElems = scElems.concat(...childElems);\n return scElems;\n }, [])\n );\n}\n\n// ----- makeArray ----- //\n\n// turn element or NodeList into an array\nexport function makeArray(obj) {\n // use object if already an array\n if (Array.isArray(obj)) return obj;\n\n // return empty array if undefined or null\n if (obj === null || obj === undefined) return [];\n\n let isArrayLike = typeof obj == 'object' && typeof obj.length == 'number';\n // convert nodeList to array\n if (isArrayLike) return [...obj];\n\n // array of single index\n return [obj];\n}\n\n// ----- docReady ----- //\n\nexport function docReady(onDocReady) {\n let readyState = document.readyState;\n if (readyState == 'complete' || readyState == 'interactive') {\n // do async to allow for other scripts to run.\n setTimeout(onDocReady);\n } else {\n document.addEventListener('DOMContentLoaded', onDocReady);\n }\n}\n\n// ----- htmlInit ----- //\n\n// source: http://bit.ly/3oYLusc\nexport function toDashed(str) {\n return str\n .replace(/(.)([A-Z])/g, function (match, $1, $2) {\n return $1 + '-' + $2;\n })\n .toLowerCase();\n}\n\n// allow user to initialize classes via [data-namespace] or .js-namespace class\n// htmlInit( Widget, 'widgetName' )\n// options are parsed from data-namespace-options\nexport function htmlInit(WidgetClass, namespace) {\n docReady(function () {\n let dashedNamespace = toDashed(namespace);\n let dataAttr = 'data-' + dashedNamespace;\n let dataAttrElems = document.querySelectorAll(`[${dataAttr}]`);\n\n [...dataAttrElems].forEach(elem => {\n let attr = elem.getAttribute(dataAttr);\n let options;\n try {\n options = attr && JSON.parse(attr);\n } catch (error) {\n // log error, do not initialize\n if (console) {\n console.error(`Error parsing ${dataAttr} on ${elem.className}: ${error}`);\n }\n return;\n }\n // initialize\n new WidgetClass(elem, options);\n });\n });\n}\n\n/**\n * Duplicate a node\n *\n * @param {Array} elems\n * @return {Array} array of element\n *\n */\nexport function duplicateElems(elems) {\n return elems.map(node => node.cloneNode(true));\n}\n\n// option validation\n/**\n *\n * @param {Object} options\n * @returns {Object} Same object of param with sanitization\n */\nexport function sanitizer(options) {\n if (Object.keys(options).includes('speed') && !Number(options.speed)) options.speed = 7;\n if (Number(options.speed) <= 0) options.speed = 1;\n\n if (Object.keys(options).includes('margin') && !Number(options.margin) && Number(options.margin) !== 0)\n options.margin = 10;\n if (Object.keys(options).includes('direction')) options.direction = options.direction.toLowerCase();\n if (Object.keys(options).includes('direction') && options.direction !== RTL && options.direction !== LTR)\n options.direction = RTL;\n\n if (Object.keys(options).includes('autoplaySpeed') && !Number(options.autoplaySpeed))\n options.autoplaySpeed = 5;\n if (Number(options.autoplaySpeed) <= 0) options.autoplaySpeed = 1;\n\n return options;\n}\n\n","import '../scss/main.scss';\nimport { LTR, RTL } from './scroll.carousel.const';\nimport {\n duplicateElems,\n filterFindElements,\n getQueryElement,\n htmlInit,\n isScrolledIntoView,\n makeArray,\n sanitizer\n} from './util';\n\n// globally unique identifiers\nlet GUID = 0;\n// internal store of all ScrollCarousel instances\nlet instances = {};\n\n/**\n * Representing the Scroll Carousel\n * @constructor\n * @param {[Node, Element, string]} element - Target element where\n * @param {ScrollCarousel.defaults} options - Configuration options of the carousel\n */\nfunction ScrollCarousel(element, options = {}) {\n let queryElement = getQueryElement(element);\n if (!queryElement) {\n if (console) console.error(`Bad element for Scroll Carousel: ${queryElement || element}`);\n return;\n }\n this.element = queryElement;\n\n // do not initialize twice on same element\n if (this.element.scrollCarouselGUID) {\n let instance = instances[this.element.scrollCarouselGUID];\n if (instance) instance.option(options);\n return instance;\n }\n\n // baseOption will be used for destroy method and reinit method\n this.baseOption = options;\n // options\n this.options = { ...this.constructor.defaults };\n // validated options\n const sanitizedOptions = sanitizer(options);\n // merge options with prototype\n this.option(sanitizedOptions);\n\n // kick things off\n this._create();\n}\n\n// default options\nScrollCarousel.defaults = {\n // movement speed of the carousel\n speed: 7,\n // handle the speed according to acceleration\n smartSpeed: false,\n // margin between two slides\n margin: 10,\n // slide will play auto\n autoplay: false,\n // speed control for autoplay\n autoplaySpeed: 5,\n // select slide with class name which you want to select for carousel.\n // other element will behave as simple\n slideSelector: null,\n // moving direction of the slides\n direction: RTL\n};\n\nlet proto = ScrollCarousel.prototype;\n\n// start creating the carousel\nproto._create = function () {\n // add id for ScrollCarousel.data\n let id = (this.guid = ++GUID);\n this.element.scrollCarouselGUID = id; // expando\n instances[id] = this; // associate via id\n\n // create viewport\n this._createViewport();\n\n // create slider\n this._createSlider();\n\n // add listeners from on option\n this.activate();\n};\n\n// assign default option with user input option\nproto.option = function (opts) {\n Object.assign(this.options, opts);\n};\n\n// main mechanism of Scroll Carousel\nproto.activate = function () {\n if (this.isActive) return;\n\n this.isActive = true;\n this.translate = 0;\n this.displacement = 0;\n this.isScrolling = true;\n this.prevPosition = document.body.scrollTop || document.documentElement.scrollTop;\n\n // baseElems will be used for destroy method\n this.baseElems = makeArray(this.element.children);\n\n // move initial slide elements so they can be loaded as slides\n let slideElems = this._filterFindSlideElements(this.element.children);\n this.slideElems = this._makeSlides(slideElems);\n\n // for ltr direction reverse the elements like rtl mode\n if (this.options.direction === LTR) {\n this.slideElems = this.slideElems.reverse();\n }\n\n // duplicate the slide array\n let duplicateSlideElems = duplicateElems(this.slideElems);\n\n this.slider.append(...this.slideElems, ...duplicateSlideElems);\n this.viewport.append(this.slider);\n this.element.append(this.viewport);\n\n // kick for ltr support\n if (this.options.direction === LTR) {\n this._supportLtr();\n }\n\n if (this.options.autoplay) {\n this._autoplay();\n }\n\n // transform function call on scroll\n window.addEventListener('scroll', () => this._transform());\n};\n\n// run interval for autoplay\nproto._autoplay = function () {\n // autoplay will set an interval. in every interval,\n // we transform the slider. the interval\n // will be removed when destroy method fired\n this.interval = setInterval(() => {\n this._transform();\n }, 10);\n};\n\n// transform the slider\nproto._transform = function () {\n if (!isScrolledIntoView(this.element)) return;\n\n if (this.options.autoplay) {\n this._setIsScrolling();\n }\n\n if (!this.options.smartSpeed) {\n this._calcRegularSpeed();\n } else {\n this._calcSmartSpeed();\n }\n};\n\n// calculate speed without smart speed\nproto._calcRegularSpeed = function () {\n const rect = this.slider.getBoundingClientRect();\n this.slider.style.transform = `translateX(${this.translate}px)`;\n const speed = this.isScrolling ? this.options.speed : 1.2;\n\n if (this.options.direction === RTL) this.translate -= speed;\n if (this.options.direction === LTR) this.translate += speed;\n\n if (this.options.direction === RTL && this.translate <= -rect.width / 2) this.translate = 0;\n if (this.options.direction === LTR && this.translate >= 0) this.translate = -rect.width / 2;\n};\n\n// calculate smart speed\nproto._calcSmartSpeed = function () {\n const documentScrollTop = document.body.scrollTop || document.documentElement.scrollTop;\n this.displacement -= this.isScrolling ? Math.abs(this.prevPosition - documentScrollTop) : 1.2;\n\n if (this.options.direction === LTR && this.displacement < 0) {\n this.displacement = 50 / (((this.options.speed * 10) / 5.5e3) % 50);\n }\n\n const translateBasic = ((this.displacement / 5.5e3) * (this.options.speed * 10)) % 50;\n\n let translate;\n if (this.options.direction === RTL) translate = translateBasic;\n if (this.options.direction === LTR) translate = -translateBasic;\n\n this.slider.style.transform = `translateX(${translate}%)`;\n this.prevPosition = documentScrollTop;\n};\n\n// initial kick for ltr direction\nproto._supportLtr = function () {\n const rect = this.slider.getBoundingClientRect();\n\n // calculate initial translate for regular speed\n this.translate = -rect.width + Math.min(document.documentElement.clientWidth, window.innerWidth);\n\n // calculate initial displacement for smartSpeed\n let translateInPercent = (100 * this.translate) / rect.width;\n this.displacement = -translateInPercent / (((this.options.speed * 10) / 5.5e3) % 50);\n\n if (this.options.smartSpeed) {\n this.slider.style.transform = `translateX(${translateInPercent}%)`;\n } else {\n this.slider.style.transform = `translateX(${this.translate}px)`;\n }\n};\n\n// check if the document is scrolling or not\nproto._setIsScrolling = function () {\n const top = document.body.scrollTop || document.documentElement.scrollTop;\n\n this.isScrolling = true;\n if (this.prevPosition === top) {\n this.isScrolling = false;\n return;\n }\n\n // for smartSpeed the prevPosition will be set from _calcSmartSpeed function\n if (!this.options.smartSpeed) this.prevPosition = top;\n};\n\n// every node will be in sc-slide\nproto._makeSlide = function (elem) {\n let slideElem = document.createElement('div');\n slideElem.style.marginRight = this.options.margin + 'px';\n slideElem.className = 'sc-slide';\n this.slideElem = slideElem;\n this.slideElem.append(elem);\n return this.slideElem;\n};\n\n// full array of node\nproto._makeSlides = function (elems) {\n return elems.map(elem => this._makeSlide(elem));\n};\n\n// slider positions the slide\nproto._createSlider = function () {\n // slider element does all the positioning\n let slider = document.createElement('div');\n slider.className = 'scroll-carousel-slider';\n this.slider = slider;\n};\n\n// slider will be in a viewport and it will transform\nproto._createViewport = function () {\n this.viewport = document.createElement('div');\n this.viewport.className = 'scroll-carousel-viewport';\n};\n\n// filtering elements if the element child structure is too much complex (specially for slideSelector option)\nproto._filterFindSlideElements = function (elems) {\n return filterFindElements(elems, this.options.slideSelector);\n};\n\n// ============================== METHOD ==============================\n\nproto.destroy = function () {\n if (!this.isActive) return;\n\n this.viewport.remove();\n this.element.append(...this.baseElems);\n\n // set flags\n this.isActive = false;\n // clear the interval\n clearInterval(this.interval);\n\n window.removeEventListener('scroll', this);\n delete this.element.scrollCarouselGUID;\n delete instances[this.guid];\n};\n\n// Re initialize the carousel after destroy\nproto.reinit = function () {\n return new ScrollCarousel(this.element, this.baseOption);\n};\n\n// ============================== DATA ATTRIBUTE ==============================\n\n/**\n * get Scroll Carousel instance from element\n * @param {[Node, Element, String]} elem - element or selector string\n * @returns {ScrollCarousel} - Scroll Carousel instance\n */\nScrollCarousel.data = function (elem) {\n elem = getQueryElement(elem);\n if (elem) return instances[elem.scrollCarouselGUID];\n};\n\n// initialize with data attribute from here\nhtmlInit(ScrollCarousel, 'carousel');\n\nexport default ScrollCarousel;\n\n\n"],"names":["root","factory","exports","module","define","amd","this","__webpack_require__","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","RTL","LTR","getQueryElement","elem","document","querySelector","makeArray","Array","isArray","length","sanitizer","options","keys","includes","Number","speed","margin","direction","toLowerCase","autoplaySpeed","GUID","instances","ScrollCarousel","element","queryElement","scrollCarouselGUID","instance","option","baseOption","constructor","defaults","sanitizedOptions","_create","console","error","smartSpeed","autoplay","slideSelector","WidgetClass","namespace","onDocReady","readyState","proto","id","guid","_createViewport","_createSlider","activate","opts","assign","isActive","translate","displacement","isScrolling","prevPosition","body","scrollTop","documentElement","baseElems","children","slideElems","_filterFindSlideElements","_makeSlides","reverse","duplicateSlideElems","map","node","cloneNode","slider","append","viewport","_supportLtr","_autoplay","window","addEventListener","_transform","interval","setInterval","el","rect","getBoundingClientRect","windowHeight","innerHeight","clientHeight","windowWidth","innerWidth","clientWidth","vertInView","top","height","horInView","left","width","isScrolledIntoView","_setIsScrolling","_calcSmartSpeed","_calcRegularSpeed","style","transform","documentScrollTop","Math","abs","translateBasic","min","translateInPercent","_makeSlide","slideElem","createElement","marginRight","className","elems","selector","filter","HTMLElement","reduce","scElems","push","matches","childElems","querySelectorAll","concat","filterFindElements","destroy","remove","clearInterval","removeEventListener","reinit","data","dataAttr","replace","match","$1","$2","forEach","attr","getAttribute","JSON","parse","setTimeout"],"sourceRoot":""} \ No newline at end of file diff --git a/example/js/scroll-carousel.js b/example/js/scroll-carousel.js index 1e0ff89..e224e06 100644 --- a/example/js/scroll-carousel.js +++ b/example/js/scroll-carousel.js @@ -4,12 +4,14 @@ let demo2 = document.querySelector('#demo2'); let demo3 = document.querySelector('#demo3'); - let dm1 = new ScrollCarousel(demo1); + let dm1 = new ScrollCarousel(demo1, { + autoplay: true + }); document.querySelector('#btn-1').addEventListener('click', function () { if (dm1.isActive) { dm1.destroy(); } else { - dm1 = new ScrollCarousel(demo1); + dm1 = dm1.reinit(); } }); @@ -18,10 +20,11 @@ smartSpeed: true }); - new ScrollCarousel(demo1); new ScrollCarousel(demo2, { autoplay: true, + autoplaySpeed: 8, smartSpeed: true, + direction: 'ltr', speed: 9, margin: 5 }); diff --git a/package.json b/package.json index f8e2a35..32a7b13 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "scroll-carousel", - "version": "1.0.0", + "version": "1.1.0", "description": "Scroll carousel, a unique content slider that specially works on window scroll.", "main": "dist/scroll.carousel.js", "types": "src/js/scroll.carousel.d.ts", diff --git a/src/js/scroll.carousel.const.js b/src/js/scroll.carousel.const.js new file mode 100644 index 0000000..4a7b19c --- /dev/null +++ b/src/js/scroll.carousel.const.js @@ -0,0 +1,2 @@ +export const RTL = 'rtl'; +export const LTR = 'ltr'; diff --git a/src/js/scroll.carousel.d.ts b/src/js/scroll.carousel.d.ts index 3a3a2dd..38b156b 100644 --- a/src/js/scroll.carousel.d.ts +++ b/src/js/scroll.carousel.d.ts @@ -5,6 +5,10 @@ declare class ScrollCarousel { * Clears all bindings. */ destroy(): void; + /** + * Re initialize the carousel after destroy + */ + reinit(): this; } declare namespace ScrollCarousel { @@ -25,11 +29,19 @@ declare namespace ScrollCarousel { * Slide will play auto */ autoplay?: boolean; + /** + * Speed control for autoplay + */ + autoplaySpeed?: number; /** * select slide with class name which you want to select for carousel. * other element will behave as simple */ slideSelector?: string; + /** + * moving direction of the slides + */ + direction?: 'rtl' | 'ltr'; } } diff --git a/src/js/scroll.carousel.js b/src/js/scroll.carousel.js index e5f6652..b3982e7 100644 --- a/src/js/scroll.carousel.js +++ b/src/js/scroll.carousel.js @@ -1,4 +1,5 @@ import '../scss/main.scss'; +import { LTR, RTL } from './scroll.carousel.const'; import { duplicateElems, filterFindElements, @@ -35,7 +36,7 @@ function ScrollCarousel(element, options = {}) { return instance; } - // baseOption will be used for destroy method + // baseOption will be used for destroy method and reinit method this.baseOption = options; // options this.options = { ...this.constructor.defaults }; @@ -58,9 +59,13 @@ ScrollCarousel.defaults = { margin: 10, // slide will play auto autoplay: false, + // speed control for autoplay + autoplaySpeed: 5, // select slide with class name which you want to select for carousel. // other element will behave as simple - slideSelector: null + slideSelector: null, + // moving direction of the slides + direction: RTL }; let proto = ScrollCarousel.prototype; @@ -92,7 +97,7 @@ proto.activate = function () { if (this.isActive) return; this.isActive = true; - this._translate = 0; + this.translate = 0; this.displacement = 0; this.isScrolling = true; this.prevPosition = document.body.scrollTop || document.documentElement.scrollTop; @@ -104,6 +109,11 @@ proto.activate = function () { let slideElems = this._filterFindSlideElements(this.element.children); this.slideElems = this._makeSlides(slideElems); + // for ltr direction reverse the elements like rtl mode + if (this.options.direction === LTR) { + this.slideElems = this.slideElems.reverse(); + } + // duplicate the slide array let duplicateSlideElems = duplicateElems(this.slideElems); @@ -111,8 +121,13 @@ proto.activate = function () { this.viewport.append(this.slider); this.element.append(this.viewport); + // kick for ltr support + if (this.options.direction === LTR) { + this._supportLtr(); + } + if (this.options.autoplay) { - this.autoplay(); + this._autoplay(); } // transform function call on scroll @@ -120,13 +135,13 @@ proto.activate = function () { }; // run interval for autoplay -proto.autoplay = function () { +proto._autoplay = function () { // autoplay will set an interval. in every interval, // we transform the slider. the interval // will be removed when destroy method fired this.interval = setInterval(() => { this._transform(); - }, 20); + }, 10); }; // transform the slider @@ -147,23 +162,53 @@ proto._transform = function () { // calculate speed without smart speed proto._calcRegularSpeed = function () { const rect = this.slider.getBoundingClientRect(); + this.slider.style.transform = `translateX(${this.translate}px)`; + const speed = this.isScrolling ? this.options.speed : 1.2; + + if (this.options.direction === RTL) this.translate -= speed; + if (this.options.direction === LTR) this.translate += speed; - this.slider.style.transform = `translateX(${this._translate}px)`; - this.isScrolling ? (this._translate -= this.options.speed) : (this._translate -= 1.2); - if (this._translate <= -rect.width / 2) this._translate = 0; + if (this.options.direction === RTL && this.translate <= -rect.width / 2) this.translate = 0; + if (this.options.direction === LTR && this.translate >= 0) this.translate = -rect.width / 2; }; // calculate smart speed proto._calcSmartSpeed = function () { const documentScrollTop = document.body.scrollTop || document.documentElement.scrollTop; - const displacementAmount = this.isScrolling ? Math.abs(this.prevPosition - documentScrollTop) : 1.5; - this.displacement -= displacementAmount; + this.displacement -= this.isScrolling ? Math.abs(this.prevPosition - documentScrollTop) : 1.2; - const translateAmount = ((this.displacement / 5.5e3) * (this.options.speed * 10)) % 50; - this.slider.style.transform = `translateX(${translateAmount}%)`; + if (this.options.direction === LTR && this.displacement < 0) { + this.displacement = 50 / (((this.options.speed * 10) / 5.5e3) % 50); + } + + const translateBasic = ((this.displacement / 5.5e3) * (this.options.speed * 10)) % 50; + + let translate; + if (this.options.direction === RTL) translate = translateBasic; + if (this.options.direction === LTR) translate = -translateBasic; + + this.slider.style.transform = `translateX(${translate}%)`; this.prevPosition = documentScrollTop; }; +// initial kick for ltr direction +proto._supportLtr = function () { + const rect = this.slider.getBoundingClientRect(); + + // calculate initial translate for regular speed + this.translate = -rect.width + Math.min(document.documentElement.clientWidth, window.innerWidth); + + // calculate initial displacement for smartSpeed + let translateInPercent = (100 * this.translate) / rect.width; + this.displacement = -translateInPercent / (((this.options.speed * 10) / 5.5e3) % 50); + + if (this.options.smartSpeed) { + this.slider.style.transform = `translateX(${translateInPercent}%)`; + } else { + this.slider.style.transform = `translateX(${this.translate}px)`; + } +}; + // check if the document is scrolling or not proto._setIsScrolling = function () { const top = document.body.scrollTop || document.documentElement.scrollTop; @@ -212,6 +257,8 @@ proto._filterFindSlideElements = function (elems) { return filterFindElements(elems, this.options.slideSelector); }; +// ============================== METHOD ============================== + proto.destroy = function () { if (!this.isActive) return; @@ -228,6 +275,13 @@ proto.destroy = function () { delete instances[this.guid]; }; +// Re initialize the carousel after destroy +proto.reinit = function () { + return new ScrollCarousel(this.element, this.baseOption); +}; + +// ============================== DATA ATTRIBUTE ============================== + /** * get Scroll Carousel instance from element * @param {[Node, Element, String]} elem - element or selector string @@ -243,3 +297,4 @@ htmlInit(ScrollCarousel, 'carousel'); export default ScrollCarousel; + diff --git a/src/js/util.js b/src/js/util.js index bfa5132..1b9cd1f 100644 --- a/src/js/util.js +++ b/src/js/util.js @@ -1,3 +1,5 @@ +import { LTR, RTL } from './scroll.carousel.const'; + /** * check an element, node, array, object is into view or not * @@ -145,8 +147,16 @@ export function duplicateElems(elems) { export function sanitizer(options) { if (Object.keys(options).includes('speed') && !Number(options.speed)) options.speed = 7; if (Number(options.speed) <= 0) options.speed = 1; + if (Object.keys(options).includes('margin') && !Number(options.margin) && Number(options.margin) !== 0) options.margin = 10; + if (Object.keys(options).includes('direction')) options.direction = options.direction.toLowerCase(); + if (Object.keys(options).includes('direction') && options.direction !== RTL && options.direction !== LTR) + options.direction = RTL; + + if (Object.keys(options).includes('autoplaySpeed') && !Number(options.autoplaySpeed)) + options.autoplaySpeed = 5; + if (Number(options.autoplaySpeed) <= 0) options.autoplaySpeed = 1; return options; }