change file path in file using title (#7649)

stephannn committed May 16, 2026 at 18:46 UTC 2ed4657d480653e5dd3167c6a9250f714fd6a9af
1 file changed +86 -7
views/default3.handlebars
+86 -7
@@ -1293,7 +1293,7 @@
1293 <option value=6>Descend by date</option>
1294 </select>
1295 </div>
1296 - <div>&nbsp;&nbsp;<span id="p13currentpath"></span></div>
1296 + <div id="p13pathrow" style="display:none" ondblclick="p13pathRowClick(event)">&nbsp;&nbsp;<span id="p13currentpath" ondblclick="p13pathRowClick(event)"></span><input type="text" id="p13currentpathinput" class="form-control form-control-sm" style="width: auto; min-width: 400px; display:none;" onkeydown="return p13onPathKeyDown(event)" onblur="p13hidePathInput()" /></div>
1297 </td>
1298 </tr>
1299 </table>
@@ -12326,6 +12326,8 @@
12326 QV('p13Connectspan', (state == 0) && (filesNode.mtype == 2)); // Files Connect button and dropdown
12327 QV('p13Connectsspan', (state == 0) && (features2 & 0x200) && (filesNode.agent != null) && (filesNode.agent.id != 3) && (filesNode.agent.id != 4) && ((features2 & 0x800000) == 0)); // Files SFTP Connect button and dropdown
12328 QV('p13Disconnect', state != 0);
12329 + QV('p13pathrow', state == 3);
12330 + if (state != 3) { QV('p13currentpathinput', false); QV('p13currentpath', true); }
12331 var str = StatusStrs[state];
12332 if (state == 3) {
12333 if (files.contype == 2) { str += ", SFTP"; }
@@ -12339,6 +12341,9 @@
12341 p13filetree = null;
12342 p13filetreelocation = [];
12343 QH('p13currentpath', '');
12344 + Q('p13currentpathinput').value = '';
12345 + QV('p13currentpathinput', false);
12346 + QV('p13currentpath', true);
12347 QE('p13FolderUp', false);
12348 QV('filesRecordIcon', false);
12349 p13setActions();
@@ -12479,7 +12484,19 @@
12484
12485 if (data.path != null) {
12486 if (data.dir == null) {
12482 - if (p13targetpath != '') { p13folderup(); }
12487 + // Path not found, go up directory tree until we find a valid path
12488 + if (p13targetpath != '') {
12489 + var pathParts = p13targetpath.split('/').filter(function(p) { return p != ''; });
12490 + if (pathParts.length > 0) {
12491 + pathParts.pop(); // Remove last part
12492 + p13targetpath = pathParts.join('/');
12493 + p13requestFolderPath(p13targetpath);
12494 + } else {
12495 + // Already at root, just refresh to root
12496 + p13targetpath = '';
12497 + p13requestFolderPath(p13targetpath);
12498 + }
12499 + }
12500 } else {
12501 data.path = data.path.replace(/\//g, '\\');
12502 if ((p13filetree != null) && (data.path == p13filetree.path)) {
@@ -12529,13 +12546,23 @@
12546 }
12547
12548 function p13updateFiles(checkedNames) {
12532 - var html1 = '', html2 = '', displayPath = '<a href=# style=cursor:pointer onclick="return p13folderup(0)">' + "Root" + '</a>', fullPath = 'Root';
12549 + var html1 = '', html2 = '', displayPath = '', displayPathInput = '';
12550 if (p13filetree == null) return;
12551 // Work on parsing the file path
12552 var x = p13filetree.path.split('\\');
12553 p13filetreelocation = [];
12554 for (var i in x) { if (x[i] != '') { p13filetreelocation.push(x[i]); } } // Remove empty spaces
12538 - for (var i in p13filetreelocation) { displayPath += ' / <a href=# style=cursor:pointer onclick="return p13folderup(' + (parseInt(i) + 1) + ')">' + EscapeHtml(p13filetreelocation[i]) + '</a>' } // Setup the path we display
12555 + // Set the breadcrumb display value
12556 + displayPath = '<a href=# style=cursor:pointer onclick="return p13folderup(0)">' + "Root" + '</a>';
12557 + for (var i in p13filetreelocation) { displayPath += ' / <a href=# style=cursor:pointer onclick="return p13folderup(' + (parseInt(i) + 1) + ')">' + EscapeHtml(p13filetreelocation[i]) + '</a>'; }
12558 + // Set the input display value
12559 + if (isWindowsNode(currentNode)) {
12560 + displayPathInput = p13filetreelocation.join('\\');
12561 + if (displayPathInput && !displayPathInput.endsWith('\\')) { displayPathInput += '\\'; }
12562 + } else {
12563 + displayPathInput = '/' + p13filetreelocation.join('/');
12564 + if (displayPathInput != '/' && !displayPathInput.endsWith('/')) { displayPathInput += '/'; }
12565 + }
12566 var newlinkpath = p13filetreelocation.join('/');
12567
12568 // Sort the files
@@ -12610,6 +12637,7 @@
12637 // Display the files and path
12638 QH('p13files', html1 + html2);
12639 QH('p13currentpath', displayPath);
12640 + Q('p13currentpathinput').value = displayPathInput;
12641 QE('p13FolderUp', p13filetreelocation.length != 0);
12642
12643 // Re-check all boxes if needed using names
@@ -12634,6 +12662,57 @@
12662 files.sendText({ action: 'open', reqid: 1, path: openfilefolder, dir: (p13getFileSelDirCount() == 1) ? true : false });
12663 }
12664
12665 + // Path input field handlers
12666 + function p13pathRowClick(event) {
12667 + if (event && event.target && event.target.closest && (event.target.closest('.toright2') || event.target.closest('select') || event.target.closest('input') || event.target.closest('button'))) { return; }
12668 + if ((!event || event.type !== 'dblclick') && event && event.target && ((event.target.tagName == 'A') || (event.target.closest && event.target.closest('a')))) { return; }
12669 + p13showPathInput();
12670 + }
12671 +
12672 + function p13showPathInput() {
12673 + var pathSpan = Q('p13currentpath');
12674 + var pathInput = Q('p13currentpathinput');
12675 + pathSpan.style.display = 'none';
12676 + pathInput.style.display = 'inline-block';
12677 + pathInput.focus();
12678 + pathInput.select();
12679 + }
12680 +
12681 + function p13hidePathInput() {
12682 + var pathSpan = Q('p13currentpath');
12683 + var pathInput = Q('p13currentpathinput');
12684 + pathInput.style.display = 'none';
12685 + pathSpan.style.display = '';
12686 + }
12687 +
12688 + function p13onPathKeyDown(event) {
12689 + if (event.key === 'Enter') {
12690 + event.preventDefault();
12691 + var pathInput = Q('p13currentpathinput');
12692 + var newPath = pathInput.value.trim();
12693 + if (newPath) {
12694 + p13targetpath = newPath.split('\\').join('/');
12695 + // Remove trailing slash for consistency
12696 + if (p13targetpath.length > 1 && p13targetpath.endsWith('/')) {
12697 + p13targetpath = p13targetpath.substring(0, p13targetpath.length - 1);
12698 + }
12699 + p13requestFolderPath(p13targetpath);
12700 + }
12701 + p13hidePathInput();
12702 + return false;
12703 + } else if (event.key === 'Escape') {
12704 + event.preventDefault();
12705 + p13hidePathInput();
12706 + p13updateFiles();
12707 + return false;
12708 + }
12709 + return true;
12710 + }
12711 +
12712 + function p13requestFolderPath(path) {
12713 + if (files) { p13storeCurrentPath(path); files.sendText({ action: 'ls', reqid: 1, path: path }); }
12714 + }
12715 +
12716 function p13gotofolder() {
12717 xxdialogButtons = 3;
12718 setModalContent('xxAddAgent', "Go To Folder", '<input type=text id=p13folderinput style=width:100% value="' + (isWindowsNode(currentNode) ? p13targetpath.replaceAll('/','\\') + '\\' : p13targetpath + '/') +'"placeholder="' + (isWindowsNode(currentNode) ? 'C:\\' : '/var/www') + '" />');
@@ -12642,18 +12721,18 @@
12721 }
12722 function p13gotofolderEx() {
12723 p13targetpath = Q('p13folderinput').value.split('\\').join('/');
12645 - if (files) { p13storeCurrentPath(p13targetpath); files.sendText({ action: 'ls', reqid: 1, path: p13targetpath }); }
12724 + p13requestFolderPath(p13targetpath);
12725 }
12726
12727 function p13folderset(x) {
12728 p13targetpath = joinPaths(p13filetree.path, p13filetree.dir[x].n).split('\\').join('/');
12650 - if (files) { p13storeCurrentPath(p13targetpath); files.sendText({ action: 'ls', reqid: 1, path: p13targetpath }); }
12729 + p13requestFolderPath(p13targetpath);
12730 }
12731
12732 function p13folderup(x) {
12733 if (x == null) { p13filetreelocation.pop(); } else { while (p13filetreelocation.length > x) { p13filetreelocation.pop(); } }
12734 p13targetpath = p13filetreelocation.join('/');
12656 - if (files) { p13storeCurrentPath(p13targetpath); files.sendText({ action: 'ls', reqid: 1, path: p13targetpath }); }
12735 + p13requestFolderPath(p13targetpath);
12736 return false;
12737 }
12738