Skip to content

Commit fbf58e2

Browse files
committed
NppExec Manual: adding some HTML/JS/CSS magic
1 parent deeaacf commit fbf58e2

File tree

6 files changed

+264
-256
lines changed

6 files changed

+264
-256
lines changed
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
body, html {
2+
margin: 0;
3+
padding: 0;
4+
height: 100%;
5+
overflow: hidden; /* Avoiding double-scrolling */
6+
font-family: sans-serif;
7+
}
8+
9+
.container {
10+
display: flex;
11+
width: 100%;
12+
height: 100vh;
13+
flex-direction: row;
14+
}
15+
16+
#toc-sidebar {
17+
position: relative;
18+
width: 30%;
19+
min-width: 100px;
20+
height: 100%;
21+
background-color: #f9f9f9; /* Optional: adds a slight distinction */
22+
}
23+
24+
#resizer {
25+
width: 6px;
26+
cursor: col-resize;
27+
background: #eee;
28+
border-left: 1px solid #ccc;
29+
border-right: 1px solid #ccc;
30+
transition: background 0.1s;
31+
z-index: 10; /* Resizer over the frames */
32+
}
33+
34+
#resizer:hover {
35+
background: #ddd;
36+
}
37+
38+
#content-area {
39+
position: relative;
40+
flex: 1;
41+
height: 100%;
42+
}
43+
44+
iframe {
45+
width: 100%;
46+
height: 100%;
47+
border: none;
48+
}
49+
50+
/* Visual Fix: disables iframe mouse capture while dragging the splitter */
51+
.dragging iframe {
52+
pointer-events: none;
53+
}
54+
55+
/* Hidden inputs for the focusing */
56+
#toc-focus-trigger, #focus-trigger {
57+
position: absolute;
58+
opacity: 0;
59+
pointer-events: none;
60+
width: 1px;
61+
height: 1px;
62+
}

docs/NppExec_Manual/main_ui.js

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
document.addEventListener('DOMContentLoaded', function() {
2+
"use strict";
3+
4+
// Resizer (Splitter)
5+
const resizer = document.getElementById('resizer');
6+
const sidebar = document.getElementById('toc-sidebar');
7+
const container = document.getElementById('main-container');
8+
9+
// Content Frame: focusing on mouse events
10+
const contentArea = document.getElementById('content-area');
11+
const contentFrame = document.getElementById('content-frame');
12+
const focusTrigger = document.getElementById('focus-trigger');
13+
14+
// TOC: focusing on mouse events
15+
const tocSidebar = document.getElementById('toc-sidebar');
16+
const tocFrame = document.getElementById('toc-frame');
17+
const tocFocusTrigger = document.getElementById('toc-focus-trigger');
18+
19+
(function handleQueryParam() {
20+
try {
21+
var query = location.search || '';
22+
var param = 'q=';
23+
var index = query.indexOf(param);
24+
25+
if (index !== -1 && contentFrame) {
26+
var value = query.slice(index + param.length);
27+
if (value) {
28+
// Modified to target the iframe element specifically
29+
contentFrame.contentWindow.location.replace('NppExec_Manual/' + value + '.html');
30+
}
31+
}
32+
} catch (e) { console.info(e); }
33+
})();
34+
35+
// Resizer logic
36+
if (resizer && sidebar && container) {
37+
resizer.addEventListener('mousedown', function(e) {
38+
e.preventDefault();
39+
container.classList.add('dragging');
40+
41+
document.addEventListener('mousemove', handleMouseMove);
42+
document.addEventListener('mouseup', function() {
43+
container.classList.remove('dragging');
44+
document.removeEventListener('mousemove', handleMouseMove);
45+
});
46+
});
47+
48+
function handleMouseMove(e) {
49+
const containerWidth = container.offsetWidth;
50+
const newWidthPercentage = (e.clientX / containerWidth) * 100;
51+
52+
// Limits: Prevents the sidebar from disappearing or becoming too huge
53+
if (newWidthPercentage > 5 && newWidthPercentage < 90) {
54+
sidebar.style.width = newWidthPercentage + '%';
55+
}
56+
}
57+
}
58+
59+
// Content Frame focusing logic
60+
if (contentArea && contentFrame && focusTrigger) {
61+
contentArea.addEventListener('mouseenter', function() {
62+
// 1. Setting the focus to the hidden focusTrigger
63+
focusTrigger.focus();
64+
// 2. Now setting the focus to the frame
65+
if (contentFrame.contentWindow) {
66+
contentFrame.contentWindow.focus();
67+
}
68+
});
69+
70+
// Additionally: ensuring the focus while scrolling
71+
contentArea.addEventListener('wheel', function() {
72+
if (document.activeElement !== contentFrame) {
73+
contentFrame.contentWindow.focus();
74+
}
75+
}, { passive: true });
76+
}
77+
78+
// TOC Frame focusing logic
79+
if (tocSidebar && tocFrame && tocFocusTrigger) {
80+
tocSidebar.addEventListener('mouseenter', function() {
81+
// 1. Focusing the left pane
82+
tocFocusTrigger.focus();
83+
// 2. Setting the focus to the TOC
84+
if (tocFrame.contentWindow) {
85+
tocFrame.contentWindow.focus();
86+
}
87+
});
88+
}
89+
});

