diff --git a/.travis.yml b/.travis.yml index f5e0d07..15951aa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,17 +1,20 @@ language: node_js node_js: - "0.12" +env: + global: + - secure: h8dx7ZK94tKsp965RwL+PjUfoOcgiGYSKnwyRGPnK4Acjgl+UhhdtOW0SkgjRW2PLr2Umpfi8jKGoS3cJCiLL4vQvDmPJ6xS3BmVYWImVJwt2vCShDc6O1z82ebUE5F9QagBapYFOG3r8dOUqEYKsL+9WLsGRckLQpvQCo0EIt948UoqoVosKKD7ALaPHKeYCeAiRthCiWrN7jTnTm5U92bLtiMIZEBZrVzHpFxnUA33TIFgnkeSCyf5sO/iwjRrGO3IEXyVOKisjzXkug/ODjVXH33M5IJl7sZ+R2ZGtCQHh0CZNDI6oyAhzz9QaItA0V1YtzvbcdyAzPsP2a2izM6EgQGsnVEm2A5BzIdo4AtUalHxssf4e9kerE8cDDKruEZhNVP5lZ8wxP5Dw9Tl704AUCDDzqJZFnf8/wwg+Vyc6+hHj5TBw5vPmoNy/yBQ9GnAYvrBUba5NJ+4aDYtxzn9Qq5JuckUiQsfKUGdYNKC/wFg0U1NR+7RA0WBnp0NyTyaGtKe6oRydIaXGX1km5aqNDIgsEqMzpZULRIHfJiOF3MIVOoZesvx/14amHpuB60XxUwVUhqjRMRQ6Fmy0gjQheTVK5LTPDJxl6vMB6wXe7F6sjeO21XlZkv5oVwgzg1p+TIgrQ7dVS+fFcCnBy8ncwF6RXVr2opZtU3i76A= + - secure: n840XxnmSzNNPVkM89uF+aa2+DWnqW1n5wWhWBUhJENu2ZlFU2y0ij9MrbwMsg+wxhGyFLCcGGKbHai5AbZb++PJxsPVNVM4ZsnIw2Dbhsqu8ksVORPgOT7l15mpD+gqmpHiVND4BQ5LSGnrwdg2U3geGJ4cUgpPIpIiHwDrkB5u5jKq4VIWggQ2Y8xKT41JleDAWT1nJfa65Rk9f6vck7YbLLEcKoy/2brTdEHKjhHWq9mDDa0fwQijmRhgfe8vEf2Kzujg4th3mnrztwVXUsKOBB3mA3XEsFFUmxvhn7bLOHWn3GMk7WFcctw7QZ66Lh6maqMujne67slyxj5KypiecqzLwiOSbq5AXQCGHvAFAhq5973Elgfwm6NOH8l+EUR/Lg4CbBjCt2JVrVdhGuVngijNaTq4Yiji4gpwf0ghoOwbG4CFTCDMKHEbliExR9VaVFcRhQM+0Dv7Hl7uJs4ofaLb25vuNNKRLtm65Vv/Ndvfe1OYnfyn3H2wdS+Pn4WrCsAzRNfzmlfwZU65am1pLmYpJ7ZDU2nDuT8GCUl+wu50Cj6U0RcNlcSJmSAcsmHJJfaNaCpqzvSvNBjQSpTMh32RWlj6BIrqCzAXEHW3xQEMfbD+VA/vZoWE4DM8ED7Ndkhu+DrHrGs23Z3n87lqOlh3FpnnKvXLlTi95sQ= before_install: - npm install -g bower grunt-cli protractor - # - webdriver-manager update + - webdriver-manager update install: - npm install script: - grunt test:development - grunt test - # - nohup webdriver-manager start & - # - grunt e2e --ci + - grunt e2e --ci after_success: - ./node_modules/coveralls/bin/coveralls.js < coverage/lcov.info -# addons: -# sauce_connect: true +addons: + sauce_connect: true diff --git a/CHANGELOG.md b/CHANGELOG.md index e69de29..227c1b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -0,0 +1,3 @@ +## Changes in 0.0.1 + + * @edwardoparearyee: First release diff --git a/Gruntfile.js b/Gruntfile.js index d7e1bf5..9986a73 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -77,7 +77,7 @@ module.exports = function (grunt) { './modules/**/*.html', './modules/**/**/*.html' ], - tasks: ['lint','less:development'] + tasks: ['less:development'] }, javascript: { files: [ @@ -160,6 +160,14 @@ module.exports = function (grunt) { } }, + protractor_webdriver: { + dist: { + options: { + command: 'webdriver-manager update && webdriver-manager start', + } + } + }, + protractor: { options: { keepAlive: false, @@ -370,6 +378,7 @@ module.exports = function (grunt) { grunt.loadNpmTasks('grunt-contrib-yuidoc'); grunt.loadNpmTasks('grunt-contrib-jasmine'); grunt.loadNpmTasks('grunt-protractor-runner'); + grunt.loadNpmTasks('grunt-protractor-webdriver'); grunt.loadNpmTasks('grunt-processhtml'); grunt.loadNpmTasks('grunt-ng-constant'); grunt.loadNpmTasks('grunt-bump'); @@ -445,6 +454,7 @@ module.exports = function (grunt) { 'copy', 'processhtml:e2e', 'connect:servertest', + 'protractor_webdriver', 'protractor:dist', 'clean:afterTest' ]); diff --git a/README.md b/README.md index 37e95b5..e5c3dda 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,66 @@ # Angular Smart Nav - +[![Sauce Test Status](https://saucelabs.com/browser-matrix/angular-smart-nav.svg)](https://saucelabs.com/u/angular-smart-nav) Show or hide a navbar when scrolling in any particular direction and or minimise nav when scrolling pass the navbar +## Install + +You can install this module using [bower][bower] like so: + +``` +bower install angular-smart-nav --save +``` + +Add the angular-smart-nav library file to your `index.html` file like so: + +```html + +``` + +Then add the module to your angular app: + +```javascript +angular.module('myApp', ['sn.smartNav']); +``` + +## Example Usage + +In your html simply add the directive to your nav: + +```html + +``` + +The directive will add the following classes to your nav: +- `scrolling-down`: when the user is scrolling down the page +- `scrolling-up`: when the user is scrolling up the page +- `minimised-mode`: when the user has scrolled beyond the height of the nav + +You still have to add your own custom styling to the nav to hide, show or minimise the navbar. The following will hide the nav when scrolling down and display it again when scrolling up: + +```css +nav { + opacity: 1; + transition: opacity .4s ease-in-out .4s; +} +nav.scrolling-down { + opacity: 0; +} +nav.scrolling-up { + opacity: 0; +} +``` + + This project structure is based on the [angular-start](https://github.com/thisissoon/angular-start ) application skeleton for a typical [AngularJS](http://angularjs.org/) web app. @@ -231,7 +285,6 @@ Once you have ensured that the development web server hosting our application is and WebDriver is updated, you can run the end-to-end tests using the supplied grunt task: ``` -nohup webdriver-manager start & grunt e2e ``` diff --git a/app/index.html b/app/index.html index e2ec950..678cf87 100644 --- a/app/index.html +++ b/app/index.html @@ -21,10 +21,6 @@ - - - - @@ -43,10 +39,33 @@ + + - + - - - + - + + + diff --git a/app/js/smartNav.js b/app/js/smartNav.js index 630c889..a12a988 100644 --- a/app/js/smartNav.js +++ b/app/js/smartNav.js @@ -51,6 +51,7 @@ angular.module('sn.smartNav', [ var scrollingDown = false; /** * @method isScrollingDown + * @private * @param {Number} currentScrollTop * @return {Boolean} True if last scroll direction is down */ @@ -68,15 +69,16 @@ angular.module('sn.smartNav', [ }; /** * Calulate the current scroll direction and add relevent classes + * @private * @method calScrollDir - * @param {Number} scrollTop + * @param {Number} scrollTop */ var calScrollDir = function calScrollDir(scrollTop){ - if ($scope.scrollingDown && isScrollingUp(scrollTop)) { + if ( scrollingDown && isScrollingUp(scrollTop) ) { scrollingDown = false; $element.removeClass('scrolling-down'); $element.addClass('scrolling-up'); - } else if (!$scope.scrollingDown && isScrollingDown(scrollTop)){ + } else if ( !scrollingDown && isScrollingDown(scrollTop) ){ scrollingDown = true; $element.removeClass('scrolling-up'); $element.addClass('scrolling-down'); @@ -84,6 +86,7 @@ angular.module('sn.smartNav', [ }; /** * Calulate if the user has scrolled beyond the height of the element + * @private * @method calMinimisedMode * @param {Number} scrollTop */ @@ -98,6 +101,7 @@ angular.module('sn.smartNav', [ * window `scroll` event handler. * Gets the current scroll postion and calulates * scroll direction and whether to enable minimise mode + * @private * @method onScroll */ var onScroll = function onScroll() { @@ -111,7 +115,7 @@ angular.module('sn.smartNav', [ lastScrollTop = scrollTop; }; - angular.element($window).on('scroll.erHeader', onScroll); + angular.element($window).on('scroll', onScroll); } }; } diff --git a/package.json b/package.json index 2e71f45..10ec2cd 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "grunt-ng-constant": "~1.1.0", "grunt-processhtml": "~0.3.7", "grunt-protractor-runner": "~2.1.0", + "grunt-protractor-webdriver": "~0.2.5", "grunt-sails-linker": "~0.10.1", "grunt-template-jasmine-istanbul": "~0.3.3", "protractor": "~2.5.1", diff --git a/tests/e2e/app.e2e.js b/tests/e2e/app.e2e.js index 6ef2e3e..7d86e15 100644 --- a/tests/e2e/app.e2e.js +++ b/tests/e2e/app.e2e.js @@ -3,11 +3,11 @@ * This module runs e2e test by setting up a module to make our * backend assertions e.g. mock the responses from our api before * lauching our actual application. - * @main sn.smartNav.e2e - * @module sn.smartNav.e2e + * @main myApp.e2e + * @module myApp.e2e * @author SOON_ */ -angular.module('sn.smartNav.e2e', ['sn.smartNav', 'ngMockE2E']) +angular.module('myApp.e2e', ['myApp', 'ngMockE2E']) /** * @method run * @param {Service} $httpBackend diff --git a/tests/e2e/specs/scenarios.js b/tests/e2e/specs/scenarios.js index 9cc6115..2a14756 100644 --- a/tests/e2e/specs/scenarios.js +++ b/tests/e2e/specs/scenarios.js @@ -3,5 +3,58 @@ /* https://github.com/angular/protractor/blob/master/docs/getting-started.md */ describe('sn.smartNav', function() { + describe('snSmartNav directive', function() { + var nav = {}; + + beforeEach(function(){ + browser.manage().deleteAllCookies(); + browser.get('http://127.0.0.1:8000/'); + browser.waitForAngular(); + browser.driver.sleep(2000); + nav = element.all(by.css('nav')).first(); + }); + + it('should not contain any classes from smartNav directive', function() { + browser.executeScript('scrollTo(0,0)'); + browser.driver.sleep(2000); + expect(nav.getAttribute('class')).not.toContain('scrolling-down'); + expect(nav.getAttribute('class')).not.toContain('scrolling-up'); + expect(nav.getAttribute('class')).not.toContain('minimised-mode'); + }); + + it('should add "scrolling-down" class', function() { + expect(nav.getAttribute('class')).not.toContain('scrolling-down'); + browser.executeScript('scrollTo(0,100)'); + browser.executeScript('scrollTo(0,200)'); + browser.executeScript('scrollTo(0,300)'); + browser.driver.sleep(2000); + expect(nav.getAttribute('class')).toContain('scrolling-down'); + }); + + it('should add "scrolling-up" class', function() { + browser.executeScript('scrollTo(0,400)'); + browser.driver.sleep(2000); + expect(nav.getAttribute('class')).not.toContain('scrolling-up'); + + browser.executeScript('scrollTo(0,300)'); + browser.executeScript('scrollTo(0,200)'); + browser.executeScript('scrollTo(0,100)'); + browser.driver.sleep(2000); + expect(nav.getAttribute('class')).toContain('scrolling-up'); + }); + + it('should add "minimised-mode" class', function() { + browser.executeScript('scrollTo(0,0)'); + browser.driver.sleep(2000); + expect(nav.getAttribute('class')).not.toContain('minimised-mode'); + + browser.executeScript('scrollTo(0,100)'); + browser.executeScript('scrollTo(0,200)'); + browser.executeScript('scrollTo(0,300)'); + browser.driver.sleep(2000); + expect(nav.getAttribute('class')).toContain('minimised-mode'); + }); + + }); }); diff --git a/tests/unit/smartNav.js b/tests/unit/smartNav.js index 2ced544..ad47388 100644 --- a/tests/unit/smartNav.js +++ b/tests/unit/smartNav.js @@ -2,12 +2,67 @@ describe('sn.smartNav', function (){ - beforeEach(function(){ - module('sn.smartNav'); + var element, $scope, $rootScope, $document, $window; + + beforeEach(module('sn.smartNav')); + + beforeEach(inject(function (_$rootScope_, $compile, $injector) { + $rootScope = _$rootScope_; + + $scope = $rootScope.$new(); + + $window = $injector.get('$window'); + + $document = $injector.get('$document'); + $document[0] = { + body: { + scrollTop: 0 + } + } + + element = ''; + + element = $compile(element)($scope); + $scope.$digest(); + + })); + + it('should add "scrolling-down" class', function(){ + $document[0].body.scrollTop = 0; + angular.element($window).triggerHandler('scroll'); + expect(element.hasClass('scrolling-down')).toBe(false); + + $document[0].body.scrollTop = 100; + angular.element($window).triggerHandler('scroll'); + expect(element.hasClass('scrolling-down')).toBe(true); + }); + + it('should add "scrolling-up" class', function(){ + $document[0].documentElement = { + scrollTop: 0 + }; + $document[0].body = undefined; + + $document[0].documentElement.scrollTop = 0; + angular.element($window).triggerHandler('scroll'); + + $document[0].documentElement.scrollTop = 100; + angular.element($window).triggerHandler('scroll'); + expect(element.hasClass('scrolling-up')).toBe(false); + + $document[0].documentElement.scrollTop = 0; + angular.element($window).triggerHandler('scroll'); + expect(element.hasClass('scrolling-up')).toBe(true); }); - it('should be true', function() { - expect(true).toBeTruthy(); + it('should add "minimised-mode" class', function(){ + $document[0].body.scrollTop = 0; + angular.element($window).triggerHandler('scroll'); + expect(element.hasClass('minimised-mode')).toBe(false); + + $document[0].body.scrollTop = 200; + angular.element($window).triggerHandler('scroll'); + expect(element.hasClass('minimised-mode')).toBe(true); }); });