diff --git a/src/pagination/docs/demo.html b/src/pagination/docs/demo.html
index 4629364907..bb7e608676 100644
--- a/src/pagination/docs/demo.html
+++ b/src/pagination/docs/demo.html
@@ -1,8 +1,9 @@
 <div ng-controller="PaginationDemoCtrl">
     <pagination num-pages="noOfPages" current-page="currentPage"></pagination>
-    <pagination num-pages="noOfPages" current-page="currentPage" class="pagination-small"></pagination>
-    <pagination num-pages="noOfPages" current-page="currentPage" class="pagination-mini"></pagination>
+    <pagination num-pages="noOfPages" current-page="currentPage" class="pagination-small" previous-text="&laquo;" next-text="&raquo;"></pagination>
+    <pagination boundary-links="true" num-pages="noOfPages" current-page="currentPage" max-size="maxSize"></pagination>
     <pagination num-pages="noOfPages" current-page="currentPage"  max-size="maxSize"></pagination>
+    <pagination direction-links="false" num-pages="noOfPages" current-page="currentPage"></pagination>
     <button class="btn" ng-click="setPage(3)">Set current page to: 3</button>
     The selected page no: {{currentPage}}
 </div>
\ No newline at end of file
diff --git a/src/pagination/docs/readme.md b/src/pagination/docs/readme.md
index 3008a2b67f..b40617116f 100644
--- a/src/pagination/docs/readme.md
+++ b/src/pagination/docs/readme.md
@@ -1,5 +1,5 @@
 A lightweight pagination directive that is focused on ... providing pagination!
 
-It will take care of visualising a pagination bar. Additionally it will make sure that the state (enabled / disabled) of the Previous / Next buttons is maintained correctly.
+It will take care of visualising a pagination bar. Additionally it will make sure that the state (enabled / disabled) of the Previous / Next and First / Last buttons (if exist) is maintained correctly.
 
 It also provides optional attribute max-size to limit the size of pagination bar.
\ No newline at end of file
diff --git a/src/pagination/pagination.js b/src/pagination/pagination.js
index b66bab5aba..bba5f11ed8 100644
--- a/src/pagination/pagination.js
+++ b/src/pagination/pagination.js
@@ -1,19 +1,45 @@
 angular.module('ui.bootstrap.pagination', [])
 
