All files cr-transclude.directive.js

89.47% Statements 34/38
90.91% Branches 20/22
100% Functions 10/10
88.57% Lines 31/35

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111          2x   3x   5x       9x 9x   9x             12x 12x         2x 2x         24x 16x     8x       10x 16x 16x 10x               10x 10x 10x 10x                       12x                         12x   6x   12x   12x 14x 14x             12x           12x 2x            
/* eslint no-unused-vars: 0 */
/* eslint import/prefer-default-export: 0 */
 
// eslint-disable-next-line import/no-extraneous-dependencies
 
const NODE_TYPE_TEXT = 3;
 
export const crTranscludeDirectiveFactory = (angular) => ([
  '$compile',
  ($compile) => ({
    restrict: 'EAC',
    compile: function crTranscludeCompile(tElement) {
      // Remove and cache any original content to act as a fallback
      const fallbackLinkFn = $compile(tElement.contents());
      tElement.empty();
 
      return function crTranscludePostLink(
        $scope,
        $element,
        $attrs,
        _controller,
        $transclude,
      ) {
        let context = null;
        let childScope = null;
 
        function useFallbackContent() {
          // Since this is the fallback content rather than the transcluded content,
          // we link against the scope of this directive rather than the transcluded scope
          fallbackLinkFn($scope, (clone) => {
            $element.append(clone);
          });
        }
 
        function updateScope(scope, varsHash) {
          if (!scope || !varsHash) {
            return;
          }
 
          angular.extend(scope, varsHash);
        }
 
        function notWhitespace(nodes) {
          for (let i = 0, ii = nodes.length; i < ii; i += 1) {
            const node = nodes[i];
            if (node.nodeType !== NODE_TYPE_TEXT || node.nodeValue.trim()) {
              return true;
            }
          }
 
          return false;
        }
 
        function transcludeCloneAttachFn(clone, transcludedScope) {
          Eif (clone.length && notWhitespace(clone)) {
            $element.append(clone);
            childScope = transcludedScope;
            updateScope(childScope, context);
          } else {
            useFallbackContent();
            /*
             * There is nothing linked against the transcluded scope
             * since no content was available,
             * so it should be safe to clean up the generated scope.
             */
            transcludedScope.$destroy();
          }
        }
 
        Iif (!$transclude) {
          throw new Error(
            'orphan',
            'Illegal use of crTransclude directive in the template! '
            + 'No parent directive that requires a transclusion found. '
            + 'Element: {0}',
          );
        }
 
        /*
         * If the attribute is of the form: `ng-transclude="ng-transclude"`
         * then treat it like the default
         */
        if ($attrs.crTransclude === $attrs.$attr.crTransclude) {
          // eslint-disable-next-line no-param-reassign
          $attrs.crTransclude = '';
        }
        const slotName = $attrs.crTransclude || $attrs.crTranscludeSlot;
 
        $scope.$watch($attrs.context, (newVal, _oldVal) => {
          context = newVal;
          updateScope(childScope, context);
        });
 
        /*
         * If the slot is required and no transclusion content
         * is provided then this call will throw an error
         */
        $transclude(transcludeCloneAttachFn, null, slotName);
 
        /*
         * If the slot is optional and no transclusion content
         * is provided then use the fallback content
         */
        if (slotName && !$transclude.isSlotFilled(slotName)) {
          useFallbackContent();
        }
      };
    },
  }),
]);