Skip to content

Commit ad3b8d7

Browse files
authored
Merge pull request #140 from mitre-attack/feature/#93-matrix-scroll-indicators
Feature/#93 matrix scroll indicators
2 parents 186eeba + 591f2c8 commit ad3b8d7

File tree

6 files changed

+102
-54
lines changed

6 files changed

+102
-54
lines changed

CHANGELOG.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@
3434
# Sub-techniques Beta
3535
## ATT&CK Website version 2.1
3636
### Fixes
37-
- added internet explorer for sub-techniques matrix. Improved behavior of sub-techniques matrix in Edge browser.
37+
- added internet explorer for sub-techniques matrix. Improved behavior of sub-techniques matrix in Edge browser. See issue [#114](https://github.com/mitre-attack/attack-website/issues/114).
38+
- added horizontal scroll indicators to matrices so that it's easier to tell when there's more to the left or right. See issue [#93](https://github.com/mitre-attack/attack-website/issues/93).
3839

3940
## ATT&CK Website version 2.0
4041
### New Features

attack-theme/static/scripts/matrix.js

+20-1
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,23 @@ function show_flat_matrix() {
5151

5252
$(".matrix-type.flat").removeClass("d-none");
5353
$(".matrix-type.side").addClass("d-none");
54-
}
54+
}
55+
56+
function computeScrollMarkers() {
57+
let beginning = $(this).scrollLeft() == 0; //is the scroll at the left side?
58+
//is the scroll at the right side?
59+
let scrollPosition = ($(this).scrollLeft() + $(this).width()); //the right side of the scroll viewport
60+
let scrollEnd = $(this).find(".matrix").width(); // the right side of the scrollABLE area
61+
let end = Math.abs(scrollPosition - scrollEnd) < 5; //are they roughly the same?
62+
let leftIndicator = $(this).parent().find(".scroll-indicator.left")
63+
let rightIndicator = $(this).parent().find(".scroll-indicator.right")
64+
if (!beginning) leftIndicator.addClass("show");
65+
else leftIndicator.removeClass("show");
66+
if (!end) rightIndicator.addClass("show");
67+
else rightIndicator.removeClass("show");
68+
}
69+
70+
$(".matrix-scroll-box").scroll(computeScrollMarkers); //respond to scrolling in matrix scroll boxes
71+
function initScrollMarkers() { $(".matrix-scroll-box").each(computeScrollMarkers); }
72+
initScrollMarkers(); //initial state for scroll markers
73+
$(window).resize(initScrollMarkers); //respond to page resize

attack-theme/static/style/_matrix.scss

+34
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,47 @@
1313
margin-bottom: 1rem;
1414
padding-bottom: 0.5rem;
1515
}
16+
.scroll-indicator-group {
17+
white-space: nowrap;
18+
display: flex;
19+
.matrix-scroll-box {
20+
flex-grow: 1;
21+
display: inline-block;
22+
}
23+
.scroll-indicator {
24+
width: 0px;
25+
display: inline-block;
26+
position: relative;
27+
.cover {
28+
width: 50px;
29+
height: 100%;
30+
position: absolute;
31+
pointer-events: none; // doesn't prevent usage of things under the cover
32+
}
33+
//safari doesn't really work with transparent in gradients, but making something almost transparent works
34+
$safari-transparent: rgba(255,255,255,0.001);
35+
&.right {
36+
.cover { right: 0; }
37+
&.show .cover {
38+
background: linear-gradient(to right, $safari-transparent, color(body));
39+
}
40+
}
41+
&.left {
42+
.cover { left: 0; }
43+
&.show .cover {
44+
background: linear-gradient(to left, $safari-transparent, color(body));
45+
}
46+
}
47+
}
48+
}
1649
}
1750

1851

1952

2053
$sizeunit: 14px;
2154

