Skip to content

Commit 4509388

Browse files
authored
Merge pull request #1060 from drgrice1/another-knowl-rework
Change knowls to being buttons that open modal dialogs.
2 parents 6ffad4d + 2931a8e commit 4509388

File tree

4 files changed

+178
-205
lines changed

4 files changed

+178
-205
lines changed

htdocs/js/Knowls/knowl.css

Lines changed: 0 additions & 101 deletions
This file was deleted.

htdocs/js/Knowls/knowl.js

Lines changed: 66 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -15,111 +15,104 @@
1515
};
1616

1717
const initializeKnowl = (knowl) => {
18-
if (getComputedStyle(knowl)?.display === '') {
19-
setTimeout(() => initializeKnowl(knowl), 100);
20-
return;
21-
}
22-
23-
knowl.dataset.bsToggle = 'collapse';
24-
if (!knowl.knowlContainer) {
25-
knowl.knowlContainer = document.createElement('div');
26-
knowl.knowlContainer.id = `knowl-uid-${knowlUID++}`;
27-
knowl.knowlContainer.classList.add('collapse');
18+
knowl.dataset.bsToggle = 'modal';
19+
if (!knowl.knowlModal) {
20+
knowl.knowlModal = document.createElement('div');
21+
knowl.knowlModal.id = `knowl-uid-${knowlUID++}`;
22+
knowl.knowlModal.classList.add('modal', 'fade');
23+
knowl.knowlModal.tabIndex = -1;
24+
knowl.knowlModal.setAttribute('aria-labelledby', `${knowl.knowlModal.id}-title`);
25+
knowl.knowlModal.setAttribute('aria-hidden', 'true');
2826

29-
const knowlOutput = document.createElement('div');
30-
knowlOutput.classList.add('knowl-output');
27+
const knowlDialog = document.createElement('div');
28+
knowlDialog.classList.add(
29+
'knowl-dialog',
30+
'modal-dialog',
31+
'modal-dialog-centered',
32+
'modal-dialog-scrollable'
33+
);
34+
knowlDialog.dataset.iframeHeight = '1';
35+
knowl.knowlModal.append(knowlDialog);
3136

3237
const knowlContent = document.createElement('div');
33-
knowlContent.classList.add('knowl-content');
34-
knowlOutput.append(knowlContent);
38+
knowlContent.classList.add('modal-content');
39+
knowlDialog.append(knowlContent);
40+
41+
const knowlHeader = document.createElement('div');
42+
knowlHeader.classList.add('modal-header');
43+
44+
const knowlTitle = document.createElement('h1');
45+
knowlTitle.classList.add('modal-title', 'fs-5');
46+
knowlTitle.id = `${knowl.knowlModal.id}-title`;
47+
knowlTitle.textContent = knowl.dataset.knowlTitle || knowl.textContent;
48+
49+
const closeButton = document.createElement('button');
50+
closeButton.type = 'button';
51+
closeButton.classList.add('btn-close');
52+
closeButton.dataset.bsDismiss = 'modal';
53+
closeButton.setAttribute('aria-label', 'Close');
54+
55+
knowlHeader.append(knowlTitle, closeButton);
56+
57+
const knowlBody = document.createElement('div');
58+
knowlBody.classList.add('modal-body');
59+
60+
knowlContent.append(knowlHeader, knowlBody);
3561

3662
if (knowl.dataset.knowlUrl) {
3763
const knowlFooter = document.createElement('div');
38-
knowlFooter.classList.add('knowl-footer');
64+
knowlFooter.classList.add('modal-footer', 'knowl-footer', 'justify-content-center', 'p-1');
3965
knowlFooter.textContent = knowl.dataset.knowlUrl;
40-
knowlOutput.append(knowlFooter);
66+
knowlContent.append(knowlFooter);
4167
}
4268

43-
knowl.knowlContainer.appendChild(knowlOutput);
44-
45-
knowl.knowlContainer.addEventListener('show.bs.collapse', () => knowl.classList.add('active'));
46-
knowl.knowlContainer.addEventListener('hide.bs.collapse', () => knowl.classList.remove('active'));
47-
48-
// If the knowl is inside a table row, then insert a new row into the table after that one to contain
49-
// the knowl content. If the knowl is inside a list element, then insert the content after the list
50-
// element. Otherwise insert the content either before the first sibling that follows it that is
51-
// display block, or append it to the first ancestor that is display block.
52-
let insertElt = knowl.closest('tr');
53-
if (insertElt) {
54-
const row = document.createElement('tr');
55-
const td = document.createElement('td');
56-
td.colSpan = insertElt.childElementCount;
57-
td.appendChild(knowl.knowlContainer);
58-
row.appendChild(td);
59-
insertElt.after(row);
60-
} else {
61-
insertElt = knowl.closest('li');
62-
if (insertElt) {
63-
const newDiv = document.createElement('div');
64-
newDiv.append(knowl.knowlContainer);
65-
insertElt.append(newDiv);
66-
} else {
67-
let append = false;
68-
insertElt = knowl;
69-
do {
70-
const lastElt = insertElt;
71-
insertElt = lastElt.nextElementSibling;
72-
if (!insertElt) {
73-
insertElt = lastElt.parentNode;
74-
append = true;
75-
}
76-
} while (getComputedStyle(insertElt)?.getPropertyValue('display') !== 'block');
69+
knowl.knowlModal.addEventListener('shown.bs.modal', () => {
70+
const heightAdjust = Math.min(
71+
600,
72+
knowlBody.scrollHeight +
73+
knowlHeader.offsetHeight +
74+
(knowlContent.querySelector('.modal-footer')?.offsetHeight || 0)
75+
);
76+
if (knowlDialog.offsetHeight < heightAdjust) knowlDialog.style.height = `${heightAdjust}px`;
77+
});
7778

78-
if (append) insertElt.append(knowl.knowlContainer);
79-
else insertElt.before(knowl.knowlContainer);
80-
}
81-
}
79+
document.body.append(knowl.knowlModal);
8280

83-
knowl.dataset.bsTarget = `#${knowl.knowlContainer.id}`;
81+
knowl.dataset.bsTarget = `#${knowl.knowlModal.id}`;
8482

8583
if (knowl.dataset.knowlContents) {
8684
// Inline html
87-
if (knowl.dataset.base64 == '1') {
88-
if (window.Base64) setInnerHTML(knowlContent, Base64.decode(knowl.dataset.knowlContents));
89-
else {
90-
setInnerHTML(knowlContent, 'ERROR: Base64 decoding not available');
91-
knowlContent.classList.add('knowl-error');
92-
}
93-
} else {
94-
setInnerHTML(knowlContent, knowl.dataset.knowlContents);
95-
}
85+
setInnerHTML(knowlBody, knowl.dataset.knowlContents);
86+
9687
// If we are using MathJax, then render math content.
9788
if (window.MathJax) {
98-
MathJax.startup.promise = MathJax.startup.promise.then(() =>
99-
MathJax.typesetPromise([knowlContent])
100-
);
89+
MathJax.startup.promise = MathJax.startup.promise.then(() => MathJax.typesetPromise([knowlBody]));
10190
}
10291
} else if (knowl.dataset.knowlUrl) {
10392
// Retrieve url content.
10493
fetch(knowl.dataset.knowlUrl)
10594
.then((response) => (response.ok ? response.text() : response))
10695
.then((data) => {
10796
if (typeof data == 'object') {
108-
knowlContent.textContent = `ERROR: ${data.status} ${data.statusText}`;
109-
knowlContent.classList.add('knowl-error');
97+
knowlBody.textContent = `ERROR: ${data.status} ${data.statusText}`;
98+
knowlBody.classList.add('knowl-error');
11099
} else {
111-
setInnerHTML(knowlContent, data);
100+
setInnerHTML(knowlBody, data);
112101
}
113102
// If we are using MathJax, then render math content.
114103
if (window.MathJax) {
115104
MathJax.startup.promise = MathJax.startup.promise.then(() =>
116-
MathJax.typesetPromise([knowlContent])
105+
MathJax.typesetPromise([knowlBody])
117106
);
118107
}
108+
})
109+
.catch((err) => {
110+
knowlBody.textContent = `ERROR: ${err}`;
111+
knowlBody.classList.add('knowl-error');
119112
});
120113
} else {
121-
knowlContent.textContent = 'ERROR: knowl content not provided.';
122-
knowlContent.classList.add('knowl-error');
114+
knowlBody.textContent = 'ERROR: knowl content not provided.';
115+
knowlBody.classList.add('knowl-error');
123116
}
124117
}
125118
};

htdocs/js/Knowls/knowl.scss

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
.knowl {
2+
color: #00a;
3+
background-color: #eef;
4+
border: 1px solid #88f;
5+
border-radius: 3px;
6+
cursor: pointer;
7+
8+
&:hover {
9+
color: #006;
10+
background-color: #ccf;
11+
border-color: #33f;
12+
}
13+
14+
&:focus-visible {
15+
border-color: #33f;
16+
box-shadow: 0px 0px 0px 0.2rem #5555ff88;
17+
outline: 0;
18+
}
19+
}
20+
21+
li > .knowl {
22+
margin: 0.2rem 0;
23+
}
24+
25+
.knowl-error {
26+
color: darkred;
27+
}
28+
29+
.knowl-footer {
30+
font-size: x-small;
31+
background: #eef;
32+
color: #555;
33+
}
34+
35+
// MathJax sets the z-index to 200 which is far below a modal dialog at 1055. So raise that above the modal dialog.
36+
// This is really a bug in MathJax. MathJax should handle this differently.
37+
.CtxtMenu_MenuFrame {
38+
z-index: 1060 !important;
39+
40+
.CtxtMenu_Menu {
41+
z-index: 1060;
42+
}
43+
}

0 commit comments

Comments
 (0)