-.directive('pagination', function() {
+.constant('paginationConfig', {
+  boundaryLinks: false,
+  directionLinks: true,
+  firstText: 'First',
+  previousText: 'Previous',
+  nextText: 'Next',
+  lastText: 'Last'
+})
+
+.directive('pagination', ['paginationConfig', function(paginationConfig) {
   return {
     restrict: 'EA',
     scope: {
       numPages: '=',
       currentPage: '=',
       maxSize: '=',
-      onSelectPage: '&',
-      nextText: '@',
-      previousText: '@'
+      onSelectPage: '&'
     },
     templateUrl: 'template/pagination/pagination.html',
     replace: true,
-    link: function(scope) {
+    link: function(scope, element, attrs) {
+
+      // Setup configuration parameters
+      var boundaryLinks = angular.isDefined(attrs.boundaryLinks) ? scope.$eval(attrs.boundaryLinks) : paginationConfig.boundaryLinks;
+      var directionLinks = angular.isDefined(attrs.directionLinks) ? scope.$eval(attrs.directionLinks) : paginationConfig.directionLinks;
+      var firstText = angular.isDefined(attrs.firstText) ? attrs.firstText : paginationConfig.firstText;
+      var previousText = angular.isDefined(attrs.previousText) ? attrs.previousText : paginationConfig.previousText;
+      var nextText = angular.isDefined(attrs.nextText) ? attrs.nextText : paginationConfig.nextText;
+      var lastText = angular.isDefined(attrs.lastText) ? attrs.lastText : paginationConfig.lastText;
+
+      // Create page object used in template
+      function makePage(number, text, isActive, isDisabled) {
+        return {
+          number: number,
+          text: text,
+          active: isActive,
+          disabled: isDisabled
+        };
+      }
+
       scope.$watch('numPages + currentPage + maxSize', function() {
         scope.pages = [];
         
@@ -29,9 +55,31 @@ angular.module('ui.bootstrap.pagination', [])
             startPage = startPage - ((startPage + maxSize - 1) - scope.numPages );
         }
 
-        for(var i=0; i < maxSize && i < scope.numPages ;i++) {
-          scope.pages.push(startPage + i);
+        // Add page number links
+        for (var number = startPage, max = startPage + maxSize; number < max; number++) {
+          var page = makePage(number, number, scope.isActive(number), false);
+          scope.pages.push(page);
         }
+
+        // Add previous & next links
+        if (directionLinks) {
+          var previousPage = makePage(scope.currentPage - 1, previousText, false, scope.noPrevious());
+          scope.pages.unshift(previousPage);
+
+          var nextPage = makePage(scope.currentPage + 1, nextText, false, scope.noNext());
+          scope.pages.push(nextPage);
+        }
+
+        // Add first & last links
+        if (boundaryLinks) {
+          var firstPage = makePage(1, firstText, false, scope.noPrevious());
+          scope.pages.unshift(firstPage);
+
+          var lastPage = makePage(scope.numPages, lastText, false, scope.noNext());
+          scope.pages.push(lastPage);
+        }
+
+
         if ( scope.currentPage > scope.numPages ) {
           scope.selectPage(scope.numPages);
         }
@@ -47,22 +95,11 @@ angular.module('ui.bootstrap.pagination', [])
       };
 
       scope.selectPage = function(page) {
-        if ( ! scope.isActive(page) ) {
+        if ( ! scope.isActive(page) && page > 0 && page <= scope.numPages) {
           scope.currentPage = page;
           scope.onSelectPage({ page: page });
         }
       };
-
-      scope.selectPrevious = function() {
-        if ( !scope.noPrevious() ) {
-          scope.selectPage(scope.currentPage-1);
-        }
-      };
-      scope.selectNext = function() {
-        if ( !scope.noNext() ) {
-          scope.selectPage(scope.currentPage+1);
-        }
-      };
     }
   };
-});
\ No newline at end of file
+}]);
\ No newline at end of file
diff --git a/src/pagination/test/pagination.spec.js b/src/pagination/test/pagination.spec.js
index 356168432a..1a49709ce4 100644
--- a/src/pagination/test/pagination.spec.js
+++ b/src/pagination/test/pagination.spec.js
@@ -1,4 +1,4 @@
-describe('pagination directive', function () {
+describe('pagination directive with default configuration', function () {
   var $rootScope, element;
   beforeEach(module('ui.bootstrap.pagination'));
   beforeEach(module('template/pagination/pagination.html'));
@@ -192,7 +192,7 @@ describe('pagination directive with max size option', function () {
 
 });
 
-describe('pagination custom', function () {
+describe('pagination directive with added first & last links', function () {
   var $rootScope, element;
   beforeEach(module('ui.bootstrap.pagination'));
   beforeEach(module('template/pagination/pagination.html'));
@@ -201,12 +201,305 @@ describe('pagination custom', function () {
     $rootScope = _$rootScope_;
     $rootScope.numPages = 5;
     $rootScope.currentPage = 3;
-    element = $compile('<pagination previous-text="<<" next-text=">>" num-pages="numPages" current-page="currentPage"></pagination>')($rootScope);
+    element = $compile('<pagination boundary-links="true" num-pages="numPages" current-page="currentPage"></pagination>')($rootScope);
     $rootScope.$digest();
   }));
 
+
+  it('contains one ul and num-pages + 4 li elements', function() {
+    expect(element.find('ul').length).toBe(1);
+    expect(element.find('li').length).toBe(9);
+    expect(element.find('li').eq(0).text()).toBe('First');
+    expect(element.find('li').eq(1).text()).toBe('Previous');
+    expect(element.find('li').eq(-2).text()).toBe('Next');
+    expect(element.find('li').eq(-1).text()).toBe('Last');
+  });
+
+  it('has first and last li visible & with borders', function() {
+    var firstLiEl = element.find('li').eq(0);
+    var lastLiEl = element.find('li').eq(-1);
+
+    expect(firstLiEl.text()).toBe('First');
+    expect(firstLiEl.css('display')).not.toBe('none');
+    expect(lastLiEl.text()).toBe('Last');
+    expect(lastLiEl.css('display')).not.toBe('none');
+  });
+
+
+  it('disables the "first" & "previous" link if current-page is 1', function() {
+    $rootScope.currentPage = 1;
+    $rootScope.$digest();
+    expect(element.find('li').eq(0).hasClass('disabled')).toBe(true);
+    expect(element.find('li').eq(1).hasClass('disabled')).toBe(true);
+  });
+
+  it('disables the "last" & "next" link if current-page is num-pages', function() {
+    $rootScope.currentPage = 5;
+    $rootScope.$digest();
+    expect(element.find('li').eq(-2).hasClass('disabled')).toBe(true);
+    expect(element.find('li').eq(-1).hasClass('disabled')).toBe(true);
+  });
+
+
+  it('changes currentPage if the "first" link is clicked', function() {
+    var first = element.find('li').eq(0).find('a').eq(0);
+    first.click();
+    $rootScope.$digest();
+    expect($rootScope.currentPage).toBe(1);
+  });
+
+  it('changes currentPage if the "last" link is clicked', function() {
+    var last = element.find('li').eq(-1).find('a').eq(0);
+    last.click();
+    $rootScope.$digest();
+    expect($rootScope.currentPage).toBe($rootScope.numPages);
+  });
+
+  it('does not change the current page on "first" click if already at first page', function() {
+    var first = element.find('li').eq(0).find('a').eq(0);
+    $rootScope.currentPage = 1;
+    $rootScope.$digest();
+    first.click();
+    $rootScope.$digest();
+    expect($rootScope.currentPage).toBe(1);
+  });
+
+  it('does not change the current page on "last" click if already at last page', function() {
+    var last = element.find('li').eq(-1).find('a').eq(0);
+    $rootScope.currentPage = $rootScope.numPages;
+    $rootScope.$digest();
+    last.click();
+    $rootScope.$digest();
+    expect($rootScope.currentPage).toBe($rootScope.numPages);
+  });
+
+  it('changes "first" & "last" text from attributes', function() {
+    element = $compile('<pagination boundary-links="true" first-text="<<<" last-text=">>>" num-pages="numPages" current-page="currentPage"></pagination>')($rootScope);
+    $rootScope.$digest();
+
+    expect(element.find('li').eq(0).text()).toBe('<<<');
+    expect(element.find('li').eq(-1).text()).toBe('>>>');
+  });
+
+  it('changes "previous" & "next" text from attributes', function() {
+    element = $compile('<pagination boundary-links="true" previous-text="<<" next-text=">>" num-pages="numPages" current-page="currentPage"></pagination>')($rootScope);
+    $rootScope.$digest();
+
+    expect(element.find('li').eq(1).text()).toBe('<<');
+    expect(element.find('li').eq(-2).text()).toBe('>>');
+  });
+
+});
+
+describe('pagination directive with just number links', function () {
+  var $rootScope, element;
+  beforeEach(module('ui.bootstrap.pagination'));
+  beforeEach(module('template/pagination/pagination.html'));
+  beforeEach(inject(function(_$compile_, _$rootScope_) {
+    $compile = _$compile_;
+    $rootScope = _$rootScope_;
+    $rootScope.numPages = 5;
+    $rootScope.currentPage = 3;
+    element = $compile('<pagination direction-links="false" num-pages="numPages" current-page="currentPage"></pagination>')($rootScope);
+    $rootScope.$digest();
+  }));
+
+  it('has a "pagination" css class', function() {
+    expect(element.hasClass('pagination')).toBe(true);
+  });
+
+  it('contains one ul and num-pages li elements', function() {
+    expect(element.find('ul').length).toBe(1);
+    expect(element.find('li').length).toBe(5);
+    expect(element.find('li').eq(0).text()).toBe('1');
+    expect(element.find('li').eq(-1).text()).toBe(''+$rootScope.numPages);
+  });
+
+  it('has the number of the page as text in each page item', function() {
+    var lis = element.find('li');
+    for(var i=0; i<$rootScope.numPages;i++) {
+      expect(lis.eq(i).text()).toEqual(''+(i+1));
+    }
+  });
+
+  it('sets the current-page to be active', function() {
+    var currentPageItem = element.find('li').eq($rootScope.currentPage-1);
+    expect(currentPageItem.hasClass('active')).toBe(true);
+  });
+
+  it('does not disable the "1" link if current-page is 1', function() {
+    $rootScope.currentPage = 1;
+    $rootScope.$digest();
+    var onePageItem = element.find('li').eq(0);
+    expect(onePageItem.hasClass('disabled')).toBe(false);
+    expect(onePageItem.hasClass('active')).toBe(true);
+  });
+
+  it('does not disable the "numPages" link if current-page is num-pages', function() {
+    $rootScope.currentPage = 5;
+    $rootScope.$digest();
+    var lastPageItem = element.find('li').eq(-1);
+    expect(lastPageItem.hasClass('disabled')).toBe(false);
+    expect(lastPageItem.hasClass('active')).toBe(true);
+  });
+
+  it('changes currentPage if a page link is clicked', function() {
+    var page2 = element.find('li').eq(1).find('a');
+    page2.click();
+    $rootScope.$digest();
+    expect($rootScope.currentPage).toBe(2);
+  });
+
+
+  it('executes the onSelectPage expression when the current page changes', function() {
+    $rootScope.selectPageHandler = jasmine.createSpy('selectPageHandler');
+    element = $compile('<pagination direction-links="false" num-pages="numPages" current-page="currentPage" on-select-page="selectPageHandler(page)"></pagination>')($rootScope);
+    $rootScope.$digest();
+    var page2 = element.find('li').eq(1).find('a').eq(0);
+    page2.click();
+    $rootScope.$digest();
+    expect($rootScope.selectPageHandler).toHaveBeenCalledWith(2);
+  });
+
+  it('changes the number of items when numPages changes', function() {
+    $rootScope.numPages = 8;
+    $rootScope.$digest();
+    expect(element.find('li').length).toBe(8);
+    expect(element.find('li').eq(0).text()).toBe('1');
+    expect(element.find('li').eq(-1).text()).toBe(''+$rootScope.numPages);
+  });
+
+  it('sets the current page to the last page if the numPages is changed to less than the current page', function() {
+    $rootScope.selectPageHandler = jasmine.createSpy('selectPageHandler');
+    element = $compile('<pagination direction-links="false" num-pages="numPages" current-page="currentPage" on-select-page="selectPageHandler(page)"></pagination>')($rootScope);
+    $rootScope.$digest();
+    $rootScope.numPages = 2;
+    $rootScope.$digest();
+    expect(element.find('li').length).toBe(2);
+    expect($rootScope.currentPage).toBe(2);
+    expect($rootScope.selectPageHandler).toHaveBeenCalledWith(2);
+  });
+});
+
+describe('setting paginationConfig', function() {
+  var $rootScope, element;
+  var originalConfig = {};
+  beforeEach(module('ui.bootstrap.pagination'));
+  beforeEach(module('template/pagination/pagination.html'));
+  beforeEach(inject(function(_$compile_, _$rootScope_, paginationConfig) {
+    $compile = _$compile_;
+    $rootScope = _$rootScope_;
+    $rootScope.numPages = 5;
+    $rootScope.currentPage = 3;
+    angular.extend(originalConfig, paginationConfig);
+    paginationConfig.boundaryLinks = true;
+    paginationConfig.directionLinks = true;
+    paginationConfig.firstText = 'FI';
+    paginationConfig.previousText = 'PR';
+    paginationConfig.nextText = 'NE';
+    paginationConfig.lastText = 'LA';
+    element = $compile('<pagination num-pages="numPages" current-page="currentPage"></pagination>')($rootScope);
+    $rootScope.$digest();
+  }));
+  afterEach(inject(function(paginationConfig) {
+    // return it to the original state
+    angular.extend(paginationConfig, originalConfig);
+  }));
+
+  it('should change paging text', function () {
+    expect(element.find('li').eq(0).text()).toBe('FI');
+    expect(element.find('li').eq(1).text()).toBe('PR');
+    expect(element.find('li').eq(-2).text()).toBe('NE');
+    expect(element.find('li').eq(-1).text()).toBe('LA');
+  });
+
+  it('contains one ul and num-pages + 4 li elements', function() {
+    expect(element.find('ul').length).toBe(1);
+    expect(element.find('li').length).toBe(9);
+  });
+
+});
+
+
+describe('pagination directive with first, last & number links', function () {
+  var $rootScope, element;
+  beforeEach(module('ui.bootstrap.pagination'));
+  beforeEach(module('template/pagination/pagination.html'));
+  beforeEach(inject(function(_$compile_, _$rootScope_) {
+    $compile = _$compile_;
+    $rootScope = _$rootScope_;
+    $rootScope.numPages = 5;
+    $rootScope.currentPage = 3;
+    element = $compile('<pagination boundary-links="true" direction-links="false" num-pages="numPages" current-page="currentPage"></pagination>')($rootScope);
+    $rootScope.$digest();
+  }));
+
+
+  it('contains one ul and num-pages + 2 li elements', function() {
+    expect(element.find('ul').length).toBe(1);
+    expect(element.find('li').length).toBe(7);
+    expect(element.find('li').eq(0).text()).toBe('First');
+    expect(element.find('li').eq(1).text()).toBe('1');
+    expect(element.find('li').eq(-2).text()).toBe(''+$rootScope.numPages);
+    expect(element.find('li').eq(-1).text()).toBe('Last');
+  });
+
+
+  it('disables the "first" & activates "1" link if current-page is 1', function() {
+    $rootScope.currentPage = 1;
+    $rootScope.$digest();
+    expect(element.find('li').eq(0).hasClass('disabled')).toBe(true);
+    expect(element.find('li').eq(1).hasClass('disabled')).toBe(false);
+    expect(element.find('li').eq(1).hasClass('active')).toBe(true);
+  });
+
+  it('disables the "last" & "next" link if current-page is num-pages', function() {
+    $rootScope.currentPage = 5;
+    $rootScope.$digest();
+    expect(element.find('li').eq(-2).hasClass('disabled')).toBe(false);
+    expect(element.find('li').eq(-2).hasClass('active')).toBe(true);
+    expect(element.find('li').eq(-1).hasClass('disabled')).toBe(true);
+  });
+
+
+  it('changes currentPage if the "first" link is clicked', function() {
+    var first = element.find('li').eq(0).find('a').eq(0);
+    first.click();
+    $rootScope.$digest();
+    expect($rootScope.currentPage).toBe(1);
+  });
+
+  it('changes currentPage if the "last" link is clicked', function() {
+    var last = element.find('li').eq(-1).find('a').eq(0);
+    last.click();
+    $rootScope.$digest();
+    expect($rootScope.currentPage).toBe($rootScope.numPages);
+  });
+
+});
+
+describe('pagination bypass configuration from attributes', function () {
+  var $rootScope, element;
+  beforeEach(module('ui.bootstrap.pagination'));
+  beforeEach(module('template/pagination/pagination.html'));
+  beforeEach(inject(function(_$compile_, _$rootScope_) {
+    $compile = _$compile_;
+    $rootScope = _$rootScope_;
+    $rootScope.numPages = 5;
+    $rootScope.currentPage = 3;
+    element = $compile('<pagination boundary-links="true" first-text="<<" previous-text="<" next-text=">" last-text=">>" num-pages="numPages" current-page="currentPage"></pagination>')($rootScope);
+    $rootScope.$digest();
+  }));
+
+  it('contains one ul and num-pages + 4 li elements', function() {
+    expect(element.find('ul').length).toBe(1);
+    expect(element.find('li').length).toBe(9);
+  });
+
   it('should change paging text from attribute', function () {
     expect(element.find('li').eq(0).text()).toBe('<<');
+    expect(element.find('li').eq(1).text()).toBe('<');
+    expect(element.find('li').eq(-2).text()).toBe('>');
     expect(element.find('li').eq(-1).text()).toBe('>>');
   });
 
diff --git a/template/pagination/pagination.html b/template/pagination/pagination.html
index 4c0d40baac..dec9c8f7cf 100644
--- a/template/pagination/pagination.html
+++ b/template/pagination/pagination.html
@@ -1,6 +1,4 @@
 <div class="pagination"><ul>
-  <li ng-class="{disabled: noPrevious()}"><a ng-click="selectPrevious()">{{previousText || 'Previous'}}</a></li>
-  <li ng-repeat="page in pages" ng-class="{active: isActive(page)}"><a ng-click="selectPage(page)">{{page}}</a></li>
-  <li ng-class="{disabled: noNext()}"><a ng-click="selectNext()">{{nextText || 'Next'}}</a></li>
+  <li ng-repeat="page in pages" ng-class="{active: page.active, disabled: page.disabled}"><a ng-click="selectPage(page.number)">{{page.text}}</a></li>
   </ul>
 </div>