pywebexec 1.7.11__py3-none-any.whl → 1.7.12__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -36,17 +36,6 @@ th {
36
36
  .outcol {
37
37
  width: 100%;
38
38
  }
39
- select { /* Safari bug */
40
- -webkit-appearance: none;
41
- -webkit-border-radius: none;
42
- appearance: none;
43
- outline: none;
44
- font-size: 15px;
45
- border: #aaa solid 1px;
46
- border-radius: 5px;
47
- padding: 0px 5px 5px 0px;
48
- min-width: 150px;
49
- }
50
39
  .output {
51
40
  background: #111;
52
41
  padding: 10px;
@@ -212,15 +201,18 @@ form {
212
201
  margin-top: 2px;
213
202
  overflow-y: auto;
214
203
  z-index: 1000;
204
+ max-height: 200px;
215
205
  }
216
206
 
217
207
  .command-item {
218
- padding: 3px 5px 3px 5px;
208
+ padding: 1px 5px 1px 5px;
209
+ margin-top: 1px;
219
210
  cursor: pointer;
211
+ outline: none; /* Remove default focus border */
220
212
  }
221
213
 
222
- .command-item:hover, .command-item.highlighted {
223
- background-color: #eee;
214
+ .command-item:hover, .command-item.highlighted, .command-item:focus {
215
+ background-color: #a7d0ff;
224
216
  }
225
217
 
226
218
  .currentcommand {
@@ -301,17 +293,9 @@ span {
301
293
  }
302
294
  .font-increase {
303
295
  background-image: url("/static/images/font-increase.svg");
304
- /*background-size: contain;*/
305
- background-repeat: no-repeat;
306
- background-position: center;
307
- background-size: 14px 14px;
308
296
  }
309
297
  .font-decrease {
310
298
  background-image: url("/static/images/font-decrease.svg");
311
- /*background-size: contain;*/
312
- background-repeat: no-repeat;
313
- background-position: center;
314
- background-size: 14px 14px;
315
299
  }
316
300
  .font-size-button {
317
301
  background-color: #444;
@@ -322,6 +306,9 @@ span {
322
306
  font-size: 14px;
323
307
  width: 20px;
324
308
  height: 20px;
309
+ background-repeat: no-repeat;
310
+ background-position: center;
311
+ background-size: 14px 14px;
325
312
  }
326
313
  .font-size-button:hover {
327
314
  background-color: #666;
@@ -1,47 +1,46 @@
1
1
  // commands.js
2
2
  let commandInput = document.getElementById('command');
3
3
  let paramsInput = document.getElementById('params');
4
- let commandListSelect = document.getElementById('commandList');
4
+ let commandListDiv = document.getElementById('commandList');
5
5
  let showCommandListButton = document.getElementById('showCommandListButton');
6
6
  let isHandlingKeydown = false;
7
7
  let firstVisibleItem = 0;
8
8
 
9
9
  function unfilterCommands() {
10
- const options = commandListSelect.options;
11
- for (let i = 0; i < options.length; i++) {
12
- options[i].style.display = 'block';
10
+ const items = commandListDiv.children;
11
+ for (let i = 0; i < items.length; i++) {
12
+ items[i].style.display = 'block';
13
13
  }
14
- commandListSelect.size = Math.min(20, commandListSelect.options.length);
14
+ commandListDiv.style.display = 'block';
15
15
  }
16
16
 
17
17
  function filterCommands() {
18
18
  const value = commandInput.value.slice(0, commandInput.selectionStart);
19
- const options = commandListSelect.options;
19
+ const items = commandListDiv.children;
20
20
  let nbVisibleItems = 0;
21
21
  firstVisibleItem = -1;
22
- for (let i = 0; i < options.length; i++) {
23
- if (options[i].text.startsWith(value)) {
24
- options[i].style.display = 'block';
22
+ for (let i = 0; i < items.length; i++) {
23
+ if (items[i].textContent.startsWith(value)) {
24
+ items[i].style.display = 'block';
25
25
  nbVisibleItems += 1;
26
26
  if (firstVisibleItem === -1) {
27
27
  firstVisibleItem = i;
28
28
  }
29
29
  } else {
30
- options[i].style.display = 'none';
30
+ items[i].style.display = 'none';
31
31
  }
32
32
  }
33
33
  if (nbVisibleItems > 1) {
34
- commandListSelect.size = Math.min(20, nbVisibleItems);
35
- commandListSelect.style.display = 'block';
34
+ commandListDiv.style.display = 'block';
36
35
  } else {
37
- commandListSelect.style.display = 'none';
36
+ commandListDiv.style.display = 'none';
38
37
  }
39
38
  }
40
39
 
41
40
  function setCommandListPosition() {
42
41
  const rect = commandInput.getBoundingClientRect();
43
- commandListSelect.style.left = `${rect.left}px`;
44
- commandListSelect.style.top = `${rect.bottom}px`;
42
+ commandListDiv.style.left = `${rect.left}px`;
43
+ commandListDiv.style.top = `${rect.bottom}px`;
45
44
  }
46
45
 
47
46
  function adjustInputWidth(input) {
@@ -49,7 +48,6 @@ function adjustInputWidth(input) {
49
48
  input.style.width = `${input.scrollWidth}px`;
50
49
  }
51
50
 
52
-
53
51
  paramsInput.addEventListener('input', () => adjustInputWidth(paramsInput));
54
52
  commandInput.addEventListener('input', () => {
55
53
  adjustInputWidth(commandInput);
@@ -73,12 +71,12 @@ commandInput.addEventListener('input', (event) => {
73
71
  commandInput.setSelectionRange(newValue.length, newValue.length);
74
72
  }
75
73
  const value = commandInput.value;
76
- const options = commandListSelect.options;
74
+ const options = commandListDiv.children;
77
75
  if (value) {
78
- const match = Array.from(options).find(option => option.text.startsWith(value));
76
+ const match = Array.from(options).find(option => option.textContent.startsWith(value));
79
77
  if (match) {
80
- commandInput.value = match.text;
81
- commandInput.setSelectionRange(value.length, match.text.length);
78
+ commandInput.value = match.textContent;
79
+ commandInput.setSelectionRange(value.length, match.textContent.length);
82
80
  } else {
83
81
  commandInput.value = value.slice(0, -1);
84
82
  }
@@ -88,17 +86,15 @@ commandInput.addEventListener('input', (event) => {
88
86
  });
89
87
 
90
88
  commandInput.addEventListener('keydown', (event) => {
91
- if (event.key === ' ' || event.key === 'ArrowRight') {
89
+ if (event.key === ' ' || event.key === 'ArrowRight' || event.key === 'Tab') {
92
90
  event.preventDefault();
93
91
  paramsInput.focus();
94
92
  paramsInput.setSelectionRange(0, paramsInput.value.length);
93
+ commandListDiv.style.display = 'none'
95
94
  } else if (event.key === 'ArrowDown') {
96
- if (commandListSelect.options.length > 1) {
97
- commandListSelect.style.display = 'block';
98
- commandListSelect.selectedIndex = firstVisibleItem;
99
- commandListSelect.focus();
100
- commandListSelect.options[firstVisibleItem].scrollIntoView();
101
- commandListSelect.options[firstVisibleItem].focus();
95
+ if (commandListDiv.children.length > 1) {
96
+ commandListDiv.style.display = 'block';
97
+ commandListDiv.children[firstVisibleItem].focus();
102
98
  }
103
99
  event.preventDefault();
104
100
  }
@@ -121,47 +117,65 @@ paramsInput.addEventListener('keydown', (event) => {
121
117
  }
122
118
  });
123
119
 
124
- commandListSelect.addEventListener('keydown', (event) => {
125
- if (event.key === 'Enter') {
126
- event.preventDefault(); // Prevent form submission
127
- const selectedOption = commandListSelect.options[commandListSelect.selectedIndex];
128
- commandInput.value = selectedOption.text;
129
- commandListSelect.style.display = 'none';
130
- adjustInputWidth(commandInput);
131
- paramsInput.focus();
132
- return;
133
- }
134
- if (event.key === 'ArrowUp' && commandListSelect.selectedIndex == 0) {
120
+ commandListDiv.addEventListener('keydown', (event) => {
121
+ const items = Array.from(commandListDiv.children);
122
+ const currentIndex = items.indexOf(document.activeElement);
123
+
124
+ if (event.key === 'Escape') {
135
125
  commandInput.focus();
136
- commandListSelect.style.display = 'none'
126
+ commandListDiv.style.display = 'none';
127
+ }else if (event.key === 'ArrowDown') {
128
+ event.preventDefault();
129
+ const nextIndex = (currentIndex + 1) % items.length;
130
+ items[nextIndex].focus();
131
+ } else if (event.key === 'ArrowUp') {
132
+ event.preventDefault();
133
+ if (currentIndex === 0 || items[currentIndex-1].style.display == 'none') {
134
+ commandInput.focus();
135
+ commandListDiv.style.display = 'none';
136
+ } else {
137
+ const prevIndex = (currentIndex - 1 + items.length) % items.length;
138
+ items[prevIndex].focus();
139
+ }
140
+ } else if (event.key === 'Enter' || event.key === 'Tab' || event.key === ' ') {
141
+ event.preventDefault(); // Prevent form submission
142
+ const selectedOption = document.activeElement;
143
+ if (selectedOption.classList.contains('command-item')) {
144
+ commandInput.value = selectedOption.textContent;
145
+ commandListDiv.style.display = 'none';
146
+ adjustInputWidth(commandInput);
147
+ paramsInput.focus();
148
+ }
137
149
  }
138
150
  });
139
151
 
140
- commandListSelect.addEventListener('click', (event) => {
152
+ commandListDiv.addEventListener('click', (event) => {
141
153
  event.preventDefault(); // Prevent form submission
142
- const selectedOption = commandListSelect.options[commandListSelect.selectedIndex];
143
- commandInput.value = selectedOption.text;
144
- commandListSelect.style.display = 'none';
145
- adjustInputWidth(commandInput);
146
- paramsInput.focus();
154
+ const selectedOption = event.target;
155
+ if (selectedOption.classList.contains('command-item')) {
156
+ commandInput.value = selectedOption.textContent;
157
+ commandListDiv.style.display = 'none';
158
+ adjustInputWidth(commandInput);
159
+ paramsInput.focus();
160
+ }
147
161
  });
148
162
 
149
163
 
150
164
  commandInput.addEventListener('click', () => {
151
165
  setCommandListPosition();
152
- if (commandListSelect.style.display == 'none')
153
- commandListSelect.style.display = 'block';
166
+ if (commandListDiv.style.display == 'none')
167
+ commandListDiv.style.display = 'block';
154
168
  else
155
- commandListSelect.style.display = 'none';
169
+ commandListDiv.style.display = 'none';
156
170
  filterCommands();
157
171
  });
158
172
 
159
173
  commandInput.addEventListener('blur', (event) => {
160
- if (event.relatedTarget === showCommandListButton || event.relatedTarget === commandListSelect) {
174
+ if (event.relatedTarget === showCommandListButton || event.relatedTarget === commandListDiv || event.relatedTarget.classList.includes('command-item')) {
161
175
  event.preventDefault();
162
176
  return;
163
177
  }
164
- commandListSelect.style.display = 'none';
178
+ commandListDiv.style.display = 'none';
165
179
  adjustInputWidth(commandInput);
166
180
  });
167
181
 
@@ -169,20 +183,16 @@ showCommandListButton.addEventListener('click', (event) => {
169
183
  event.preventDefault();
170
184
  setCommandListPosition();
171
185
  unfilterCommands();
172
- if (commandListSelect.style.display == 'none')
173
- commandListSelect.style.display = 'block';
174
- else
175
- commandListSelect.style.display = 'none';
176
186
  });
177
187
 
178
188
  window.addEventListener('click', (event) => {
179
- if (!commandInput.contains(event.target) && !commandListSelect.contains(event.target) && !showCommandListButton.contains(event.target)) {
180
- commandListSelect.style.display = 'none';
189
+ if (!commandInput.contains(event.target) && !commandListDiv.contains(event.target) && !showCommandListButton.contains(event.target)) {
190
+ commandListDiv.style.display = 'none';
181
191
  }
182
192
  });
183
193
 
184
194
  window.addEventListener('keydown', (event) => {
185
- if ([commandInput, paramsInput, commandListSelect].includes(document.activeElement)) return;
195
+ if ([commandInput, paramsInput, commandListDiv].includes(document.activeElement)) return;
186
196
  if (event.code === `Key${event.key.toUpperCase()}`) {
187
197
  commandInput.focus();
188
198
  commandInput.dispatchEvent(new KeyboardEvent('keydown', event));
@@ -207,22 +217,22 @@ async function fetchExecutables() {
207
217
  throw new Error('Failed to fetch command status');
208
218
  }
209
219
  const executables = await response.json();
210
- commandListSelect.innerHTML = '';
220
+ commandListDiv.innerHTML = '';
211
221
  executables.forEach(executable => {
212
- const option = document.createElement('option');
213
- option.className = 'command-item';
214
- option.text = executable;
215
- commandListSelect.appendChild(option);
222
+ const div = document.createElement('div');
223
+ div.className = 'command-item';
224
+ div.textContent = executable;
225
+ div.tabIndex = 0; // Make the div focusable
226
+ commandListDiv.appendChild(div);
216
227
  });
217
228
  } catch (error) {
218
229
  alert("Failed to fetch executables");
219
230
  }
220
- commandListSelect.size = Math.min(20, commandListSelect.options.length);
221
- if (commandListSelect.options.length == 1) {
222
- commandInput.value = commandListSelect.options[0].text;
231
+ if (commandListDiv.children.length == 1) {
232
+ commandInput.value = commandListDiv.children[0].textContent;
223
233
  showCommandListButton.style.display = 'none';
224
234
  }
225
- if (commandListSelect.options.length == 0)
235
+ if (commandListDiv.children.length == 0)
226
236
  document.getElementById('launchForm').style.display = 'none';
227
237
 
228
238
  }
@@ -19,7 +19,7 @@
19
19
  <div id="showCommandListButton" class="show-command-list-button">
20
20
  <span class="arrow">&#9660;</span>
21
21
  </div>
22
- <select id="commandList" class="command-list" size="20"></select>
22
+ <div id="commandList" class="command-list"></div>
23
23
  <input type="text" id="params" name="params" oninput="this.style.width = ((this.value.length + 1) * 8) + 'px';">
24
24
  </div>
25
25
  <button type="submit">Run</button>
pywebexec/version.py CHANGED
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '1.7.11'
16
- __version_tuple__ = version_tuple = (1, 7, 11)
15
+ __version__ = version = '1.7.12'
16
+ __version_tuple__ = version_tuple = (1, 7, 12)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: pywebexec
3
- Version: 1.7.11
3
+ Version: 1.7.12
4
4
  Summary: Simple Python HTTP Exec Server
5
5
  Home-page: https://github.com/joknarf/pywebexec
6
6
  Author: Franck Jouvanceau
@@ -1,8 +1,8 @@
1
1
  pywebexec/__init__.py,sha256=4spIsVaF8RJt8S58AG_wWoORRNkws9Iwqprj27C3ljM,99
2
2
  pywebexec/pywebexec.py,sha256=MmpHK2SscvIPj1gmV9AcJXYfeaL-at5BDgLhKIxzZBc,33604
3
- pywebexec/version.py,sha256=TBdoKbRERu0RLmgOlLn0qO1c9vmbdCN_H7OMlZVRf8o,413
3
+ pywebexec/version.py,sha256=dSwjHj4iLBCyQl7aZEEt5q3jGDuArBY7LwcMyXcjaUg,413
4
4
  pywebexec/static/css/Consolas NF.ttf,sha256=DJEOzF0eqZ-kxu3Gs_VE8X0NJqiobBzmxWDGpdgGRxI,1313900
5
- pywebexec/static/css/style.css,sha256=uv8BQzD0SGa2pmUfiFYt1UVLJhBE6DpFLUIEAuBV6Z8,8218
5
+ pywebexec/static/css/style.css,sha256=6Q89tdXTzuGaMJJ26gp-YD2L0eIsFb7C83IYOoMJb8g,7915
6
6
  pywebexec/static/css/xterm.css,sha256=uo5phWaUiJgcz0DAzv46uoByLLbJLeetYosL1xf68rY,5559
7
7
  pywebexec/static/images/aborted.svg,sha256=2nuvSwGBIZGWtlM1DrBO3qiSq1reDbcZDAj9rJXBnjY,380
8
8
  pywebexec/static/images/copy.svg,sha256=d9OwtGh5GzzZHzYcDrLfNxZYLth1Q64x7bRyYxu4Px0,622
@@ -20,7 +20,7 @@ pywebexec/static/images/popup.svg,sha256=0Bl9A_v5cBsMPn6FnOlVWlAQKgd2zqiWQbhjcL9
20
20
  pywebexec/static/images/resume.svg,sha256=99LP1Ya2JXakRCO9kW8JMuT_4a_CannF65EiuwtvK4A,607
21
21
  pywebexec/static/images/running.svg,sha256=fBCYwYb2O9K4N3waC2nURP25NRwZlqR4PbDZy6JQMww,610
22
22
  pywebexec/static/images/success.svg,sha256=NVwezvVMplt46ElW798vqGfrL21Mw_DWHUp_qiD_FU8,489
23
- pywebexec/static/js/commands.js,sha256=HNaAwJWW7EGHX4VrkQpfTyH92SsEbygSVa_jERk4tcc,7957
23
+ pywebexec/static/js/commands.js,sha256=1g771zk-EV1H7vKGWZSrTK_avWF6pBgdIy860hodxiw,8332
24
24
  pywebexec/static/js/popup.js,sha256=_2GzUizJ-sdZFWG7SZwbYJTPbu4EvVq7D5Q_UE8nepA,9452
25
25
  pywebexec/static/js/script.js,sha256=bmaR9TJhZMEK_Niz0TCp8CJdnLKh4ayaxLvqgjxdoRs,18482
26
26
  pywebexec/static/js/xterm/LICENSE,sha256=EU1P4eXTull-_T9I80VuwnJXubB-zLzUl3xpEYj2T1M,1083
@@ -33,11 +33,11 @@ pywebexec/static/js/xterm/addon-unicode11.js.map,sha256=paDj5KKtTIUGedQn2x7CaUTD
33
33
  pywebexec/static/js/xterm/xterm.js,sha256=H5kaw7Syg-v5bmCuI6AKUnZd06Lkb6b92p8aqwMvdJU,289441
34
34
  pywebexec/static/js/xterm/xterm.js.map,sha256=Y7O2Pb-fIS7Z8AC1D5s04_aiW_Jf1f4mCfN0U_OI6Zw,1118392
35
35
  pywebexec/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
- pywebexec/templates/index.html,sha256=vSR_PrREGvR6jbKKysABBYfvurw4OyarDrvcnHwRqnI,2969
36
+ pywebexec/templates/index.html,sha256=KSdQYBdzWKP6v0ETZsMO_729aosGBAzJxAss8T5jCto,2953
37
37
  pywebexec/templates/popup.html,sha256=f5m4u8WKpkevL2mQamGqo4_y-rSuLOXGuNsezuUbniY,1508
38
- pywebexec-1.7.11.dist-info/LICENSE,sha256=gRJf0JPT_wsZJsUGlWPTS8Vypfl9vQ1qjp6sNbKykuA,1064
39
- pywebexec-1.7.11.dist-info/METADATA,sha256=-n08jreVl7Ju9m-EjnKXlFNtojek5i11pAZmDHh5jpk,8149
40
- pywebexec-1.7.11.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
41
- pywebexec-1.7.11.dist-info/entry_points.txt,sha256=l52GBkPCXRkmlHfEyoVauyfBdg8o-CAtC8qQpOIjJK0,55
42
- pywebexec-1.7.11.dist-info/top_level.txt,sha256=vHoHyzngrfGdm_nM7Xn_5iLmaCrf10XO1EhldgNLEQ8,10
43
- pywebexec-1.7.11.dist-info/RECORD,,
38
+ pywebexec-1.7.12.dist-info/LICENSE,sha256=gRJf0JPT_wsZJsUGlWPTS8Vypfl9vQ1qjp6sNbKykuA,1064
39
+ pywebexec-1.7.12.dist-info/METADATA,sha256=9LbZYl-e-jOLwTE48iI17WHMvnd1ukT7zMcL2Z8QLSE,8149
40
+ pywebexec-1.7.12.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
41
+ pywebexec-1.7.12.dist-info/entry_points.txt,sha256=l52GBkPCXRkmlHfEyoVauyfBdg8o-CAtC8qQpOIjJK0,55
42
+ pywebexec-1.7.12.dist-info/top_level.txt,sha256=vHoHyzngrfGdm_nM7Xn_5iLmaCrf10XO1EhldgNLEQ8,10
43
+ pywebexec-1.7.12.dist-info/RECORD,,