From 3c27263b4f6471b0fcb15141be5e82bc588d2f1e Mon Sep 17 00:00:00 2001 From: James Wilson Date: Sat, 21 Apr 2018 23:01:18 -0500 Subject: [PATCH] v3.0.0 - Rebuild scrollNav to use native JavaScript Replaced jQuery with native JS and removed all production dependencies (development does require deps). Reduced the number of user options to simplify the API and reduced the amount of DOM manipulation to reduce likelihood of browser bugs. Includes a full set of test suites for all modules (unless noted). --- .eslintignore | 1 + .eslintrc.json | 21 + .gitignore | 3 + .jestrc.json | 10 + .jshintrc | 14 - .prettierrc.json | 3 + .travis.yml | 11 +- CHANGELOG.md | 20 +- CONTRIBUTING.md | 113 +- Gruntfile.js | 210 - LICENSE-MIT | 35 +- README.md | 543 +- bower.json | 15 +- dist/jquery.scrollNav.js | 452 - dist/jquery.scrollNav.min.js | 4 - dist/scrollNav.min.js | 2 + dist/scrollNav.min.js.map | 1 + dist/scrollNav.min.mjs | 2 + dist/scrollNav.min.mjs.map | 1 + dist/scrollNav.min.umd.js | 2 + dist/scrollNav.min.umd.js.map | 1 + jest.setup.js | 13 + jest.transform.js | 3 + libs/jquery-loader.js | 12 - libs/jquery/jquery.js | 9555 ----------- libs/qunit/qunit.css | 244 - libs/qunit/qunit.js | 2152 --- package-lock.json | 13662 ++++++++++++++-- package.json | 58 +- scrollNav.jquery.json | 34 - src/.jshintrc | 16 - src/scrollNav.js | 551 +- src/scrollNav.v2-7-3.js | 587 + src/scrollTo.js | 40 + src/setupClickHandlers.js | 31 + src/setupResizeHandler.js | 11 + src/setupScrollHandler.js | 23 + src/teardownClickHandlers.js | 6 + src/teardownResizeHandler.js | 3 + src/teardownScrollHandler.js | 3 + src/util/calculateScrollDuration.js | 5 + src/util/createList.js | 28 + src/util/createNav.js | 9 + src/util/easing.js | 24 + src/util/extend.js | 20 + src/util/getActiveSection.js | 29 + src/util/getOrSetID.js | 17 + src/util/getTargetYPosition.js | 26 + src/util/getYPosition.js | 15 + src/util/insertNav.js | 14 + src/util/insertVisualDebugger.js | 20 + src/util/nextUntil.js | 22 + src/util/populateSectionData.js | 35 + src/util/updateActiveNavItem.js | 25 + src/util/updatePositionData.js | 14 + test/.eslintrc.json | 5 + test/.jshintrc | 32 - test/coverage/clover.xml | 282 + test/coverage/coverage-final.json | 24 + test/coverage/lcov.info | 610 + test/fixtures/navMarkup.js | 38 + test/fixtures/noSectionsMarkup.js | 33 + test/fixtures/pennerEasing.js | 58 + test/fixtures/sectionData.js | 50 + test/fixtures/sectionMarkup.js | 37 + test/scrollNav.html | 36 - test/scrollNav_test.js | 329 - test/tests/scrollNav.test.js | 378 + test/tests/scrollTo.test.js | 32 + test/tests/setupClickHandlers.test.js | 67 + test/tests/setupResizeHandler.test.js | 42 + test/tests/setupScrollHander.test.js | 55 + test/tests/teardownClickHandlers.test.js | 35 + test/tests/teardownResizeHandler.test.js | 44 + test/tests/teardownScrollHander.test.js | 49 + .../util/calculateScrollDuration.test.js | 24 + test/tests/util/createList.test.js | 84 + test/tests/util/createNav.test.js | 23 + test/tests/util/easing.test.js | 114 + test/tests/util/extend.test.js | 32 + test/tests/util/getActiveSection.test.js | 31 + test/tests/util/getOrSetID.test.js | 51 + test/tests/util/getTargetYPosition.test.js | 35 + test/tests/util/getYPosition.test.js | 75 + test/tests/util/insertNav.test.js | 65 + test/tests/util/insertVisualDebugger.test.js | 15 + test/tests/util/nextUntil.test.js | 20 + test/tests/util/populateSectionData.test.js | 55 + test/tests/util/updateActiveNavItem.test.js | 66 + test/tests/util/updatePositionData.test.js | 57 + test/util/simulateEvent.js | 14 + 91 files changed, 16245 insertions(+), 15523 deletions(-) create mode 100644 .eslintignore create mode 100644 .eslintrc.json create mode 100644 .jestrc.json delete mode 100644 .jshintrc create mode 100644 .prettierrc.json delete mode 100644 Gruntfile.js delete mode 100644 dist/jquery.scrollNav.js delete mode 100644 dist/jquery.scrollNav.min.js create mode 100644 dist/scrollNav.min.js create mode 100644 dist/scrollNav.min.js.map create mode 100644 dist/scrollNav.min.mjs create mode 100644 dist/scrollNav.min.mjs.map create mode 100644 dist/scrollNav.min.umd.js create mode 100644 dist/scrollNav.min.umd.js.map create mode 100644 jest.setup.js create mode 100644 jest.transform.js delete mode 100644 libs/jquery-loader.js delete mode 100644 libs/jquery/jquery.js delete mode 100644 libs/qunit/qunit.css delete mode 100644 libs/qunit/qunit.js delete mode 100644 scrollNav.jquery.json delete mode 100644 src/.jshintrc create mode 100644 src/scrollNav.v2-7-3.js create mode 100644 src/scrollTo.js create mode 100644 src/setupClickHandlers.js create mode 100644 src/setupResizeHandler.js create mode 100644 src/setupScrollHandler.js create mode 100644 src/teardownClickHandlers.js create mode 100644 src/teardownResizeHandler.js create mode 100644 src/teardownScrollHandler.js create mode 100644 src/util/calculateScrollDuration.js create mode 100644 src/util/createList.js create mode 100644 src/util/createNav.js create mode 100644 src/util/easing.js create mode 100644 src/util/extend.js create mode 100644 src/util/getActiveSection.js create mode 100644 src/util/getOrSetID.js create mode 100644 src/util/getTargetYPosition.js create mode 100644 src/util/getYPosition.js create mode 100644 src/util/insertNav.js create mode 100644 src/util/insertVisualDebugger.js create mode 100644 src/util/nextUntil.js create mode 100644 src/util/populateSectionData.js create mode 100644 src/util/updateActiveNavItem.js create mode 100644 src/util/updatePositionData.js create mode 100644 test/.eslintrc.json delete mode 100644 test/.jshintrc create mode 100644 test/coverage/clover.xml create mode 100644 test/coverage/coverage-final.json create mode 100644 test/coverage/lcov.info create mode 100644 test/fixtures/navMarkup.js create mode 100644 test/fixtures/noSectionsMarkup.js create mode 100644 test/fixtures/pennerEasing.js create mode 100644 test/fixtures/sectionData.js create mode 100644 test/fixtures/sectionMarkup.js delete mode 100644 test/scrollNav.html delete mode 100644 test/scrollNav_test.js create mode 100644 test/tests/scrollNav.test.js create mode 100644 test/tests/scrollTo.test.js create mode 100644 test/tests/setupClickHandlers.test.js create mode 100644 test/tests/setupResizeHandler.test.js create mode 100644 test/tests/setupScrollHander.test.js create mode 100644 test/tests/teardownClickHandlers.test.js create mode 100644 test/tests/teardownResizeHandler.test.js create mode 100644 test/tests/teardownScrollHander.test.js create mode 100644 test/tests/util/calculateScrollDuration.test.js create mode 100644 test/tests/util/createList.test.js create mode 100644 test/tests/util/createNav.test.js create mode 100644 test/tests/util/easing.test.js create mode 100644 test/tests/util/extend.test.js create mode 100644 test/tests/util/getActiveSection.test.js create mode 100644 test/tests/util/getOrSetID.test.js create mode 100644 test/tests/util/getTargetYPosition.test.js create mode 100644 test/tests/util/getYPosition.test.js create mode 100644 test/tests/util/insertNav.test.js create mode 100644 test/tests/util/insertVisualDebugger.test.js create mode 100644 test/tests/util/nextUntil.test.js create mode 100644 test/tests/util/populateSectionData.test.js create mode 100644 test/tests/util/updateActiveNavItem.test.js create mode 100644 test/tests/util/updatePositionData.test.js create mode 100644 test/util/simulateEvent.js diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..cc34c5c --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +test/coverage diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..d60b4c1 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,21 @@ +{ + "env": { + "browser": true, + "es6": true + }, + "plugins": ["prettier"], + "extends": ["eslint:recommended", "prettier"], + "parserOptions": { + "sourceType": "module", + "ecmaVersion": 2017 + }, + "globals": { + "module": false + }, + "rules": { + "prettier/prettier": "error", + "linebreak-style": ["error", "unix"], + "quotes": ["error", "single"], + "semi": ["error", "always"] + } +} diff --git a/.gitignore b/.gitignore index fdc5c82..a74394d 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,6 @@ /node_modules/ npm-debug.log bower_components + +## Test Coverage Files +test/coverage/ diff --git a/.jestrc.json b/.jestrc.json new file mode 100644 index 0000000..e4e5ca6 --- /dev/null +++ b/.jestrc.json @@ -0,0 +1,10 @@ +{ + "collectCoverage": true, + "coverageDirectory": "test/coverage", + "collectCoverageFrom": ["src/**/*.js"], + "coveragePathIgnorePatterns": ["/node_modules", "/src/scrollNav.v2-7-3.js"], + "transform": { + "^.+\\.js$": "/jest.transform.js" + }, + "setupFiles": ["/jest.setup.js"] +} diff --git a/.jshintrc b/.jshintrc deleted file mode 100644 index 8c86fc7..0000000 --- a/.jshintrc +++ /dev/null @@ -1,14 +0,0 @@ -{ - "curly": true, - "eqeqeq": true, - "immed": true, - "latedef": true, - "newcap": true, - "noarg": true, - "sub": true, - "undef": true, - "unused": true, - "boss": true, - "eqnull": true, - "node": true -} diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..544138b --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,3 @@ +{ + "singleQuote": true +} diff --git a/.travis.yml b/.travis.yml index 1cb90c2..d015fc4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,8 @@ language: node_js node_js: - - 0.10 -before_script: - - npm install -g grunt-cli - - npm install semver - - npm install util \ No newline at end of file + - "8" + - "10" +install: + - npm install + - npm install codecov + - codecov diff --git a/CHANGELOG.md b/CHANGELOG.md index ae90217..689fba6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,16 @@ And constructed with these guidelines: For more information on semantic versioning, please visit http://semver.org/. +## v3.0.0 - December 22, 2018 + +Version 3 is a complete re-write of scrollnav to move the project away from +jQuery, update to the latest es6 features, and remove all production +dependencies. This update also removes a number of user options to simplify +the API and reduces the amount of DOM manipulation to reduce likelihood of +browser bugs. Includes a full set of test suites for all modules (unless +noted). Please read through the [readme](https://github.com/jimmynotjim/scrollNav/blob/master/README.md) for further +details. + ## v2.7.3 - March 19, 2018 * Added BEM-style active classes @@ -50,13 +60,13 @@ For more information on semantic versioning, please visit http://semver.org/. ## v2.3.0 - October 9, 2014 -* Updated min Node to 0.10.* +* Updated min Node to 0.10.\* * Updated all Node plugins to latest ## v2.2.0 - March 14, 2014 * Added option to change the classname used throughout the plugin. -* Updated jQuery dep to 1.9.* +* Updated jQuery dep to 1.9.\* ## v2.1.1 - December 13, 2013 @@ -67,7 +77,7 @@ Added `scrollNav` namespace to event listeners to avoid crashing in to user defi v2.1 adds support for public methods, a new destroy method, custom callbacks for init, render and destroy, and small bugfixes. * Reorganized core to allow for new public methods -* Added destroy method to core to allow for breaking down the plugin and it's dom * changes +* Added destroy method to core to allow for breaking down the plugin and it's dom \* changes * Added the option to add callback functions to init, render and destroy * Squashed a bug when wrapping sub-sections in their div * Updated core init in test for easier reuse @@ -83,7 +93,7 @@ Double releasing to include changelog and readme updates in Bower. One day I'll Bugfixes for the following: * package.json now includes semver: Ooops, sorry -* Moved jQuery dependency from package.json to bower.json and updated jQuery dep to v1.8.* +* Moved jQuery dependency from package.json to bower.json and updated jQuery dep to v1.8.\* * Removed unneeded build dirs from bower install * Updated gitignore to ignore bower_components @@ -100,7 +110,7 @@ v2 is a complete re-write of scrollNav and includes better code organization, ne * Added option to change insertion target. * Added Bower support for easy project dependency management. * Updated the class names of scrollNav elements to follow BEM conventions. -* Updated existing settings option naming for the following (*this may break your current setups*): +* Updated existing settings option naming for the following (_this may break your current setups_): * `titleText` -> `headlineText` * `location` -> `insertLocation` diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e0ad853..bfed2e9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,31 +1,104 @@ -# Contributing +# Contributing Guideline -## Important notes -Please don't edit files in the `dist` subdirectory as they are generated via Grunt. You'll find source code in the `src` subdirectory! +Thanks for contributing to scrollNav. Without you and the Open Source community +this project wouldn't be possible. Before you get started, please familiarize +yourself with the project and its standards. + +## Issue Reports + +If you're looking for a way to contribute to this project, your best bet is +to [start with the current issues][1]. Whether it's a new feature you'd like +added, a bug you've found, or a question about using the plugin, there's always +a chance you're not alone. Take a look through both the open and closed issues +before creating a new one yourself. + +### Improvements/features + +Before working on a new feature please submit an issue suggesting the feature +and ensure that it is greenlighted. I'd hate for you to spend your time +building a new feature that doesn't fit the project's scope or intentions. + +### Bugs + +Before submitting a bug report, please create a reproducable test, either as a +failing unit test on your own fork, or by forking the starter demo from Codepen +and adjusting as necessary. It's a whole lot easier to address issues if I can +understand the situation. If it's not obvious what's broken in your demo, +include step-by-step instructions on how to reproduce the problem within the +issue description. + +## Pull Requests + +You've found a bug or had a feature greenlighted and you're ready to dig in and +get to work. Congrats! This project was built and continues to improve from +direct contributions from folks like you. Before you get too far, please be +sure to read through and understand the steps below. + +### Important notes + +Please don't edit files in the `dist` subdirectory as they are generated via +NPM script. You'll find source code in the `src` subdirectory. ### Code style -Regarding code style like indentation and whitespace, **follow the conventions you see used in the source already.** -### PhantomJS -While Grunt can run the included unit tests via [PhantomJS](http://phantomjs.org/), this shouldn't be considered a substitute for the real thing. Please be sure to test the `test/*.html` unit test file(s) in _actual_ browsers. +This project utilizes [Prettier][11] to ensure a consistent code style. Write +your changes however you prefer but be sure to run `npm run format` prior to +submitting a Pull Request. Don't worry about making a lot of small commits, +your changes will be squashed within Github when the Pull Request is merged. + +### Testing + +This project uses [Jest][12] for its unit tests. Prior to submitting a +Pull Request, please ensure new functionality is tested and adjustments to +previous functionality continue to pass. A failing test is better than no +test at all and gives me a place to start reviewing. -## Modifying the code -First, ensure that you have the latest [Node.js](http://nodejs.org/) and [npm](http://npmjs.org/) installed. +Additionally, it's a good idea to ensure your changes work in actual browsers. +Including a demo on [Codepen][13] is a great way to ensure your changes are +reviewed and merged in a timely manner. I've [created a base Pen][2] for you +to fork and edit. -Test that Grunt's CLI is installed by running `grunt --version`. If the command isn't found, run `npm install -g grunt-cli`. For more information about installing Grunt, see the [getting started guide](http://gruntjs.com/getting-started). +### Modifying the code + +First, ensure that you are working with [Node.js][14] version 8 or later and +[npm][15] version 5 or later. Older versions of Node are supported but it's +best to work with the Long Term Support (LTS), currently version 8. 1. Fork and clone the repo. -1. Run `npm install` to install all dependencies (including Grunt). -1. Run `grunt` to grunt this project. +1. Run `npm install` to install the development dependencies. +1. Create a new branch that's appropriately named. Please don't work directly + in your `master` branch, it makes testing locally difficult. +1. Add failing tests for the change you want to make in the `test/tests` + directory. Run `npm test` to see the tests fail. +1. Edit the source files in the `src` directory. +1. Run `npm test` to see if the tests pass. Repeat steps 2-4 until done. +1. Run `npm run build` to generate the transpiled files in the `dist` + directory. +1. Update the documentation to reflect any changes in functionality. +1. Commit and push your the branch to Github. +1. Navigate to your branch on Github and then to the + `dist/scrollNav.min.js` file. +1. Select the "Raw" button and copy the file URL. +1. Fork the starter demo in Codepen and then click settings. +1. Under "Add External Scripts/Pens" replace the existing + `dist/scrollNav.min.js` file URL with your raw file URL. +1. Test the interactions and ensure your intended changes work as expected. +1. Submit a Pull Request making sure to write a descriptive comment and + include your forked Codepen URL. + +**Note: If none of this makes sense, it's ok. Any contribution is a useful one, +even if it's not accepted. Please feel free to reach out to me to ask for help +or clarification, I'm [@jimmynotim on Twitter][21].** + +To view all available build tasks run `npm run` without any arguments. -Assuming that you don't see any red, you're ready to go. Just be sure to run `grunt` after making any changes, to ensure that nothing is broken. +[1]: https://github.com/jimmynotjim/scrollNav/issues +[2]: https://codepen.io/jimmynotjim/pen/OZKeyd -## Submitting pull requests +[11]: https://prettier.io/ +[12]: https://facebook.github.io/jest/ +[13]: https://codepen.io/ +[14]: http://nodejs.org/ +[15]: http://npmjs.org/ -1. Create a new branch, please don't work in your `master` branch directly. -1. Add failing tests for the change you want to make. Run `grunt` to see the tests fail. -1. Fix stuff. -1. Run `grunt` to see if the tests pass. Repeat steps 2-4 until done. -1. Open `test/*.html` unit test file(s) in actual browser to ensure tests pass everywhere. -1. Update the documentation to reflect any changes. -1. Push to your fork and submit a pull request. +[21]: https://twitter.com/jimmynotjim diff --git a/Gruntfile.js b/Gruntfile.js deleted file mode 100644 index df026b7..0000000 --- a/Gruntfile.js +++ /dev/null @@ -1,210 +0,0 @@ -var f = require('util').format; -var semver = require('semver'); -module.exports = function(grunt) { - 'use strict'; - - // Load Grunt tasks declared in the package.json file - require('load-grunt-tasks')(grunt); - - // Project configuration. - grunt.initConfig({ - - // Metadata. - pkg: grunt.file.readJSON('package.json'), - banner: '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - ' + - '<%= grunt.template.today("yyyy-mm-dd") %>\n' + - '<%= pkg.homepage ? "* " + pkg.homepage + "\\n" : "" %>' + - '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' + - ' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */\n', - - // Constants - version: '<%= pkg.version %>', - name: '<%= pkg.name %>', - buildDir: 'dist', - sourceDir: 'src', - testDir: 'test', - - // Task configuration. - clean: { - files: ['<%= buildDir %>'] - }, - concat: { - options: { - banner: '<%= banner %>', - stripBanners: true - }, - dist: { - src: ['<%= sourceDir %>/<%= name %>.js'], - dest: '<%= buildDir %>/jquery.<%= name %>.js' - } - }, - uglify: { - options: { - banner: '<%= banner %>' - }, - dist: { - src: '<%= concat.dist.dest %>', - dest: '<%= buildDir %>/jquery.<%= name %>.min.js' - } - }, - qunit: { - files: ['<%= testDir %>/**/*.html'] - }, - sed: { - version: { - pattern: '%VERSION%', - replacement: '<%= version %>', - path: ['<%= uglify.dist.dest %>', '<%= concat.dist.dest %>'] - } - }, - jshint: { - gruntfile: { - options: { - jshintrc: '.jshintrc', - reporterOutput: '' - }, - src: 'Gruntfile.js' - }, - src: { - options: { - jshintrc: '<%= sourceDir %>/.jshintrc', - reporterOutput: '' - }, - src: ['<%= sourceDir %>/**/*.js'] - }, - test: { - options: { - jshintrc: 'test/.jshintrc', - reporterOutput: '' - }, - src: ['<%= testDir %>/**/*.js'] - } - }, - watch: { - gruntfile: { - files: '<%= jshint.gruntfile.src %>', - tasks: ['jshint:gruntfile'] - }, - src: { - files: '<%= jshint.src.src %>', - tasks: ['jshint:src', 'qunit'] - }, - test: { - files: '<%= jshint.test.src %>', - tasks: ['jshint:test', 'qunit'] - } - }, - exec: { - open_qunit_browser: { - cmd: 'open <%= testDir %>/scrollNav.html' - }, - git_is_clean: { - cmd: 'test -z "$(git status --porcelain)"' - }, - git_on_master: { - cmd: 'test $(git symbolic-ref --short -q HEAD) = master' - }, - git_add: { - cmd: 'git add .' - }, - git_commit: { - cmd: function(m) { return f('git commit -m "%s"', m); } - }, - git_tag: { - cmd: function(v) { return f('git tag v%s -am "%s"', v, v); } - }, - git_push: { - cmd: 'git push && git push --tags' - }, - readme: { - cmd: 'sed -E -i "" \'s/v[0-9]+\\.[0-9]+\\.[0-9]+/v<%= version %>/\' README.md', - }, - publish_assets: { - cmd: [ - 'cp -r <%= buildDir %> <%= name %>.js', - 'zip -r <%= name %>.js/<%= name %>.js.zip <%= name %>.js', - 'git checkout gh-pages', - 'rm -rf releases/latest', - 'cp -r <%= name %>.js releases/<%= version %>', - 'cp -r <%= name %>.js releases/latest', - 'git add releases/<%= version %> releases/latest', - 'sed -E -i "" \'s/v[0-9]+\\.[0-9]+\\.[0-9]+/v<%= version %>/\' index.html', - 'git add index.html', - 'git commit -m "Add assets for <%= version %>."', - 'git push', - 'git checkout -', - 'rm -rf <%= name %>.js' - ].join(' && ') - } - } - }); - -grunt.registerTask('release', 'Ship it.', function(version) { - var curVersion = grunt.config.get('version'); - - version = semver.inc(curVersion, version) || version; - - if (!semver.valid(version) || semver.lte(version, curVersion)) { - grunt.fatal('invalid version dummy'); - } - - grunt.config.set('version', version); - - grunt.task.run([ - 'exec:git_on_master', - 'exec:git_is_clean', - 'lint', - 'test', - 'manifests:' + version, - 'exec:readme', - 'build', - 'exec:git_add', - 'exec:git_commit:' + version, - 'exec:git_tag:' + version, - 'exec:git_push', - 'exec:publish_assets' - ]); - }); - - grunt.registerTask('manifests', 'Update manifests.', function(version) { - var _ = grunt.util._; - var pkg = grunt.file.readJSON('package.json'); - var bower = grunt.file.readJSON('bower.json'); - var jqueryPlugin = grunt.file.readJSON('scrollNav.jquery.json'); - - bower = JSON.stringify(_.extend(bower, { - name: pkg.name, - version: version, - author: pkg.author, - keywords: pkg.keywords - }), null, 2); - - jqueryPlugin = JSON.stringify(_.extend(jqueryPlugin, { - name: pkg.name, - title: pkg.name, - version: version, - author: pkg.author, - description: pkg.description, - keywords: pkg.keywords, - homepage: pkg.homepage, - bugs: pkg.bugs, - maintainers: pkg.contributors - }), null, 2); - - pkg = JSON.stringify(_.extend(pkg, { - version: version - }), null, 2); - - grunt.file.write('package.json', pkg); - grunt.file.write('bower.json', bower); - grunt.file.write('scrollNav.jquery.json', jqueryPlugin); - }); - - // Load Tasks. - grunt.registerTask('default', 'build'); - grunt.registerTask('build', ['jshint', 'qunit', 'clean', 'concat', 'uglify']); - grunt.registerTask('lint', ['jshint']); - grunt.registerTask('test', ['qunit']); - grunt.registerTask('test:browser', ['exec:open_qunit_browser']); - -}; diff --git a/LICENSE-MIT b/LICENSE-MIT index 0ad46f8..d4be8a4 100644 --- a/LICENSE-MIT +++ b/LICENSE-MIT @@ -1,22 +1,19 @@ -Copyright (c) 2013 James Wilson +Copyright (c) 2018 James Wilson -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: +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 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. +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. diff --git a/README.md b/README.md index b0c7904..2633cc4 100644 --- a/README.md +++ b/README.md @@ -1,329 +1,340 @@ -[![build status](https://secure.travis-ci.org/jimmynotjim/scrollNav.png?branch=master)](http://travis-ci.org/jimmynotjim/scrollNav) +# [scrollnav.js][1] -# [jQuery scrollNav][1] +[![npm](https://img.shields.io/npm/v/scrollnav.svg)](https://www.npmjs.com/package/scrollnav) +[![Build Status](https://travis-ci.org/jimmynotjim/scrollnav.svg?branch=master)](https://travis-ci.org/jimmynotjim/scrollnav) +[![Codecov](https://img.shields.io/codecov/c/github/codecov/example-python.svg)](https://codecov.io/gh/jimmynotjim/scrollnav) +[![license](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/jimmynotjim/scrollnav/blob/master/LICENSE-MIT) -A jQuery plugin for building a scrolling side navigation menu +## Introduction -## Getting Started +scrollnav.js is a small (2.4kb gzipped), dependency free JavaScript plugin +for auto generating single page navigation with active highlighting. Useful +for creating a Table of Contents for a large document (think Wikis), +navigation for a single page website, or anything else you might think of. + +scrollnav works by scanning a block of content for section landmarks +(typically heading elements) and generating a list of links from those +landmarks. It then tracks the scroll location of the document and highlights +the appropriate link. While previous versions injected wrappers within the +content, the current version (ver 3) takes a much lighter approach, only +changing the DOM as necessary. Visit the live demo at [scrollnav.com][1] +to see for yourself. -Install with Bower `bower install scrollNav` +## Browser Compatibility -Or download the latest [zipped package][zip]. +scrollnav supports all browsers that are ES5-compliant (IE8 and below are +not supported). -[zip]: https://github.com/jimmynotjim/scrollNav/archive/master.zip +## Getting Started +The compiled, production ready plugin is available in the `dist` directory. +Please don't use the `src` directory unless you plan to build the entire +source. -## Examples +### Install -Check out [the homepage][1] to see it in action. +#### Download -## Features +[scrollnav@v3.0.0](https://unpkg.com/scrollnav@3.0.0/dist/scrollnav.min.umd.js) -* ### Simple to set up +```html + +``` - With a single file import and function in your footer, you're on your way. +#### CDN -* ### Fully customizable +```html + +``` - Very little styling is set for you, but the bit that is, is fully customizable. +#### Package manager -* ### Tiny Size +[Yarn][13]: `yarn add scrollnav` - At 1.5kb min'd and GZip'd, scrollNav is pretty unintrusive. If you use Ajax to import and initiate it, it's almost negligable. +It's the new hotness, it's also better at managing dependencies than all it's predecesors. -## Requirements -* For in-page usage [jQuery 1.8.0][16] or greater and [html5shiv][17]/[modernizr][18] for older browser support -* To build source [Node 0.10.0][19] or greater and [grunt 0.4.0][20] or greater +[NPM][12]: `npm install scrollnav` -## Usage +Good'ol NPM, it's always there, except when it isn't. Things have settled down a bit, but it was dicey there for a while. Even still, there's a reason even Yarn uses the NPM registry. -### Import +[Bower][11]: `bower install scrollnav --save` -Start by importing the script to your page, the best location is in the footer, but no matter what, make sure it follows your jQuery file. +The folks from Bower no longer recommend using Bower. Luckily they've provided a guide on [how to migrate to Yarn](https://bower.io/blog/2017/how-to-migrate-away-from-bower/). If you don't want to or can't migrate, scrollnav will continue to be available on Bower as long as it continues to run. -```html - -``` -### Build your page +### Usage -Include a class or id hook on the element you want to apply the plugin to and include an `

