├── .gitignore ├── .npmignore ├── src ├── img │ ├── arrow-black.png │ └── arrow-white.png ├── css │ └── ue-scroll.css └── js │ └── ue-scroll.js ├── postcss.config.js ├── LICENSE ├── package.json ├── CHANGELOG.md ├── webpack.config.js ├── dist ├── ue-scroll.min.js └── ue-scroll.min.css └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log* 3 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | docs/ 2 | *.lock* 3 | *.log* -------------------------------------------------------------------------------- /src/img/arrow-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/azrsix/ue-scroll-js/HEAD/src/img/arrow-black.png -------------------------------------------------------------------------------- /src/img/arrow-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/azrsix/ue-scroll-js/HEAD/src/img/arrow-white.png -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = ({ file, options, env }) => ({ 2 | plugins: { 3 | 'postcss-import': {}, 4 | 'postcss-cssnext': { warnForDuplicates: false }, 5 | 'cssnano': file.extname.match(/\.css$/) ? {} : false 6 | } 7 | }); 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018, azrsix 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ue-scroll-js", 3 | "version": "2.0.2", 4 | "description": "Lightweight JavaScript library for scroll up", 5 | "keywords": [ 6 | "scroll", 7 | "javascript" 8 | ], 9 | "homepage": "https://azrsix.github.io/ue-scroll-js/", 10 | "bugs": { 11 | "url": "https://github.com/azrsix/ue-scroll-js/issues" 12 | }, 13 | "license": "MIT", 14 | "files": [ 15 | "dist", 16 | "src", 17 | "LICENSE", 18 | "package.json", 19 | "postcss.config.js", 20 | "README.md", 21 | "webpack.config.js" 22 | ], 23 | "repository": { 24 | "type": "git", 25 | "url": "https://github.com/azrsix/ue-scroll-js.git" 26 | }, 27 | "main": "src/js/ue-scroll.js", 28 | "unpkg": "dist/ue-scroll.min.js", 29 | "devDependencies": { 30 | "@babel/core": "^7.8.4", 31 | "@babel/preset-env": "^7.8.4", 32 | "babel-loader": "^8.0.6", 33 | "babel-minify-webpack-plugin": "^0.3.1", 34 | "css-loader": "^3.4.2", 35 | "cssnano": "^4.1.10", 36 | "file-loader": "^5.0.2", 37 | "mini-css-extract-plugin": "^0.9.0", 38 | "postcss": "^7.0.26", 39 | "postcss-cssnext": "^3.1.0", 40 | "postcss-import": "^12.0.1", 41 | "postcss-loader": "^3.0.0", 42 | "style-loader": "^1.1.3", 43 | "url-loader": "^3.0.0", 44 | "webpack": "^4.41.6", 45 | "webpack-cli": "^3.3.11" 46 | }, 47 | "scripts": { 48 | "dev": "webpack --watch", 49 | "build": "webpack" 50 | }, 51 | "author": "azrsix" 52 | } 53 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## [Unreleased] 4 | 5 | ## [v2.0.2] - 2020-02-17 [YANKED] 6 | 7 | ### Security 8 | 9 | * Updated "devDependencies" packages (because vulnerability measures) 10 | * This vulnerability is no impact for ue-scroll-js itself 11 | 12 | ## [v2.0.1] - 2019-08-22 [YANKED] 13 | 14 | ### Security 15 | 16 | * Updated "devDependencies" packages (because vulnerability measures) 17 | * This vulnerability is no impact for ue-scroll-js itself 18 | 19 | ## [v2.0.0] - 2018-10-05 20 | 21 | ### Changed 22 | 23 | * Unite source file into src/js/ue-scroll.js 24 | * Update build tools (webpack 4 and Babel 7) 25 | * Added Japanese document 26 | 27 | ### Removed 28 | 29 | * Removed src/js/ue-scroll.esm.js (united into src/js/ue-scroll.js) 30 | 31 | ## [v1.0.1] - 2018-05-02 32 | 33 | ### Fixed 34 | 35 | * Fixed some mistake in document 36 | 37 | ## [v1.0.0] - 2018-05-02 38 | 39 | ### Added 40 | 41 | * Released first major version 42 | * Implemented option to enable cancellation during scrolling 43 | 44 | ### Fixed 45 | 46 | * Fixed some typo in document 47 | 48 | ## [v0.0.1] - 2018-03-09 49 | 50 | ### Added 51 | 52 | * First released ue-scroll.js 53 | 54 | [Unreleased]: https://github.com/azrsix/ue-scroll/compare/v2.0.2...HEAD 55 | [v2.0.2]: https://github.com/azrsix/ue-scroll/compare/v2.0.1...v2.0.2 56 | [v2.0.1]: https://github.com/azrsix/ue-scroll/compare/v2.0.0...v2.0.1 57 | [v2.0.0]: https://github.com/azrsix/ue-scroll/compare/v1.0.1...v2.0.0 58 | [v1.0.1]: https://github.com/azrsix/ue-scroll/compare/v1.0.0...v1.0.1 59 | [v1.0.0]: https://github.com/azrsix/ue-scroll/compare/v0.0.1...v1.0.0 60 | [v0.0.1]: https://github.com/azrsix/ue-scroll/tree/v0.0.1 61 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const webpack = require('webpack'); 3 | const MinifyPlugin = require('babel-minify-webpack-plugin'); 4 | const MiniCssExtractPlugin = require("mini-css-extract-plugin"); 5 | const pkg = require('./package.json'); 6 | 7 | const config = { 8 | mode: 'production', 9 | entry: ['./src/css/ue-scroll.css', './src/js/ue-scroll.js'], 10 | output: { 11 | path: path.resolve(__dirname, 'dist'), 12 | filename: 'ue-scroll.min.js', 13 | library: 'UeScroll', 14 | libraryExport: 'default', 15 | libraryTarget: 'umd' 16 | }, 17 | module: { 18 | rules: [{ 19 | test: /\.js$/, 20 | exclude: /node_modules/, 21 | use: [{ 22 | loader: 'babel-loader', 23 | options: { 24 | presets: ['@babel/preset-env'] 25 | } 26 | }] 27 | }, { 28 | test: /\.css$/, 29 | use: [{ 30 | loader: MiniCssExtractPlugin.loader 31 | }, { 32 | loader: 'css-loader', 33 | options: { 34 | importLoaders: 1 35 | } 36 | }, { 37 | loader: 'postcss-loader' 38 | }] 39 | }, { 40 | test: /\.(?:jpe?g|png|gif|svg|ico)(?:\?.+)?$/, 41 | use: [{ 42 | loader: 'url-loader', 43 | options: { 44 | limit: 8192, 45 | name: './img/[name].[ext]' 46 | } 47 | }] 48 | }] 49 | }, 50 | plugins: [ 51 | new MinifyPlugin(), 52 | new MiniCssExtractPlugin({ 53 | filename: 'ue-scroll.min.css' 54 | }), 55 | new webpack.BannerPlugin({ 56 | banner: `ue-scroll.js v${pkg.version}\n(c) 2018 ${pkg.author}\nReleased under the MIT license`, 57 | exclude: /\.css$/, 58 | }) 59 | ] 60 | }; 61 | 62 | module.exports = config; 63 | -------------------------------------------------------------------------------- /src/css/ue-scroll.css: -------------------------------------------------------------------------------- 1 | /* ue-scroll.css */ 2 | 3 | :root { 4 | --color-black: #000; 5 | --color-gray: #999; 6 | --color-white: #fff; 7 | --effect-shadow: rgba(0, 0, 0, 0.2); 8 | --btn-width: 50px; 9 | --btn-height: 50px; 10 | --btn-cursor: pointer; 11 | --btn-position-top: auto; 12 | --btn-position-right: 20px; 13 | --btn-position-bottom: 20px; 14 | --btn-position-left: auto; 15 | --btn-z-index: 100; 16 | --arrow-black-img: '../img/arrow-black.png'; 17 | --arrow-white-img: '../img/arrow-white.png'; 18 | --arrow-size: 40%; 19 | --arrow-repeat: no-repeat; 20 | --arrow-position: center; 21 | } 22 | 23 | .ue-scroll { 24 | display: none; 25 | position: fixed; 26 | transform: translate3d(0, 0, 0); 27 | cursor: var(--btn-cursor); 28 | top: var(--btn-position-top); 29 | right: var(--btn-position-right); 30 | bottom: var(--btn-position-bottom); 31 | left: var(--btn-position-left); 32 | z-index: var(--btn-z-index); 33 | width: var(--btn-width); 34 | height: var(--btn-height); 35 | background-size: var(--arrow-size); 36 | background-repeat: var(--arrow-repeat); 37 | background-position: var(--arrow-position); 38 | &.btn-black { 39 | background-color: var(--color-black); 40 | } 41 | &.btn-gray { 42 | background-color: var(--color-gray); 43 | } 44 | &.btn-white { 45 | background-color: var(--color-white); 46 | } 47 | &.border-black { 48 | border: 1px solid var(--color-black); 49 | } 50 | &.border-white { 51 | border: 1px solid var(--color-white); 52 | } 53 | &.border-gray { 54 | border: 1px solid var(--color-gray); 55 | } 56 | &.arrow-black { 57 | background-image: url(var(--arrow-black-img)); 58 | } 59 | &.arrow-white { 60 | background-image: url(var(--arrow-white-img)); 61 | } 62 | &.shadow { 63 | box-shadow: 0 0 10px var(--effect-shadow); 64 | } 65 | &.circle { 66 | border-radius: 50%; 67 | } 68 | &.rounded-rectangle { 69 | border-radius: 20%; 70 | } 71 | &.square { 72 | border-radius: 0%; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /dist/ue-scroll.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * ue-scroll.js v2.0.2 3 | * (c) 2018 azrsix 4 | * Released under the MIT license 5 | */ 6 | !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.UeScroll=t():e.UeScroll=t()}(window,(function(){return function(e){function t(o){if(n[o])return n[o].exports;var r=n[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,t),r.l=!0,r.exports}var n={};return t.m=e,t.c=n,t.d=function(e,n,o){t.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:o})},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,n){if(1&n&&(e=t(e)),8&n)return e;if(4&n&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(t.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var r in e)t.d(o,r,function(t){return e[t]}.bind(null,r));return o},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s=0)}([function(e,t,n){n(1),e.exports=n(2)},function(){},function(e,t,n){"use strict";n.r(t),t.default={init:function(e){var t=window,n=t.document,o=Object.assign({element:"#ue-scroll",position:200,scrollSpeed:10,fadeSpeed:10,cancelByScroll:!0,cancelByClick:!0,cancelByKeydown:!0},e),r=n.querySelector(o.element),l=void 0!==t.ontouchstart;if(null!==r){var c,i=!1,a=!1,u=0,d=function(){a&&(clearInterval(c),a=!1)};n.addEventListener("DOMContentLoaded",(function(){r.style.display="none",r.style.opacity=0}),!1),t.addEventListener("scroll",(function(){var e,t,c=n.body.scrollTop||n.documentElement.scrollTop,a=function(e){r.style.opacity=e};!i&&c>=o.position&&(r.style.display="block",i=!0,clearInterval(e),e=setInterval((function(){!function(t){a(t+=.05),1<=t&&(clearInterval(e),r.style.opacity=1)}(parseFloat(r.style.opacity))}),o.fadeSpeed)),i&&ce&&(clearInterval(t),r.style.opacity=0,r.style.display="none")}(parseFloat(r.style.opacity))}),o.fadeSpeed)),!l&&o.cancelByScroll&&(c>u&&d(),u=c)})),o.cancelByClick&&t.addEventListener(l?"touchstart":"click",(function(e){e.target!==r&&d()})),o.cancelByKeydown&&t.addEventListener("keydown",(function(){d()})),r.addEventListener("click",(function(){var e=function(e,n){t.scrollTo(e,Math.floor(n-n/(2*o.scrollSpeed))),0>=n&&(clearInterval(c),a=!1,r.style.opacity=0)};return a||(a=!0,clearInterval(c),c=setInterval((function(){var t=n.body.scrollLeft||n.documentElement.scrollLeft,o=n.body.scrollTop||n.documentElement.scrollTop;e(t,o)}),o.scrollSpeed)),!1}))}}}}]).default})); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ue-scroll.js 2 | 3 | Lightweight JavaScript library for scroll up. 4 | 5 | Demo and documentation: 6 | https://azrsix.github.io/ue-scroll-js/ 7 | 8 | ## Getting Started 9 | 10 | ### Install by npm (recommended) 11 | 12 | ``` 13 | $ npm install ue-scroll-js --save 14 | ``` 15 | 16 | ### or Yarn 17 | 18 | ``` 19 | $ yarn add ue-scroll-js 20 | ``` 21 | 22 | ### Using CDN 23 | 24 | ``` 25 | 26 | 27 | ``` 28 | 29 | ### Basic Usage 30 | 31 | ``` 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
40 | Your main contents 41 |
42 | 43 |
44 | 47 | 48 | 49 | ``` 50 | 51 | ### or Set initial options 52 | 53 | ``` 54 | 55 |
56 | 62 | ``` 63 | 64 | ### Use on ES6 modules 65 | 66 | ``` 67 | 'use strict'; 68 | import ue from 'ue-scroll-js'; 69 | // Run this script 70 | ue.init(); 71 | ``` 72 | 73 | By the default, ue-scroll.js automatically detect element having '#ue-scroll'. It needs to be started after DOM is rendered. 74 | 75 | ## Options 76 | 77 | | Key | Data Type | Default Value | Description | 78 | | --------------- | --------- | ------------- | ---------------------------------------------------------------------------- | 79 | | element | String | '#ue-scroll' | Specify an element with a CSS selector. | 80 | | position | Number | 200 | Specify the scroll position where the button is displayed. | 81 | | scrollSpeed | Number | 10 | Specify the speed of scrolling (Recommend 20 or less) | 82 | | fadeSpeed | Number | 10 | Specify the speed of fade (Recommend 20 or less) | 83 | | cancelByScroll | Boolean | true | Cancel scrolling when scroll down (This setting is ignored on touch devices) | 84 | | cancelByClick | Boolean | true | Cancel scrolling when window clicking. | 85 | | cancelByKeydown | Boolean | true | Cancel scrolling when pressed any key. | 86 | 87 | In addition, You can freely change the color, design, position etc of buttons with CSS! 88 | 89 | ## Examples 90 | 91 | Please refer to the [documentation](https://azrsix.github.io/ue-scroll-js/docs.html#examples "ue-scroll.js"). 92 | -------------------------------------------------------------------------------- /dist/ue-scroll.min.css: -------------------------------------------------------------------------------- 1 | .ue-scroll{display:none;position:fixed;-webkit-transform:translateZ(0);transform:translateZ(0);cursor:pointer;top:auto;right:20px;bottom:20px;left:auto;z-index:100;width:50px;height:50px;background-size:40%;background-repeat:no-repeat;background-position:50%}.ue-scroll.btn-black{background-color:#000}.ue-scroll.btn-gray{background-color:#999}.ue-scroll.btn-white{background-color:#fff}.ue-scroll.border-black{border:1px solid #000}.ue-scroll.border-white{border:1px solid #fff}.ue-scroll.border-gray{border:1px solid #999}.ue-scroll.arrow-black{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGUAAAA0CAYAAACTrvadAAADOklEQVR42u1bz0tUURQ+jYajUTiUMItxYbjISBdCEajYREFiYAgOQbYxV7bJVjVLdwmtZHDlxp07EfdBCEK7Fi1btZpt/8DrXryvXtPM9N79zvtx3zsffAjK3Hff+ea9e75zjkTuY17xm+FHxUESpIoVRa+Dx4pXJDTpYKOLID6/KN6QECWHS4rNPoL4/K44IeGKH/q8aIUQJMhpCVt8GDHnhWfBBxI+flTMOeEBXJMw8qFm0l2PgVsSThxTim0mQXzumGRBYIF7zGIEeag4JCGOhqUYBfF5pnhNQh0O6wkI4vOrYlVC3t8Uvk1QEJ/6zLol4e8uyC4QWO3e75uftmvcFRn+YMgcvLbBPA/UuUbNWWG71pLIcXHQIkE8UhzuWLNsfm+75nqRBamag9Y2eB+od+9k0Pzddu13RfQyk6Ap3A4RNDRx2KUCNcxmwWzpeYIpti6AjuRdkEegIA8tr/sUuKYuhFbyKsga6CVmwOvrlPmn5fV1QbSWN0G2AEF+EF8H8TZwlunP3cmLKdxh8iBcGAdN5pzLgujMZZ/Zg3DhuhHcdm/PXDWFpzF5EC5owU+APW66JMgYaApfJ2jctPB7lPOG2QT4vm6ksOeS4ntgz/tZNpnToAepp7z/TWDvnyiDDbPFlD0IF1YpJw2zFcL6IOMZ+4LVwfuZJIcf+bMMly9mAffvmc+nYgqblE0PwgW0kv04aVPYomx7EC5UwWzyRRKb1P/3cUxueBAuXFX8DNzzmzjvGZ3nbZC7uKx4QFjDrMS9KXSet07uY4CwFrMeDilzbQaZ582SB+FKcLbTzjjncuZBuIC0mKGG2XJOPQgXnoBVjKmoF3yZcw/CBaTFHLphho7luORBuIC0mD3zRuqJEmHzvC56EM7sFDGZG90WLRM2z9sggT5DkRZzM/ilrhA2z7sgevzGMGFzzC3/9W9rCtvmfSr4tzaItJh1w8zag9Qk/n3PZ9sWs+77R57tLYIH4cKriLHdC9bIwjr3A876TUEQtsV8ZOprf6Ee4rEakBhbYeE/sT3t5++WxYPEhpkeJvM8TAWk83FblXiy4SZdDKwHE6bRKLWvtniQWDBmxNDx7Tq8/gth0QtD0LQNngAAAABJRU5ErkJggg==)}.ue-scroll.arrow-white{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGUAAAA0CAYAAACTrvadAAADWUlEQVR42u1av2sUURBek0juEpQcGrjiUigpkqApDpSDGPREwRBBOcghGJuYKjYmlV55XQ6swpEqjZ2dSHpBhICdhaWV1bX+AfecJy8xnLu3t++b/T0fDAsHuztvvr335psZx0k5lFJ3yH5o6/f77+g64QhiJeSJGgAR85Eu0xKdeAjZUt74RnZVohQdGRfIWsofP8muScTCJ2SCrKuC4aZELjxCpsx5YYN7EkF+QkrmnECwIZHkI6RiUl4O7EhEcUIWyXqKF22dLEh07Qi5rUICnU3v6TIpUQ5GyJoKH1/JLku0RyNkU0WH72RlifpwUbinooc+sxaEAXdCOkBgtXqvmastbgkT/wiZNAevLU5O61x0nTFnhS3WhBA6aMEgfiArDjyzYH63xWaeCSmbg9YW+169E1Mj2wee/SZ3WoYWPA+Kwl2/oDEkDp3cNMxooVUwW3oWVYptCqBTWSfkAUjIfcv3PgbeqQuhpawSsgFqiWXw/TX68n9bvl8XRCtZI2QH2EJ+cXUQ6TlLwFmm77uRFVHY5tAgjD7NgSJzJc2E6LT0kFODMPp2xRBui6dpFYXHYWgQRh+LtDV+AnzcThMhs6AofBWVcDP/5oNMN8z0gQzu180YfB4jewv4fJhYkalHeUANUo/Z/20gQ/ycuIYZOXQ3Tg3CuI5GJhpmbvO8Afsgcwn7wOrgeuadtP7lTcm+lNCtuAqof41qXKKwlUQNkqBK9sOoRWE3yRqEca1lMJt8HoWT08A8b6QahHHNl8i+AGt+HdqaGeZ5m05KQb5fJDsCG2Zj3E6h87x1J+WgNYwjLWYzHFLgcgaZ502MBmFMcHZjzTh1mTpLGoSRHGSK075hRjeuZ1GDMBLzCKxiLAZ94YssaxBGYmqgyFwZdc/cy4MGYSQGaTFrrPuVsDt50iDM2SkiMrfcHloA53mbTs5hdBzSYm6dfdTmYcg876ojOI1lEZxj7v7d/gFRqPfRJaHCtTZo3WLWDTMH0CAVoWDo+WzbYm7bzPZmXoMwkvMyYGwPzmpkAZT7EVv9Jj/ENALou/HBm/3aoO3/bhKMSsyqT2yPPfXdkNJKbjUIIzHLHiLzxLcC4vJ3a0hI2Yi5bgbWzydMM0FqXz3RIKEQM2vI6HkNr/8Bm6ReqxbVux8AAAAASUVORK5CYII=)}.ue-scroll.shadow{-webkit-box-shadow:0 0 10px rgba(0,0,0,.2);box-shadow:0 0 10px rgba(0,0,0,.2)}.ue-scroll.circle{border-radius:50%}.ue-scroll.rounded-rectangle{border-radius:20%}.ue-scroll.square{border-radius:0} 2 | -------------------------------------------------------------------------------- /src/js/ue-scroll.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const init = (settings) => { 4 | 5 | const defaults = { 6 | element: '#ue-scroll', 7 | position: 200, 8 | scrollSpeed: 10, 9 | fadeSpeed: 10, 10 | cancelByScroll: true, 11 | cancelByClick: true, 12 | cancelByKeydown: true 13 | }; 14 | 15 | const w = window; 16 | const d = w.document; 17 | const opts = Object.assign(defaults, settings); 18 | const btn = d.querySelector(opts.element); 19 | const isTouchDevice = (typeof w.ontouchstart !== 'undefined'); 20 | 21 | // Element not found 22 | if (btn === null) return; 23 | 24 | let isVisibleBtn = false; 25 | let isScrolling = false; 26 | let beforeScroll = 0; 27 | let scrollAnimation; 28 | 29 | // For canceling scroll 30 | const cancelScrolling = () => { 31 | if (isScrolling) { 32 | clearInterval(scrollAnimation); 33 | isScrolling = false; 34 | } 35 | }; 36 | 37 | // Init styles 38 | d.addEventListener('DOMContentLoaded', () => { 39 | btn.style.display = 'none'; 40 | btn.style.opacity = 0; 41 | }, false); 42 | 43 | // Fade in and out 44 | w.addEventListener('scroll', () => { 45 | let fadeInAnimation; 46 | let fadeOutAnimation; 47 | const scroll = d.body.scrollTop || d.documentElement.scrollTop; 48 | const setOpacity = (opacity) => { 49 | btn.style.opacity = opacity; 50 | }; 51 | const fadeInArrow = (opacity) => { 52 | setOpacity(opacity += 0.05); 53 | if (opacity >= 1.0) { 54 | clearInterval(fadeInAnimation); 55 | btn.style.opacity = 1.0; 56 | } 57 | }; 58 | const fadeOutArrow = (opacity) => { 59 | setOpacity(opacity -= 0.05); 60 | if (opacity < 0.1) { 61 | clearInterval(fadeOutAnimation); 62 | btn.style.opacity = 0.0; 63 | btn.style.display = 'none'; 64 | } 65 | }; 66 | if (!isVisibleBtn && scroll >= opts.position) { 67 | btn.style.display = 'block'; 68 | isVisibleBtn = true; 69 | clearInterval(fadeInAnimation); 70 | fadeInAnimation = setInterval(() => { 71 | fadeInArrow(parseFloat(btn.style.opacity)); 72 | }, opts.fadeSpeed); 73 | } 74 | if (isVisibleBtn && scroll < opts.position) { 75 | isVisibleBtn = false; 76 | clearInterval(fadeOutAnimation); 77 | fadeOutAnimation = setInterval(() => { 78 | fadeOutArrow(parseFloat(btn.style.opacity)); 79 | }, opts.fadeSpeed); 80 | } 81 | // Canceling scroll by reverse scrolling 82 | if (!isTouchDevice && opts.cancelByScroll) { 83 | if (scroll > beforeScroll) cancelScrolling(); 84 | beforeScroll = scroll; 85 | } 86 | }); 87 | 88 | // Canceling scroll on click or tap 89 | if (opts.cancelByClick) { 90 | w.addEventListener((isTouchDevice) ? 'touchstart' : 'click', (e) => { 91 | if (e.target !== btn) cancelScrolling(); 92 | }); 93 | } 94 | 95 | // Canceling scroll on any keypress 96 | if (opts.cancelByKeydown) { 97 | w.addEventListener('keydown', () => { 98 | cancelScrolling(); 99 | }); 100 | } 101 | 102 | // Scroll to top 103 | btn.addEventListener('click', () => { 104 | const scrollPage = (x, y) => { 105 | w.scrollTo(x, Math.floor(y - y / (opts.scrollSpeed * 2))); 106 | if (y <= 0) { 107 | clearInterval(scrollAnimation); 108 | isScrolling = false; 109 | btn.style.opacity = 0.0; 110 | } 111 | }; 112 | if (!isScrolling) { 113 | isScrolling = true; 114 | clearInterval(scrollAnimation); 115 | scrollAnimation = setInterval(() => { 116 | const x = d.body.scrollLeft || d.documentElement.scrollLeft; 117 | const y = d.body.scrollTop || d.documentElement.scrollTop; 118 | scrollPage(x, y); 119 | }, opts.scrollSpeed); 120 | } 121 | return false; 122 | }); 123 | 124 | }; 125 | 126 | export default { 127 | init: init 128 | }; 129 | --------------------------------------------------------------------------------