Repository: eduardomb/scroll-up-bar Branch: master Commit: 31802a2f884a Files: 21 Total size: 42.6 KB Directory structure: gitextract_86oyerqg/ ├── .gitignore ├── .jshintrc ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Gruntfile.js ├── LICENSE.md ├── README.md ├── bower.json ├── dist/ │ └── scroll-up-bar.js ├── example/ │ ├── callback.html │ ├── offset.html │ └── simple.html ├── karma.conf.js ├── package.json ├── scripts/ │ └── release.sh ├── scroll-up-bar.jquery.json ├── src/ │ └── scroll-up-bar.js └── test/ ├── basicSpec.js ├── callbackSpec.js └── fixtures/ ├── styles.css └── topbar.html ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ node_modules bower_components ================================================ FILE: .jshintrc ================================================ { "undef": true, "unused": true, "camelcase": true, "curly": true, "indent": 2, "latedef": true, "newcap": true, "noarg": true, "noempty": true, "nonew": true, "quotmark": "single", "strict": true, "trailing": true, "maxlen": 79, "browser": true, "jquery": true, "globals": { "jQuery": true, "module": true, "document": true, "describe": true, "jasmine": true, "it": true, "loadFixtures": true, "loadStyleFixtures": true, "expect": true, "beforeEach": true } } ================================================ FILE: CHANGELOG.md ================================================ # 0.3.0 ## BUg Fixes * Prevent bar from being partially visible after elastic scroll ## Features * Add simplified fallback implementation for iOS devices * Add support for variable height bars * Add support for bars with offset top * Add visibility state handlers * Add `destroy` method # 0.2.0 ## Bug Fixes * Fix scrolling misbehaviour on IE * Fix bar positioning when scrolling for the first time through arrows or page down/up buttons ## Features * Implement karma unit tests * Add HTTPS support for example page * Automate build and test tasks with Grunt, npm and bower * Change directory structure: there is a `dist` folder now ================================================ FILE: CONTRIBUTING.md ================================================ # Contributing ## Building Dependencies for building from source and running tests: * [Git](http://git-scm.com/) - follow the [Github Guide to Installing Git](https://help.github.com/articles/set-up-git) * [Node.js](http://nodejs.org) - depending on your system, you can install Node either from source or as a pre-packaged bundle * [Grunt](http://gruntjs.com) - run: `sudo npm install -g grunt-cli` * [Bower](http://bower.io/): - run: `sudo npm install -g bower` Use Grunt to generate the non-minified and minified scroll-up-bar files: ```shell # Clone your Github repository: git clone git://github.com:/scroll-up-bar.git # Go to the scroll-up-bar directory: cd scroll-up-bar # Install node.js dependencies: npm install # Install bower components: bower install # Build scroll-up-bar: grunt build ``` ## Code Style * JavaScript style should follow the [Google JS style guide](http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml) * Wrap code at 80 chars * Check syntax with `grunt jshint` * Be consistent with the code around you! ## Pull Request * Always have test coverage for new features or bug fixes, and never break existing tests. Use `grunt test` to run tests * Commits should represent one logical change each; if a feature goes through multiple iterations, squash your commits into to one * If you need to change a commit after the pull request was sent, ammend it and force the push instead of opening a new pull request ## Commit Messages Follow the Tim Pope's [commit message format](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html). In summary, the rules are * Title: 50 chars or less. * Body: wrap it to about 72 characters or so. * Write your commit message in the imperative: "Fix bug" and not "Fixed bug". ================================================ FILE: Gruntfile.js ================================================ module.exports = function(grunt) { 'use strict'; grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), concat: { options: { separator: ';', banner: '/* <%= pkg.name %> v<%= pkg.version %> (<%= pkg.homepage %>) */\n' }, dist: { src: ['src/**/*.js'], dest: 'dist/<%= pkg.name %>.js' } }, uglify: { options: { banner: '/* <%= pkg.name %> v<%= pkg.version %> (<%= pkg.homepage %>) */\n' }, dist: { files: { 'dist/<%= pkg.name %>.min.js': ['<%= concat.dist.dest %>'] } } }, jshint: { files: ['Gruntfile.js', 'src/**/*.js', 'test/**/*.js'] }, karma: { unit: { configFile: 'karma.conf.js' }, continuous: { configFile: 'karma.conf.js', singleRun: true } }, watch: { files: ['<%= jshint.files %>'], tasks: ['jshint', 'karma'] } }); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-karma'); grunt.loadNpmTasks('grunt-contrib-watch'); grunt.loadNpmTasks('grunt-contrib-concat'); grunt.registerTask('test', ['karma:unit']); grunt.registerTask('build', ['jshint', 'karma:continuous', 'concat', 'uglify']); grunt.registerTask('default', ['build']); }; ================================================ FILE: LICENSE.md ================================================ Copyright (c) 2016 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. ================================================ FILE: README.md ================================================ # ScrollUpBar Plugin The scroll up bar plugin (jQuery) hides the top bar when scrolling down, and show it when scrolling up. It's specially useful on mobile interfaces to save some precious space. ## Demos * [Simple](http://eduardomb.github.io/scroll-up-bar) * [Bar with offset](http://eduardomb.github.io/scroll-up-bar/offset.html) * [Viewport callbacks](http://eduardomb.github.io/scroll-up-bar/callback.html) ## Installation Include [jQuery](http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js) and `scroll-up-bar.min.js` scripts: ```html ``` [Bower](https://github.com/bower/bower) users can get the source with: ```sh bower install scroll-up-bar ``` ## Basic Usage Create a top bar using position absolute. ```html
Top bar
``` _Tip: you can also add top different than zero_ And then invoke `scrollupbar()` on the element. ```javascript $('#topbar').scrollupbar(); ``` _Alternatively you can invoke with `$.scrollupbar($('#topbar'))`_ ## Options You can pass callback functions in initialization to handle bar visibility events. * `enterViewport` - when the bar enters the viewport * `fullyEnterViewport` - when the bar is completely in the viewport * `exitViewport` - when the bar completely leaves the viewport * `partiallyExitViewport` - when the bar goes from being fully in the viewport to only partially Checkout the [callback example](http://eduardomb.github.io/scroll-up-bar/callback.html). ## Properties There are two global boolean properties that are updated according to bar visibility. * `$.scrollupbar.isInViewport` - true if any part of the bar is visible, false if not * `$.scrollupbar.isFullyInViewport` - true if the entire bar is visible ## Methods * `$.scrollupbar.destroy` - restores bar to original position and disables plugin ## Browser support The plugin was tested on: * Chrome * Firefox * Safari * Opera * IE ## Contributing Read the [Contributing document](CONTRIBUTING.md) for instructions on how to set up your development environment to build and test scroll-up-bar. ================================================ FILE: bower.json ================================================ { "name": "scroll-up-bar", "main": "dist/scroll-up-bar.min.js", "version": "0.3.0", "homepage": "https://github.com/eduardomb/scroll-up-bar", "authors": [ "Eduardo Barbosa " ], "description": "The scroll up bar plugin (jQuery) hides the top bar when scrolling down, and show it when scrolling up.", "keywords": [ "scroll", "up", "bar", "jquery" ], "license": "MIT", "ignore": [ "**/.*", "node_modules", "bower_components", "test", "tests" ], "dependencies": { "jquery": "~2.1.1" }, "devDependencies" : { "jasmine-jquery": "~2.0.5" } } ================================================ FILE: dist/scroll-up-bar.js ================================================ /* scroll-up-bar v0.3.0 (https://github.com/eduardomb/scroll-up-bar) */ (function($) { 'use strict'; var _destroyFn; $.scrollupbar = function($bar, options) { // Default options options = $.extend({ enterViewport: $.noop, fullyEnterViewport: $.noop, exitViewport: $.noop, partiallyExitViewport: $.noop }, options); function isFullyInViewport() { return $window.scrollTop() <= $bar.offset().top; } function isInViewport() { return $window.scrollTop() < $bar.offset().top + $bar.outerHeight(); } var $window = $(window), $document = $(document), minY = $bar.css('position') == 'fixed' ? 0 : $bar.offset().top, lastY = $window.scrollTop(), // Use last Y to detect scroll direction. initialPosTop = $bar.position().top, timeout; $.scrollupbar.isInViewport = isInViewport(); $.scrollupbar.isFullyInViewport = isFullyInViewport(); $window.on('scroll.scrollupbar', function() { var y = $window.scrollTop(), barHeight = $bar.outerHeight(); // Ignore elastic scrolling. if (y < 0 || y > ($document.height() - $window.height())) { return; } // Cancel the event fired by the previous scroll. if (timeout) { clearTimeout(timeout); } if (y < lastY) { // Scrolling up // If the bar is hidden, place it right above the top frame. if (!$.scrollupbar.isInViewport && lastY - barHeight >= minY) { $bar.css('top', lastY - barHeight); $.scrollupbar.isInViewport = true; options.enterViewport(); } // Scrolls up bigger than the bar's height fixes the bar on top. if (isFullyInViewport()) { if (y >= minY) { $bar.css({ 'position': 'fixed', 'top': 0 }); } else { $bar.css({ 'position': 'absolute', 'top': initialPosTop }); } if (!$.scrollupbar.isFullyInViewport) { $.scrollupbar.isFullyInViewport = true; options.fullyEnterViewport(); } } // Fire an event to reveal the entire bar after 400ms if the scroll // wasn't big enough. timeout = setTimeout(function() { if (!$.scrollupbar.isFullyInViewport) { $bar.css({ 'position': 'fixed', 'top': $bar.offset().top - y }); $bar.animate({'top': 0}, 100, function() { $.scrollupbar.isFullyInViewport = true; options.fullyEnterViewport(); }); } }, 400); } else if (y > lastY) { // Scrolling down // Unfix the bar allowing it to scroll with the page. if ($.scrollupbar.isFullyInViewport) { $bar.css({ // translate3d fixes iOS invisible element bug when changing // position values while scrolling. 'transform': 'translate3d(0, 0, 0)', 'position': 'absolute', 'top': lastY > minY ? lastY : initialPosTop }); if (!isFullyInViewport()) { $.scrollupbar.isFullyInViewport = false; options.partiallyExitViewport(); } } if ($.scrollupbar.isInViewport && !isInViewport()) { $.scrollupbar.isInViewport = false; options.exitViewport(); } // Fire an event to hide the entire bar after 400ms if the scroll // wasn't big enough. timeout = setTimeout(function() { if (isInViewport() && y - barHeight >= minY) { $bar.animate({'top': y - barHeight}, 100, function() { $.scrollupbar.isInViewport = false; options.exitViewport(); }); } }, 400); } lastY = y; }); _destroyFn = function() { // Unbind all listeners added by scrollupbar plugin $window.off('.scrollupbar'); // Restore original bar position. $bar.css({ 'position': 'absolute', 'top': initialPosTop }); }; return $bar; }; $.scrollupbar.destroy = function() { if (_destroyFn) { return _destroyFn(); } }; $.fn.scrollupbar = function(options) { return $.scrollupbar(this, options); }; })(jQuery); ================================================ FILE: example/callback.html ================================================ Scroll up bar
Top bar with callbacks

ScrollUpBar plugin example

The scroll up bar plugin hides the top bar when scrolling down, and show it when scrolling up.

Usage instructions available on GitHub. Stop reading now and scroll.

Adipisicing harum quam consequatur deserunt minima. Eligendi quos iure voluptatem corrupti amet ipsa a excepturi ratione sit ex est. Ducimus perspiciatis sunt iusto architecto hic possimus tempore harum quasi expedita!

Sit iste rerum fugit aliquid vero? In aut quos earum asperiores facilis iste eius. Soluta voluptatum repudiandae dignissimos eius iste mollitia eos veritatis magni commodi. Vero nulla vel error eius?

Dolor ab nesciunt deserunt quibusdam quaerat culpa dolor perspiciatis laboriosam consequatur sed? Eligendi praesentium odit itaque assumenda rem maxime ipsum quos pariatur deserunt commodi odio odit? Quaerat minus illo culpa.

Ipsum deleniti natus id assumenda dolore itaque ipsum. Eum nobis necessitatibus eius unde modi. Inventore accusamus vero deleniti aspernatur totam. Nam magni nostrum nesciunt consequatur delectus molestias eveniet velit eveniet.

Adipisicing debitis amet repudiandae blanditiis consequatur libero. Mollitia accusamus minima quam ad saepe minus! Et eum aliquam possimus iure iste eveniet ex? Consequatur repellendus ex architecto voluptate sapiente, molestiae quam.

Consectetur numquam debitis commodi minima doloremque voluptas minima sapiente obcaecati veritatis quia corrupti officia mollitia. Sunt modi libero error possimus illo asperiores eum. Aspernatur voluptatem incidunt officiis eos pariatur? Architecto!

Elit harum mollitia amet quod facilis! Repudiandae deserunt labore sint officiis assumenda consequuntur sunt accusantium tempora. Officia repellendus corrupti qui impedit ea minus quam magni. Praesentium doloremque veniam delectus officiis.

Amet ut ullam ea magnam omnis quidem repellat facilis soluta. Deserunt praesentium eius magnam sapiente beatae quae exercitationem dolores reprehenderit iste facere commodi. Enim ipsa labore laborum adipisci illo sapiente.

================================================ FILE: example/offset.html ================================================ Scroll up bar
Top bar with offset top

ScrollUpBar plugin example

The scroll up bar plugin hides the top bar when scrolling down, and show it when scrolling up.

Usage instructions available on GitHub. Stop reading now and scroll.

Adipisicing harum quam consequatur deserunt minima. Eligendi quos iure voluptatem corrupti amet ipsa a excepturi ratione sit ex est. Ducimus perspiciatis sunt iusto architecto hic possimus tempore harum quasi expedita!

Sit iste rerum fugit aliquid vero? In aut quos earum asperiores facilis iste eius. Soluta voluptatum repudiandae dignissimos eius iste mollitia eos veritatis magni commodi. Vero nulla vel error eius?

Dolor ab nesciunt deserunt quibusdam quaerat culpa dolor perspiciatis laboriosam consequatur sed? Eligendi praesentium odit itaque assumenda rem maxime ipsum quos pariatur deserunt commodi odio odit? Quaerat minus illo culpa.

Ipsum deleniti natus id assumenda dolore itaque ipsum. Eum nobis necessitatibus eius unde modi. Inventore accusamus vero deleniti aspernatur totam. Nam magni nostrum nesciunt consequatur delectus molestias eveniet velit eveniet.

Adipisicing debitis amet repudiandae blanditiis consequatur libero. Mollitia accusamus minima quam ad saepe minus! Et eum aliquam possimus iure iste eveniet ex? Consequatur repellendus ex architecto voluptate sapiente, molestiae quam.

Consectetur numquam debitis commodi minima doloremque voluptas minima sapiente obcaecati veritatis quia corrupti officia mollitia. Sunt modi libero error possimus illo asperiores eum. Aspernatur voluptatem incidunt officiis eos pariatur? Architecto!

Elit harum mollitia amet quod facilis! Repudiandae deserunt labore sint officiis assumenda consequuntur sunt accusantium tempora. Officia repellendus corrupti qui impedit ea minus quam magni. Praesentium doloremque veniam delectus officiis.

Amet ut ullam ea magnam omnis quidem repellat facilis soluta. Deserunt praesentium eius magnam sapiente beatae quae exercitationem dolores reprehenderit iste facere commodi. Enim ipsa labore laborum adipisci illo sapiente.

================================================ FILE: example/simple.html ================================================ Scroll up bar
Top bar

ScrollUpBar plugin example

The scroll up bar plugin hides the top bar when scrolling down, and show it when scrolling up.

Usage instructions available on GitHub. Stop reading now and scroll.

Adipisicing harum quam consequatur deserunt minima. Eligendi quos iure voluptatem corrupti amet ipsa a excepturi ratione sit ex est. Ducimus perspiciatis sunt iusto architecto hic possimus tempore harum quasi expedita!

Sit iste rerum fugit aliquid vero? In aut quos earum asperiores facilis iste eius. Soluta voluptatum repudiandae dignissimos eius iste mollitia eos veritatis magni commodi. Vero nulla vel error eius?

Dolor ab nesciunt deserunt quibusdam quaerat culpa dolor perspiciatis laboriosam consequatur sed? Eligendi praesentium odit itaque assumenda rem maxime ipsum quos pariatur deserunt commodi odio odit? Quaerat minus illo culpa.

Ipsum deleniti natus id assumenda dolore itaque ipsum. Eum nobis necessitatibus eius unde modi. Inventore accusamus vero deleniti aspernatur totam. Nam magni nostrum nesciunt consequatur delectus molestias eveniet velit eveniet.

Adipisicing debitis amet repudiandae blanditiis consequatur libero. Mollitia accusamus minima quam ad saepe minus! Et eum aliquam possimus iure iste eveniet ex? Consequatur repellendus ex architecto voluptate sapiente, molestiae quam.

Consectetur numquam debitis commodi minima doloremque voluptas minima sapiente obcaecati veritatis quia corrupti officia mollitia. Sunt modi libero error possimus illo asperiores eum. Aspernatur voluptatem incidunt officiis eos pariatur? Architecto!

Elit harum mollitia amet quod facilis! Repudiandae deserunt labore sint officiis assumenda consequuntur sunt accusantium tempora. Officia repellendus corrupti qui impedit ea minus quam magni. Praesentium doloremque veniam delectus officiis.

Amet ut ullam ea magnam omnis quidem repellat facilis soluta. Deserunt praesentium eius magnam sapiente beatae quae exercitationem dolores reprehenderit iste facere commodi. Enim ipsa labore laborum adipisci illo sapiente.

================================================ FILE: karma.conf.js ================================================ // Karma configuration // Generated on Sat Jun 21 2014 16:23:42 GMT-0300 (BRT) module.exports = function(config) { 'use strict'; config.set({ // base path that will be used to resolve all patterns (eg. files, exclude) basePath: '', // frameworks to use // available frameworks: https://npmjs.org/browse/keyword/karma-adapter frameworks: ['jasmine'], // list of files / patterns to load in the browser files: [ 'bower_components/jquery/dist/jquery.min.js', 'bower_components/jasmine-jquery/lib/jasmine-jquery.js', 'src/*.js', 'test/fixtures/**/*.html', 'test/fixtures/**/*.css', 'test/**/*Spec.js' ], // list of files to exclude exclude: [], // preprocess matching files before serving them to the browser. Available // preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor preprocessors: {}, // test results reporter to use // possible values: 'dots', 'progress' // available reporters: https://npmjs.org/browse/keyword/karma-reporter reporters: ['progress'], // web server port port: 9876, // enable / disable colors in the output (reporters and logs) colors: true, // level of logging // possible values: config.LOG_DISABLE || config.LOG_ERROR || // config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG logLevel: config.LOG_INFO, // enable / disable watching file and executing tests whenever any file // changes autoWatch: true, // start these browsers. Available browser launchers: // https://npmjs.org/browse/keyword/karma-launcher browsers: ['Chrome', 'Firefox', 'Safari', 'Opera'], // Continuous Integration mode // if true, Karma captures browsers, runs the tests and exits singleRun: false }); }; ================================================ FILE: package.json ================================================ { "name": "scroll-up-bar", "version": "0.3.0", "description": "The scroll up bar plugin (jQuery) hides the top bar when scrolling down, and show it when scrolling up.", "main": "src/scroll-up-bar.js", "scripts": { "test": "grunt test" }, "repository": { "type": "git", "url": "https://github.com/eduardomb/scroll-up-bar.git" }, "keywords": [ "scroll", "up", "bar", "jquery" ], "author": "Eduardo Martins Barbosa", "license": "MIT", "bugs": { "url": "https://github.com/eduardomb/scroll-up-bar/issues" }, "homepage": "https://github.com/eduardomb/scroll-up-bar", "devDependencies": { "karma": "^0.12.16", "karma-chrome-launcher": "^0.1.4", "karma-jasmine": "^0.2.2", "karma-firefox-launcher": "^0.1.3", "karma-safari-launcher": "^0.1.1", "karma-opera-launcher": "^0.1.0", "karma-ie-launcher": "^0.1.5", "grunt": "^0.4.5", "grunt-contrib-uglify": "^0.5.0", "grunt-contrib-jshint": "^0.10.0", "grunt-contrib-watch": "^0.6.1", "grunt-contrib-concat": "^0.4.0", "grunt-karma": "^0.8.3" }, "dependencies": { "bower": "^1.3.5" } } ================================================ FILE: scripts/release.sh ================================================ # Update version on package.json # Update version on bower.json # Update version on scroll-up-bar.jquery.json # Update changelog # Add IE to karma.conf.js browsers # Open karma test address in iPhone and Android # Build (Can't run before updating package.json to update dist files header comment) # Remove IE from karma.conf.js browsers # Commit 'Release x.x.x' # Add tag 'x.x.x' # Update branch gh-pages # push with tag ================================================ FILE: scroll-up-bar.jquery.json ================================================ { "name": "scroll-up-bar", "version": "0.3.0", "title": "Scroll up bar", "author": { "name": "Eduardo Martins Barbosa", "email": "eduardomb@ufmg.br" }, "licenses": [{ "type": "MIT", "url": "http://opensource.org/licenses/MIT" }], "dependencies": { "jquery": "~2.1.1" }, "description": "The scroll up bar plugin (jQuery) hides the top bar when scrolling down, and show it when scrolling up.", "keywords": [ "scroll", "up", "bar", "jquery" ], "demo": "http://eduardomb.github.io/scroll-up-bar/" } ================================================ FILE: src/scroll-up-bar.js ================================================ (function($) { 'use strict'; var _destroyFn; $.scrollupbar = function($bar, options) { // Default options options = $.extend({ enterViewport: $.noop, fullyEnterViewport: $.noop, exitViewport: $.noop, partiallyExitViewport: $.noop }, options); function isFullyInViewport() { return $window.scrollTop() <= $bar.offset().top; } function isInViewport() { return $window.scrollTop() < $bar.offset().top + $bar.outerHeight(); } var $window = $(window), $document = $(document), minY = $bar.css('position') == 'fixed' ? 0 : $bar.offset().top, lastY = $window.scrollTop(), // Use last Y to detect scroll direction. initialPosTop = $bar.position().top, timeout; $.scrollupbar.isInViewport = isInViewport(); $.scrollupbar.isFullyInViewport = isFullyInViewport(); $window.on('scroll.scrollupbar', function() { var y = $window.scrollTop(), barHeight = $bar.outerHeight(); // Ignore elastic scrolling. if (y < 0 || y > ($document.height() - $window.height())) { return; } // Cancel the event fired by the previous scroll. if (timeout) { clearTimeout(timeout); } if (y < lastY) { // Scrolling up // If the bar is hidden, place it right above the top frame. if (!$.scrollupbar.isInViewport && lastY - barHeight >= minY) { $bar.css('top', lastY - barHeight); $.scrollupbar.isInViewport = true; options.enterViewport(); } // Scrolls up bigger than the bar's height fixes the bar on top. if (isFullyInViewport()) { if (y >= minY) { $bar.css({ 'position': 'fixed', 'top': 0 }); } else { $bar.css({ 'position': 'absolute', 'top': initialPosTop }); } if (!$.scrollupbar.isFullyInViewport) { $.scrollupbar.isFullyInViewport = true; options.fullyEnterViewport(); } } // Fire an event to reveal the entire bar after 400ms if the scroll // wasn't big enough. timeout = setTimeout(function() { if (!$.scrollupbar.isFullyInViewport) { $bar.css({ 'position': 'fixed', 'top': $bar.offset().top - y }); $bar.animate({'top': 0}, 100, function() { $.scrollupbar.isFullyInViewport = true; options.fullyEnterViewport(); }); } }, 400); } else if (y > lastY) { // Scrolling down // Unfix the bar allowing it to scroll with the page. if ($.scrollupbar.isFullyInViewport) { $bar.css({ // translate3d fixes iOS invisible element bug when changing // position values while scrolling. 'transform': 'translate3d(0, 0, 0)', 'position': 'absolute', 'top': lastY > minY ? lastY : initialPosTop }); if (!isFullyInViewport()) { $.scrollupbar.isFullyInViewport = false; options.partiallyExitViewport(); } } if ($.scrollupbar.isInViewport && !isInViewport()) { $.scrollupbar.isInViewport = false; options.exitViewport(); } // Fire an event to hide the entire bar after 400ms if the scroll // wasn't big enough. timeout = setTimeout(function() { if (isInViewport() && y - barHeight >= minY) { $bar.animate({'top': y - barHeight}, 100, function() { $.scrollupbar.isInViewport = false; options.exitViewport(); }); } }, 400); } lastY = y; }); _destroyFn = function() { // Unbind all listeners added by scrollupbar plugin $window.off('.scrollupbar'); // Restore original bar position. $bar.css({ 'position': 'absolute', 'top': initialPosTop }); }; return $bar; }; $.scrollupbar.destroy = function() { if (_destroyFn) { return _destroyFn(); } }; $.fn.scrollupbar = function(options) { return $.scrollupbar(this, options); }; })(jQuery); ================================================ FILE: test/basicSpec.js ================================================ jasmine.getFixtures().fixturesPath = 'base/test/fixtures'; jasmine.getStyleFixtures().fixturesPath = 'base/test/fixtures'; describe('Scrolling', function() { 'use strict'; // Returns page Y offset. Don't use window.scrollY or tests will crash on IE. var pageY = function() { return $(window).scrollTop(); }; // Perform the scroll up and fire the scroll event. var scrollUp = function(px) { window.scrollTo(0, pageY() - px); $('html').trigger('scroll'); }; // Perform the scroll down and fire the scroll event. var scrollDown = function(px) { window.scrollTo(0, pageY() + px); $('html').trigger('scroll'); }; beforeEach(function() { loadFixtures('topbar.html'); loadStyleFixtures('styles.css'); // Disable animations. jQuery.fx.off = true; // Destroy plugin instances from previous tests. $.scrollupbar.destroy(); // Reset scroll before each test. window.scrollTo(0, 0); }); it('scroll down should not affect bar before offset is reached', function() { var $topbar = $('#topbar'); // Install the Jasmine Clock to mock setTimeout. jasmine.clock().install(); // Invoke scroll-up-bar plugin on topbar. $topbar.scrollupbar(); scrollDown(50); // Expect the bar to be on its original position. expect($topbar.offset().top).toBe(100); // Wait 401ms, when the complete hiding will be triggered. jasmine.clock().tick(401); // Expect the bar to still be on its original position expect($topbar.offset().top).toBe(100); // Uninstall Jasmine Clock. jasmine.clock().uninstall(); }); it('scroll up should not affect bar before offset is reached', function() { var $topbar = $('#topbar'); // Install the Jasmine Clock to mock setTimeout. jasmine.clock().install(); // Invoke scroll-up-bar plugin on topbar. $topbar.scrollupbar(); scrollDown(120); scrollUp(50); // Expect the bar to be on its original position. expect($topbar.offset().top).toBe(100); // Wait 401ms, when the complete hiding will be triggered. jasmine.clock().tick(401); // Expect the bar to still be on its original position expect($topbar.offset().top).toBe(100); // Uninstall Jasmine Clock. jasmine.clock().uninstall(); }); it('should hide the bar on scroll down', function() { var $topbar = $('#topbar'), topbarHeight = $topbar.outerHeight(); $topbar.scrollupbar(); // Scroll down 'till bar offset. scrollDown(100); scrollDown(topbarHeight); // Expect the bar not to be visible. expect($topbar.offset().top + topbarHeight <= pageY()).toBeTruthy(); }); it('should show the bar on scroll up', function() { var $topbar = $('#topbar'), topbarHeight = $topbar.outerHeight(); $topbar.scrollupbar(); // Scroll down 'till bar offset. scrollDown(100); // In order to scroll up, we need to scroll down first. scrollDown(2 * topbarHeight); scrollUp(topbarHeight); // Expect the bar to be visible. expect($topbar.offset().top).toBe(pageY()); }); it('should finish showing the bar after a tiny scroll up', function() { var $topbar = $('#topbar'), topbarHeight = $topbar.outerHeight(); // Install the Jasmine Clock to mock setTimeout. jasmine.clock().install(); $topbar.scrollupbar(); // Scroll down 'till bar offset. scrollDown(100); // In order to scroll up, we need to scroll down first. scrollDown(2 * topbarHeight); scrollUp(0.5 * topbarHeight); // Expect the bar to be partially visible. expect($topbar.offset().top).toBe(pageY() - 0.5 * topbarHeight); // Wait 401ms, when the complete showing will be triggered. jasmine.clock().tick(401); // Expect the bar to be fully visible. expect($topbar.offset().top).toBe(pageY()); // Uninstall Jasmine Clock. jasmine.clock().uninstall(); }); it('should finish hiding the bar after a tiny scroll down', function() { var $topbar = $('#topbar'), topbarHeight = $topbar.outerHeight(); // Install the Jasmine Clock to mock setTimeout. jasmine.clock().install(); $topbar.scrollupbar(); // Scroll down 'till bar offset. scrollDown(100); // Scroll away from page top, then scroll up to reveal the bar and finally // do a tiny scroll down. scrollDown(2 * topbarHeight); scrollUp(topbarHeight); scrollDown(0.5 * topbarHeight); // Expect the bar to be partially visible. expect($topbar.offset().top).toBe(pageY() - 0.5 * topbarHeight); // Wait 401ms, when the complete hiding will be triggered. jasmine.clock().tick(401); // Expect the bar not to be visible. expect($topbar.offset().top + topbarHeight <= pageY()).toBeTruthy(); // Uninstall Jasmine Clock. jasmine.clock().uninstall(); }); it('should not finish hiding the bar if it is near page top', function() { var $topbar = $('#topbar'), topbarHeight = $topbar.outerHeight(); // Install the Jasmine Clock to mock setTimeout. jasmine.clock().install(); // Invoke scroll-up-bar plugin on topbar. $topbar.scrollupbar(); // Scroll down 'till bar offset. scrollDown(100); scrollDown(0.5 * topbarHeight); // Expect the bar to be partially visible. expect($topbar.offset().top).toBe(pageY() - 0.5 * topbarHeight); // Wait 401ms, when the complete hiding might be triggered. jasmine.clock().tick(401); // Expect the bar to still be partially visible. expect($topbar.offset().top).toBe(pageY() - 0.5 * topbarHeight); // Uninstall Jasmine Clock. jasmine.clock().uninstall(); }); }); ================================================ FILE: test/callbackSpec.js ================================================ jasmine.getFixtures().fixturesPath = 'base/test/fixtures'; jasmine.getStyleFixtures().fixturesPath = 'base/test/fixtures'; describe('Callbacks', function() { 'use strict'; // Returns page Y offset. Don't use window.scrollY or tests will crash on IE. var pageY = function() { return $(window).scrollTop(); }; // Perform the scroll up and fire the scroll event. var scrollUp = function(px) { window.scrollTo(0, pageY() - px); $('html').trigger('scroll'); }; // Perform the scroll down and fire the scroll event. var scrollDown = function(px) { window.scrollTo(0, pageY() + px); $('html').trigger('scroll'); }; beforeEach(function() { loadFixtures('topbar.html'); loadStyleFixtures('styles.css'); // Disable animations. jQuery.fx.off = true; // Destroy plugin instances from previous tests. $.scrollupbar.destroy(); // Reset scroll before each test. window.scrollTo(0, 0); }); it('should trigger enterViewport', function() { var $topbar = $('#topbar'), barHeight = $topbar.outerHeight(), callback = jasmine.createSpy('callback'); // Invoke scroll-up-bar plugin on topbar. $topbar.scrollupbar({enterViewport: callback}); // Scroll down enough to hide bar scrollDown($topbar.offset().top + barHeight); // Scroll up to make bar enter viewport scrollUp(1); // Expect the callback to have been called expect(callback).toHaveBeenCalled(); }); it('should trigger fullyEnterViewport', function() { var $topbar = $('#topbar'), barHeight = $topbar.outerHeight(), callback = jasmine.createSpy('callback'); // Invoke scroll-up-bar plugin on topbar. $topbar.scrollupbar({fullyEnterViewport: callback}); // Scroll down enough to hide bar scrollDown($topbar.offset().top + barHeight); // Scroll up to make bar fully enter viewport scrollUp(barHeight); // Expect the callback to have been called expect(callback).toHaveBeenCalled(); }); it('should trigger exitViewport', function() { var $topbar = $('#topbar'), barHeight = $topbar.outerHeight(), callback = jasmine.createSpy('callback'); // Invoke scroll-up-bar plugin on topbar. $topbar.scrollupbar({exitViewport: callback}); // Scroll down enough to hide bar scrollDown($topbar.offset().top + barHeight); // Expect the callback to have been called expect(callback).toHaveBeenCalled(); }); it('should trigger partiallyExitViewport', function() { var $topbar = $('#topbar'), callback = jasmine.createSpy('callback'); // Invoke scroll-up-bar plugin on topbar. $topbar.scrollupbar({partiallyExitViewport: callback}); // Scroll down enought to start hiding the bar. scrollDown($topbar.offset().top + 1); // Expect the callback to have been called expect(callback).toHaveBeenCalled(); }); }); ================================================ FILE: test/fixtures/styles.css ================================================ #topbar, #document { font-family: Arial; font-size: 28px; line-height: 1.6; } #topbar { box-sizing: border-box; position: absolute; top: 100px; left: 0; z-index: 1; width: 100%; height: 64px; padding: 10px; text-align: center; background: rgba(0, 0, 0, 0.8); color: #fff; } #document { max-width: 900px; margin: 0 auto; padding-top: 56px; } ================================================ FILE: test/fixtures/topbar.html ================================================
Top bar

ScrollUpBar plugin example

Adipisicing harum quam consequatur deserunt minima. Eligendi quos iure voluptatem corrupti amet ipsa a excepturi ratione sit ex est. Ducimus perspiciatis sunt iusto architecto hic possimus tempore harum quasi expedita!

Sit iste rerum fugit aliquid vero? In aut quos earum asperiores facilis iste eius. Soluta voluptatum repudiandae dignissimos eius iste mollitia eos veritatis magni commodi. Vero nulla vel error eius?

Dolor ab nesciunt deserunt quibusdam quaerat culpa dolor perspiciatis laboriosam consequatur sed? Eligendi praesentium odit itaque assumenda rem maxime ipsum quos pariatur deserunt commodi odio odit? Quaerat minus illo culpa.

Ipsum deleniti natus id assumenda dolore itaque ipsum. Eum nobis necessitatibus eius unde modi. Inventore accusamus vero deleniti aspernatur totam. Nam magni nostrum nesciunt consequatur delectus molestias eveniet velit eveniet.

Adipisicing debitis amet repudiandae blanditiis consequatur libero. Mollitia accusamus minima quam ad saepe minus! Et eum aliquam possimus iure iste eveniet ex? Consequatur repellendus ex architecto voluptate sapiente, molestiae quam.

Consectetur numquam debitis commodi minima doloremque voluptas minima sapiente obcaecati veritatis quia corrupti officia mollitia. Sunt modi libero error possimus illo asperiores eum. Aspernatur voluptatem incidunt officiis eos pariatur? Architecto!

Sit iste rerum fugit aliquid vero? In aut quos earum asperiores facilis iste eius. Soluta voluptatum repudiandae dignissimos eius iste mollitia eos veritatis magni commodi. Vero nulla vel error eius?

Elit harum mollitia amet quod facilis! Repudiandae deserunt labore sint officiis assumenda consequuntur sunt accusantium tempora. Officia repellendus corrupti qui impedit ea minus quam magni. Praesentium doloremque veniam delectus officiis.

Amet ut ullam ea magnam omnis quidem repellat facilis soluta. Deserunt praesentium eius magnam sapiente beatae quae exercitationem dolores reprehenderit iste facere commodi. Enim ipsa labore laborum adipisci illo sapiente.

Sit iste rerum fugit aliquid vero? In aut quos earum asperiores facilis iste eius. Soluta voluptatum repudiandae dignissimos eius iste mollitia eos veritatis magni commodi. Vero nulla vel error eius?