text: 'use strict';
  
  /**
   * @ngdoc directive
   * @name ngSwitch
   * @restrict EA
   *
   * @description
   * The `ngSwitch` directive is used to conditionally swap DOM structure on your template based on a scope expression.
   * Elements within `ngSwitch` but without `ngSwitchWhen` or `ngSwitchDefault` directives will be preserved at the location
   * as specified in the template.
   *
   * The directive itself works similar to ngInclude, however, instead of downloading template code (or loading it
   * from the template cache), `ngSwitch` simply chooses one of the nested elements and makes it visible based on which element
   * matches the value obtained from the evaluated expression. In other words, you define a container element
   * (where you place the directive), place an expression on the **`on="..."` attribute**
   * (or the **`ng-switch="..."` attribute**), define any inner elements inside of the directive and place
   * a when attribute per element. The when attribute is used to inform ngSwitch which element to display when the on
   * expression is evaluated. If a matching expression is not found via a when attribute then an element with the default
   * attribute is displayed.
   *
   * <div class="alert alert-info">
   * Be aware that the attribute values to match against cannot be expressions. They are interpreted
   * as literal string values to match against.
   * For example, **`ng-switch-when="someVal"`** will match against the string `"someVal"` not against the
   * value of the expression `$scope.someVal`.
   * </div>
  
   * @animations
   * enter - happens after the ngSwitch contents change and the matched child element is placed inside the container
   * leave - happens just after the ngSwitch contents change and just before the former contents are removed from the DOM
   *
   * @usage
   *
   * ```
   * <ANY ng-switch="expression">
   *   <ANY ng-switch-when="matchValue1">...</ANY>
   *   <ANY ng-switch-when="matchValue2">...</ANY>
   *   <ANY ng-switch-default>...</ANY>
   * </ANY>
   * ```
   *
   *
   * @scope
   * @priority 800
   * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.
   * On child elements add:
   *
   * * `ngSwitchWhen`: the case statement to match against. If match then this
   *   case will be displayed. If the same match appears multiple times, all the
   *   elements will be displayed.
   * * `ngSwitchDefault`: the default case when no other case match. If there
   *   are multiple default cases, all of them will be displayed when no other
   *   case match.
   *
   *
   * @example
    <example module="ngAnimate" deps="angular-animate.js" animations="true">
      <file name="index.html">
        <div ng-controller="Ctrl">
          <select ng-model="selection" ng-options="item for item in items">
          </select>
          <tt>selection={{selection}}</tt>
          <hr/>
          <div class="animate-switch-container"
            ng-switch on="selection">
              <div class="animate-switch" ng-switch-when="settings">Settings Div</div>
              <div class="animate-switch" ng-switch-when="home">Home Span</div>
              <div class="animate-switch" ng-switch-default>default</div>
          </div>
        </div>
      </file>
      <file name="script.js">
        function Ctrl($scope) {
          $scope.items = ['settings', 'home', 'other'];
          $scope.selection = $scope.items[0];
        }
      </file>
      <file name="animations.css">
        .animate-switch-container {
          position:relative;
          background:white;
          border:1px solid black;
          height:40px;
          overflow:hidden;
        }
  
        .animate-switch {
          padding:10px;
        }
  
        .animate-switch.ng-animate {
          -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
          transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
  
          position:absolute;
          top:0;
          left:0;
          right:0;
          bottom:0;
        }
  
        .animate-switch.ng-leave.ng-leave-active,
        .animate-switch.ng-enter {
          top:-50px;
        }
        .animate-switch.ng-leave,
        .animate-switch.ng-enter.ng-enter-active {
          top:0;
        }
      </file>
      <file name="protractor.js" type="protractor">
        var switchElem = element(by.css('[ng-switch]'));
        var select = element(by.model('selection'));
  
        it('should start in settings', function() {
          expect(switchElem.getText()).toMatch(/Settings Div/);
        });
        it('should change to home', function() {
          select.element.all(by.css('option')).get(1).click();
          expect(switchElem.getText()).toMatch(/Home Span/);
        });
        it('should select default', function() {
          select.element.all(by.css('option')).get(2).click();
          expect(switchElem.getText()).toMatch(/default/);
        });
      </file>
    </example>
   */
  var ngSwitchDirective = ['$animate', function($animate) {
    return {
      restrict: 'EA',
      require: 'ngSwitch',
  
      // asks for $scope to fool the BC controller module
      controller: ['$scope', function ngSwitchController() {
       this.cases = {};
      }],
      link: function(scope, element, attr, ngSwitchController) {
        var watchExpr = attr.ngSwitch || attr.on,
            selectedTranscludes = [],
            selectedElements = [],
            previousElements = [],
            selectedScopes = [];
  
        scope.$watch(watchExpr, function ngSwitchWatchAction(value) {
          var i, ii;
          for (i = 0, ii = previousElements.length; i < ii; ++i) {
            previousElements[i].remove();
          }
          previousElements.length = 0;
  
          for (i = 0, ii = selectedScopes.length; i < ii; ++i) {
            var selected = selectedElements[i];
            selectedScopes[i].$destroy();
            previousElements[i] = selected;
            $animate.leave(selected, function() {
              previousElements.splice(i, 1);
            });
          }
  
          selectedElements.length = 0;
          selectedScopes.length = 0;
  
          if ((selectedTranscludes = ngSwitchController.cases['!' + value] || ngSwitchController.cases['?'])) {
            scope.$eval(attr.change);
            forEach(selectedTranscludes, function(selectedTransclude) {
              var selectedScope = scope.$new();
              selectedScopes.push(selectedScope);
              selectedTransclude.transclude(selectedScope, function(caseElement) {
                var anchor = selectedTransclude.element;
  
                selectedElements.push(caseElement);
                $animate.enter(caseElement, anchor.parent(), anchor);
              });
            });
          }
        });
      }
    };
  }];
  
  var ngSwitchWhenDirective = ngDirective({
    transclude: 'element',
    priority: 800,
    require: '^ngSwitch',
    link: function(scope, element, attrs, ctrl, $transclude) {
      ctrl.cases['!' + attrs.ngSwitchWhen] = (ctrl.cases['!' + attrs.ngSwitchWhen] || []);
      ctrl.cases['!' + attrs.ngSwitchWhen].push({ transclude: $transclude, element: element });
    }
  });
  
  var ngSwitchDefaultDirective = ngDirective({
    transclude: 'element',
    priority: 800,
    require: '^ngSwitch',
    link: function(scope, element, attr, ctrl, $transclude) {
      ctrl.cases['?'] = (ctrl.cases['?'] || []);
      ctrl.cases['?'].push({ transclude: $transclude, element: element });
     }
  });
  