2255
.matrix {
56+
white-space: normal;
2357
line-height: $sizeunit;
2458
&.side {
2559
// thead {

attack-theme/templates/general/attack-index.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ <h2>{{parsed.matrix_name}}</h2>
5757

5858
{% block scripts %}
5959
<!--SCRIPTS-->
60-
<script src="/theme/scripts/matrix.js"></script>
6160
{{ super() }}
61+
<script src="/theme/scripts/matrix.js"></script>
6262
<script src="/theme/scripts/bootstrap-tourist.js"></script>
6363
<script src="/theme/scripts/tour/tour-introduction.js"></script>
6464
{% endblock %}

attack-theme/templates/macros/matrix.html

+44-50
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,10 @@
11
<!--
22
create a new matrix supporting subtechniques and cell colors.
3-
Params: tactics: Tactic[]
4-
5-
Tactic object format: {
6-
id: uid of tactic
7-
name: display name of tactic
8-
url: url of the tactic page
9-
techniques: Technique[]
10-
}
11-
12-
Technique object format: {
13-
id: uid of technique
14-
name: technique name
15-
url: url of the technique page
16-
color: optional, the color with which to style the technique
17-
subtechniques: Technique[] or []
18-
}
19-
3+
Params:
4+
matrices: Matrix[] of matrices to display on the page
5+
has_subtechniques: boolean, true if the matrix has subtechniques in it
6+
tour_technique: the technique to use in the sub-techniques tour
7+
isIndex: boolean, true if this matrix is going on the index page
208
-->
219

2210
{% macro matrices(matrices, has_subtechniques, tour_technique, isIndex) %}
@@ -52,53 +40,59 @@
5240
<div id="layouts-content">
5341
<div class="matrix-type side">
5442
{% for matrix in matrices %}
55-
<div class="matrix-container p-3">
56-
{% if matrices | length > 1%}
57-
<h3 class="text-center matrix-title">{{matrix.name}}</h3>
58-
{% endif %}
59-
<div class="overflow-x-auto pb-3">
60-
{{ matrix_side(matrix.tactics, tour_technique) }}
61-
</div>
62-
{% if not isIndex %}
63-
<div class="timestamp deemphasis text-center pt-3">Last modified: {{matrix.timestamp}}</div>
64-
{% endif %}
65-
</div>
43+
{{ matrix_box('side', matrix, matrices | length, tour_technique, isIndex) }}
6644
{% endfor %}
6745
</div>
6846
<div class="matrix-type flat d-none">
6947
{% for matrix in matrices %}
70-
<div class="matrix-container p-3">
71-
{% if matrices | length > 1%}
72-
<h3 class="text-center matrix-title">{{matrix.name}}</h3>
73-
{% endif %}
74-
<div class="overflow-x-auto pb-3">
75-
{{ matrix_flat(matrix.tactics, tour_technique) }}
76-
</div>
77-
{% if not isIndex %}
78-
<div class="timestamp deemphasis text-center pt-3">Last modified: {{matrix.timestamp}}</div>
79-
{% endif %}
80-
</div>
48+
{{ matrix_box('flat', matrix, matrices | length, tour_technique, isIndex) }}
8149
{% endfor %}
8250
</div>
8351
</div>
8452
{% else %}
8553
{% for matrix in matrices %}
86-
<div class="matrix-container p-3">
87-
{% if matrices | length > 1%}
88-
<h3 class="text-center matrix-title">{{matrix.name}}</h3>
89-
{% endif %}
90-
<div class="overflow-x-auto pb-3">
91-
{{ matrix_side(matrix.tactics, tour_technique) }}
92-
</div>
93-
{% if not isIndex %}
94-
<div class="timestamp deemphasis text-center pt-3">Last modified: {{matrix.timestamp}}</div>
95-
{% endif %}
96-
</div>
54+
{{ matrix_box('side', matrix, matrices | length, tour_technique, isIndex) }}
9755
{% endfor %}
9856
{% endif %}
9957
</div>
10058
{% endmacro %}
10159

60+
<!--
61+
matrix container helper
62+
creates a matrix container with timestamp, overflow markers, and title
63+
params:
64+
whichmatrix: "flat" or "side"
65+
matrix: the matrix object to display
66+
num_matrices: number, the number of matrices on this page. Used to determine if title is necessary
67+
tour_technique: the technique to use in the matrix tour
68+
isIndex: boolean, is this matrix being displayed on the index page?
69+
-->
70+
{% macro matrix_box(whichmatrix, matrix, num_matrices, tour_technique, isIndex) %}
71+
<div class="matrix-container p-3">
72+
{% if num_matrices >1 %}
73+
<h3 class="text-center matrix-title">{{matrix.name}}</h3>
74+
{% endif %}
75+
<div class="scroll-indicator-group">
76+
<div class="scroll-indicator left">
77+
<div class="cover"></div>
78+
</div>
79+
<div class="overflow-x-auto matrix-scroll-box pb-3">
80+
{% if whichmatrix == 'side' %}
81+
{{ matrix_side(matrix.tactics, tour_technique) }}
82+
{% elif whichmatrix == 'flat' %}
83+
{{ matrix_flat(matrix.tactics, tour_technique) }}
84+
{% endif %}
85+
</div>
86+
<div class="scroll-indicator right">
87+
<div class="cover"></div>
88+
</div>
89+
</div>
90+
{% if not isIndex %}
91+
<div class="timestamp deemphasis text-center pt-3">Last modified: {{matrix.timestamp}}</div>
92+
{% endif %}
93+
</div>
94+
{% endmacro %}
95+
10296

10397
{% macro matrix_flat(tactics, tour) %}
10498
<table class="matrix flat">

attack-theme/templates/matrices/matrix.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ <h1>{{parsed.name}} {{matrix_plural}}</h1>
7070

7171
{% block scripts %}
7272
<!--SCRIPTS-->
73-
<script src="/theme/scripts/matrix.js"></script>
7473
{{ super() }}
74+
<script src="/theme/scripts/matrix.js"></script>
7575
<script src="/theme/scripts/navigation.js"></script>
7676
<script src="/theme/scripts/bootstrap-tourist.js"></script>
7777
<script src="/theme/scripts/tour/tour-matrices.js"></script>

0 commit comments

Comments
 (0)