Update term tags display and fix a layout issue (#1208)
* Fix layout issue with term expression display * Update display of term tags * Update tag notification to include disambiguation information
This commit is contained in:
parent
06d23f59d8
commit
5b58a9aeef
@ -699,6 +699,26 @@ button.action-button[data-icon=source-term]::before {
|
|||||||
.tag-inner {
|
.tag-inner {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
.tag-details-disambiguation-list::before {
|
||||||
|
content: 'Only: ';
|
||||||
|
}
|
||||||
|
.tag-details-disambiguation-list ruby>rt {
|
||||||
|
display: inline;
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
.tag-details-disambiguation-list ruby>rt::before {
|
||||||
|
content: '(';
|
||||||
|
}
|
||||||
|
.tag-details-disambiguation-list ruby>rt::after {
|
||||||
|
content: ')';
|
||||||
|
}
|
||||||
|
.tag-details-disambiguation-list[data-unmatched-expression-count='0'],
|
||||||
|
.tag-details-disambiguation-list:not([data-unmatched-expression-count]) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.tag-details-disambiguation:not(:last-child)::after {
|
||||||
|
content: ', ';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Entries */
|
/* Entries */
|
||||||
@ -755,13 +775,13 @@ button.action-button[data-icon=source-term]::before {
|
|||||||
display: inline;
|
display: inline;
|
||||||
}
|
}
|
||||||
.term-expression {
|
.term-expression {
|
||||||
display: inline;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
.term-expression-details {
|
.term-expression-details {
|
||||||
display: inline;
|
display: inline;
|
||||||
}
|
}
|
||||||
.term-expression-details>.tags {
|
.term-expression-details>.tags {
|
||||||
display: inline;
|
display: none;
|
||||||
}
|
}
|
||||||
.term-expression-details>.frequencies {
|
.term-expression-details>.frequencies {
|
||||||
display: none;
|
display: none;
|
||||||
@ -769,6 +789,15 @@ button.action-button[data-icon=source-term]::before {
|
|||||||
.term-expression-list>.term-expression:not(:last-of-type)>.term-expression-text-container>.term-expression-text::after {
|
.term-expression-list>.term-expression:not(:last-of-type)>.term-expression-text-container>.term-expression-text::after {
|
||||||
content: '\3001';
|
content: '\3001';
|
||||||
}
|
}
|
||||||
|
.term-details {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
.term-tags {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
.entry[data-expression-multi=true] .term-details {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Entry indicator */
|
/* Entry indicator */
|
||||||
|
@ -15,7 +15,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="term-expression-list"></div>
|
<div class="term-expression-list"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="term-reasons"></div>
|
<div class="term-details">
|
||||||
|
<div class="term-tags tag-list"></div>
|
||||||
|
<div class="term-reasons"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="entry-body">
|
<div class="entry-body">
|
||||||
@ -137,6 +140,10 @@
|
|||||||
<div class="footer-notification-body"></div>
|
<div class="footer-notification-body"></div>
|
||||||
<button class="footer-notification-close-button"><span class="footer-notification-close-button-icon icon" data-icon="cross"></span></button>
|
<button class="footer-notification-close-button"><span class="footer-notification-close-button-icon icon" data-icon="cross"></span></button>
|
||||||
</div></template>
|
</div></template>
|
||||||
|
<template id="footer-notification-tag-details-template" data-remove-whitespace-text="true">
|
||||||
|
<div class="tag-details"></div>
|
||||||
|
<div class="tag-details-disambiguation-list"></div>
|
||||||
|
</div></template>
|
||||||
<template id="profile-list-item-template"><label class="profile-list-item">
|
<template id="profile-list-item-template"><label class="profile-list-item">
|
||||||
<div class="profile-list-item-selection"><label class="radio"><input type="radio" class="profile-entry-is-default-radio" name="profile-entry-default-radio"><span class="radio-body"><span class="radio-border"></span><span class="radio-dot"></span></span></label></div>
|
<div class="profile-list-item-selection"><label class="radio"><input type="radio" class="profile-entry-is-default-radio" name="profile-entry-default-radio"><span class="radio-body"><span class="radio-border"></span><span class="radio-dot"></span></span></label></div>
|
||||||
<div class="profile-list-item-name"></div>
|
<div class="profile-list-item-name"></div>
|
||||||
|
@ -16,6 +16,37 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
class DictionaryDataUtil {
|
class DictionaryDataUtil {
|
||||||
|
static groupTermTags(definition) {
|
||||||
|
const {expressions} = definition;
|
||||||
|
const expressionsLength = expressions.length;
|
||||||
|
const uniqueCheck = (expressionsLength > 1);
|
||||||
|
const resultsMap = new Map();
|
||||||
|
const results = [];
|
||||||
|
for (let i = 0; i < expressionsLength; ++i) {
|
||||||
|
const {termTags, expression, reading} = expressions[i];
|
||||||
|
for (const tag of termTags) {
|
||||||
|
if (uniqueCheck) {
|
||||||
|
const {name, category, notes, dictionary} = tag;
|
||||||
|
const key = this._createMapKey([name, category, notes, dictionary]);
|
||||||
|
const index = resultsMap.get(key);
|
||||||
|
if (typeof index !== 'undefined') {
|
||||||
|
const existingItem = results[index];
|
||||||
|
existingItem.expressions.push({index: i, expression, reading});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
resultsMap.set(key, results.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
const item = {
|
||||||
|
tag,
|
||||||
|
expressions: [{index: i, expression, reading}]
|
||||||
|
};
|
||||||
|
results.push(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
static groupTermFrequencies(frequencies) {
|
static groupTermFrequencies(frequencies) {
|
||||||
const map1 = new Map();
|
const map1 = new Map();
|
||||||
for (const {dictionary, expression, reading, hasReading, frequency} of frequencies) {
|
for (const {dictionary, expression, reading, hasReading, frequency} of frequencies) {
|
||||||
@ -26,7 +57,7 @@ class DictionaryDataUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const readingKey = hasReading ? reading : null;
|
const readingKey = hasReading ? reading : null;
|
||||||
const key = JSON.stringify([expression, readingKey], null, 0);
|
const key = this._createMapKey([expression, readingKey]);
|
||||||
let frequencyData = map2.get(key);
|
let frequencyData = map2.get(key);
|
||||||
if (typeof frequencyData === 'undefined') {
|
if (typeof frequencyData === 'undefined') {
|
||||||
frequencyData = {expression, reading: readingKey, frequencies: new Set()};
|
frequencyData = {expression, reading: readingKey, frequencies: new Set()};
|
||||||
@ -179,4 +210,8 @@ class DictionaryDataUtil {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static _createMapKey(array) {
|
||||||
|
return JSON.stringify(array);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,7 @@ class DisplayGenerator {
|
|||||||
const pitchesContainer = node.querySelector('.term-pitch-accent-group-list');
|
const pitchesContainer = node.querySelector('.term-pitch-accent-group-list');
|
||||||
const frequencyGroupListContainer = node.querySelector('.frequency-group-list');
|
const frequencyGroupListContainer = node.querySelector('.frequency-group-list');
|
||||||
const definitionsContainer = node.querySelector('.term-definition-list');
|
const definitionsContainer = node.querySelector('.term-definition-list');
|
||||||
|
const termTagsContainer = node.querySelector('.term-tags');
|
||||||
|
|
||||||
const {expressions, type, reasons, frequencies} = details;
|
const {expressions, type, reasons, frequencies} = details;
|
||||||
const definitions = (type === 'term' ? [details] : details.definitions);
|
const definitions = (type === 'term' ? [details] : details.definitions);
|
||||||
@ -56,6 +57,7 @@ class DisplayGenerator {
|
|||||||
const pitches = DictionaryDataUtil.getPitchAccentInfos(details);
|
const pitches = DictionaryDataUtil.getPitchAccentInfos(details);
|
||||||
const pitchCount = pitches.reduce((i, v) => i + v.pitches.length, 0);
|
const pitchCount = pitches.reduce((i, v) => i + v.pitches.length, 0);
|
||||||
const groupedFrequencies = DictionaryDataUtil.groupTermFrequencies(frequencies);
|
const groupedFrequencies = DictionaryDataUtil.groupTermFrequencies(frequencies);
|
||||||
|
const termTags = DictionaryDataUtil.groupTermTags(details);
|
||||||
|
|
||||||
const uniqueExpressions = new Set();
|
const uniqueExpressions = new Set();
|
||||||
const uniqueReadings = new Set();
|
const uniqueReadings = new Set();
|
||||||
@ -80,6 +82,7 @@ class DisplayGenerator {
|
|||||||
this._appendMultiple(frequencyGroupListContainer, this._createFrequencyGroup.bind(this), groupedFrequencies, false);
|
this._appendMultiple(frequencyGroupListContainer, this._createFrequencyGroup.bind(this), groupedFrequencies, false);
|
||||||
this._appendMultiple(pitchesContainer, this._createPitches.bind(this), pitches);
|
this._appendMultiple(pitchesContainer, this._createPitches.bind(this), pitches);
|
||||||
this._appendMultiple(definitionsContainer, this._createTermDefinitionItem.bind(this), definitions);
|
this._appendMultiple(definitionsContainer, this._createTermDefinitionItem.bind(this), definitions);
|
||||||
|
this._appendMultiple(termTagsContainer, this._createTermTag.bind(this), termTags, expressions.length);
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
@ -119,6 +122,45 @@ class DisplayGenerator {
|
|||||||
return this._templates.instantiate('footer-notification');
|
return this._templates.instantiate('footer-notification');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createTagFooterNotificationDetails(tagNode) {
|
||||||
|
const node = this._templates.instantiateFragment('footer-notification-tag-details');
|
||||||
|
|
||||||
|
const details = tagNode.dataset.details;
|
||||||
|
node.querySelector('.tag-details').textContent = details;
|
||||||
|
|
||||||
|
let disambiguation = null;
|
||||||
|
try {
|
||||||
|
let a = tagNode.dataset.disambiguation;
|
||||||
|
if (typeof a !== 'undefined') {
|
||||||
|
a = JSON.parse(a);
|
||||||
|
if (Array.isArray(a)) { disambiguation = a; }
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// NOP
|
||||||
|
}
|
||||||
|
|
||||||
|
if (disambiguation !== null) {
|
||||||
|
const disambiguationContainer = node.querySelector('.tag-details-disambiguation-list');
|
||||||
|
const copyAttributes = ['totalExpressionCount', 'matchedExpressionCount', 'unmatchedExpressionCount'];
|
||||||
|
for (const attribute of copyAttributes) {
|
||||||
|
const value = tagNode.dataset[attribute];
|
||||||
|
if (typeof value === 'undefined') { continue; }
|
||||||
|
disambiguationContainer.dataset[attribute] = value;
|
||||||
|
}
|
||||||
|
for (const {expression, reading} of disambiguation) {
|
||||||
|
const segments = this._japaneseUtil.distributeFurigana(expression, reading);
|
||||||
|
const disambiguationItem = document.createElement('span');
|
||||||
|
disambiguationItem.className = 'tag-details-disambiguation';
|
||||||
|
this._appendFurigana(disambiguationItem, segments, (container, text) => {
|
||||||
|
container.appendChild(document.createTextNode(text));
|
||||||
|
});
|
||||||
|
disambiguationContainer.appendChild(disambiguationItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
createProfileListItem() {
|
createProfileListItem() {
|
||||||
return this._templates.instantiate('profile-list-item');
|
return this._templates.instantiate('profile-list-item');
|
||||||
}
|
}
|
||||||
@ -321,6 +363,16 @@ class DisplayGenerator {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_createTermTag(details, totalExpressionCount) {
|
||||||
|
const {tag, expressions} = details;
|
||||||
|
const node = this._createTag(tag);
|
||||||
|
node.dataset.disambiguation = `${JSON.stringify(expressions)}`;
|
||||||
|
node.dataset.totalExpressionCount = `${totalExpressionCount}`;
|
||||||
|
node.dataset.matchedExpressionCount = `${expressions.length}`;
|
||||||
|
node.dataset.unmatchedExpressionCount = `${Math.max(0, totalExpressionCount - expressions.length)}`;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
_createSearchTag(text) {
|
_createSearchTag(text) {
|
||||||
return this._createTag({
|
return this._createTag({
|
||||||
notes: '',
|
notes: '',
|
||||||
|
@ -58,8 +58,13 @@ class DisplayNotification {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setContent(text) {
|
setContent(value) {
|
||||||
this._body.textContent = text;
|
if (typeof value === 'string') {
|
||||||
|
this._body.textContent = value;
|
||||||
|
} else {
|
||||||
|
this._body.textContent = '';
|
||||||
|
this._body.appendChild(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
isClosing() {
|
isClosing() {
|
||||||
|
@ -837,18 +837,17 @@ class Display extends EventDispatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_onTagClick(e) {
|
_onTagClick(e) {
|
||||||
const node = e.currentTarget;
|
this._showTagNotification(e.currentTarget);
|
||||||
const {dataset: {details}} = node;
|
|
||||||
this._showTagNotification(details);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_showTagNotification(content) {
|
_showTagNotification(tagNode) {
|
||||||
if (this._tagNotification === null) {
|
if (this._tagNotification === null) {
|
||||||
const node = this._displayGenerator.createEmptyFooterNotification();
|
const node = this._displayGenerator.createEmptyFooterNotification();
|
||||||
node.classList.add('click-scannable');
|
node.classList.add('click-scannable');
|
||||||
this._tagNotification = new DisplayNotification(this._tagNotificationContainer, node);
|
this._tagNotification = new DisplayNotification(this._tagNotificationContainer, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const content = this._displayGenerator.createTagFooterNotificationDetails(tagNode);
|
||||||
this._tagNotification.setContent(content);
|
this._tagNotification.setContent(content);
|
||||||
this._tagNotification.open();
|
this._tagNotification.open();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user