var app = angular.module('plunker', [
'ngRoute',
'pymaster.jq-one-page-nav'
]);
app.directive('onEnter', function () {
return function(scope, element, attrs) {
element.bind("keydown keypress", function(event) {
if(event.which === 13) {
scope.$apply(function(){
scope.$eval(attrs.onEnter, {'$event': event});
});
event.preventDefault();
}
});
};
});
app.config(function ($routeProvider) {
$routeProvider
.when('/page/:page', {
templateUrl: 'page.html',
controller: 'PageCtrl',
controllerAs: 'page',
resolve: {
presetItems: function ($route, pageCache) {
var page = $route.current.params.page;
return (pageCache(page).get('nav') ||
['Page '+page, 'is', 'here']);
}
}
})
.otherwise({redirectTo: '/page/1'});
});
app.factory('pageCache', function ($cacheFactory) {
return function pageCache(page) {
var ID_PREFIX = 'page-';
var cacheId = ID_PREFIX + page;
return $cacheFactory.get(cacheId) || $cacheFactory(cacheId);
};
});
app.controller('MainCtrl', function($scope, $route, $location) {
$scope.$location = $location;
$scope.PAGES = [1, 2, 3];
$scope.flatUIColor = function (num) {
switch (num % 4) {
case 0:
return '#2ecc71';
case 1:
return '#e74c3c';
case 2:
return '#3498db';
case 3:
return '#e67e22';
}
};
});
app.controller('PageCtrl', function($scope, $timeout, presetItems, pageCache, $routeParams) {
var self = this;
var navId = 0,
page = $routeParams.page;
this.nav = [];
this.addNavItem = function () {
if (!this.newItem) {
return;
}
var item = addNavItem(this.nav, this.newItem);
this.newItem = '';
$timeout(function () {
$scope.$emit('jqOnePageNav.scrollTo', item.id);
}, 50);
};
init();
function init () {
angular.forEach(presetItems, function (c) {
addNavItem(self.nav, c);
});
$scope.$on('$destroy', function () {
var save = [];
angular.forEach(self.nav, function (c) {
save.push(c.name);
});
pageCache(page).put('nav', save);
});
}
function addNavItem(list, name) {
var item = {
id: 'nav-' + (++navId),
name: name
};
list.push(item);
return item;
}
});
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS + jQuery One Page Nav</title>
<link data-require="bootstrap-css@3.2.0" data-semver="3.2.0" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" />
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://pc035860.github.io/jQuery-One-Page-Nav/jquery.nav.js"></script>
<script data-require="angular.js@1.2.x" src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.24/angular.min.js" data-semver="1.2.24"></script>
<script data-require="angular.js@1.2.x" src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.24/angular-route.min.js" data-semver="1.2.24"></script>
<script src="jq-one-page-nav.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<div class="container">
<h1 class="text-center">AngularJS + jQuery One Page Nav</h1>
<ul class="page-nav">
<li ng-repeat="p in PAGES"
ng-class="{active: $location.path() == '/page/'+p}"><a ng-href="#/page/{{ p }}">Page {{ p }}</a></li>
</ul>
</div>
<div ng-view></div>
</body>
</html>
/* Put your css in here */
body {
background-color: #505050;
color: white;
}
.page-nav {
list-style: none;
margin: 0; padding: 0;
text-align: center;
}
.page-nav li {
display: inline-block;
margin: 0 5px;
}
.page-nav li a {
transition: border-color 300ms ease;
-webkit-box-sizing: border-box;
box-sizing: border-box;
max-height: 40px;
position: relative;
top: 2px;
display: block;
padding: 8px 10px;
border-bottom: 1px solid rgba(255, 255, 255, 0.3);
text-decoration: none !important;
color: rgba(255, 255, 255, 0.3);
}
.page-nav li a:hover {
color: rgba(255, 255, 255, 0.5);
border-color: rgba(255, 241, 38, 0.8);
}
.page-nav li a:focus, .page-nav li a:active {
color: rgba(255, 255, 255, 1);
border-color: rgba(255, 241, 38, 1);
}
.page-nav li.active a {
color: rgba(255, 255, 255, 0.8);
border-color: rgba(255, 241, 38, 1);
border-bottom-width: 3px;
top: 0;
}
.dots {
position: fixed;
width: 100%;
bottom: 20px;
left: 0;
}
.dots ul {
list-style: none;
margin: 0;
padding: 0;
text-align: center;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.dots li {
position: relative;
display: inline-block;
width: 16px;
height: 16px;
margin: 0 8px;
cursor: pointer;
border-radius: 50%;
box-shadow: 0 0 0 2px rgba(255, 255, 255, 0);
-webkit-transition: box-shadow 0.3s ease;
transition: box-shadow 0.3s ease;
}
.dots .current {
box-shadow: 0 0 0 2px white;
}
.dots a {
position: absolute;
left: 0; top: 0;
width: 100%; height: 100%;
outline: none;
border-radius: 50%;
text-indent: -999em;
cursor: pointer;
background-color: #fff;
background-color: rgba(255, 255, 255, 0.7);
-webkit-transition: background-color 0.3s ease, -webkit-transform 0.3s ease;
transition: background-color 0.3s ease, transform 0.3s ease;
}
.dots a:hover, .dots a:focus, .dots .current a {
background-color: #fff;
}
.dots .current a {
-webkit-transform: scale(0.4);
transform: scale(0.4);
}
.dots input[type="text"] {
display: inline-block;
width: 80%;
}
.dots button {
position: relative; top: -1px;
width: 19%;
}
.page {
position: relative;
width: 100%;
height: 100vh;
text-align: center;
}
.page h2 {
position: absolute;
left: 50%; top: 50%;
margin: 0;
color: white;
line-height: 1.6;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
/*global angular*/
angular.module('pymaster.jq-one-page-nav', [])
.directive('jqOnePageNav', function ($timeout, $rootScope) {
return {
restrict: 'EA',
scope: {
items: '=',
liTrigger: '=',
options: '='
},
replace: true,
template: '\
<div class="jq-one-page-nav">\
<ul>\
<li ng-repeat="item in items" ng-click="handleClick($event)">\
<a ng-href="#{{ item.id }}" ng-bind="item.name" title="{{ item.name }}"></a>\
</li>\
</ul>\
</div>\
',
link: function (scope, iElm, iAttrs) {
var api, elmDestroyed, dereg;
scope.handleClick = function ($evt) {
if (api && !!scope.liTrigger) {
$($evt.currentTarget).find('a').trigger('click.onePageNav');
}
};
scope.$watchCollection('items', function () {
if (api) {
api.destroy();
}
$timeout(function () {
var options = scope.options || {},
apiDataName = options.apiDataName || 'onePageNav';
if (!elmDestroyed) {
api = iElm.find('ul').onePageNav(options).data(apiDataName);
api.scrollChange();
}
});
});
dereg = $rootScope.$on('jqOnePageNav.scrollTo', function ($evt, target) {
if (api) {
api.scrollTo('#' + target);
}
});
iElm.bind('$destroy', function () {
elmDestroyed = true;
if (api) {
api.destroy();
}
if (dereg) {
dereg();
}
});
}
};
});
<section class="page"
id="{{item.id}}"
ng-repeat="item in page.nav"
ng-style="{'background-color': flatUIColor($index)}">
<h2 ng-bind="item.name"></h2>
</section>
<nav class="dots">
<div class="container">
<p style="margin-bottom: 25px;">
<input type="text" class="form-control" placeholder="Add new nav items here!"
ng-model="page.newItem"
on-enter="page.addNavItem()"><button class="btn btn-default" ng-click="page.addNavItem()">Add</button>
</p>
<div jq-one-page-nav items="page.nav"></div>
</div>
</nav>