This fn returns false if any of the following is true:
a) animations on any parent element are disabled, and animations on the element aren't explicitly allowed
b) a parent element has an ongoing structural animation, and animateChildren is false
c) the element is not a child of the body
d) the element is not a child of the $rootElement
function areAnimationsAllowed(node, parentNode, event) {
      var bodyNode = $document[0].body;
      var rootNode = getDomNode($rootElement);

      var bodyNodeDetected = (node === bodyNode) || node.nodeName === 'HTML';
      var rootNodeDetected = (node === rootNode);
      var parentAnimationDetected = false;
      var elementDisabled = disabledElementsLookup.get(node);
      var animateChildren;

      var parentHost = jqLite.data(node, NG_ANIMATE_PIN_DATA);
      if (parentHost) {
        parentNode = getDomNode(parentHost);
      }

      while (parentNode) {
        if (!rootNodeDetected) {
          // AngularJS doesn't want to attempt to animate elements outside of the application
          // therefore we need to ensure that the rootElement is an ancestor of the current element
          rootNodeDetected = (parentNode === rootNode);
        }

        if (parentNode.nodeType !== ELEMENT_NODE) {
          // no point in inspecting the #document element
          break;
        }

        var details = activeAnimationsLookup.get(parentNode) || {};
        // either an enter, leave or move animation will commence
        // therefore we can't allow any animations to take place
        // but if a parent animation is class-based then that's ok
        if (!parentAnimationDetected) {
          var parentNodeDisabled = disabledElementsLookup.get(parentNode);

          if (parentNodeDisabled === true && elementDisabled !== false) {
            // disable animations if the user hasn't explicitly enabled animations on the
            // current element
            elementDisabled = true;
            // element is disabled via parent element, no need to check anything else
            break;
          } else if (parentNodeDisabled === false) {
            elementDisabled = false;
          }
          parentAnimationDetected = details.structural;
        }

        if (isUndefined(animateChildren) || animateChildren === true) {
          var value = jqLite.data(parentNode, NG_ANIMATE_CHILDREN_DATA);
          if (isDefined(value)) {
            animateChildren = value;
          }
        }

        // there is no need to continue traversing at this point
        if (parentAnimationDetected && animateChildren === false) break;

        if (!bodyNodeDetected) {
          // we also need to ensure that the element is or will be a part of the body element
          // otherwise it is pointless to even issue an animation to be rendered
          bodyNodeDetected = (parentNode === bodyNode);
        }

        if (bodyNodeDetected && rootNodeDetected) {
          // If both body and root have been found, any other checks are pointless,
          // as no animation data should live outside the application
          break;
        }

        if (!rootNodeDetected) {
          // If `rootNode` is not detected, check if `parentNode` is pinned to another element
          parentHost = jqLite.data(parentNode, NG_ANIMATE_PIN_DATA);
          if (parentHost) {
            // The pin target element becomes the next parent element
            parentNode = getDomNode(parentHost);
            continue;
          }
        }

        parentNode = parentNode.parentNode;
      }

      var allowAnimation = (!parentAnimationDetected || animateChildren) && elementDisabled !== true;
      return allowAnimation && rootNodeDetected && bodyNodeDetected;
    }