docs: function($anchorScroll, $http, $location, $route, $sce, $scope) {
    this.$http = $http;
    this.$route = $route;
    this.$scope = $scope;
  
    this.loadTableOfContents();
  
    $scope.items = [];
    $scope.isMenuVisible = false;
    var defaultItem = {
      title: 'Protractor API Docs',
      description: 'Welcome to the Protractor API docs page. These pages ' +
      'contain the Protractor reference materials.'
    };
    $scope.currentItem = defaultItem;
  
    // Watch for location changes to show the correct item.
    $scope.$on('$locationChangeSuccess', function() {
      // Not going to api? ignore event.
      if (!$location.url().match(/^\/api/)) {
        return;
      }
  
      var view = $route.current.params.view,
          item = _.findWhere($scope.items, {name: view});
  
      if (view && item) {
        $scope.showElement(item);
      } else {
        // No view? Show default item.
        $scope.currentItem = defaultItem;
      }
    });
  
    $scope.toggleMenuLabel = function() {
      return $scope.isMenuVisible ? 'Hide list' : 'Show list';
    };
  
    $scope.toggleMenu = function() {
      $scope.isMenuVisible = !$scope.isMenuVisible;
    };
  
    $scope.showElement = function(item) {
      // Update the query string with the view name.
      $location.search('view', item.name);
      $scope.currentItem = item;
  
      // Scroll to the top.
      $anchorScroll();
    };
  
    /**
     * Use the $sce service to trust the html rendered in the view.
     * @param html
     */
    $scope.trust = function(html) {
      if (!html) {
        return;
      }
  
      // Does it come with a type? Types come escaped as [description](theType).
      var match;
      while (match = html.match(/(\[(.*?)\]\((.*?)\))/)) {
        var link = '<a href="' +
            (match[3].match(/^https?:\/\//) ? '' : '#/api?view=') + match[3] +
            '">' + match[2] + '</a>';
        html = html.replace(match[1], link);
      }
  
      return $sce.trustAsHtml(html);
    };
  }