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;
  }
}
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) {
          
          
          classCounts = createMap();
          element.data('$classCounts', classCounts);
        }

        if (name !== 'ngClass') {
          if (!indexWatchExpression) {
            indexWatchExpression = $parse('$index', function moduloTwo($index) {
              
              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) {
          
          
          
          if (newModulo === selector) {
            addClasses(oldClassString);
          } else {
            removeClasses(oldClassString);
          }

          oldModulo = newModulo;
        }

        function ngClassWatchAction(newClassString) {
          if (oldModulo === selector) {
            updateClasses(oldClassString, newClassString);
          }

          oldClassString = newClassString;
        }
      }
    };
  }];

  
  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;
  }
}
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 ; } }
/* exported
ngClassDirective,
ngClassEvenDirective,
ngClassOddDirective
/ * exported ngClassDirective ngClassEvenDirective ngClassOddDirective