whole_func_string: function classDirective(name, selector) {
    name = 'ngClass' + name;
    var indexWatchExpression;
  
    return ['$parse', function($parse) {
      return {
        restrict: 'AC',
        link: function(scope, element, attr) {
          var classCounts = element.data('$classCounts');
          var oldModulo = true;
          var oldClassString;
  
          if (!classCounts) {
            // Use createMap() to prevent class assumptions involving property
            // names in Object.prototype
            classCounts = createMap();
            element.data('$classCounts', classCounts);
          }
  
          if (name !== 'ngClass') {
            if (!indexWatchExpression) {
              indexWatchExpression = $parse('$index', function moduloTwo($index) {
                // eslint-disable-next-line no-bitwise
                return $index & 1;
              });
            }
  
            scope.$watch(indexWatchExpression, ngClassIndexWatchAction);
          }
  
          scope.$watch($parse(attr[name], toClassString), ngClassWatchAction);
  
          function addClasses(classString) {
            classString = digestClassCounts(split(classString), 1);
            attr.$addClass(classString);
          }
  
          function removeClasses(classString) {
            classString = digestClassCounts(split(classString), -1);
            attr.$removeClass(classString);
          }
  
          function updateClasses(oldClassString, newClassString) {
            var oldClassArray = split(oldClassString);
            var newClassArray = split(newClassString);
  
            var toRemoveArray = arrayDifference(oldClassArray, newClassArray);
            var toAddArray = arrayDifference(newClassArray, oldClassArray);
  
            var toRemoveString = digestClassCounts(toRemoveArray, -1);
            var toAddString = digestClassCounts(toAddArray, 1);
  
            attr.$addClass(toAddString);
            attr.$removeClass(toRemoveString);
          }
  
          function digestClassCounts(classArray, count) {
            var classesToUpdate = [];
  
            forEach(classArray, function(className) {
              if (count > 0 || classCounts[className]) {
                classCounts[className] = (classCounts[className] || 0) + count;
                if (classCounts[className] === +(count > 0)) {
                  classesToUpdate.push(className);
                }
              }
            });
  
            return classesToUpdate.join(' ');
          }
  
          function ngClassIndexWatchAction(newModulo) {
            // This watch-action should run before the `ngClassWatchAction()`, thus it
            // adds/removes `oldClassString`. If the `ngClass` expression has changed as well, the
            // `ngClassWatchAction()` will update the classes.
            if (newModulo === selector) {
              addClasses(oldClassString);
            } else {
              removeClasses(oldClassString);
            }
  
            oldModulo = newModulo;
          }
  
          function ngClassWatchAction(newClassString) {
            if (oldModulo === selector) {
              updateClasses(oldClassString, newClassString);
            }
  
            oldClassString = newClassString;
          }
        }
      };
    }];
  
    // Helpers
    function arrayDifference(tokens1, tokens2) {
      if (!tokens1 || !tokens1.length) return [];
      if (!tokens2 || !tokens2.length) return tokens1;
  
      var values = [];
  
      outer:
      for (var i = 0; i < tokens1.length; i++) {
        var token = tokens1[i];
        for (var j = 0; j < tokens2.length; j++) {
          if (token === tokens2[j]) continue outer;
        }
        values.push(token);
      }
  
      return values;
    }
  
    function split(classString) {
      return classString && classString.split(' ');
    }
  
    function toClassString(classValue) {
      if (!classValue) return classValue;
  
      var classString = classValue;
  
      if (isArray(classValue)) {
        classString = classValue.map(toClassString).join(' ');
      } else if (isObject(classValue)) {
        classString = Object.keys(classValue).
          filter(function(key) { return classValue[key]; }).
          join(' ');
      } else if (!isString(classValue)) {
        classString = classValue + '';
      }
  
      return classString;
    }
  }
func_code_string: function classDirective(name, selector) {
    name = 'ngClass' + name;
    var indexWatchExpression;
  
    return ['$parse', function($parse) {
      return {
        restrict: 'AC',
        link: function(scope, element, attr) {
          var classCounts = element.data('$classCounts');
          var oldModulo = true;
          var oldClassString;
  
          if (!classCounts) {
            // Use createMap() to prevent class assumptions involving property
            // names in Object.prototype
            classCounts = createMap();
            element.data('$classCounts', classCounts);
          }
  
          if (name !== 'ngClass') {
            if (!indexWatchExpression) {
              indexWatchExpression = $parse('$index', function moduloTwo($index) {
                // eslint-disable-next-line no-bitwise
                return $index & 1;
              });
            }
  
            scope.$watch(indexWatchExpression, ngClassIndexWatchAction);
          }
  
          scope.$watch($parse(attr[name], toClassString), ngClassWatchAction);
  
          function addClasses(classString) {
            classString = digestClassCounts(split(classString), 1);
            attr.$addClass(classString);
          }
  
          function removeClasses(classString) {
            classString = digestClassCounts(split(classString), -1);
            attr.$removeClass(classString);
          }
  
          function updateClasses(oldClassString, newClassString) {
            var oldClassArray = split(oldClassString);
            var newClassArray = split(newClassString);
  
            var toRemoveArray = arrayDifference(oldClassArray, newClassArray);
            var toAddArray = arrayDifference(newClassArray, oldClassArray);
  
            var toRemoveString = digestClassCounts(toRemoveArray, -1);
            var toAddString = digestClassCounts(toAddArray, 1);
  
            attr.$addClass(toAddString);
            attr.$removeClass(toRemoveString);
          }
  
          function digestClassCounts(classArray, count) {
            var classesToUpdate = [];
  
            forEach(classArray, function(className) {
              if (count > 0 || classCounts[className]) {
                classCounts[className] = (classCounts[className] || 0) + count;
                if (classCounts[className] === +(count > 0)) {
                  classesToUpdate.push(className);
                }
              }
            });
  
            return classesToUpdate.join(' ');
          }
  
          function ngClassIndexWatchAction(newModulo) {
            // This watch-action should run before the `ngClassWatchAction()`, thus it
            // adds/removes `oldClassString`. If the `ngClass` expression has changed as well, the
            // `ngClassWatchAction()` will update the classes.
            if (newModulo === selector) {
              addClasses(oldClassString);
            } else {
              removeClasses(oldClassString);
            }
  
            oldModulo = newModulo;
          }
  
          function ngClassWatchAction(newClassString) {
            if (oldModulo === selector) {
              updateClasses(oldClassString, newClassString);
            }
  
            oldClassString = newClassString;
          }
        }
      };
    }];
  
    // Helpers
    function arrayDifference(tokens1, tokens2) {
      if (!tokens1 || !tokens1.length) return [];
      if (!tokens2 || !tokens2.length) return tokens1;
  
      var values = [];
  
      outer:
      for (var i = 0; i < tokens1.length; i++) {
        var token = tokens1[i];
        for (var j = 0; j < tokens2.length; j++) {
          if (token === tokens2[j]) continue outer;
        }
        values.push(token);
      }
  
      return values;
    }
  
    function split(classString) {
      return classString && classString.split(' ');
    }
  
    function toClassString(classValue) {
      if (!classValue) return classValue;
  
      var classString = classValue;
  
      if (isArray(classValue)) {
        classString = classValue.map(toClassString).join(' ');
      } else if (isObject(classValue)) {
        classString = Object.keys(classValue).
          filter(function(key) { return classValue[key]; }).
          join(' ');
      } else if (!isString(classValue)) {
        classString = classValue + '';
      }
  
      return classString;
    }
  }
func_documentation_string: /* exported
  ngClassDirective,
  ngClassEvenDirective,
  ngClassOddDirective