AngularJS paginator directive with service

HTML

<div ng-app="ui" ng-controller="Ctrl">
    
    <button ng-click="updateProducts()">Regenerate Products List</button>

    <div class="navigation">
        <div class="items-count">{{products.firstItemNumber}} - {{products.lastItemNumber}} of {{products.totalItemCount}} items</div>
        <div class="pages clearfix" ng-show="products.totalItemCount > products.itemsPerPage">
            <button ng-disabled="products.first" ng-click="products.prev()">&lt; Prev</button>
            <ul clearfix>
                <li ng-show="products.firstPageInRange != 1" ng-click="products.setPage(products.firstPageInRange - 1)">
                    ... {{products.firstPageInRange}}
                </li>
    
                <li ng-repeat="page in products.pagesInRange" ng-click="products.setPage(page)" ng-class="{active: page == products.current}">
                    {{page}}
                </li>
    
                <li ng-show="products.lastPageInRange != products.pageCount" ng-click="products.setPage(products.lastPageInRange + 1)">
                    ...{{products.lastPageInRange}}
                </li>
            </ul>
            <button ng-disabled="products.last" ng-click="products.next()">Next &gt;</button>
        </div>
        <div class="sorter">
            Sort by: 
            <select ng-model="sorting">
                <option value="-Price">Price descending</option>
                <option value="Price">Price ascending</option>
                <option value="Name">Name A-Z</option>
                <option value="-Name">Name Z-A</option>
            </select> 
        </div>
    </div>
    
    <div class="items clearfix">
        <div ng-repeat="item in products.items" class="item">
            <div class="image">
                <img ng-src="{{item.Thumb}}" alt="{{item.Name}}" />
            </div>
            <div class="name">
                <a ng-href="{{item.Detail}}" target="_blank">{{item.Name}}</a>
            </div>
            <div...

CSS

.clearfix:after { 
   content: "."; 
   visibility: hidden; 
   display: block; 
   height: 0; 
   clear: both;
}

.container {
    padding: 10px;
}

.navigation {
    margin-bottom: 10px;
}

.navigation .pages > * {
    float: left;
}

.navigation .pages ul li {
    float: left;
    padding: 0 5px;
    cursor: pointer;
}

.navigation .pages ul li.active {
    font-weight: bold;
}

.items {
    border-left: 1px solid black;
    border-top: 1px solid black;
    max-width: 423px;
}

.items .item {
    float: left;
    border-bottom: 1px solid black;
    border-right: 1px solid black;
    padding: 10px;
    width: 120px;
}

.item .price {
    font-weight: bold;
}

JavaScript

/**
 * uiPaginate implementation using a service
 * The service is a function that accepts two parameters and returns a paginator
 * object that exposes methods useful to render the view
 *
 * @param items {Array} the array of objects to be paginated
 * 
 * @param options {Object} options to configure the service behaviour; accepted
 *        options are:
 *        - itemsPerPage {Number}: the number of items to show in every page
 *        - currentPage {Number}: the 1-based number of the first page to load
 *        - scrollingStyle {'all' | 'jumping' | 'sliding'}: the name of the
 *          algorithm to use to calculate the "pagesInRange" array (try them to
 *          see the differences)
 *        - pagesInRangeSize {Number}: the size of the "pagesInRange" array (just
 *          used by 'jumping' and 'sliding' algorithms)
 *
 * @returns {Object} a paginator that exposes these methods and properties:
 *          - items {Array}: the list of items in the current page
 *          - firstItemNumber {Number}: the absolute number of the first element
 *            in the current page
 *          - lastItemNumber {Number}: the absolute number of the last element
 *            in the current page
 *          - current {Number}: the 1-based number of the current page
 *          - first {Boolean}: true if the current page is the first page
 *          - last {Boolean}: true if the current page is the last page
 *          - pagesInRange {Array<Number>}: an array of page numbers which size
 *            and behaviour is determined by the 'pagesInRangeSize' and
 *            'scrollingStyle' parameters
 *          - firstPageInRange {Number}: the number of the first page inside
 *            'pagesInRange' parameter
 *          - lastPageInRange {Number}: the number of the last page inside
 *            'pagesInRange' parameter
 *          - pageCount {Number}: the total number of pages
 *          - totalItemCount {Number}: the total number of items that were
 *    ...