| 1 | var jumpToCode = (function init() {
|
|---|
| 2 | // Classes of code we would like to highlight in the file view
|
|---|
| 3 | var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no'];
|
|---|
| 4 |
|
|---|
| 5 | // Elements to highlight in the file listing view
|
|---|
| 6 | var fileListingElements = ['td.pct.low'];
|
|---|
| 7 |
|
|---|
| 8 | // We don't want to select elements that are direct descendants of another match
|
|---|
| 9 | var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > `
|
|---|
| 10 |
|
|---|
| 11 | // Selector that finds elements on the page to which we can jump
|
|---|
| 12 | var selector =
|
|---|
| 13 | fileListingElements.join(', ') +
|
|---|
| 14 | ', ' +
|
|---|
| 15 | notSelector +
|
|---|
| 16 | missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b`
|
|---|
| 17 |
|
|---|
| 18 | // The NodeList of matching elements
|
|---|
| 19 | var missingCoverageElements = document.querySelectorAll(selector);
|
|---|
| 20 |
|
|---|
| 21 | var currentIndex;
|
|---|
| 22 |
|
|---|
| 23 | function toggleClass(index) {
|
|---|
| 24 | missingCoverageElements
|
|---|
| 25 | .item(currentIndex)
|
|---|
| 26 | .classList.remove('highlighted');
|
|---|
| 27 | missingCoverageElements.item(index).classList.add('highlighted');
|
|---|
| 28 | }
|
|---|
| 29 |
|
|---|
| 30 | function makeCurrent(index) {
|
|---|
| 31 | toggleClass(index);
|
|---|
| 32 | currentIndex = index;
|
|---|
| 33 | missingCoverageElements.item(index).scrollIntoView({
|
|---|
| 34 | behavior: 'smooth',
|
|---|
| 35 | block: 'center',
|
|---|
| 36 | inline: 'center'
|
|---|
| 37 | });
|
|---|
| 38 | }
|
|---|
| 39 |
|
|---|
| 40 | function goToPrevious() {
|
|---|
| 41 | var nextIndex = 0;
|
|---|
| 42 | if (typeof currentIndex !== 'number' || currentIndex === 0) {
|
|---|
| 43 | nextIndex = missingCoverageElements.length - 1;
|
|---|
| 44 | } else if (missingCoverageElements.length > 1) {
|
|---|
| 45 | nextIndex = currentIndex - 1;
|
|---|
| 46 | }
|
|---|
| 47 |
|
|---|
| 48 | makeCurrent(nextIndex);
|
|---|
| 49 | }
|
|---|
| 50 |
|
|---|
| 51 | function goToNext() {
|
|---|
| 52 | var nextIndex = 0;
|
|---|
| 53 |
|
|---|
| 54 | if (
|
|---|
| 55 | typeof currentIndex === 'number' &&
|
|---|
| 56 | currentIndex < missingCoverageElements.length - 1
|
|---|
| 57 | ) {
|
|---|
| 58 | nextIndex = currentIndex + 1;
|
|---|
| 59 | }
|
|---|
| 60 |
|
|---|
| 61 | makeCurrent(nextIndex);
|
|---|
| 62 | }
|
|---|
| 63 |
|
|---|
| 64 | return function jump(event) {
|
|---|
| 65 | if (
|
|---|
| 66 | document.getElementById('fileSearch') === document.activeElement &&
|
|---|
| 67 | document.activeElement != null
|
|---|
| 68 | ) {
|
|---|
| 69 | // if we're currently focused on the search input, we don't want to navigate
|
|---|
| 70 | return;
|
|---|
| 71 | }
|
|---|
| 72 |
|
|---|
| 73 | switch (event.which) {
|
|---|
| 74 | case 78: // n
|
|---|
| 75 | case 74: // j
|
|---|
| 76 | goToNext();
|
|---|
| 77 | break;
|
|---|
| 78 | case 66: // b
|
|---|
| 79 | case 75: // k
|
|---|
| 80 | case 80: // p
|
|---|
| 81 | goToPrevious();
|
|---|
| 82 | break;
|
|---|
| 83 | }
|
|---|
| 84 | };
|
|---|
| 85 | })();
|
|---|
| 86 | window.addEventListener('keydown', jumpToCode);
|
|---|