Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions elements/nuxeo-data-grid/nuxeo-document-grid-thumbnail.js
Original file line number Diff line number Diff line change
Expand Up @@ -216,15 +216,15 @@ Polymer({
</style>

<div class="bubbleBox grid-box" selection-mode$="[[selectionMode]]">
<div class="thumbnailContainer" on-tap="handleClick" tabindex="0">
<img src="[[_thumbnail(doc)]]" alt$="[[doc.title]]" />
</div>
<template is="dom-if" if="[[_hasDocument(doc)]]">
<a class="title" href$="[[urlFor(doc)]]" on-tap="handleClick" on-keydown="_handleKeydown" tabindex="0">
<a class="title" href$="[[urlFor(doc)]]" on-tap="handleClick" on-keydown="_handleKeydown">
<div class="thumbnailContainer">
<img src="[[_thumbnail(doc)]]" alt="" />
</div>
<div class="dataContainer">
<div class="title" id="title">[[doc.title]]</div>
<nuxeo-tag>[[formatDocType(doc.type)]]</nuxeo-tag>
<nuxeo-tooltip for="title">[[doc.title]]</nuxeo-tooltip>
<nuxeo-tooltip for="title" aria-hidden="true">[[doc.title]]</nuxeo-tooltip>
</div>
</a>
<div class="actions">
Expand Down Expand Up @@ -339,6 +339,6 @@ Polymer({
},

_computeTitle(doc) {
return `${doc && doc.title}${this.i18n && this.i18n('command.select')}`;
return this.i18n && this.i18n('command.select');
},
});
16 changes: 9 additions & 7 deletions elements/nuxeo-home.html
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@
overflow: hidden;
white-space: nowrap;
display: block;
width: calc(100% - 38px);
}

