Skip to content

Commit 4241c3c

Browse files
authored
XWIKI-22581: FocusCatcher input has no label (#3577)
* Replaced the FocusCatcher artificial input with a semantically better span. * Updated the style of the gallery to use css grid instead of hackish solutions all around. * Improved accessibility by changing the div interactive controllers with buttons. * Fixed the full screen display vertical overflow issue.
1 parent b1e5e4f commit 4241c3c

File tree

3 files changed

+52
-51
lines changed

3 files changed

+52
-51
lines changed

xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/ApplicationResources.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1399,6 +1399,7 @@ core.widgets.gallery.previousImage=Show previous image
13991399
core.widgets.gallery.nextImage=Show next image
14001400
core.widgets.gallery.maximize=Maximize
14011401
core.widgets.gallery.minimize=Minimize
1402+
core.widgets.gallery.index.description=Press the right and left arrow keys to quickly navigate through the images.
14021403

14031404
core.widgets.suggest.noResults=No results!
14041405
core.widgets.suggest.showResults=Go to search page\u2026

xwiki-platform-core/xwiki-platform-web/xwiki-platform-web-war/src/main/webapp/resources/uicomponents/widgets/gallery/gallery.css

Lines changed: 35 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
background-color: black;
33
max-width: 100%;
44
padding: 10px;
5+
border-radius: 7px; /* Same value as @border-radius-base from Flamingo. */
56
/* Position relative is required because some of the inner elements have position absolute and the gallery container
67
must be their offset parent. */
78
position: relative;
@@ -10,13 +11,9 @@
1011
/* Those width/height values can be overridden by the inline styling added with the macro parameters */
1112
width: 620px;
1213
height: 349px;
13-
}
14-
15-
.xGallery:before {
16-
content: "";
17-
display: inline-block;
18-
height: 100%;
19-
vertical-align: middle;
14+
display: grid;
15+
grid-template-columns: 1fr 10fr 1fr;
16+
grid-template-rows: 1fr 10fr 1fr;
2017
}
2118

2219
.xGallery.maximized {
@@ -26,83 +23,82 @@
2623
top: 0;
2724
z-index: 1001;
2825
width: 100% !important;
26+
border-radius: 0;
2927
}
3028

3129
.xGallery .currentImage {
32-
max-height: 100%;
30+
grid-area: 2 / 2 / 3 / 3;
31+
align-self: center;
32+
justify-self: center;
33+
object-fit: scale-down;
3334
max-width: 100%;
34-
padding: 22px;
35-
vertical-align: middle;
35+
max-height: 100%;
36+
}
37+
38+
/* Transparent buttons that should fill the space they've been given on the grid */
39+
.xGallery .previous, .xGallery .next,
40+
.xGallery .maximize, .xGallery .minimize {
41+
background-color: transparent;
42+
border-color: transparent;
43+
width: 100%;
44+
height: 100%;
3645
}
3746

3847
.xGallery .previous, .xGallery .next {
3948
color: #A0A0A0;
40-
cursor: pointer;
4149
font-family: courier,monospace;
4250
font-size: 32px;
4351
font-weight: 100;
44-
height: 124px;
45-
line-height: 124px;
46-
margin-top: -64px;
47-
position: absolute;
4852
text-align: center;
49-
top: 50%;
50-
width: 32px;
5153
}
5254

5355
.xGallery .previous:hover, .xGallery .next:hover {
5456
color: white;
5557
}
5658

5759
.xGallery .previous {
58-
left: 0;
60+
grid-area: 2 / 1 / 3 / 2;
5961
}
6062

6163
.xGallery .next {
62-
right: 0;
64+
grid-area: 2 / 3 / 3 / 4;
6365
}
6466

6567
.xGallery .index {
66-
bottom: 10px;
6768
color: #C0C0C0;
6869
font-family: sans-serif;
6970
font-size: smaller;
70-
left: 10px;
7171
line-height: 1;
72-
position: absolute;
72+
grid-area: 3 / 1 / 4 / 2;
73+
align-self: end;
7374
}
7475

7576
.xGallery .loading {
7677
background-image: url('loading.gif') !important;
7778
}
7879

