From 34dbe9e95d1ffeb8ec362c166bdc5c4904dd6fcf Mon Sep 17 00:00:00 2001 From: Marco Dickert Date: Mon, 20 Feb 2017 14:50:22 +0100 Subject: [PATCH] added keystrokes, extended multiselect function --- ifm.php | 83 ++++++++++++++++++++++++++++++++++++++++++++++----- src/ifm.js | 79 +++++++++++++++++++++++++++++++++++++++++++----- src/style.css | 4 +++ 3 files changed, 152 insertions(+), 14 deletions(-) diff --git a/ifm.php b/ifm.php index ef7b735..839f0d0 100644 --- a/ifm.php +++ b/ifm.php @@ -291,6 +291,10 @@ input[name=newperms] { width: 7em; } #filetable tr th.buttons { min-width: 95px; } #filetable tr.clickable-row.active td { background-color: lightblue; } +#filetable tbody tr.highlightedItem td { border-top: 1px solid #555 !important; border-bottom: 1px solid #555 !important; } +#filetable tbody tr.highlightedItem td:first-child { border-left: 1px solid #555; } +#filetable tbody tr.highlightedItem td:last-child { border-right: 1px solid #555; } +#filetable tbody tr.highlightedItem td:first-child a { outline: none; } #navbar { max-width: 100%; } @@ -485,13 +489,13 @@ function IFM() { this.rebuildFileTable = function( data ) { var newRows = $(document.createElement('tbody')); for(i=0;i'; + var newrow = ''; if(data[i].type=="file") { - newrow += '"'; newrow += '> '+data[i].name+''; } else { - newrow += ' '; + newrow += ' '; if( data[i].name == ".." ) newrow += "[ up ]"; else newrow += data[i].name; newrow += ''; @@ -540,13 +544,13 @@ function IFM() { if(ifm.inArray(1,[self.config.edit, self.config.rename, self.config.delete, self.config.extract])) { newrow += ''; if( data[i].name.toLowerCase().substr(-4) == ".zip" && self.config.extract == 1 ) { - newrow += ''; + newrow += ''; } else if( self.config.edit == 1 && data[i].type != "dir" ) { - newrow += ''; + newrow += ''; } if( data[i].name != ".." && data[i].name != "." ) { - if(self.config.rename == 1) newrow += ''; - if(self.config.delete == 1) newrow += ''; + if(self.config.rename == 1) newrow += ''; + if(self.config.delete == 1) newrow += ''; } newrow += ''; } @@ -569,6 +573,7 @@ function IFM() { }; this.changeDirectory = function( newdir, options={} ) { + console.log( "changeDirectory, newdir="+newdir ); config = { absolute: false, pushState: true }; jQuery.extend( config, options ); if( ! config.absolute ) newdir = self.pathCombine( self.currentDir, newdir ); @@ -1055,6 +1060,39 @@ function IFM() { this.task_update = function(progress, id) { $('#'+id+' .progress-bar').css('width', progress+'%').attr('aria-valuenow', progress); }; + this.selectItem = function( direction ) { + var highlightedItem = $('.highlightedItem'); + if( ! highlightedItem.length ) { + $('#filetable tbody tr:first-child').addClass( 'highlightedItem' ); + } else { + var newItem = ( direction=="next" ? highlightedItem.next() : highlightedItem.prev() ); + + if( newItem.is( 'tr' ) ) { + highlightedItem.removeClass( 'highlightedItem' ); + newItem.addClass( 'highlightedItem' ); + newItem.find( 'a' ).first().focus(); + if( ! this.isElementInViewport( newItem ) ) { + var scrollOffset = ( direction=="next" ? ( highlightedItem.offset().top - 15 ) : ( highlightedItem.offset().top - ( window.innerHeight || document.documentElement.clientHeight ) + highlightedItem.height() + 15 ) ); + $('html, body').animate({ + scrollTop: scrollOffset + }, 500 + ); + } + } + } + } + this.isElementInViewport = function isElementInViewport (el) { + if (typeof jQuery === "function" && el instanceof jQuery) { + el = el[0]; + } + var rect = el.getBoundingClientRect(); + return ( + rect.top >= 60 && + rect.left >= 0 && + rect.bottom <= ( (window.innerHeight || document.documentElement.clientHeight) ) && + rect.right <= (window.innerWidth || document.documentElement.clientWidth) + ); + } this.generateGuid = function() { var result, i, j; result = ''; @@ -1083,6 +1121,10 @@ function IFM() { if( $('#filetable tr.active').length > 0 ) { e.preventDefault(); self.multiDeleteDialog(); + } else { + var item = $('.highlightedItem'); + if( item.length ) + self.deleteFileDialog( item.data( 'filename' ) ); } break; case 'g': @@ -1117,6 +1159,33 @@ function IFM() { e.preventDefault(); self.changeDirectory( '..' ); break; + case 'ArrowRight': + e.preventDefault(); + var item = $('.highlightedItem'); + if( item.hasClass('isDir') ) + self.changeDirectory( item.data( 'filename' ) ); + break; + case 'ArrowDown': + e.preventDefault(); + self.selectItem('next'); + break; + case 'ArrowUp': + e.preventDefault(); + self.selectItem('prev'); + break; + case 'Escape': + if( $(':focus').is( '.clickable-row td:first-child a:first-child' ) && $('.highlightedItem').length ) { + e.preventDefault(); + $('.highlightedItem').removeClass( 'highlightedItem' ); + } + break; + case ' ': // todo: make it work only when noting other is focused + if( $(':focus').is( '.clickable-row td:first-child a:first-child' ) ) { + e.preventDefault(); + var item = $('.highlightedItem'); + if( item.is( 'tr' ) ) item.toggleClass( 'active' ); + } + break; } console.log( "key: "+e.key ); diff --git a/src/ifm.js b/src/ifm.js index bdee261..ed913e0 100644 --- a/src/ifm.js +++ b/src/ifm.js @@ -56,13 +56,13 @@ function IFM() { this.rebuildFileTable = function( data ) { var newRows = $(document.createElement('tbody')); for(i=0;i'; + var newrow = ''; if(data[i].type=="file") { - newrow += '"'; newrow += '> '+data[i].name+''; } else { - newrow += ' '; + newrow += ' '; if( data[i].name == ".." ) newrow += "[ up ]"; else newrow += data[i].name; newrow += ''; @@ -111,13 +111,13 @@ function IFM() { if(ifm.inArray(1,[self.config.edit, self.config.rename, self.config.delete, self.config.extract])) { newrow += ''; if( data[i].name.toLowerCase().substr(-4) == ".zip" && self.config.extract == 1 ) { - newrow += ''; + newrow += ''; } else if( self.config.edit == 1 && data[i].type != "dir" ) { - newrow += ''; + newrow += ''; } if( data[i].name != ".." && data[i].name != "." ) { - if(self.config.rename == 1) newrow += ''; - if(self.config.delete == 1) newrow += ''; + if(self.config.rename == 1) newrow += ''; + if(self.config.delete == 1) newrow += ''; } newrow += ''; } @@ -140,6 +140,7 @@ function IFM() { }; this.changeDirectory = function( newdir, options={} ) { + console.log( "changeDirectory, newdir="+newdir ); config = { absolute: false, pushState: true }; jQuery.extend( config, options ); if( ! config.absolute ) newdir = self.pathCombine( self.currentDir, newdir ); @@ -626,6 +627,39 @@ function IFM() { this.task_update = function(progress, id) { $('#'+id+' .progress-bar').css('width', progress+'%').attr('aria-valuenow', progress); }; + this.selectItem = function( direction ) { + var highlightedItem = $('.highlightedItem'); + if( ! highlightedItem.length ) { + $('#filetable tbody tr:first-child').addClass( 'highlightedItem' ); + } else { + var newItem = ( direction=="next" ? highlightedItem.next() : highlightedItem.prev() ); + + if( newItem.is( 'tr' ) ) { + highlightedItem.removeClass( 'highlightedItem' ); + newItem.addClass( 'highlightedItem' ); + newItem.find( 'a' ).first().focus(); + if( ! this.isElementInViewport( newItem ) ) { + var scrollOffset = ( direction=="next" ? ( highlightedItem.offset().top - 15 ) : ( highlightedItem.offset().top - ( window.innerHeight || document.documentElement.clientHeight ) + highlightedItem.height() + 15 ) ); + $('html, body').animate({ + scrollTop: scrollOffset + }, 500 + ); + } + } + } + } + this.isElementInViewport = function isElementInViewport (el) { + if (typeof jQuery === "function" && el instanceof jQuery) { + el = el[0]; + } + var rect = el.getBoundingClientRect(); + return ( + rect.top >= 60 && + rect.left >= 0 && + rect.bottom <= ( (window.innerHeight || document.documentElement.clientHeight) ) && + rect.right <= (window.innerWidth || document.documentElement.clientWidth) + ); + } this.generateGuid = function() { var result, i, j; result = ''; @@ -654,6 +688,10 @@ function IFM() { if( $('#filetable tr.active').length > 0 ) { e.preventDefault(); self.multiDeleteDialog(); + } else { + var item = $('.highlightedItem'); + if( item.length ) + self.deleteFileDialog( item.data( 'filename' ) ); } break; case 'g': @@ -688,6 +726,33 @@ function IFM() { e.preventDefault(); self.changeDirectory( '..' ); break; + case 'ArrowRight': + e.preventDefault(); + var item = $('.highlightedItem'); + if( item.hasClass('isDir') ) + self.changeDirectory( item.data( 'filename' ) ); + break; + case 'ArrowDown': + e.preventDefault(); + self.selectItem('next'); + break; + case 'ArrowUp': + e.preventDefault(); + self.selectItem('prev'); + break; + case 'Escape': + if( $(':focus').is( '.clickable-row td:first-child a:first-child' ) && $('.highlightedItem').length ) { + e.preventDefault(); + $('.highlightedItem').removeClass( 'highlightedItem' ); + } + break; + case ' ': // todo: make it work only when noting other is focused + if( $(':focus').is( '.clickable-row td:first-child a:first-child' ) ) { + e.preventDefault(); + var item = $('.highlightedItem'); + if( item.is( 'tr' ) ) item.toggleClass( 'active' ); + } + break; } console.log( "key: "+e.key ); diff --git a/src/style.css b/src/style.css index 6c25802..3631102 100644 --- a/src/style.css +++ b/src/style.css @@ -27,6 +27,10 @@ input[name=newperms] { width: 7em; } #filetable tr th.buttons { min-width: 95px; } #filetable tr.clickable-row.active td { background-color: lightblue; } +#filetable tbody tr.highlightedItem td { border-top: 1px solid #555 !important; border-bottom: 1px solid #555 !important; } +#filetable tbody tr.highlightedItem td:first-child { border-left: 1px solid #555; } +#filetable tbody tr.highlightedItem td:last-child { border-right: 1px solid #555; } +#filetable tbody tr.highlightedItem td:first-child a { outline: none; } #navbar { max-width: 100%; }