` for each section you want to inlcude in the navigation. +scrollnav works by scanning the given [HTML Node Element][25] for section +landmarks, by default `h2` elements, that it then uses to generate the nav. +If we were to look at a typical document, it might look like this: ```html -
-
-
-

This is the main heading for the article

-

This is a sub-heading for the article

-
-

Yada yada yada...

-

This is a section heading

-

More yada yada...

-

Another section heading

-

More more yada...

-
-
+
+

First section

+ ... +

Second section

+ ... +

Third section

+ ... +
``` -### Initialize +#### Initialize -Now initialize the plugin with your hook for the article +First, initialize scrollnav with the HTML Element. In this example we'll use +`.querySelector()` but you could also use `.getElementByID()` or +`.getElementByClassName()`. +```js +const content = document.querySelector('.main-content'); +scrollnav.init(content); ``` -$('.post__article').scrollNav(); -``` - -and the plugin scans the article, grabs all the `

`s, adds them to the navigation list and inserts the list before the article. It's that easy...well almost. - -### Styling -To keep the plugin simple there are no styles added to the navigation, that's all up to you. The nav structure looks like this and includes class names in the [BEM Methodology][3] style (for a good overview read [MindBEMding - getting your head 'round BEM syntax][4]): +scrollnav will then loop through the the `h2` elements, add an ID if they don't +already have one, build the nav, and then inject it just before the content +Node. The result for our example document would look like this: ```html +
+

First Heading

+ ... +
``` +#### Styles -### Reset Positions on DOM Change - -There are a couple of ways you can reset scrollNav's positions when the DOM changes: - -#### Manually - -Simply call the `resetPos` method on your own: - -``` -$.fn.scrollNav('resetPos'); -``` +To keep the plugin simple there are no styles added to the navigation, that's +all up to you ([view the demo site][1] for exmaples of the most common use +cases). The nav structure provides [BEM Methodology][23] class names for each +of the elements to provide consistent styling hooks (for a good overview read +[MindBEMding - getting your head 'round BEM syntax][24]). As the user scrolls +the document, scrollnav adds a `scroll-nav__item--active` modifier for the +item's relative section that currently intersects with the activation +threshold ([enable `debug` mode](#additional-options) to highlight the +threshold). -#### Automatically +### Settings and options -Utilize [mutation observers][21] to call the `resetPos` method automatically: +scrollnav includes some default settings that work for most situations, but if +your project requires a bit more customization, scrollnav can most likely meet +those. To modify either, pass in a single object (include settings and options +as one object) as the second argument like this: -``` -var $; -var observer_target = document.querySelector('.post__article'); -var observer = new MutationObserver(function(mutations) { - mutations.forEach(function() { - $.fn.scrollNav('resetPos'); +```js + scrollnav.init(content, { + key: value }); -}); -var observer_config = { - attributes: true, - childList: true, - characterData: true, - subtree: true -}; -observer.observe(observer_target, observer_config); ``` -## Default `options` - -There are a few customizable options in scrollNav using key : value pairs. These are the defaults. - +#### Default settings + +The following settings are editable to overwrite the default. + +```js +{ + sections: 'selector', + // string + // + // Sets the querySelector for the content's section landmarks, by default + // it's 'h2'. + + insertTarget: targetNode, + // HTML Node + // + // Sets the target Node for injecting the navigation, by default it's the + // content Node passed to scrollnav. + + insertLocation: 'relativeLocation' + // string + // + // Sets the injection location relative to the insertTarget, by default it's + // 'before'. + // + // available options are 'append', 'prepend', 'after', or 'before' + + easingStyle: 'easingName', + // string + // + // Sets the easing type for the scroll animation that is triggered by the + // click event on a nav item, by default it's 'easeOutQuad'. + // + // available options are 'linear' 'easeInQuad', 'easeOutQuad', + // 'easeInOutQuad', 'easeInCubic', 'easeOutCubic', 'easeInOutCubic', + // 'easeInQuart', 'easeOutQuart', 'easeInOutQuart', 'easeInQuint', + // 'easeOutQuint', easeInOutQuint + + updateHistory: true + // boolean + // + // Sets the history behavior when a nav item is clicked, by default it's true +} ``` -$('.post-article').scrollNav({ - sections: 'h2', - subSections: false, - sectionElem: 'section', - className: 'scroll-nav', - showHeadline: true, - headlineText: 'Scroll To', - showTopLink: true, - topLinkText: 'Top', - fixedMargin: 40, - scrollOffset: 40, - animated: true, - speed: 500, - insertTarget: this.selector, - insertLocation: 'insertBefore', - activeClass: 'active', - arrowKeys: false, - scrollToHash: true, - onInit: null, - onRender: null, - onDestroy: null -}); -``` - -### Sections - -As mentioned, the script automatically searches for `

`s within the target article. If your page structure differs, feel free to target another selector, like an `

` or `

` or even a class, like `.scroll-headline`. - -### Sub-Sections - -Set to `false` by default, the plugin supports nesting sub-sections within each section in the final nav. Available selectors are the same as Sections. - -### Section Wrapper Element - -If your article already contains `section` tags, you'll want to change this to `'div'`. Sub-sections aren't affected by this option. - -### Class Name - -If you want to change the default `scroll-nav` class naming used throughout (including in the BEM syntax for the child elems), you can do so by changing this value to your own. -### Show Headline - -Set this to `false` to remove the Headline Text entirely. - -### Headline Text - -scrollNav's default title text is 'Scroll To', but feel free to modify it to whatever works for you, like 'Article Sections' or 'Page Navigation'. - -### Show Top Link - -Set this to `false` to remove the Top Link nav item entirely. - -### Top Link Text - -scrollNav's default return to the top link text is 'Top', but feel free to modify it to whatever works for you. - -### Fixed Margin - -This is the `top` dimension you set for the `.scroll-nav.fixed` class, which is applied as the user scrolls down the page and is removed as they scroll above the article. You definitely want to set this if you don't use the default 40px, otherwise the nav will jump around as the user scrolls past the top of the article. - -### Scroll Offset - -This option affects two things. First is the "active state" boundries within the viewport. The bounderies are within a distance from the top and bottom of the viewport equal to this amount. Second is the destination when animating the page scroll. This will place the heading of the section right at the top of the "active state" boundry. - -### Animated Scrolling - -The plugin animates the page scroll when clicking on a nav link by default. Set this to `false` if you do not wish to animate the scroll. - -### Scrolling Speed - -Change this to either increase or decrease the animated page scroll speed. - -### Insertion Target - -If you need to insert the nav relative to an element other than the one scrollNav is initialized on, you can change it here. - -### Insertion Location - -You can pass any of the following jQuery insertion methods to change where scrollNav is inserted in relation to the targeted container. `insertBefore`, `prependTo`, `appendTo`, or `insertAfter` - -### Arrow Key Navigation +#### Additional options + +These additional options are editable but are not set by default. + +```js +{ + subSections: '...', + // string + // + // Sets the querySelector for the content's sub-section landmarks. + + onScroll: function() {...}, + // function + // + // Sets the callback to be triggered after the window scrolls when triggered + // by the click event on a nav item. + + onInit: function() {...}, + // function + // + // Sets the callback to be triggered after the .init() method has completed. + + onUpdatePositions: function() {...}, + // function + // + // Sets the callback to be triggered after the .updatePositions() method + // has completed. + + onDestroy: function() {...}, + // function + // + // Sets the callback to be triggered after the .destroy() method has + // completed. + + debug: false + // boolean + // + // Enables scrollnav's built in debug mode to log errors to the console and + // display the active area threshold on screen, helpful for when you've hit a + // snag you can't easily identify. +} +``` -Set this to `true` to allow up/down arrow keys to jump through each section. +#### Available methods -### Active Class +In addition to the `.init()` method scrollnav provides two additional public +methods. -By default, scrollNav will use the class `".active"` to indicate which nav item is currently in view. If you need a different class name, add it here. +#### destroy() -### Scroll to hash +To remove the current instance of scrollnav call the destroy method. If you +need to trigger a callback after scrollnav has been removed, use the +`onDestroy` option described above (passed either in the original init or with +the destroy method). -Set this to false if you use hashed (http://example.com/#home) values for routing. +```js +scrollnav.destroy(); +``` -### Callback functions +#### updatePositions() -There are three new callback functions that you can utilize to accommodate anything you need to run after specific scrollNav events. They are `onInit`, `onRender`, and `onDestroy`. Add them to your options just like any other and they should look like this: +scrollnav doesn't track outside DOM changes. If your page's content is dynamic +and updates after scrollnav is initialized you'll need to recalcuate the +position data with the updatePositions method. If you need to trigger a +callback after the position data has been recalculated, use the +`onUpdatePositions` option described above (passed either in the original init +or with the updatePositions method). +```js +scrollnav.updatePositions(); ``` -$('.post__article').scrollNav({ - onInit: function() { - callback actions in here - } -}); -``` - -## Errors - -The plugin will refuse to build and log an error message if it doesn't find your desired container, the insertion target or any of the headlines specified within the container. If the nav doesn't show up on load, check your browser's console. ## Issues -There are a few known issues, including poor location updating when scrolling on touch devices. If you find any others please submit them to [the issue tracker][5]. +Please read and understand the [Contributing Guidelines][4] prior to [opening +an issue][2]. Ensuring your issue conforms to the guidelines gives it a better +chance I'll be able to help address it. + +## Questions +For questions about using scrollnav in your own project, your best bet is to +post it to [Stack Overflow][21]. The community there is great at lending a hand +and can often respond faster than I can, plus it becomes searchable for future +developers who may run into the same question. If you're still stuck, please +feel free to reach out to me to ask for help or clarification, I'm [@jimmynotim +on Twitter][22]. + +## Changelog + +v3.0.0 is the current stable release. For detailed changes in each release +please refer to the [release notes][5]. Please be sure you understand the +changes before updating, v3 is a complete re-write of the plugin (as is v2 +compared to v1 before it). + +## Contributions + +scrollnav is built and maintained by [James Wilson (@jimmynotjim)][31]. +I wouldn't be able to continue this project without a lot of help from the +Open Source community. I welcome feedback and enhancements, but first, please +make sure to read the [Contributing Guide][4]. + +Thank you to everyone who has already contributed to scrollnav! + +* [Chris Garcia (@pixelbandito)][43] +* [Eric Clemmons (@ericclemmons)][32] +* [Felix Borzik (@Borzik)][39] +* [Jeff Byrnes (@jeffbyrnes)][33] +* [Jeff Coburn (@coburnicus)][34] +* [Jen Germann (@germanny)][35] +* [Jim Schmid (@sheeep)][44] +* [Marc Amos (@marcamos)][38] +* [Masud Rahman (@frutiger)][40] +* [Meghdad Hadidi (@MeghdadHadidi)][37] +* [Michael Benin (@michael-benin-CN)][45] +* [Rob Loach (@RobLoach)][41] +* [Thomas Guillary @thomasguillory][46] +* [Will Moore (@willthemoor)][42] +* [Wizcover (@wizcover)][36] ## License -scrollNav is Copyright © 2012-2018 James Wilson, released under the [MIT license][6]. This means you can re-create, edit or share the plugin as long as you maintain the same open licensing. - -## Version - -Latest stable version is v2.7.3. Make sure to view [the changelog][15] before updating, v2 is a complete re-write of the plugin. - -## Testing - -Tests are written using QUnit. To run the test suite with PhantomJS, run `$ grunt test` or `$ grunt watch`. To run the test in your default browser run `$ grunt test:browser`. +scrollnav is Copyright © 2012-2018 James Wilson, released under the +[MIT license][3]. This means you can re-create, edit or share the plugin as +long as you maintain the same open licensing. -## Developers - -Please read the [contributing guidelines][14] and [issue tracker][5] before starting on code. - -In order to build and test scrollNav.js, you'll need to install its dev dependencies `$ npm install` and have grunt-cli globally installed `$ npm install -g grunt-cli`. - -Available Grunt tasks that will be useful in development. - -* grunt lint – Runs source and test files through JSHint. -* grunt test – Runs the test suite with PhantomJS. -* grunt concat - Builds the source to /dist. -* grunt uglify - Minifies the source to /dist. -* grunt build - Runs all of the above and rebuilds from source . -* grunt watch – Runs all of the above whenever a file is modified. - -## Author - -[James Wilson (@jimmynotjim)][7] - -## With Help From - -* [Eric Clemmons (@ericclemmons)][8] -* [Jeff Byrnes (@jeffbyrnes)][9] -* [Jeff Coburn (@coburnicus)][10] -* [Jen Germann (@germanny)][11] -* [Wizcover (@wizcover)][12] -* [MeghdadHadidi (@MeghdadHadidi)][13] -* [Marc Amos (@marcamos)][23] -* [Felix Borzik (@Borzik)][24] -* [Masud Rahman (@frutiger)][25] -* [Rob Loach (@RobLoach)][26] -* [Will Moore (@willthemoor)][27] -* [Chris Garcia (@pixelbandito)][28] -* [Jim Schmid (@sheeep)][29] [1]: http://scrollnav.com -[2]: # -[3]: http://bem.info/method/ -[4]: http://csswizardry.com/2013/01/mindbemding-getting-your-head-round-bem-syntax/ -[5]: https://github.com/jimmynotjim/scrollNav/issues -[6]: https://github.com/jimmynotjim/scrollNav/blob/master/LICENSE-MIT -[7]: http://github.com/jimmynotjim -[8]: https://github.com/ericclemmons -[9]: https://github.com/jeffbyrnes -[10]: https://github.com/coburnicus -[11]: https://github.com/germanny -[12]: https://github.com/wizcover -[13]: https://github.com/MeghdadHadidi -[14]: https://github.com/jimmynotjim/scrollNav/blob/master/CONTRIBUTING.md -[15]: https://github.com/jimmynotjim/scrollNav/blob/master/CHANGELOG.md -[16]: http://jquery.com/ -[17]: https://github.com/aFarkas/html5shiv -[18]: http://modernizr.com/ -[19]: http://nodejs.org/ -[20]: http://gruntjs.com/ -[21]: https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver -[22]: http://caniuse.com/#search=mutation%20observer -[23]: http://github.com/marcamos -[24]: http://github.com/borzik -[25]: http://github.com/frutiger -[26]: http://github.com/RobLoach -[27]: http://github.com/willthemoor -[28]: http://github.com/pixelbandito -[29]: http://github.com/sheeep +[2]: https://github.com/jimmynotjim/scrollnav/issues +[3]: https://github.com/jimmynotjim/scrollnav/blob/master/LICENSE-MIT +[4]: https://github.com/jimmynotjim/scrollnav/blob/master/CONTRIBUTING.md +[5]: https://github.com/jimmynotjim/scrollnav/blob/master/CHANGELOG.md + +[11]: https://bower.io/ +[12]: https://www.npmjs.com/package/scrollnav +[13]: https://yarnpkg.com/en/package/scrollnav + +[21]: https://stackoverflow.com/questions +[22]: https://twitter.com/jimmynotjim +[23]: http://bem.info/method/ +[24]: http://csswizardry.com/2013/01/mindbemding-getting-your-head-round-bem-syntax/ +[25]: https://developer.mozilla.org/en-US/docs/Web/API/Element + +[31]: http://github.com/jimmynotjim +[32]: https://github.com/ericclemmons +[33]: https://github.com/jeffbyrnes +[34]: https://github.com/coburnicus +[35]: https://github.com/germanny +[36]: https://github.com/wizcover +[37]: https://github.com/MeghdadHadidi +[38]: http://github.com/marcamos +[39]: http://github.com/borzik +[40]: http://github.com/frutiger +[41]: http://github.com/RobLoach +[42]: http://github.com/willthemoor +[43]: http://github.com/pixelbandito +[44]: http://github.com/sheeep +[45]: http://github.com/michael-benin-CN +[46]: http://github.com/thomasguillory + diff --git a/bower.json b/bower.json index c47ab96..eb2256b 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "scrollNav", - "version": "2.7.3", + "version": "3.0.0", "author": { "name": "James Wilson", "email": "jimmynotjim@me.com", @@ -10,12 +10,8 @@ "type": "git", "url": "https://github.com/jimmynotjim/scrollNav.git" }, - "main": [ - "./dist/jquery.scrollNav.min.js" - ], - "dependencies": { - "jquery": "~1.9.*" - }, + "main": ["./dist/scrollNav.min.umd.js"], + "dependencies": {}, "ignore": [ "node_modules", "libs", @@ -24,11 +20,12 @@ ".*", "*.json", "CONTRIBUTING.md", - "*.txt", - "Gruntfile.js" + "*.txt" ], "keywords": [ "scrollnav", + "javascript", + "es6", "jquery", "navigation", "scrolling", diff --git a/dist/jquery.scrollNav.js b/dist/jquery.scrollNav.js deleted file mode 100644 index 014c48a..0000000 --- a/dist/jquery.scrollNav.js +++ /dev/null @@ -1,452 +0,0 @@ -/*! scrollNav - v2.7.3 - 2018-03-19 -* http://scrollnav.com -* Copyright (c) 2018 James Wilson; Licensed MIT */ -(function($) { - - // Animate scrolling to section location - var scroll_to = function(value, speed, offset, animated) { - if ( $(value).length > 0 ) { - var destination = $(value).offset().top; - speed = animated ? speed : 0; - - // Add a class to the scrolled-to section - $('.' + S.settings.className + '__focused-section').removeClass(S.settings.className + '__focused-section'); - $(value).addClass(S.settings.className + '__focused-section'); - - $('html:not(:animated),body:not(:animated)') - .animate({scrollTop: destination - offset }, speed ); - } - }; - - // Get url hash if one exists - var get_hash = function() { - return window.location.hash; - }; - - var S = { - classes: { - loading: 'sn-loading', - failed: 'sn-failed', - success: 'sn-active' - }, - defaults: { - sections: 'h2', - subSections: false, - sectionElem: 'section', - className: 'scroll-nav', - showHeadline: true, - headlineText: 'Scroll To', - showTopLink: true, - topLinkText: 'Top', - fixedMargin: 40, - scrollOffset: 40, - animated: true, - speed: 500, - insertLocation: 'insertBefore', - arrowKeys: false, - scrollToHash: true, - onInit: null, - onRender: null, - onDestroy: null, - onResetPos: null - }, - _set_body_class: function(state) { - // Set and swap our loading hooks to the body - - var $body = $('body'); - - if (state === 'loading') { - $body.addClass(S.classes.loading); - } else if (state === 'success') { - $body.removeClass(S.classes.loading).addClass(S.classes.success); - } else { - $body.removeClass(S.classes.loading).addClass(S.classes.failed); - } - }, - _find_sections: function($el) { - // Find the html for each section - - var target_elems = S.settings.sections; - var raw_html = []; - - if (S.settings.showTopLink) { - var $firstElem = $el.children().first(); - - if ( !$firstElem.is(target_elems) ) { - raw_html.push( $firstElem.nextUntil(target_elems).addBack() ); - } - } - - $el.find(target_elems).each(function() { - raw_html.push( $(this).nextUntil(target_elems).addBack() ); - }); - - S.sections = { - raw: raw_html - }; - }, - _setup_sections: function(sections) { - // Wrap each section and add it's details to the section array - - var section_data = []; - - $(sections).each(function(i) { - var sub_data = []; - var $this_section = $(this); - var section_id = 'scrollNav-' + (i + 1); - var isFirst = function() { return i === 0; }; - var hasHeading = function() { return !$this_section.eq(0).is(S.settings.sections); }; - var text = ( S.settings.showTopLink && isFirst() && hasHeading() ) ? S.settings.topLinkText : $this_section.filter(S.settings.sections).text(); - - $this_section.wrapAll('<' + S.settings.sectionElem + ' id="' + section_id + '" class="' + S.settings.className + '__section" />'); - - if (S.settings.subSections) { - var $sub_sections = $this_section.filter(S.settings.subSections); - - if ($sub_sections.length > 0) { - $sub_sections.each(function(i) { - var sub_id = section_id + '-' + (i + 1); - var sub_text = $(this).text(); - var $this_sub = $this_section.filter($(this).nextUntil($sub_sections).addBack()); - - $this_sub.wrapAll('
'); - sub_data.push( {id: sub_id, text: sub_text} ); - }); - } - } - - section_data.push( {id: section_id, text: text, sub_sections: sub_data} ); - }); - - S.sections.data = section_data; - }, - _tear_down_sections: function(sections) { - $(sections).each(function() { - var sub_sections = this.sub_sections; - - $('#' + this.id).children().unwrap(); - - if (sub_sections.length > 0) { - $(sub_sections).each(function() { - $('#' + this.id).children().unwrap(); - }); - } - }); - }, - _setup_nav: function(sections) { - // Populate an ordered list from the section array we built - - var $headline = $('', {'class': S.settings.className + '__heading', text: S.settings.headlineText}); - var $wrapper = $('
', {'class': S.settings.className + '__wrapper'}); - var $nav = $('