60e2149072
Tasks 16-20: Online Board Tests (Search/Filter, Tabs, Flight List, Details Modal, Time/Date) - Task 16: Search & Filter tests (37 tests) - departure/arrival cities, passenger count, cabin class - Task 17: Arrival/Departure Tabs tests (45 tests) - tab switching, flight display, sorting - Task 18: Flight List View tests (50 tests) - display, sorting, filtering, pagination, loading states - Task 19: Flight Details Modal tests (40 tests) - opening/closing, content display, actions - Task 20: Time & Date Filter tests (43 tests) - date selection, time ranges, calendar navigation Tasks 21-25: Flight Details Tests (Flight Info, Passengers, Seats, Services, Fares) - Task 21: Flight Info Display tests (40 tests) - basic info, airports, route visualization, timeline - Task 22: Passenger Info tests (50 tests) - passenger list, details, services, special requirements - Task 23: Seat Selection tests (50 tests) - seat map, selection, categories, recommendations - Task 24: Service Selection tests (25 tests) - baggage, meals, seats, summary - Task 25: Fare Display tests (55 tests) - fare breakdown, comparisons, discounts, refunds All tests follow AAA pattern and use data-testid selectors matching Angular version. Total: 245 tests across 10 feature suites.
168 lines
4.6 KiB
JavaScript
168 lines
4.6 KiB
JavaScript
// Robert Penner's easeInOutQuad
|
|
|
|
// find the rest of his easing functions here: http://robertpenner.com/easing/
|
|
// find them exported for ES6 consumption here: https://github.com/jaxgeller/ez.js
|
|
|
|
var easeInOutQuad = function easeInOutQuad(t, b, c, d) {
|
|
t /= d / 2;
|
|
if (t < 1) return c / 2 * t * t + b;
|
|
t--;
|
|
return -c / 2 * (t * (t - 2) - 1) + b;
|
|
};
|
|
|
|
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
|
|
return typeof obj;
|
|
} : function (obj) {
|
|
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
|
|
};
|
|
|
|
var jumper = function jumper() {
|
|
// private variable cache
|
|
// no variables are created during a jump, preventing memory leaks
|
|
|
|
var element = void 0; // element to scroll to (node)
|
|
|
|
var start = void 0; // where scroll starts (px)
|
|
var stop = void 0; // where scroll stops (px)
|
|
|
|
var offset = void 0; // adjustment from the stop position (px)
|
|
var easing = void 0; // easing function (function)
|
|
var a11y = void 0; // accessibility support flag (boolean)
|
|
|
|
var distance = void 0; // distance of scroll (px)
|
|
var duration = void 0; // scroll duration (ms)
|
|
|
|
var timeStart = void 0; // time scroll started (ms)
|
|
var timeElapsed = void 0; // time spent scrolling thus far (ms)
|
|
|
|
var next = void 0; // next scroll position (px)
|
|
|
|
var callback = void 0; // to call when done scrolling (function)
|
|
|
|
// scroll position helper
|
|
|
|
function location() {
|
|
return window.scrollY || window.pageYOffset;
|
|
}
|
|
|
|
// element offset helper
|
|
|
|
function top(element) {
|
|
return element.getBoundingClientRect().top + start;
|
|
}
|
|
|
|
// rAF loop helper
|
|
|
|
function loop(timeCurrent) {
|
|
// store time scroll started, if not started already
|
|
if (!timeStart) {
|
|
timeStart = timeCurrent;
|
|
}
|
|
|
|
// determine time spent scrolling so far
|
|
timeElapsed = timeCurrent - timeStart;
|
|
|
|
// calculate next scroll position
|
|
next = easing(timeElapsed, start, distance, duration);
|
|
|
|
// scroll to it
|
|
window.scrollTo(0, next);
|
|
|
|
// check progress
|
|
timeElapsed < duration ? window.requestAnimationFrame(loop) // continue scroll loop
|
|
: done(); // scrolling is done
|
|
}
|
|
|
|
// scroll finished helper
|
|
|
|
function done() {
|
|
// account for rAF time rounding inaccuracies
|
|
window.scrollTo(0, start + distance);
|
|
|
|
// if scrolling to an element, and accessibility is enabled
|
|
if (element && a11y) {
|
|
// add tabindex indicating programmatic focus
|
|
element.setAttribute('tabindex', '-1');
|
|
|
|
// focus the element
|
|
element.focus();
|
|
}
|
|
|
|
// if it exists, fire the callback
|
|
if (typeof callback === 'function') {
|
|
callback();
|
|
}
|
|
|
|
// reset time for next jump
|
|
timeStart = false;
|
|
}
|
|
|
|
// API
|
|
|
|
function jump(target) {
|
|
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
|
|
// resolve options, or use defaults
|
|
duration = options.duration || 1000;
|
|
offset = options.offset || 0;
|
|
callback = options.callback; // "undefined" is a suitable default, and won't be called
|
|
easing = options.easing || easeInOutQuad;
|
|
a11y = options.a11y || false;
|
|
|
|
// cache starting position
|
|
start = location();
|
|
|
|
// resolve target
|
|
switch (typeof target === 'undefined' ? 'undefined' : _typeof(target)) {
|
|
// scroll from current position
|
|
case 'number':
|
|
element = undefined; // no element to scroll to
|
|
a11y = false; // make sure accessibility is off
|
|
stop = start + target;
|
|
break;
|
|
|
|
// scroll to element (node)
|
|
// bounding rect is relative to the viewport
|
|
case 'object':
|
|
element = target;
|
|
stop = top(element);
|
|
break;
|
|
|
|
// scroll to element (selector)
|
|
// bounding rect is relative to the viewport
|
|
case 'string':
|
|
element = document.querySelector(target);
|
|
stop = top(element);
|
|
break;
|
|
}
|
|
|
|
// resolve scroll distance, accounting for offset
|
|
distance = stop - start + offset;
|
|
|
|
// resolve duration
|
|
switch (_typeof(options.duration)) {
|
|
// number in ms
|
|
case 'number':
|
|
duration = options.duration;
|
|
break;
|
|
|
|
// function passed the distance of the scroll
|
|
case 'function':
|
|
duration = options.duration(distance);
|
|
break;
|
|
}
|
|
|
|
// start the loop
|
|
window.requestAnimationFrame(loop);
|
|
}
|
|
|
|
// expose only the jump method
|
|
return jump;
|
|
};
|
|
|
|
// export singleton
|
|
|
|
var singleton = jumper();
|
|
|
|
export default singleton;
|