Dictionary image display refactoring (#1687)
* Generalize image definition generation * Enable optional aspect ratio * Move styles * Update styles * Add more options for collapsing images * Add image options for collapsing * Improve layout for images that are collapsed
This commit is contained in:
parent
76276e78da
commit
f3cf4d10c7
@ -1571,6 +1571,8 @@ button.definition-item-expansion-button:focus:focus-visible+.definition-item-con
|
||||
.gloss-image-link {
|
||||
cursor: inherit;
|
||||
color: inherit;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
}
|
||||
.gloss-image-link[href]:hover {
|
||||
cursor: pointer;
|
||||
@ -1588,7 +1590,7 @@ button.definition-item-expansion-button:focus:focus-visible+.definition-item-con
|
||||
white-space: normal;
|
||||
color: var(--text-color-light3);
|
||||
}
|
||||
.gloss-item[data-has-image=true][data-image-load-state=load-error] .gloss-image-container-overlay::after {
|
||||
.gloss-image-link[data-has-image=true][data-image-load-state=load-error] .gloss-image-container-overlay::after {
|
||||
content: 'Image failed to load';
|
||||
display: table-cell;
|
||||
width: 100%;
|
||||
@ -1599,15 +1601,17 @@ button.definition-item-expansion-button:focus:focus-visible+.definition-item-con
|
||||
}
|
||||
.gloss-image {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
object-fit: contain;
|
||||
border: none;
|
||||
outline: none;
|
||||
}
|
||||
.gloss-image-link[data-has-aspect-ratio=true] .gloss-image {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
vertical-align: top;
|
||||
object-fit: contain;
|
||||
border: none;
|
||||
outline: none;
|
||||
}
|
||||
.gloss-image:not([src]) {
|
||||
display: none;
|
||||
@ -1619,13 +1623,15 @@ button.definition-item-expansion-button:focus:focus-visible+.definition-item-con
|
||||
image-rendering: pixelated;
|
||||
image-rendering: crisp-edges;
|
||||
}
|
||||
.gloss-image-aspect-ratio-sizer {
|
||||
content: '';
|
||||
.gloss-image-link[data-has-aspect-ratio=true] .gloss-image-aspect-ratio-sizer {
|
||||
display: inline-block;
|
||||
width: 0;
|
||||
vertical-align: top;
|
||||
font-size: 0;
|
||||
}
|
||||
.gloss-image-link-text {
|
||||
display: none;
|
||||
}
|
||||
.gloss-image-link-text::before {
|
||||
content: '[';
|
||||
}
|
||||
@ -1633,9 +1639,38 @@ button.definition-item-expansion-button:focus:focus-visible+.definition-item-con
|
||||
content: ']';
|
||||
}
|
||||
.gloss-image-description {
|
||||
display: block;
|
||||
white-space: pre-line;
|
||||
}
|
||||
|
||||
.gloss-image-link[data-collapsed=true] .gloss-image-container,
|
||||
:root[data-glossary-layout-mode=compact] .gloss-image-link[data-collapsible=true] .gloss-image-container {
|
||||
display: none;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 100%;
|
||||
z-index: 1;
|
||||
}
|
||||
.entry:nth-last-of-type(1):not(:nth-of-type(1)) .gloss-image-link[data-collapsed=true] .gloss-image-container,
|
||||
:root[data-glossary-layout-mode=compact] .entry:nth-last-of-type(1):not(:nth-of-type(1)) .gloss-image-link[data-collapsible=true] .gloss-image-container {
|
||||
bottom: 100%;
|
||||
top: auto;
|
||||
}
|
||||
.gloss-image-link[data-collapsed=true]:hover .gloss-image-container,
|
||||
.gloss-image-link[data-collapsed=true]:focus .gloss-image-container,
|
||||
:root[data-glossary-layout-mode=compact] .gloss-image-link[data-collapsible=true]:hover .gloss-image-container,
|
||||
:root[data-glossary-layout-mode=compact] .gloss-image-link[data-collapsible=true]:focus .gloss-image-container {
|
||||
display: block;
|
||||
}
|
||||
.gloss-image-link[data-collapsed=true] .gloss-image-link-text,
|
||||
:root[data-glossary-layout-mode=compact] .gloss-image-link[data-collapsible=true] .gloss-image-link-text {
|
||||
display: inline;
|
||||
}
|
||||
.gloss-image-link[data-collapsed=true]~.gloss-image-description,
|
||||
:root[data-glossary-layout-mode=compact] .gloss-image-description {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
|
||||
/* Kanji */
|
||||
.kanji-glyph-container {
|
||||
@ -2110,32 +2145,6 @@ button.footer-notification-close-button {
|
||||
color: var(--text-color-light3);
|
||||
}
|
||||
|
||||
:root[data-glossary-layout-mode=compact] .gloss-image-container {
|
||||
display: none;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 100%;
|
||||
z-index: 1;
|
||||
}
|
||||
:root[data-glossary-layout-mode=compact] .entry:nth-last-of-type(1):not(:nth-of-type(1)) .gloss-image-container {
|
||||
bottom: 100%;
|
||||
top: auto;
|
||||
}
|
||||
:root[data-glossary-layout-mode=compact] .gloss-image-link {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
:root[data-glossary-layout-mode=compact] .gloss-image-link:hover .gloss-image-container,
|
||||
:root[data-glossary-layout-mode=compact] .gloss-image-link:focus .gloss-image-container {
|
||||
display: block;
|
||||
}
|
||||
:root:not([data-glossary-layout-mode=compact]) .gloss-image-link-text {
|
||||
display: none;
|
||||
}
|
||||
:root:not([data-glossary-layout-mode=compact]) .gloss-image-description {
|
||||
display: block;
|
||||
}
|
||||
|
||||
:root[data-popup-display-mode=full-width] .frame-resizer-container {
|
||||
display: none;
|
||||
}
|
||||
|
@ -104,6 +104,16 @@
|
||||
"type": "boolean",
|
||||
"description": "Whether or not the image should appear pixelated at sizes larger than the image's native resolution.",
|
||||
"default": false
|
||||
},
|
||||
"collapsed": {
|
||||
"type": "boolean",
|
||||
"description": "Whether or not the image is collapsed by default.",
|
||||
"default": false
|
||||
},
|
||||
"collapsible": {
|
||||
"type": "boolean",
|
||||
"description": "Whether or not the image can be collapsed.",
|
||||
"default": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -57,7 +57,8 @@
|
||||
</li></template>
|
||||
<template id="definition-disambiguation-template"><span class="definition-disambiguation"></span></template>
|
||||
<template id="gloss-item-template"><li class="gloss-item click-scannable"><span class="gloss-separator"> </span><span class="gloss-content"></span></li></template>
|
||||
<template id="gloss-item-image-template"><li class="gloss-item click-scannable" data-has-image="true"><span class="gloss-separator"> </span><span class="gloss-content"><a class="gloss-image-link" target="_blank" rel="noreferrer noopener"><span class="gloss-image-container"><span class="gloss-image-aspect-ratio-sizer"></span><img class="gloss-image" alt=""><span class="gloss-image-container-overlay"></span></span><span class="gloss-image-link-text">Image</span></a> <span class="gloss-image-description"></span></span></li></template>
|
||||
<template id="gloss-item-image-template"><a class="gloss-image-link" target="_blank" rel="noreferrer noopener"><span class="gloss-image-container"><span class="gloss-image-aspect-ratio-sizer"></span><img class="gloss-image" alt=""><span class="gloss-image-container-overlay"></span></span><span class="gloss-image-link-text">Image</span></a></template>
|
||||
<template id="gloss-item-image-description-template"> <span class="gloss-image-description"></span></template>
|
||||
<template id="inflection-template"><span class="inflection"></span><span class="inflection-separator"> </span></template>
|
||||
|
||||
<!-- Frequency templates -->
|
||||
|
@ -309,7 +309,26 @@ class DisplayGenerator {
|
||||
}
|
||||
|
||||
_createTermDefinitionEntryImage(data, dictionary) {
|
||||
const {path, width, height, preferredWidth, preferredHeight, title, description, pixelated} = data;
|
||||
const {description} = data;
|
||||
|
||||
const node = this._templates.instantiate('gloss-item');
|
||||
|
||||
const contentContainer = node.querySelector('.gloss-content');
|
||||
const image = this._createDefinitionImage(data, dictionary);
|
||||
contentContainer.appendChild(image);
|
||||
|
||||
if (typeof description === 'string') {
|
||||
const fragment = this._templates.instantiateFragment('gloss-item-image-description');
|
||||
const container = fragment.querySelector('.gloss-image-description');
|
||||
this._setMultilineTextContent(container, description);
|
||||
contentContainer.appendChild(fragment);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
_createDefinitionImage(data, dictionary) {
|
||||
const {path, width, height, preferredWidth, preferredHeight, title, pixelated, collapsed, collapsible} = data;
|
||||
|
||||
const usedWidth = (
|
||||
typeof preferredWidth === 'number' ?
|
||||
@ -327,6 +346,9 @@ class DisplayGenerator {
|
||||
node.dataset.path = path;
|
||||
node.dataset.dictionary = dictionary;
|
||||
node.dataset.imageLoadState = 'not-loaded';
|
||||
node.dataset.hasAspectRatio = 'true';
|
||||
node.dataset.collapsed = typeof collapsed === 'boolean' ? `${collapsed}` : 'false';
|
||||
node.dataset.collapsible = typeof collapsible === 'boolean' ? `${collapsible}` : 'true';
|
||||
|
||||
const imageContainer = node.querySelector('.gloss-image-container');
|
||||
imageContainer.style.width = `${usedWidth}em`;
|
||||
@ -338,35 +360,29 @@ class DisplayGenerator {
|
||||
aspectRatioSizer.style.paddingTop = `${aspectRatio * 100.0}%`;
|
||||
|
||||
const image = node.querySelector('img.gloss-image');
|
||||
const imageLink = node.querySelector('.gloss-image-link');
|
||||
image.dataset.pixelated = `${pixelated === true}`;
|
||||
|
||||
if (this._mediaLoader !== null) {
|
||||
this._mediaLoader.loadMedia(
|
||||
path,
|
||||
dictionary,
|
||||
(url) => this._setImageData(node, image, imageLink, url, false),
|
||||
() => this._setImageData(node, image, imageLink, null, true)
|
||||
(url) => this._setImageData(node, image, url, false),
|
||||
() => this._setImageData(node, image, null, true)
|
||||
);
|
||||
}
|
||||
|
||||
if (typeof description === 'string') {
|
||||
const container = node.querySelector('.gloss-image-description');
|
||||
this._setMultilineTextContent(container, description);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
_setImageData(container, image, imageLink, url, unloaded) {
|
||||
_setImageData(node, image, url, unloaded) {
|
||||
if (url !== null) {
|
||||
image.src = url;
|
||||
imageLink.href = url;
|
||||
container.dataset.imageLoadState = 'loaded';
|
||||
node.href = url;
|
||||
node.dataset.imageLoadState = 'loaded';
|
||||
} else {
|
||||
image.removeAttribute('src');
|
||||
imageLink.removeAttribute('href');
|
||||
container.dataset.imageLoadState = unloaded ? 'unloaded' : 'load-error';
|
||||
node.removeAttribute('href');
|
||||
node.dataset.imageLoadState = unloaded ? 'unloaded' : 'load-error';
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -306,10 +306,8 @@ class DictionaryImporter {
|
||||
}
|
||||
|
||||
async _formatDictionaryTermGlossaryImage(data, context, entry) {
|
||||
const {path, width: preferredWidth, height: preferredHeight, title, description, pixelated} = data;
|
||||
const {path, width: preferredWidth, height: preferredHeight, title, description, pixelated, collapsed, collapsible} = data;
|
||||
const {width, height} = await this._getImageMedia(path, context, entry);
|
||||
|
||||
// Create new data
|
||||
const newData = {
|
||||
type: 'image',
|
||||
path,
|
||||
@ -321,7 +319,8 @@ class DictionaryImporter {
|
||||
if (typeof title === 'string') { newData.title = title; }
|
||||
if (typeof description === 'string') { newData.description = description; }
|
||||
if (typeof pixelated === 'boolean') { newData.pixelated = pixelated; }
|
||||
|
||||
if (typeof collapsed === 'boolean') { newData.collapsed = collapsed; }
|
||||
if (typeof collapsible === 'boolean') { newData.collapsible = collapsible; }
|
||||
return newData;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user