From 94a173a8557c7c28440882dafe21b036bd988708 Mon Sep 17 00:00:00 2001 From: Eder Sampaio Date: Fri, 25 May 2018 08:08:58 -0300 Subject: [PATCH] [FEAT] add new project struture --- .babelrc | 3 + .editorconfig | 9 ++ .eslintrc.json | 13 ++ CONTRIBUTING.md | 12 ++ LICENSE.md | 7 + dist/vanillajs-scrollspy.js | 240 ++++++++++++++++++++++++++++ dist/vanillajs-scrollspy.js.map | 1 + dist/vanillajs-scrollspy.min.js | 2 + dist/vanillajs-scrollspy.min.js.map | 1 + examples/index.html | 110 +++++++++++++ index.js | 1 + lib/index.js | 129 +++++++++++++++ lib/index2.js | 102 ++++++++++++ src/index.js | 100 ++++++++++++ src/index2.js | 99 ++++++++++++ webpack.config.babel.js | 28 ++++ 16 files changed, 857 insertions(+) create mode 100644 .babelrc create mode 100644 .editorconfig create mode 100644 .eslintrc.json create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE.md create mode 100644 dist/vanillajs-scrollspy.js create mode 100644 dist/vanillajs-scrollspy.js.map create mode 100644 dist/vanillajs-scrollspy.min.js create mode 100644 dist/vanillajs-scrollspy.min.js.map create mode 100644 examples/index.html create mode 100644 index.js create mode 100644 lib/index.js create mode 100644 lib/index2.js create mode 100644 src/index.js create mode 100644 src/index2.js create mode 100644 webpack.config.babel.js diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..4ddd2ff --- /dev/null +++ b/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ['env'], +} diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..c6c8b36 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..5e8313f --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,13 @@ +{ + "extends": "airbnb-base", + "plugins": [ + "import" + ], + "env": { + "browser": true, + "node": true + }, + "globals": { + "document": false + } +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..e06bd60 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,12 @@ +# Contributing + +1. Fork it! +2. Create your feature branch: `git checkout -b my-new-feature` +3. Commit your changes: `git commit -m 'Add some feature'` +4. Push to the branch: `git push origin my-new-feature` + +*All commands to build and test are available on [package.json](package.json).* + +*Remember that we have a pre-push hook with steps that analyzes and prevents mistakes.* + +**After your pull request is merged**, you can safely delete your branch. diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..719583e --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,7 @@ +Copyright 2018 - Eder Sampaio + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/dist/vanillajs-scrollspy.js b/dist/vanillajs-scrollspy.js new file mode 100644 index 0000000..bfbfaae --- /dev/null +++ b/dist/vanillajs-scrollspy.js @@ -0,0 +1,240 @@ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define([], factory); + else if(typeof exports === 'object') + exports["VanillaScrollspy"] = factory(); + else + root["VanillaScrollspy"] = factory(); +})(window, function() { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { +/******/ configurable: false, +/******/ enumerable: true, +/******/ get: getter +/******/ }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = "./index.js"); +/******/ }) +/************************************************************************/ +/******/ ({ + +/***/ "./index.js": +/*!******************!*\ + !*** ./index.js ***! + \******************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +module.exports = __webpack_require__(/*! ./src/index */ "./src/index.js").default; + +/***/ }), + +/***/ "./src/index.js": +/*!**********************!*\ + !*** ./src/index.js ***! + \**********************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var fncAnimation = function fncAnimation(callback) { + window.setTimeout(callback, 1000 / 60); + return callback; +}; + +window.requestAnimFrame = function () { + return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || fncAnimation; +}(); + +var VanillaScrollspy = function () { + function VanillaScrollspy(menu) { + var speed = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 2000; + var easing = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'easeOutSine'; + + _classCallCheck(this, VanillaScrollspy); + + this.menu = menu; + this.speed = speed; + this.easing = easing; + } + + _createClass(VanillaScrollspy, [{ + key: 'scrollToY', + value: function scrollToY() { + var _this = this; + + var targetY = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; + + var scrollTargetY = targetY; + var scrollY = window.scrollY || document.documentElement.scrollTop; + var currentTime = 0; + var time = Math.max(0.1, Math.min(Math.abs(scrollY - scrollTargetY) / this.speed, 0.8)); + + var easingEquations = { + easeOutSine: function easeOutSine(pos) { + return Math.sin(pos * (Math.PI / 2)); + }, + easeInOutSine: function easeInOutSine(pos) { + return -0.5 * (Math.cos(Math.PI * pos) - 1); + }, + easeInOutQuint: function easeInOutQuint(pos) { + /* eslint-disable-next-line */ + if ((pos /= 0.5) < 1) { + return 0.5 * Math.pow(pos, 5); + } + return 0.5 * (Math.pow(pos - 2, 5) + 2); + } + }; + + var tick = function tick() { + currentTime += 1 / 60; + var p = currentTime / time; + var t = easingEquations[_this.easing](p); + + if (p < 1) { + window.requestAnimFrame(tick); + window.scrollTo(0, scrollY + (scrollTargetY - scrollY) * t); + } else { + window.scrollTo(0, scrollTargetY); + } + }; + + tick(); + } + }, { + key: 'menuControl', + value: function menuControl() { + var i = void 0; + var currLink = void 0; + var refElement = void 0; + var links = this.menu.querySelectorAll('a[href^="#"]'); + var scrollPos = window.scrollY || document.documentElement.scrollTop; + + for (i = 0; i < links.length; i += 1) { + currLink = links[i]; + refElement = document.querySelector(currLink.getAttribute('href')); + + if (refElement.offsetTop <= scrollPos && refElement.offsetTop + refElement.clientHeight > scrollPos) { + currLink.classList.add('active'); + } else { + currLink.classList.remove('active'); + } + } + } + }, { + key: 'animated', + value: function animated() { + var self = this; + function control(e) { + e.preventDefault(); + var target = document.querySelector(this.hash); + self.scrollToY(target.offsetTop); + } + + var i = void 0; + var link = void 0; + var links = this.menu.querySelectorAll('a[href^="#"]'); + + for (i = 0; i < links.length; i += 1) { + link = links[i]; + link.addEventListener('click', control); + } + } + }, { + key: 'init', + value: function init() { + var _this2 = this; + + this.animated(); + document.addEventListener('scroll', function () { + _this2.menuControl(); + }); + } + }]); + + return VanillaScrollspy; +}(); + +exports.default = VanillaScrollspy; + +/***/ }) + +/******/ }); +}); +//# sourceMappingURL=vanillajs-scrollspy.js.map \ No newline at end of file diff --git a/dist/vanillajs-scrollspy.js.map b/dist/vanillajs-scrollspy.js.map new file mode 100644 index 0000000..f016d56 --- /dev/null +++ b/dist/vanillajs-scrollspy.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack://VanillaScrollspy/webpack/universalModuleDefinition","webpack://VanillaScrollspy/webpack/bootstrap","webpack://VanillaScrollspy/./index.js","webpack://VanillaScrollspy/./src/index.js"],"names":["module","exports","require","default","fncAnimation","callback","window","setTimeout","requestAnimFrame","requestAnimationFrame","webkitRequestAnimationFrame","mozRequestAnimationFrame","VanillaScrollspy","menu","speed","easing","targetY","scrollTargetY","scrollY","document","documentElement","scrollTop","currentTime","time","Math","max","min","abs","easingEquations","easeOutSine","pos","sin","PI","easeInOutSine","cos","easeInOutQuint","tick","p","t","scrollTo","i","currLink","refElement","links","querySelectorAll","scrollPos","length","querySelector","getAttribute","offsetTop","clientHeight","classList","add","remove","self","control","e","preventDefault","target","hash","scrollToY","link","addEventListener","animated","menuControl"],"mappings":"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","file":"vanillajs-scrollspy.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([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"VanillaScrollspy\"] = factory();\n\telse\n\t\troot[\"VanillaScrollspy\"] = factory();\n})(window, function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./index.js\");\n","module.exports = require('./src/index').default;\n","const fncAnimation = (callback) => {\n window.setTimeout(callback, 1000 / 60);\n return callback;\n};\n\nwindow.requestAnimFrame = (() =>\n window.requestAnimationFrame ||\n window.webkitRequestAnimationFrame ||\n window.mozRequestAnimationFrame ||\n fncAnimation\n)();\n\nexport default class VanillaScrollspy {\n constructor(menu, speed = 2000, easing = 'easeOutSine') {\n this.menu = menu;\n this.speed = speed;\n this.easing = easing;\n }\n scrollToY(targetY = 0) {\n const scrollTargetY = targetY;\n const scrollY = window.scrollY || document.documentElement.scrollTop;\n let currentTime = 0;\n const time = Math.max(0.1, Math.min(Math.abs(scrollY - scrollTargetY) / this.speed, 0.8));\n\n const easingEquations = {\n easeOutSine(pos) {\n return Math.sin(pos * (Math.PI / 2));\n },\n easeInOutSine(pos) {\n return (-0.5 * (Math.cos(Math.PI * pos) - 1));\n },\n easeInOutQuint(pos) {\n /* eslint-disable-next-line */\n if ((pos /= 0.5) < 1) {\n return 0.5 * (pos ** 5);\n }\n return 0.5 * (((pos - 2) ** 5) + 2);\n },\n };\n\n const tick = () => {\n currentTime += 1 / 60;\n const p = currentTime / time;\n const t = easingEquations[this.easing](p);\n\n if (p < 1) {\n window.requestAnimFrame(tick);\n window.scrollTo(0, scrollY + ((scrollTargetY - scrollY) * t));\n } else {\n window.scrollTo(0, scrollTargetY);\n }\n };\n\n tick();\n }\n menuControl() {\n let i;\n let currLink;\n let refElement;\n const links = this.menu.querySelectorAll('a[href^=\"#\"]');\n const scrollPos = window.scrollY || document.documentElement.scrollTop;\n\n for (i = 0; i < links.length; i += 1) {\n currLink = links[i];\n refElement = document.querySelector(currLink.getAttribute('href'));\n\n if (\n refElement.offsetTop <= scrollPos &&\n (refElement.offsetTop + refElement.clientHeight) > scrollPos\n ) {\n currLink.classList.add('active');\n } else {\n currLink.classList.remove('active');\n }\n }\n }\n animated() {\n const self = this;\n function control(e) {\n e.preventDefault();\n const target = document.querySelector(this.hash);\n self.scrollToY(target.offsetTop);\n }\n\n let i;\n let link;\n const links = this.menu.querySelectorAll('a[href^=\"#\"]');\n\n for (i = 0; i < links.length; i += 1) {\n link = links[i];\n link.addEventListener('click', control);\n }\n }\n init() {\n this.animated();\n document.addEventListener('scroll', () => {\n this.menuControl();\n });\n }\n}\n"],"sourceRoot":""} \ No newline at end of file diff --git a/dist/vanillajs-scrollspy.min.js b/dist/vanillajs-scrollspy.min.js new file mode 100644 index 0000000..6eee431 --- /dev/null +++ b/dist/vanillajs-scrollspy.min.js @@ -0,0 +1,2 @@ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.VanillaScrollspy=t():e.VanillaScrollspy=t()}(window,function(){return function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:o})},n.r=function(e){Object.defineProperty(e,"__esModule",{value:!0})},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=1)}([function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var o=function(){function e(e,t){for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:2e3,o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"easeOutSine";!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.menu=t,this.speed=n,this.easing=o}return o(e,[{key:"scrollToY",value:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,n=window.scrollY||document.documentElement.scrollTop,o=0,r=Math.max(.1,Math.min(Math.abs(n-t)/this.speed,.8)),i={easeOutSine:function(e){return Math.sin(e*(Math.PI/2))},easeInOutSine:function(e){return-.5*(Math.cos(Math.PI*e)-1)},easeInOutQuint:function(e){return(e/=.5)<1?.5*Math.pow(e,5):.5*(Math.pow(e-2,5)+2)}};!function u(){var a=(o+=1/60)/r,c=i[e.easing](a);a<1?(window.requestAnimFrame(u),window.scrollTo(0,n+(t-n)*c)):window.scrollTo(0,t)}()}},{key:"menuControl",value:function(){var e=void 0,t=void 0,n=void 0,o=this.menu.querySelectorAll('a[href^="#"]'),r=window.scrollY||document.documentElement.scrollTop;for(e=0;er?t.classList.add("active"):t.classList.remove("active")}},{key:"animated",value:function(){var e=this;function t(t){t.preventDefault();var n=document.querySelector(this.hash);e.scrollToY(n.offsetTop)}var n=void 0,o=this.menu.querySelectorAll('a[href^="#"]');for(n=0;n {\n window.setTimeout(callback, 1000 / 60);\n return callback;\n};\n\nwindow.requestAnimFrame = (() =>\n window.requestAnimationFrame ||\n window.webkitRequestAnimationFrame ||\n window.mozRequestAnimationFrame ||\n fncAnimation\n)();\n\nexport default class VanillaScrollspy {\n constructor(menu, speed = 2000, easing = 'easeOutSine') {\n this.menu = menu;\n this.speed = speed;\n this.easing = easing;\n }\n scrollToY(targetY = 0) {\n const scrollTargetY = targetY;\n const scrollY = window.scrollY || document.documentElement.scrollTop;\n let currentTime = 0;\n const time = Math.max(0.1, Math.min(Math.abs(scrollY - scrollTargetY) / this.speed, 0.8));\n\n const easingEquations = {\n easeOutSine(pos) {\n return Math.sin(pos * (Math.PI / 2));\n },\n easeInOutSine(pos) {\n return (-0.5 * (Math.cos(Math.PI * pos) - 1));\n },\n easeInOutQuint(pos) {\n /* eslint-disable-next-line */\n if ((pos /= 0.5) < 1) {\n return 0.5 * (pos ** 5);\n }\n return 0.5 * (((pos - 2) ** 5) + 2);\n },\n };\n\n const tick = () => {\n currentTime += 1 / 60;\n const p = currentTime / time;\n const t = easingEquations[this.easing](p);\n\n if (p < 1) {\n window.requestAnimFrame(tick);\n window.scrollTo(0, scrollY + ((scrollTargetY - scrollY) * t));\n } else {\n window.scrollTo(0, scrollTargetY);\n }\n };\n\n tick();\n }\n menuControl() {\n let i;\n let currLink;\n let refElement;\n const links = this.menu.querySelectorAll('a[href^=\"#\"]');\n const scrollPos = window.scrollY || document.documentElement.scrollTop;\n\n for (i = 0; i < links.length; i += 1) {\n currLink = links[i];\n refElement = document.querySelector(currLink.getAttribute('href'));\n\n if (\n refElement.offsetTop <= scrollPos &&\n (refElement.offsetTop + refElement.clientHeight) > scrollPos\n ) {\n currLink.classList.add('active');\n } else {\n currLink.classList.remove('active');\n }\n }\n }\n animated() {\n const self = this;\n function control(e) {\n e.preventDefault();\n const target = document.querySelector(this.hash);\n self.scrollToY(target.offsetTop);\n }\n\n let i;\n let link;\n const links = this.menu.querySelectorAll('a[href^=\"#\"]');\n\n for (i = 0; i < links.length; i += 1) {\n link = links[i];\n link.addEventListener('click', control);\n }\n }\n init() {\n this.animated();\n document.addEventListener('scroll', () => {\n this.menuControl();\n });\n }\n}\n","module.exports = require('./src/index').default;\n"],"sourceRoot":""} \ No newline at end of file diff --git a/examples/index.html b/examples/index.html new file mode 100644 index 0000000..53a0edc --- /dev/null +++ b/examples/index.html @@ -0,0 +1,110 @@ + + + + + VanillaJS ScrollSpy + + + + +
+
+ +
+
+ +
+
+

Home

+
+
+ +
+
+

Portfolio

+
+
+ +
+
+

About

+
+
+ +
+
+

Contact

+
+
+ + + + + diff --git a/index.js b/index.js new file mode 100644 index 0000000..8f59cdf --- /dev/null +++ b/index.js @@ -0,0 +1 @@ +module.exports = require('./src/index').default; diff --git a/lib/index.js b/lib/index.js new file mode 100644 index 0000000..283a643 --- /dev/null +++ b/lib/index.js @@ -0,0 +1,129 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var fncAnimation = function fncAnimation(callback) { + window.setTimeout(callback, 1000 / 60); + return callback; +}; + +window.requestAnimFrame = function () { + return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || fncAnimation; +}(); + +var VanillaScrollspy = function () { + function VanillaScrollspy(menu) { + var speed = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 2000; + var easing = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'easeOutSine'; + + _classCallCheck(this, VanillaScrollspy); + + this.menu = menu; + this.speed = speed; + this.easing = easing; + } + + _createClass(VanillaScrollspy, [{ + key: 'scrollToY', + value: function scrollToY() { + var _this = this; + + var targetY = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; + + var scrollTargetY = targetY; + var scrollY = window.scrollY || document.documentElement.scrollTop; + var currentTime = 0; + var time = Math.max(0.1, Math.min(Math.abs(scrollY - scrollTargetY) / this.speed, 0.8)); + + var easingEquations = { + easeOutSine: function easeOutSine(pos) { + return Math.sin(pos * (Math.PI / 2)); + }, + easeInOutSine: function easeInOutSine(pos) { + return -0.5 * (Math.cos(Math.PI * pos) - 1); + }, + easeInOutQuint: function easeInOutQuint(pos) { + /* eslint-disable-next-line */ + if ((pos /= 0.5) < 1) { + return 0.5 * Math.pow(pos, 5); + } + return 0.5 * (Math.pow(pos - 2, 5) + 2); + } + }; + + var tick = function tick() { + currentTime += 1 / 60; + var p = currentTime / time; + var t = easingEquations[_this.easing](p); + + if (p < 1) { + window.requestAnimFrame(tick); + window.scrollTo(0, scrollY + (scrollTargetY - scrollY) * t); + } else { + window.scrollTo(0, scrollTargetY); + } + }; + + tick(); + } + }, { + key: 'menuControl', + value: function menuControl() { + var i = void 0; + var currLink = void 0; + var refElement = void 0; + var links = this.menu.querySelectorAll('a[href^="#"]'); + var scrollPos = window.scrollY || document.documentElement.scrollTop; + + for (i = 0; i < links.length; i += 1) { + currLink = links[i]; + refElement = document.querySelector(currLink.getAttribute('href')); + + if (refElement.offsetTop <= scrollPos && refElement.offsetTop + refElement.clientHeight > scrollPos) { + currLink.classList.add('active'); + } else { + currLink.classList.remove('active'); + } + } + } + }, { + key: 'animated', + value: function animated() { + var self = this; + function control(e) { + e.preventDefault(); + var target = document.querySelector(this.hash); + self.scrollToY(target.offsetTop); + } + + var i = void 0; + var link = void 0; + var links = this.menu.querySelectorAll('a[href^="#"]'); + + for (i = 0; i < links.length; i += 1) { + link = links[i]; + link.addEventListener('click', control); + } + } + }, { + key: 'init', + value: function init() { + var _this2 = this; + + this.animated(); + document.addEventListener('scroll', function () { + _this2.menuControl(); + }); + } + }]); + + return VanillaScrollspy; +}(); + +exports.default = VanillaScrollspy; \ No newline at end of file diff --git a/lib/index2.js b/lib/index2.js new file mode 100644 index 0000000..062a49d --- /dev/null +++ b/lib/index2.js @@ -0,0 +1,102 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +var fncAnimation = function fncAnimation(callback) { + window.setTimeout(callback, 1000 / 60); +}; + +window.requestAnimFrame = function () { + return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || fncAnimation; +}(); + +var scrollToY = function scrollToY() { + var targetY = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; + var scrollSpeed = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 2000; + var easingScroll = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'easeOutSine'; + + var scrollTargetY = targetY; + var speed = scrollSpeed; + var easing = easingScroll; + + var scrollY = window.scrollY || document.documentElement.scrollTop; + var currentTime = 0; + var time = Math.max(0.1, Math.min(Math.abs(scrollY - scrollTargetY) / speed, 0.8)); + + var easingEquations = { + easeOutSine: function easeOutSine(pos) { + return Math.sin(pos * (Math.PI / 2)); + }, + easeInOutSine: function easeInOutSine(pos) { + return -0.5 * (Math.cos(Math.PI * pos) - 1); + }, + easeInOutQuint: function easeInOutQuint(pos) { + /* eslint-disable-next-line */ + if ((pos /= 0.5) < 1) { + return 0.5 * Math.pow(pos, 5); + } + return 0.5 * (Math.pow(pos - 2, 5) + 2); + } + }; + + function tick() { + currentTime += 1 / 60; + var p = currentTime / time; + var t = easingEquations[easing](p); + + if (p < 1) { + window.requestAnimFrame(tick); + window.scrollTo(0, scrollY + (scrollTargetY - scrollY) * t); + } else { + window.scrollTo(0, scrollTargetY); + } + } + + tick(); +}; + +var menuControl = function menuControl(menu) { + var i = void 0; + var currLink = void 0; + var refElement = void 0; + var links = menu.querySelectorAll('a[href^="#"]'); + var scrollPos = window.scrollY || document.documentElement.scrollTop; + + for (i = 0; i < links.length; i += 1) { + currLink = links[i]; + refElement = document.querySelector(currLink.getAttribute('href')); + + if (refElement.offsetTop <= scrollPos && refElement.offsetTop + refElement.clientHeight > scrollPos) { + currLink.classList.add('active'); + } else { + currLink.classList.remove('active'); + } + } +}; + +var animated = function animated(menu, speed, easing) { + function control(e) { + e.preventDefault(); + var target = document.querySelector(this.hash); + scrollToY(target.offsetTop, speed, easing); + } + + var i = void 0; + var link = void 0; + var links = menu.querySelectorAll('a[href^="#"]'); + + for (i = 0; i < links.length; i += 1) { + link = links[i]; + link.addEventListener('click', control); + } +}; + +var vanillaScrollspy = function vanillaScrollspy(menu, speed, easing) { + animated(menu, speed, easing); + document.addEventListener('scroll', function () { + menuControl(menu); + }); +}; + +exports.default = vanillaScrollspy; \ No newline at end of file diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..fa6ea60 --- /dev/null +++ b/src/index.js @@ -0,0 +1,100 @@ +const fncAnimation = (callback) => { + window.setTimeout(callback, 1000 / 60); + return callback; +}; + +window.requestAnimFrame = (() => + window.requestAnimationFrame || + window.webkitRequestAnimationFrame || + window.mozRequestAnimationFrame || + fncAnimation +)(); + +export default class VanillaScrollspy { + constructor(menu, speed = 2000, easing = 'easeOutSine') { + this.menu = menu; + this.speed = speed; + this.easing = easing; + } + scrollToY(targetY = 0) { + const scrollTargetY = targetY; + const scrollY = window.scrollY || document.documentElement.scrollTop; + let currentTime = 0; + const time = Math.max(0.1, Math.min(Math.abs(scrollY - scrollTargetY) / this.speed, 0.8)); + + const easingEquations = { + easeOutSine(pos) { + return Math.sin(pos * (Math.PI / 2)); + }, + easeInOutSine(pos) { + return (-0.5 * (Math.cos(Math.PI * pos) - 1)); + }, + easeInOutQuint(pos) { + /* eslint-disable-next-line */ + if ((pos /= 0.5) < 1) { + return 0.5 * (pos ** 5); + } + return 0.5 * (((pos - 2) ** 5) + 2); + }, + }; + + const tick = () => { + currentTime += 1 / 60; + const p = currentTime / time; + const t = easingEquations[this.easing](p); + + if (p < 1) { + window.requestAnimFrame(tick); + window.scrollTo(0, scrollY + ((scrollTargetY - scrollY) * t)); + } else { + window.scrollTo(0, scrollTargetY); + } + }; + + tick(); + } + menuControl() { + let i; + let currLink; + let refElement; + const links = this.menu.querySelectorAll('a[href^="#"]'); + const scrollPos = window.scrollY || document.documentElement.scrollTop; + + for (i = 0; i < links.length; i += 1) { + currLink = links[i]; + refElement = document.querySelector(currLink.getAttribute('href')); + + if ( + refElement.offsetTop <= scrollPos && + (refElement.offsetTop + refElement.clientHeight) > scrollPos + ) { + currLink.classList.add('active'); + } else { + currLink.classList.remove('active'); + } + } + } + animated() { + const self = this; + function control(e) { + e.preventDefault(); + const target = document.querySelector(this.hash); + self.scrollToY(target.offsetTop); + } + + let i; + let link; + const links = this.menu.querySelectorAll('a[href^="#"]'); + + for (i = 0; i < links.length; i += 1) { + link = links[i]; + link.addEventListener('click', control); + } + } + init() { + this.animated(); + document.addEventListener('scroll', () => { + this.menuControl(); + }); + } +} diff --git a/src/index2.js b/src/index2.js new file mode 100644 index 0000000..e3cf9a2 --- /dev/null +++ b/src/index2.js @@ -0,0 +1,99 @@ +const fncAnimation = (callback) => { + window.setTimeout(callback, 1000 / 60); +}; + +window.requestAnimFrame = (() => + window.requestAnimationFrame || + window.webkitRequestAnimationFrame || + window.mozRequestAnimationFrame || + fncAnimation +)(); + +const scrollToY = (targetY = 0, scrollSpeed = 2000, easingScroll = 'easeOutSine') => { + const scrollTargetY = targetY; + const speed = scrollSpeed; + const easing = easingScroll; + + const scrollY = window.scrollY || document.documentElement.scrollTop; + let currentTime = 0; + const time = Math.max(0.1, Math.min(Math.abs(scrollY - scrollTargetY) / speed, 0.8)); + + const easingEquations = { + easeOutSine(pos) { + return Math.sin(pos * (Math.PI / 2)); + }, + easeInOutSine(pos) { + return (-0.5 * (Math.cos(Math.PI * pos) - 1)); + }, + easeInOutQuint(pos) { + /* eslint-disable-next-line */ + if ((pos /= 0.5) < 1) { + return 0.5 * (pos ** 5); + } + return 0.5 * (((pos - 2) ** 5) + 2); + }, + }; + + function tick() { + currentTime += 1 / 60; + const p = currentTime / time; + const t = easingEquations[easing](p); + + if (p < 1) { + window.requestAnimFrame(tick); + window.scrollTo(0, scrollY + ((scrollTargetY - scrollY) * t)); + } else { + window.scrollTo(0, scrollTargetY); + } + } + + tick(); +}; + +const menuControl = (menu) => { + let i; + let currLink; + let refElement; + const links = menu.querySelectorAll('a[href^="#"]'); + const scrollPos = window.scrollY || document.documentElement.scrollTop; + + for (i = 0; i < links.length; i += 1) { + currLink = links[i]; + refElement = document.querySelector(currLink.getAttribute('href')); + + if ( + refElement.offsetTop <= scrollPos && + (refElement.offsetTop + refElement.clientHeight) > scrollPos + ) { + currLink.classList.add('active'); + } else { + currLink.classList.remove('active'); + } + } +}; + +const animated = (menu, speed, easing) => { + function control(e) { + e.preventDefault(); + const target = document.querySelector(this.hash); + scrollToY(target.offsetTop, speed, easing); + } + + let i; + let link; + const links = menu.querySelectorAll('a[href^="#"]'); + + for (i = 0; i < links.length; i += 1) { + link = links[i]; + link.addEventListener('click', control); + } +}; + +const vanillaScrollspy = (menu, speed, easing) => { + animated(menu, speed, easing); + document.addEventListener('scroll', () => { + menuControl(menu); + }); +}; + +export default vanillaScrollspy; diff --git a/webpack.config.babel.js b/webpack.config.babel.js new file mode 100644 index 0000000..7c47308 --- /dev/null +++ b/webpack.config.babel.js @@ -0,0 +1,28 @@ +import { join } from 'path'; + +const include = join(__dirname, 'src'); + +export default { + mode: 'development', + entry: './index', + output: { + path: join(__dirname, 'dist'), + libraryTarget: 'umd', + library: 'VanillaScrollspy', + }, + devtool: 'source-map', + module: { + rules: [ + { + test: /\.js$/, + exclude: /node_modules/, + loader: 'babel-loader', + query: { + presets: [ + ['es2015', { modules: false }] + ], + }, + }, + ], + }, +};