79-
.xGallery .focusCatcher {
80-
background-color: black;
81-
border: 0 none;
82-
color: black;
83-
height: 1px;
84-
left: 0;
85-
overflow: hidden;
86-
position: absolute;
87-
top: 0;
88-
width: 1px;
89-
z-index: -1;
90-
}
91-
9280
.xGallery .maximize, .xGallery .minimize {
93-
cursor: pointer;
9481
height: 16px;
9582
opacity: .5;
96-
position: absolute;
97-
right: 10px;
98-
top: 10px;
9983
width: 16px;
84+
grid-area: 1 / 3 / 2 / 4;
85+
justify-self: end;
10086
}
10187

10288
.xGallery .maximize:hover, .xGallery .minimize:hover {
10389
opacity: 1;
10490
}
10591

92+
/* Elements on the left of the grid are left aligned */
93+
.xGallery .index, .xGallery .previous {
94+
text-align: start;
95+
}
96+
97+
/* Elements on the right of the grid are right aligned */
98+
.xGallery .maximize, .xGallery .minimize, .xGallery .next {
99+
text-align: end;
100+
}
101+
106102
.xGallery .maximize {
107103
background: transparent url('maximize.gif') no-repeat scroll center;
108104
}

xwiki-platform-core/xwiki-platform-web/xwiki-platform-web-war/src/main/webapp/resources/uicomponents/widgets/gallery/gallery.js

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,25 +22,29 @@ var XWiki = (function (XWiki) {
2222
XWiki.Gallery = Class.create({
2323
initialize : function(container) {
2424
this.images = this._collectImages(container);
25-
2625
this.container = container.update(
27-
'<input type="text" tabindex="-1" class="focusCatcher"/>' +
26+
'<button class="maximize" title="${escapetool.xml($services.localization.render("core.widgets.gallery.maximize"))}"></button>' +
27+
'<button class="previous" title="${escapetool.xml($services.localization.render("core.widgets.gallery.previousImage"))}">&lt;</button>' +
2828
'<img class="currentImage" alt="${escapetool.xml($services.localization.render("core.widgets.gallery.currentImage"))}"/>' +
29-
'<div class="previous" title="${escapetool.xml($services.localization.render("core.widgets.gallery.previousImage"))}">&lt;</div>' +
30-
'<div class="next" title="${escapetool.xml($services.localization.render("core.widgets.gallery.nextImage"))}">&gt;</div>' +
31-
'<div class="index">0 / 0</div>' +
32-
'<div class="maximize" title="${escapetool.xml($services.localization.render("core.widgets.gallery.maximize"))}"></div>'
29+
'<button class="next" title="${escapetool.xml($services.localization.render("core.widgets.gallery.nextImage"))}">&gt;</button>' +
30+
'<div class="index" tabindex="0" title="${escapetool.xml($services.localization.render("core.widgets.gallery.index.description"))}" aria-description="${escapetool.xml($services.localization.render("core.widgets.gallery.index.description"))}">0 / 0</div>'
3331
);
34-
this.container.addClassName('xGallery');
35-
36-
this.focusCatcher = this.container.down('.focusCatcher');
32+
this.container.addClassName('xGallery');
33+
34+
// Instead of an arbitrary element to catch focus, we use the index.
35+
// This index already stores the current image state, might as well be responsible for providing quick controls and
36+
// explanations about these quick controls.
37+
// Note that wrapping the image in an interactive container to handle this would have been a good solution too.
38+
// However, this wrapping caused the image to overflow the CSS grid vertically when in maximized mode.
39+
// Technically I couldn't find a CSS solution to prevent this, so I decided to make do without wrapping.
40+
this.focusCatcher = this.container.down('.index');
3741
this.focusCatcher.observe('keydown', this._onKeyDown.bindAsEventListener(this));
38-
this.container.observe('click', function() {
39-
this.focusCatcher.focus();
40-
}.bind(this));
4142

4243
this.container.down('.previous').observe('click', this._onPreviousImage.bind(this));
4344
this.container.down('.next').observe('click', this._onNextImage.bind(this));
45+
this.container.observe('click', function() {
46+
this.focusCatcher.focus();
47+
}.bind(this));
4448

4549
this.currentImage = this.container.down('.currentImage');
4650
this.currentImage.observe('load', this._onLoadImage.bind(this));

0 commit comments

Comments
 (0)