.task-box {
Expand Down Expand Up @@ -136,8 +135,9 @@
>
<nuxeo-data-table-column name="[[i18n('documentContentView.datatable.header.title')]]" flex="100">
<template>
<nuxeo-document-thumbnail document="[[item]]"></nuxeo-document-thumbnail>
<a class="ellipsis" href$="[[urlFor(item)]]">[[item.title]]</a>
<a class="ellipsis" href$="[[urlFor(item)]]"
><nuxeo-document-thumbnail document="[[item]]" alt=""></nuxeo-document-thumbnail>[[item.title]]</a
>
</template>
</nuxeo-data-table-column>
<nuxeo-data-table-column name="[[i18n('documentContentView.datatable.header.modified')]]" flex="50">
Expand Down Expand Up @@ -213,8 +213,9 @@
>
<nuxeo-data-table-column name="[[i18n('documentContentView.datatable.header.title')]]" flex="100">
<template>
<nuxeo-document-thumbnail document="[[item]]"></nuxeo-document-thumbnail>
<a class="ellipsis" href$="[[urlFor(item)]]">[[item.title]]</a>
<a class="ellipsis" href$="[[urlFor(item)]]"
><nuxeo-document-thumbnail document="[[item]]" alt=""></nuxeo-document-thumbnail>[[item.title]]</a
>
</template>
</nuxeo-data-table-column>
<nuxeo-data-table-column name="[[i18n('recentDocumentsTable.type')]]" flex="50">
Expand Down Expand Up @@ -253,8 +254,9 @@
>
<nuxeo-data-table-column name="[[i18n('documentContentView.datatable.header.title')]]" flex="100">
<template>
<nuxeo-document-thumbnail document="[[item]]"></nuxeo-document-thumbnail>
<a class="ellipsis" href$="[[urlFor(item)]]">[[item.title]]</a>
<a class="ellipsis" href$="[[urlFor(item)]]"
><nuxeo-document-thumbnail document="[[item]]" alt=""></nuxeo-document-thumbnail>[[item.title]]</a
>
</template>
</nuxeo-data-table-column>
<nuxeo-data-table-column name="[[i18n('documentContentView.datatable.header.modified')]]" flex="50">
Expand Down
6 changes: 3 additions & 3 deletions elements/nuxeo-publication/nuxeo-document-publications.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ Polymer({
}

.ellipsis {
width: calc(100% - 38px);
display: block;
text-overflow: ellipsis;
overflow: hidden;
Expand Down Expand Up @@ -116,8 +115,9 @@ Polymer({
>
<nuxeo-data-table-column name="[[i18n('documentContentView.datatable.header.path')]]" flex="200">
<template>
<nuxeo-document-thumbnail document="[[item]]"></nuxeo-document-thumbnail>
<a class$="path ellipsis [[_ellipsisDirection()]]" href$="[[urlFor(item)]]">[[item.path]]&lrm;</a>
<a class$="path ellipsis [[_ellipsisDirection()]]" href$="[[urlFor(item)]]"
><nuxeo-document-thumbnail document="[[item]]" alt=""></nuxeo-document-thumbnail>[[item.path]]&lrm;</a
>
<nuxeo-tooltip>[[item.path]]</nuxeo-tooltip>
</template>
</nuxeo-data-table-column>
Expand Down
4 changes: 2 additions & 2 deletions elements/nuxeo-results/nuxeo-default-results.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,8 @@ Polymer({
flex="100"
>
<template>
<nuxeo-document-thumbnail document="[[item]]"></nuxeo-document-thumbnail>
<a class="title ellipsis" href$="[[urlFor(item)]]" on-tap="_navigateLink" data-index="[[index]]">
<a class="title ellipsis" href$="[[urlFor(item)]]" on-tap="_navigateLink" data-index="[[index]]"
><nuxeo-document-thumbnail document="[[item]]" alt=""></nuxeo-document-thumbnail>
[[item.title]]
</a>
Comment thread
swarnadipa-dev marked this conversation as resolved.
</template>
Expand Down
6 changes: 3 additions & 3 deletions elements/nuxeo-results/nuxeo-document-content.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ Polymer({
overflow: hidden;
white-space: nowrap;
display: block;
width: calc(100% - 38px);
}

.capitalize {
Expand Down Expand Up @@ -160,8 +159,9 @@ Polymer({
filter-expression="$term*"
>
<template>
<nuxeo-document-thumbnail document="[[item]]"></nuxeo-document-thumbnail>
<a class="title ellipsis" href$="[[urlFor(item)]]" on-tap="_navigate">[[item.title]]</a>
<a class="title ellipsis" href$="[[urlFor(item)]]" on-tap="_navigate"
><nuxeo-document-thumbnail document="[[item]]" alt=""></nuxeo-document-thumbnail>[[item.title]]</a
>
</template>
</nuxeo-data-table-column>
<nuxeo-data-table-column name="[[i18n('documentContentView.datatable.header.type')]]" field="type" hidden>
Expand Down
6 changes: 3 additions & 3 deletions elements/nuxeo-results/nuxeo-document-trash-content.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ Polymer({
overflow: hidden;
white-space: nowrap;
display: block;
width: calc(100% - 38px);
}

.capitalize {
Expand Down Expand Up @@ -168,8 +167,9 @@ Polymer({
filter-expression="$term*"
>
<template>
<nuxeo-document-thumbnail document="[[item]]"></nuxeo-document-thumbnail>
<a class="title ellipsis" href$="[[urlFor(item)]]" on-tap="_navigate">[[item.title]]</a>
<a class="title ellipsis" href$="[[urlFor(item)]]" on-tap="_navigate"
><nuxeo-document-thumbnail document="[[item]]" alt=""></nuxeo-document-thumbnail>[[item.title]]</a
>
</template>
</nuxeo-data-table-column>
<nuxeo-data-table-column name="[[i18n('documentContentView.datatable.header.type')]]" field="type" hidden>
Expand Down
5 changes: 3 additions & 2 deletions elements/search/assets/nuxeo-assets-search-results.html
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,9 @@
flex="100"
>
<template>
<nuxeo-document-thumbnail document="[[item]]"></nuxeo-document-thumbnail>
<a class="ellipsis" href$="[[urlFor(item)]]" on-click="_navigate">[[item.title]]</a>
<a class="ellipsis" href$="[[urlFor(item)]]" on-click="_navigate"
><nuxeo-document-thumbnail document="[[item]]" alt=""></nuxeo-document-thumbnail>[[item.title]]</a
>
</template>
</nuxeo-data-table-column>

Expand Down
5 changes: 3 additions & 2 deletions elements/search/default/nuxeo-default-search-results.html
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,9 @@
flex="100"
>
<template>
<nuxeo-document-thumbnail document="[[item]]"></nuxeo-document-thumbnail>
<a class="ellipsis" href$="[[urlFor(item)]]">[[item.title]]</a>
<a class="ellipsis" href$="[[urlFor(item)]]"
><nuxeo-document-thumbnail document="[[item]]" alt=""></nuxeo-document-thumbnail>[[item.title]]</a
>
</template>
</nuxeo-data-table-column>

Expand Down
5 changes: 3 additions & 2 deletions elements/search/expired/nuxeo-expired-search-results.html
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,9 @@
flex="100"
>
<template>
<nuxeo-document-thumbnail document="[[item]]"></nuxeo-document-thumbnail>
<a class="ellipsis" href$="[[urlFor(item)]]" on-tap="_navigate">[[item.title]]</a>
<a class="ellipsis" href$="[[urlFor(item)]]" on-tap="_navigate"
><nuxeo-document-thumbnail document="[[item]]" alt=""></nuxeo-document-thumbnail>[[item.title]]</a
>
</template>
</nuxeo-data-table-column>

Expand Down
10 changes: 6 additions & 4 deletions elements/search/nxql/nuxeo-nxql-search-results.html
Original file line number Diff line number Diff line change
Expand Up @@ -79,15 +79,17 @@
hidden
>
<template>
<nuxeo-document-thumbnail document="[[item]]"></nuxeo-document-thumbnail>
<a class="ellipsis" href$="[[urlFor(item)]]">[[item.title]]</a>
<a class="ellipsis" href$="[[urlFor(item)]]"
><nuxeo-document-thumbnail document="[[item]]" alt=""></nuxeo-document-thumbnail>[[item.title]]</a
>
Comment thread
swarnadipa-dev marked this conversation as resolved.
</template>
</nuxeo-data-table-column>

<nuxeo-data-table-column name="[[i18n('label.path')]]" field="ecm:path" sort-by="ecm:path" flex="100">
<template>
<nuxeo-document-thumbnail document="[[item]]"></nuxeo-document-thumbnail>
<a class="ellipsis" href$="[[urlFor(item)]]" on-tap="_navigate">[[item.path]]</a>
<a class="ellipsis" href$="[[urlFor(item)]]" on-tap="_navigate"
><nuxeo-document-thumbnail document="[[item]]" alt=""></nuxeo-document-thumbnail>[[item.path]]</a
>
Comment thread
swarnadipa-dev marked this conversation as resolved.
<nuxeo-tooltip>[[item.path]]</nuxeo-tooltip>
</template>
</nuxeo-data-table-column>
Expand Down
5 changes: 3 additions & 2 deletions elements/search/trash/nuxeo-trash-search-results.html
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,9 @@
flex="30"
>
<template>
<nuxeo-document-thumbnail document="[[item]]"></nuxeo-document-thumbnail>
<a class="ellipsis" href$="[[urlFor(item)]]">[[item.title]]</a>
<a class="ellipsis" href$="[[urlFor(item)]]"
><nuxeo-document-thumbnail document="[[item]]" alt=""></nuxeo-document-thumbnail>[[item.title]]</a
>
</template>
</nuxeo-data-table-column>

Expand Down
75 changes: 75 additions & 0 deletions test/nuxeo-assets-search-results.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/**
@license
©2023 Hyland Software, Inc. and its affiliates. All rights reserved.
All Hyland product names are registered or unregistered trademarks of Hyland Software, Inc. or its affiliates.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

/**
* Tests for WEBUI-1736 (nuxeo-assets-search-results):
*
* The fix applies WCAG H2 technique: `<nuxeo-document-thumbnail alt="">` is
* combined with the document title text inside a single `<a>` element so that
* screen readers do not announce the link twice.
*/

/** Recursively collect all elements matching selector, descending into <template> content. */
function queryAllDeep(root, selector) {
const results = [];
root.querySelectorAll(selector).forEach((el) => results.push(el));
root.querySelectorAll('template').forEach((t) => {
results.push(...queryAllDeep(t.content, selector));
});
return results;
}

let tmpl;

suiteSetup(async () => {
const url = '/elements/search/assets/nuxeo-assets-search-results.html';
const selector = 'dom-module#nuxeo-assets-search-results template';
const response = await fetch(url);
expect(response.ok, `Failed to fetch ${url}: ${response.status} ${response.statusText}`).to.be.true;
const text = await response.text();
const doc = new DOMParser().parseFromString(text, 'text/html');
tmpl = doc.querySelector(selector);
expect(tmpl, `Template not found for selector "${selector}" in ${url}`).to.not.be.null;
});

suite('nuxeo-assets-search-results', () => {
suite('WCAG H2: thumbnail combined with title text in one link', () => {
test('nuxeo-document-thumbnail is present in the template', () => {
const thumbnails = queryAllDeep(tmpl.content, 'nuxeo-document-thumbnail');
expect(thumbnails.length).to.be.greaterThan(0, 'should have at least one nuxeo-document-thumbnail');
});

test('every nuxeo-document-thumbnail has alt="" (decorative image)', () => {
const thumbnails = queryAllDeep(tmpl.content, 'nuxeo-document-thumbnail');
thumbnails.forEach((thumb) => {
expect(thumb.getAttribute('alt')).to.equal(
'',
`thumbnail should have alt="" but got "${thumb.getAttribute('alt')}"`,
);
});
});

test('every nuxeo-document-thumbnail is inside an <a> link', () => {
const thumbnails = queryAllDeep(tmpl.content, 'nuxeo-document-thumbnail');
thumbnails.forEach((thumb) => {
const link = thumb.closest('a');
expect(link, 'nuxeo-document-thumbnail should be a descendant of an <a> element').to.exist;
});
});
});
});
49 changes: 49 additions & 0 deletions test/nuxeo-default-results.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,53 @@ suite('nuxeo-default-results', () => {
element.$.results._refreshAndFetch.restore();
});
});

suite('WCAG H2: thumbnail combined with title in one link', () => {
// Recursively collect elements matching selector, descending into <template> content.
function queryAllDeep(root, selector) {
const results = [];
root.querySelectorAll(selector).forEach((el) => results.push(el));
root.querySelectorAll('template').forEach((t) => {
results.push(...queryAllDeep(t.content, selector));
});
return results;
}

let tmpl;

suiteSetup(async () => {
const url = '/elements/nuxeo-results/nuxeo-default-results.js';
const response = await fetch(url);
expect(response.ok, `Failed to fetch ${url}: ${response.status} ${response.statusText}`).to.be.true;
const jsText = await response.text();
const htmlTagIdx = jsText.indexOf('html`');
expect(htmlTagIdx, `html\` template literal not found in ${url}`).to.be.greaterThan(-1);
const htmlEndIdx = jsText.indexOf('`', htmlTagIdx + 5);
expect(htmlEndIdx, `Closing \` for html\` template literal not found in ${url}`).to.be.greaterThan(htmlTagIdx);
const templateHtml = jsText.substring(htmlTagIdx + 5, htmlEndIdx);
const doc = new DOMParser().parseFromString(`<div>${templateHtml}</div>`, 'text/html');
tmpl = doc.body.firstElementChild;
expect(tmpl, `Failed to parse html\` template literal from ${url}`).to.exist;
});

test('nuxeo-document-thumbnail has alt="" (decorative image)', () => {
const thumbnails = queryAllDeep(tmpl, 'nuxeo-document-thumbnail');
expect(thumbnails.length).to.be.greaterThan(0, 'should have at least one nuxeo-document-thumbnail');
thumbnails.forEach((thumb) => {
expect(thumb.getAttribute('alt')).to.equal(
'',
`thumbnail should have alt="" but got "${thumb.getAttribute('alt')}"`,
);
});
});

test('nuxeo-document-thumbnail is inside an <a> link', () => {
const thumbnails = queryAllDeep(tmpl, 'nuxeo-document-thumbnail');
expect(thumbnails.length).to.be.greaterThan(0);
thumbnails.forEach((thumb) => {
const link = thumb.closest('a');
expect(link, 'nuxeo-document-thumbnail should be a descendant of an <a> element').to.exist;
});
});
});
});
Loading
Loading