function collectDirectives(node, directives, attrs, maxPriority, ignoreDirective) {
      var nodeType = node.nodeType,
          attrsMap = attrs.$attr,
          match,
          nodeName,
          className;

      switch (nodeType) {
        case NODE_TYPE_ELEMENT: /* Element */

          nodeName = nodeName_(node);

          // use the node name: <directive>
          addDirective(directives,
              directiveNormalize(nodeName), 'E', maxPriority, ignoreDirective);

          // iterate over the attributes
          for (var attr, name, nName, value, ngPrefixMatch, nAttrs = node.attributes,
                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {
            var attrStartName = false;
            var attrEndName = false;

            var isNgAttr = false, isNgProp = false, isNgEvent = false;
            var multiElementMatch;

            attr = nAttrs[j];
            name = attr.name;
            value = attr.value;

            nName = directiveNormalize(name.toLowerCase());

            // Support ng-attr-*, ng-prop-* and ng-on-*
            if ((ngPrefixMatch = nName.match(NG_PREFIX_BINDING))) {
              isNgAttr = ngPrefixMatch[1] === 'Attr';
              isNgProp = ngPrefixMatch[1] === 'Prop';
              isNgEvent = ngPrefixMatch[1] === 'On';

              // Normalize the non-prefixed name
              name = name.replace(PREFIX_REGEXP, '')
                .toLowerCase()
                .substr(4 + ngPrefixMatch[1].length).replace(/_(.)/g, function(match, letter) {
                  return letter.toUpperCase();
                });

            // Support *-start / *-end multi element directives
            } else if ((multiElementMatch = nName.match(MULTI_ELEMENT_DIR_RE)) && directiveIsMultiElement(multiElementMatch[1])) {
              attrStartName = name;
              attrEndName = name.substr(0, name.length - 5) + 'end';
              name = name.substr(0, name.length - 6);
            }

            if (isNgProp || isNgEvent) {
              attrs[nName] = value;
              attrsMap[nName] = attr.name;

              if (isNgProp) {
                addPropertyDirective(node, directives, nName, name);
              } else {
                addEventDirective(directives, nName, name);
              }
            } else {
              // Update nName for cases where a prefix was removed
              // NOTE: the .toLowerCase() is unnecessary and causes https://github.com/angular/angular.js/issues/16624 for ng-attr-*
              nName = directiveNormalize(name.toLowerCase());
              attrsMap[nName] = name;

              if (isNgAttr || !attrs.hasOwnProperty(nName)) {
                attrs[nName] = value;
                if (getBooleanAttrName(node, nName)) {
                  attrs[nName] = true; // presence means true
                }
              }

              addAttrInterpolateDirective(node, directives, value, nName, isNgAttr);
              addDirective(directives, nName, 'A', maxPriority, ignoreDirective, attrStartName,
                            attrEndName);
            }
          }

          if (nodeName === 'input' && node.getAttribute('type') === 'hidden') {
            // Hidden input elements can have strange behaviour when navigating back to the page
            // This tells the browser not to try to cache and reinstate previous values
            node.setAttribute('autocomplete', 'off');
          }

          // use class as directive
          if (!cssClassDirectivesEnabled) break;
          className = node.className;
          if (isObject(className)) {
              // Maybe SVGAnimatedString
              className = className.animVal;
          }
          if (isString(className) && className !== '') {
            while ((match = CLASS_DIRECTIVE_REGEXP.exec(className))) {
              nName = directiveNormalize(match[2]);
              if (addDirective(directives, nName, 'C', maxPriority, ignoreDirective)) {
                attrs[nName] = trim(match[3]);
              }
              className = className.substr(match.index + match[0].length);
            }
          }
          break;
        case NODE_TYPE_TEXT: /* Text Node */
          addTextInterpolateDirective(directives, node.nodeValue);
          break;
        case NODE_TYPE_COMMENT: /* Comment */
          if (!commentDirectivesEnabled) break;
          collectCommentDirectives(node, directives, attrs, maxPriority, ignoreDirective);
          break;
      }

      directives.sort(byPriority);
      return directives;
    }
Looks for directives on the given node and adds them to the directive collection which is
sorted.

@param node Node to search.
@param directives An array to which the directives are added to. This array is sorted before
       the function returns.
@param attrs The shared attrs object which is used to populate the normalized attributes.
@param {number=} maxPriority Max directive priority.