docs/NppExec_Manual/search.js

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,54 @@ window.onload = function() {
66
var helpTopics = document.getElementById('matching-topics');
77
/* Keyword search <input> */
88
var searchBox = document.getElementById('topic-search-box');
9+
10+
/* When TOC gets the focus, setting the focus to helpTopics or searchBox */
11+
window.addEventListener('focus', function() {
12+
var helpTopics = document.getElementById('matching-topics');
13+
var searchBox = document.getElementById('topic-search-box');
14+
var searchResults = document.getElementById('search-results');
15+
16+
if (searchResults && searchResults.style.display !== 'none') {
17+
helpTopics.focus();
18+
} else {
19+
searchBox.focus();
20+
}
21+
});
22+
923
/* Shows the page mapped to the active <select> item */
1024
var clickToView = function(evnt) {
1125
evnt.preventDefault(); // Cancel any submit action
1226
try {
1327
if (!Boolean(helpTopics.value)) // Nothing selected
1428
return;
1529

16-
var searchParam = helpTopics[helpTopics.selectedIndex].dataset.contains
17-
var targetURI = helpTopics.value + encodeURI('?contains=' + searchParam)
18-
parent.frames['content'].location.replace(targetURI)
30+
var searchParam = helpTopics[helpTopics.selectedIndex].dataset.contains;
31+
var targetURI = helpTopics.value + encodeURI('?contains=' + searchParam);
32+
parent.frames['content'].location.replace(targetURI);
33+
34+
setTimeout(function() {
35+
helpTopics.focus();
36+
}, 100);
1937
} catch (e) {
2038
/* Handle the DOMException that may be thrown by trying to access cross-origin frames on the `file://` protocol
2139
* See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Property_access_denied
2240
*/
2341
if (e instanceof DOMException) {
24-
/* Open the requested doc in a "modal" window */
25-
window.open(targetURI, '_bank','noopener')
42+
/* Open the requested doc in a "modal" window */
43+
window.open(targetURI, '_bank','noopener');
44+
45+
setTimeout(function() {
46+
window.focus();
47+
helpTopics.focus();
48+
}, 100);
2649
} else {
27-
var docIndex = helpTopics.selectedIndex
28-
var requestedDoc = (docIndex >= 0) ? helpTopics[docIndex].innerHTML : helpTopics.value;
29-
window.alert('"' + requestedDoc + '" is missing or access is restricted.')
50+
var docIndex = helpTopics.selectedIndex;
51+
var requestedDoc = (docIndex >= 0) ? helpTopics[docIndex].innerHTML : helpTopics.value;
52+
window.alert('"' + requestedDoc + '" is missing or access is restricted.');
53+
54+
setTimeout(function() {
55+
helpTopics.focus();
56+
}, 100);
3057
}
3158
}
3259
};
@@ -88,11 +115,23 @@ window.onload = function() {
88115
/* Min visible size is 2 b/c the <optgroup> label is counted */
89116
helpTopics.size = Math.max(foundTopics.length + 1, 2);
90117
/* Make sure mobile <select> boxes are never blank */
91-
helpTopics.selectedIndex = 0;
118+
//helpTopics.selectedIndex = 0;
92119
helpTopics.addEventListener('change', clickToView, { 'passive': false });
93120
helpTopics.addEventListener('focus',
94121
/* Selecting the first <option> should *also* fire a 'change' event */
95122
function() { if (this.selectedIndex === 0) this.selectedIndex-- }, { 'once': true });
123+
124+
var focusContent = function(evnt) {
125+
if (evnt.type === 'dblclick' || evnt.key === 'Enter' || evnt.keyCode === 13) {
126+
setTimeout(function() {
127+
if (parent.frames['content']) {
128+
parent.frames['content'].focus();
129+
}
130+
}, 100);
131+
}
132+
};
133+
helpTopics.addEventListener('keydown', focusContent);
134+
helpTopics.addEventListener('dblclick', focusContent);
96135
}
97136
} catch (e) {
98137
console.error(e.message)

docs/NppExec_Manual/style.css

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,14 @@ button#goto-doc {
8080
code {
8181
font-family: "Courier New", Courier, mono;
8282
}
83+
84+
#matching-topics option:checked {
85+
background: #0078d7 !important; /* Standard Windows blue */
86+
color: white !important;
87+
}
88+
89+
/* For some browsers such as Chrome/Edge */
90+
#matching-topics:focus-within option:checked {
91+
background-color: #0078d7 !important;
92+
color: white !important;
93+
}

0 commit comments

Comments
 (0)