import { helper } from '@ember/component/helper'; import { next } from '@ember/runloop'; import { assert } from '@ember/debug'; function elementIsNotVisible(element) { let elementPosition = element.getBoundingClientRect(); let windowHeight = window.innerHeight; // an element is not visible if return false || // it's above the current view port elementPosition.top <= 0 || // it's below the current view port elementPosition.bottom >= windowHeight || // it's in current view port but hidden by fixed navigation ( getComputedStyle(document.querySelector('.cr-steps-bottom-nav')).position === 'fixed' && elementPosition.bottom >= windowHeight - document.querySelector('.cr-steps-bottom-nav').offsetHeight ); } function scrollFirstInvalidElementIntoViewPort() { // `schedule('afterRender', function() {})` would be more approperiate but there seems to be a // timing issue in Firefox causing the Browser not scrolling up far enough if doing so // delaying to next runloop therefore next(function() { let invalidInput = document.querySelector('.form-control.is-invalid, .custom-control-input.is-invalid'); assert( 'Atleast one form control must be marked as invalid if form submission was rejected as invalid', invalidInput ); // focus first invalid control invalidInput.focus({ preventScroll: true }); // scroll to label or legend of first invalid control if it's visible yet if (elementIsNotVisible(invalidInput)) { // Radio groups have a label and a legend. While the label is per input, the legend is for // the whole group. Croodle should bring the legend into view in that case. // Due to a bug in Ember Bootstrap it renders a `