1
0
mirror of https://github.com/misterunknown/ifm.git synced 2025-08-13 11:34:00 +02:00
Files
php-ifm/build/ifm.js
2017-07-06 17:24:15 +02:00

1241 lines
34 KiB
JavaScript

/**
* IFM constructor
*
* @param object params - object with some configuration values, currently you only can set the api url
*/
function IFM( params ) {
var self = this; // reference to ourself, because "this" does not work within callbacks
// set the backend for the application
params = params || {};
self.api = params.api || window.location.pathname;
this.editor = null; // global ace editor
this.fileChanged = false; // flag for check if file was changed already
this.currentDir = ""; // this is the global variable for the current directory; it is used for AJAX requests
this.rootElement = "";
/**
* Shows a bootstrap modal
*
* @param string content - content of the modal
* @param object options - options for the modal
*/
this.showModal = function( content, options = {} ) {
var modal = $( document.createElement( 'div' ) )
.addClass( "modal fade" )
.attr( 'id', 'ifmmodal' )
.attr( 'role', 'dialog' );
var modalDialog = $( document.createElement( 'div' ) )
.addClass( "modal-dialog" )
.attr( 'role', 'document' );
if( options.large == true ) modalDialog.addClass( 'modal-lg' );
var modalContent = $(document.createElement('div'))
.addClass("modal-content")
.append( content );
modalDialog.append( modalContent );
modal.append( modalDialog );
$( document.body ).append( modal );
modal.on('hide.bs.modal', function () { $(this).remove(); });
modal.on('shown.bs.modal', function () {
var formElements = $(this).find('input, button');
if( formElements.length > 0 ) {
formElements.first().focus();
}
});
modal.modal('show');
};
/**
* Hides a bootstrap modal
*/
this.hideModal = function() {
$('#ifmmodal').modal('hide');
};
/**
* Reloads the file table
*/
this.refreshFileTable = function () {
var id = self.generateGuid();
self.task_add( "Refresh", id );
$.ajax({
url: self.api,
type: "POST",
data: {
api: "getFiles",
dir: self.currentDir
},
dataType: "json",
success: self.rebuildFileTable,
error: function( response ) { self.showMessage( "General error occured: No or broken response", "e" ); },
complete: function() { self.task_done( id ); }
});
};
/**
* Rebuilds the file table with fetched items
*
* @param object data - object with items
*/
this.rebuildFileTable = function( data ) {
data.forEach( function( item ) {
item.guid = self.generateGuid();
item.linkname = ( item.name == ".." ) ? "[ up ]" : item.name;
item.download = {};
item.download.name = ( item.name == ".." ) ? "." : item.name;
item.download.allowed = self.config.download;
item.download.currentDir = self.currentDir;
if( ! self.config.chmod )
item.readonly = "readonly";
if( self.config.edit || self.config.rename || self.config.delete || self.config.extract || self.config.copymove ) {
item.ftbuttons = true;
item.button = [];
}
if( item.type == "dir" ) {
item.download.action = "zipnload";
item.download.icon = "icon icon-download-cloud";
item.rowclasses = "isDir";
} else {
item.download.action = "download";
item.download.icon = "icon icon-download";
if( item.icon.indexOf( 'file-image' ) !== -1 && self.config.isDocroot )
item.tooltip = 'data-toggle="tooltip" title="<img src=\'' + self.pathCombine( self.currentDir, item.name ) + '\' class=\'imgpreview\'>"';
if( item.name.toLowerCase().substr(-4) == ".zip" )
item.eaction = "extract";
else
item.eaction = "edit";
if( self.config.edit && item.name.toLowerCase().substr(-4) != ".zip" )
item.button.push({
action: "edit",
icon: "icon icon-pencil",
title: "edit"
});
else
item.button.push({
action: "extract",
icon: "icon icon-archive",
title: "extract"
});
}
if( ! self.inArray( item.name, [".", ".."] ) ) {
if( self.config.copymove )
item.button.push({
action: "copymove",
icon: "icon icon-folder-open-empty",
title: "copy/move"
});
if( self.config.rename )
item.button.push({
action: "rename",
icon: "icon icon-terminal",
title: "rename"
});
if( self.config.delete )
item.button.push({
action: "delete",
icon: "icon icon-trash",
title: "delete"
});
}
});
var newTBody = Mustache.render( self.templates.filetable, { items: data, config: self.config } );
$( "#filetable tbody" ).remove();
$( "#filetable" ).append( $(newTBody) );
$( '.clickable-row' ).click( function( event ) {
if( event.ctrlKey ) {
$( this ).toggleClass( 'selectedItem' );
}
});
$( 'a[data-toggle="tooltip"]' ).tooltip({
animated: 'fade',
placement: 'right',
html: true
});
$( 'a.ifmitem' ).each( function() {
if( $(this).data( "type" ) == "dir" ) {
$(this).on( 'click', function( e ) {
e.stopPropagation();
self.changeDirectory( $(this).parent().parent().data( 'filename' ) );
return false;
});
} else {
if( self.config.isDocroot )
$(this).attr( "href", self.pathCombine( self.currentDir, $(this).parent().parent().data( 'filename' ) ) );
else
$(this).on( 'click', function() {
$( '#d_' + this.id ).submit();
return false;
});
}
});
$( 'a[name="start_download"]' ).on( 'click', function(e) {
e.stopPropagation();
$( '#d_' + $(this).data( 'guid' ) ).submit();
return false;
});
$( 'input[name="newpermissions"]' ).on( 'keypress', function( e ) {
if( e.key == "Enter" ) {
e.stopPropagation();
self.changePermissions( $( this ).data( 'filename' ), $( this ).val() );
return false;
}
});
$( 'a[name^="do-"]' ).on( 'click', function() {
var action = this.name.substr( this.name.indexOf( '-' ) + 1 );
switch( action ) {
case "rename":
self.showRenameFileDialog( $(this).data( 'name' ) );
break;
case "extract":
self.showExtractFileDialog( $(this).data( 'name' ) );
break;
case "edit":
self.editFile( $(this).data( 'name' ) );
break;
case "delete":
self.showDeleteFileDialog( $(this).data( 'name' ) );
break;
case "copymove":
self.showCopyMoveDialog( $(this).data( 'name' ) );
break;
}
});
};
/**
* Changes the current directory
*
* @param string newdir - target directory
* @param object options - options for changing the directory
*/
this.changeDirectory = function( newdir, options={} ) {
config = { absolute: false, pushState: true };
jQuery.extend( config, options );
if( ! config.absolute ) newdir = self.pathCombine( self.currentDir, newdir );
$.ajax({
url: self.api,
type: "POST",
data: ({
api: "getRealpath",
dir: newdir
}),
dataType: "json",
success: function( data ) {
self.currentDir = data.realpath;
self.refreshFileTable();
$( "#currentDir" ).val( self.currentDir );
if( config.pushState ) history.pushState( { dir: self.currentDir }, self.currentDir, "#"+self.currentDir );
},
error: function() { self.showMessage( "General error occured: No or broken response", "e" ); }
});
};
/**
* Shows a file, either a new file or an existing
*/
this.showFileDialog = function () {
var filename = arguments.length > 0 ? arguments[0] : "newfile.txt";
var content = arguments.length > 1 ? arguments[1] : "";
self.showModal( Mustache.render( self.templates.file, { filename: filename } ), { large: true } );
var form = $('#formFile');
form.find('input[name="filename"]').on( 'keypress', self.preventEnter );
form.find('#buttonSave').on( 'click', function() {
self.saveFile( form.find('input[name=filename]').val(), self.editor.getValue() );
self.hideModal();
return false;
});
form.find('#buttonSaveNotClose').on( 'click', function() {
self.saveFile( form.find('input[name=filename]').val(), self.editor.getValue() );
return false;
});
form.find('#buttonClose').on( 'click', function() {
self.hideModal();
return false;
});
form.find('#editoroptions').popover({
html: true,
title: function() { return $('#editoroptions-head').html(); },
content: function() {
var content = $('#editoroptions-content').clone()
var aceSession = self.editor.getSession();
content.removeClass( 'hide' );
content.find( '#editor-wordwrap' )
.prop( 'checked', ( aceSession.getOption( 'wrap' ) == 'off' ? false : true ) )
.on( 'change', function() { self.editor.setOption( 'wrap', $( this ).is( ':checked' ) ); });
content.find( '#editor-softtabs' )
.prop( 'checked', aceSession.getOption( 'useSoftTabs' ) )
.on( 'change', function() { self.editor.setOption( 'useSoftTabs', $( this ).is( ':checked' ) ); });
content.find( '#editor-tabsize' )
.val( aceSession.getOption( 'tabSize' ) )
.on( 'keydown', function( e ) { if( e.key == 'Enter' ) { self.editor.setOption( 'tabSize', $( this ).val() ); } });
return content;
}
});
form.on( 'remove', function () { self.editor = null; self.fileChanged = false; });
// Start ACE
self.editor = ace.edit("content");
self.editor.$blockScrolling = 'Infinity';
self.editor.getSession().setValue(content);
self.editor.focus();
self.editor.on("change", function() { self.fileChanged = true; });
// word wrap checkbox
$('#aceWordWrap').on( 'change', function (event) {
self.editor.getSession().setUseWrapMode( $(this).is(':checked') );
});
};
/**
* Saves a file
*/
this.saveFile = function( filename, content ) {
$.ajax({
url: self.api,
type: "POST",
data: ({
api: "saveFile",
dir: self.currentDir,
filename: filename,
content: content
}),
dataType: "json",
success: function( data ) {
if( data.status == "OK" ) {
self.showMessage( "File successfully edited/created.", "s" );
self.refreshFileTable();
} else self.showMessage( "File could not be edited/created:" + data.message, "e" );
},
error: function() { self.showMessage( "General error occured", "e" ); }
});
self.fileChanged = false;
};
/**
* Edit a file
*
* @params string name - name of the file
*/
this.editFile = function( name ) {
$.ajax({
url: self.api,
type: "POST",
dataType: "json",
data: ({
api: "getContent",
dir: self.currentDir,
filename: name
}),
success: function( data ) {
if( data.status == "OK" && data.data.content != null ) {
self.showFileDialog( data.data.filename, data.data.content );
}
else if( data.status == "OK" && data.data.content == null ) {
self.showMessage( "The content of this file cannot be fetched.", "e" );
}
else self.showMessage( "Error: "+data.message, "e" );
},
error: function() { self.showMessage( "This file can not be displayed or edited.", "e" ); }
});
};
/**
* Shows the create directory dialog
*/
this.showCreateDirDialog = function() {
self.showModal( self.templates.createdir );
var form = $( '#formCreateDir' );
form.find( 'input[name=dirname]' ).on( 'keypress', self.preventEnter );
form.find( '#buttonSave' ).on( 'click', function() {
self.createDir( form.find( 'input[name=dirname] ').val() );
self.hideModal();
return false;
});
form.find( '#buttonCancel' ).on( 'click', function() {
self.hideModal();
return false;
});
};
/**
* Create a directory
*/
this.createDir = function( dirname ) {
$.ajax({
url: self.api,
type: "POST",
data: ({
api: "createDir",
dir: self.currentDir,
dirname: dirname
}),
dataType: "json",
success: function( data ){
if( data.status == "OK" ) {
self.showMessage( "Directory sucessfully created.", "s" );
self.refreshFileTable();
}
else {
self.showMessage( "Directory could not be created: "+data.message, "e" );
}
},
error: function() { self.showMessage( "General error occured.", "e" ); }
});
};
/**
* Shows the delete file dialog
*
* @param string name - name of the file
*/
this.showDeleteFileDialog = function( filename ) {
self.showModal( Mustache.render( self.templates.deletefile, { filename: name } ) );
var form = $( '#formDeleteFile' );
form.find( '#buttonYes' ).on( 'click', function() {
self.deleteFile( self.JSEncode( filename ) );
self.hideModal();
return false;
});
form.find( '#buttonNo' ).on( 'click', function() {
self.hideModal();
return false;
});
};
/**
* Deletes a file
*
* @params string name - name of the file
*/
this.deleteFile = function( filename ) {
$.ajax({
url: self.api,
type: "POST",
data: ({
api: "delete",
dir: self.currentDir,
filename: filename
}),
dataType: "json",
success: function(data) {
if(data.status == "OK") {
self.showMessage("File successfully deleted", "s");
self.refreshFileTable();
} else self.showMessage("File could not be deleted", "e");
},
error: function() { self.showMessage("General error occured", "e"); }
});
};
/**
* Show the rename file dialog
*
* @params string name - name of the file
*/
this.showRenameFileDialog = function( filename ) {
self.showModal( Mustache.render( self.templates.renamefile, { filename: filename } ) );
var form = $( '#formRenameFile' );
form.find( 'input[name=newname]' ).on( 'keypress', self.preventEnter );
form.find( '#buttonRename' ).on( 'click', function() {
self.renameFile( filename, form.find( 'input[name=newname]' ).val() );
self.hideModal();
return false;
});
form.find( '#buttonCancel' ).on( 'click', function() {
self.hideModal();
return false;
});
};
/**
* Renames a file
*
* @params string name - name of the file
*/
this.renameFile = function( filename, newname ) {
$.ajax({
url: ifm.api,
type: "POST",
data: ({
api: "rename",
dir: ifm.currentDir,
filename: filename,
newname: newname
}),
dataType: "json",
success: function(data) {
if(data.status == "OK") {
ifm.showMessage("File successfully renamed", "s");
ifm.refreshFileTable();
} else ifm.showMessage("File could not be renamed: "+data.message, "e");
},
error: function() { ifm.showMessage("General error occured", "e"); }
});
};
/**
* Show the copy/move dialog
*
* @params string name - name of the file
*/
this.showCopyMoveDialog = function( name ) {
self.showModal( self.templates.copymove );
$.ajax({
url: self.api,
type: "POST",
data: ({
api: "getFolderTree",
dir: self.currentDir
}),
dataType: "json",
success: function( data ) {
$( '#copyMoveTree' ).treeview( { data: data, levels: 0, expandIcon: "icon icon-folder-empty", collapseIcon: "icon icon-folder-open-empty" } );
},
error: function() { self.hideModal(); self.showMessage( "Error while fetching the folder tree.", "e" ) }
});
$( '#copyButton' ).on( 'click', function() {
self.copyMove( name, $('#copyMoveTree .node-selected').data('path'), 'copy' );
self.hideModal();
return false;
});
$( '#moveButton' ).on( 'click', function() {
self.copyMove( name, $('#copyMoveTree .node-selected').data('path'), 'move' );
self.hideModal();
return false;
});
$( '#cancelButton' ).on( 'click', function() {
self.hideModal();
return false;
});
};
/**
* Copy or moves a file
*
* @params string name - name of the file
*/
this.copyMove = function( source, destination, action ) {
var id = self.generateGuid();
self.task_add( action.charAt(0).toUpperCase() + action.slice(1) + " " + source + " to " + destination, id );
$.ajax({
url: self.api,
type: "POST",
data: {
dir: self.currentDir,
api: "copyMove",
action: action,
filename: source,
destination: destination
},
dataType: "json",
success: function(data) {
if( data.status == "OK" ) {
self.showMessage( data.message, "s" );
} else {
self.showMessage( data.message, "e" );
}
self.refreshFileTable();
},
error: function() {
self.showMessage( "General error occured.", "e" );
},
complete: function() {
self.task_done( id );
}
});
};
/**
* Shows the extract file dialog
*
* @param string name - name of the file
*/
this.showExtractFileDialog = function( filename ) {
var targetDirSuggestion = '';
if( filename.lastIndexOf( '.' ) > 1 )
targetDirSuggestion = filename.substr( 0, filename.lastIndexOf( '.' ) );
else targetDirSuggestion = filename;
self.showModal( Mustache.render( self.templates.extractfile, { filename: filename, destination: targetDirSuggestion } ) );
var form = $('#formExtractFile');
form.find('#buttonExtract').on( 'click', function() {
var t = form.find('input[name=extractTargetLocation]:checked').val();
if( t == "custom" ) t = form.find('#extractCustomLocation').val();
self.extractFile( self.JSEncode( filename ), t );
self.hideModal();
return false;
});
form.find('#buttonCancel').on( 'click', function() {
self.hideModal();
return false;
});
form.find('#extractCustomLocation').on( 'click', function(e) {
$(e.target).prev().children().first().prop( 'checked', true );
});
};
/**
* Extracts a file
*
* @param string filename - name of the file
* @param string destination - name of the target directory
*/
this.extractFile = function( filename, destination ) {
$.ajax({
url: self.api,
type: "POST",
data: {
api: "extract",
dir: self.currentDir,
filename: filename,
targetdir: destination
},
dataType: "json",
success: function( data ) {
if( data.status == "OK" ) {
self.showMessage( "File successfully extracted", "s" );
self.refreshFileTable();
} else self.showMessage( "File could not be extracted. Error: " + data.message, "e" );
},
error: function() { self.showMessage( "General error occured", "e" ); }
});
};
/**
* Shows the upload file dialog
*/
this.showUploadFileDialog = function() {
self.showModal( self.templates.uploadfile );
var form = $('#formUploadFile');
form.find( 'input[name=newfilename]' ).on( 'keypress', self.preventEnter );
form.find( '#buttonUpload' ).on( 'click', function() {
self.uploadFile();
self.hideModal();
return false;
});
form.find( '#buttonCancel' ).on( 'click', function() {
self.hideModal();
return false;
});
};
/**
* Uploads a file
*/
this.uploadFile = function() {
var ufile = document.getElementById( 'ufile' ).files[0];
var data = new FormData();
var newfilename = $("#formUploadFile input[name^=newfilename]").val();
data.append('api', 'upload');
data.append('dir', self.currentDir);
data.append('file', ufile);
data.append('newfilename', newfilename);
var id = self.generateGuid();
$.ajax({
url: self.api,
type: "POST",
data: data,
processData: false,
contentType: false,
dataType: "json",
xhr: function(){
var xhr = $.ajaxSettings.xhr() ;
xhr.upload.onprogress = function(evt){ self.task_update(evt.loaded/evt.total*100,id); } ;
xhr.upload.onload = function(){ console.log('Uploading '+newfilename+' done.') } ;
return xhr ;
},
success: function(data) {
if(data.status == "OK") {
self.showMessage("File successfully uploaded", "s");
if(data.cd == self.currentDir) self.refreshFileTable();
} else self.showMessage("File could not be uploaded: "+data.message, "e");
},
error: function() { self.showMessage("General error occured", "e"); },
complete: function() { self.task_done(id); }
});
self.task_add("Upload "+ufile.name, id);
};
/**
* Change the permissions of a file
*
* @params object e - event object
* @params string name - name of the file
*/
this.changePermissions = function( filename, newperms) {
$.ajax({
url: self.api,
type: "POST",
data: ({
api: "changePermissions",
dir: self.currentDir,
filename: filename,
chmod: newperms
}),
dataType: "json",
success: function( data ){
if( data.status == "OK" ) {
self.showMessage( "Permissions successfully changed.", "s" );
self.refreshFileTable();
}
else {
self.showMessage( "Permissions could not be changed: "+data.message, "e");
}
},
error: function() { self.showMessage("General error occured.", "e"); }
});
};
/**
* Show the remote upload dialog
*/
this.showRemoteUploadDialog = function() {
self.showModal( self.templates.remoteupload );
var form = $('#formRemoteUpload');
form.find( '#url' )
.on( 'keypress', self.preventEnter )
.on( 'change keyup', function() {
$("#filename").val($(this).val().substr($(this).val().lastIndexOf("/")+1));
});
form.find( '#filename' )
.on( 'keypress', self.preventEnter )
.on( 'keyup', function() { $("#url").off( 'change keyup' ); });
form.find( '#buttonUpload' ).on( 'click', function() {
self.remoteUpload();
self.hideModal();
return false;
});
form.find( '#buttonCancel' ).on( 'click', function() {
self.hideModal();
return false;
});
};
/**
* Remote uploads a file
*/
this.remoteUpload = function() {
var filename = $("#formRemoteUpload #filename").val();
var id = ifm.generateGuid();
$.ajax({
url: ifm.api,
type: "POST",
data: ({
api: "remoteUpload",
dir: ifm.currentDir,
filename: filename,
method: $("#formRemoteUpload input[name=method]:checked").val(),
url: encodeURI($("#url").val())
}),
dataType: "json",
success: function(data) {
if(data.status == "OK") {
ifm.showMessage("File successfully uploaded", "s");
ifm.refreshFileTable();
} else ifm.showMessage("File could not be uploaded:<br />"+data.message, "e");
},
error: function() { ifm.showMessage("General error occured", "e"); },
complete: function() { ifm.task_done(id); }
});
ifm.task_add("Remote upload: "+filename, id);
};
/**
* Shows the ajax request dialog
*/
this.showAjaxRequestDialog = function() {
self.showModal( self.templates.ajaxrequest );
var form = $('#formAjaxRequest');
form.find( '#ajaxurl' ).on( 'keypress', self.preventEnter );
form.find( '#buttonRequest' ).on( 'click', function() {
self.ajaxRequest();
return false;
});
form.find( '#buttonClose' ).on( 'click', function() {
self.hideModal();
return false;
});
};
/**
* Performs an ajax request
*/
this.ajaxRequest = function() {
$.ajax({
url : $("#ajaxurl").val(),
cache : false,
data : $('#ajaxdata').val().replace(/\n/g,"&"),
type : $('#ajaxrequest input[name=arMethod]:checked').val(),
success : function(response) { $("#ajaxresponse").text(response); },
error : function(e) { self.showMessage("Error: "+e, "e"); console.log(e); }
});
};
/**
* Shows the delete dialog for multiple files
*/
this.showMultiDeleteDialog = function() {
self.showModal( Mustache.render( self.templates.multidelete, { count: $('#filetable tr.selectedItem').length } ) );
var form = $('#formDeleteFiles');
form.find( '#buttonYes' ).on( 'click', function() {
self.multiDelete();
self.hideModal();
return false;
});
form.find( '#buttonNo' ).on( 'click', function() {
self.hideModal();
return false;
});
};
/**
* Deletes multiple files
*/
this.multiDelete = function() {
var elements = $('#filetable tr.selectedItem');
var filenames = [];
for(var i=0;typeof(elements[i])!='undefined';filenames.push(elements[i++].getAttribute('data-filename')));
$.ajax({
url: self.api,
type: "POST",
data: ({
api: "multidelete",
dir: self.currentDir,
filenames: filenames
}),
dataType: "json",
success: function(data) {
if(data.status == "OK") {
if(data.errflag == 1)
ifm.showMessage("All files successfully deleted.", "s");
else if(data.errflag == 0)
ifm.showMessage("Some files successfully deleted. "+data.message);
else
ifm.showMessage("Files could not be deleted. "+data.message, "e");
ifm.refreshFileTable();
} else ifm.showMessage("Files could not be deleted:<br />"+data.message, "e");
},
error: function() { ifm.showMessage("General error occured", "e"); }
});
};
// --------------------
// helper functions
// --------------------
/**
* Shows a notification
*
* @param string m - message text
* @param string t - message type (e: error, s: success)
*/
this.showMessage = function(m, t) {
var msgType = (t == "e")?"danger":(t == "s")?"success":"info";
var element = ( self.config.inline ) ? self.rootElement : "body";
$.notify(
{ message: m },
{ type: msgType, delay: 5000, mouse_over: 'pause', offset: { x: 15, y: 65 }, element: element }
);
};
/**
* Combines two path components
*
* @param string a - component 1
* @param string b - component 2
*/
this.pathCombine = function(a, b) {
if(a == "" && b == "") return "";
if(b[0] == "/") b = b.substring(1);
if(a == "") return b;
if(a[a.length-1] == "/") a = a.substring(0, a.length-1);
if(b == "") return a;
return a+"/"+b;
};
/**
* Prevents a user to submit a form via clicking enter
*
* @param object e - click event
*/
this.preventEnter = function(e) {
if( e.keyCode == 13 ) return false;
else return true;
}
/**
* Checks if an element is part of an array
*
* @param obj needle - search item
* @param array haystack - array to search
*/
this.inArray = function(needle, haystack) {
for(var i = 0; i < haystack.length; i++) { if(haystack[i] == needle) return true; } return false;
};
/**
* Adds a task to the taskbar.
*
* @param string name - description of the task
* @param string id - identifier for the task
*/
this.task_add = function( name, id ) {
if( ! document.getElementById( "waitqueue" ) ) {
$( document.body ).prepend( '<div id="waitqueue"></div>' );
}
$( "#waitqueue" ).prepend('\
<div id="'+id+'" class="panel panel-default">\
<div class="panel-body">\
<div class="progress">\
<div class="progress-bar progress-bar-info progress-bar-striped active" role="progressbar" aria-valuenow="100" aria-valuemax="100" style="width:100%"></div>\
<span class="progbarlabel">'+name+'</span>\
</div>\
</div>\
</div>\
');
};
/**
* Removes a task from the taskbar
*
* @param string id - task identifier
*/
this.task_done = function(id) {
$("#"+id).remove();
if($("#waitqueue>div").length == 0) {
$("#waitqueue").remove();
}
};
/**
* Updates a task
*
* @param integer progress - percentage of status
* @param string id - task identifier
*/
this.task_update = function(progress, id) {
$('#'+id+' .progress-bar').css('width', progress+'%').attr('aria-valuenow', progress);
};
/**
* Highlights an item in the file table
*
* @param object param - either an element id or a jQuery object
*/
this.highlightItem = function( param ) {
var highlight = function( el ) {
el.addClass( 'highlightedItem' ).siblings().removeClass( 'highlightedItem' );
el.find( 'a' ).first().focus();
if( ! self.isElementInViewport( el ) ) {
var scrollOffset = 0;
if( param=="prev" )
scrollOffset = el.offset().top - ( window.innerHeight || document.documentElement.clientHeight ) + el.height() + 15;
else
scrollOffset = el.offset().top - 55;
$('html, body').animate( { scrollTop: scrollOffset }, 200 );
}
};
if( param.jquery ) {
highlight( param );
} else {
var highlightedItem = $('.highlightedItem');
if( ! highlightedItem.length ) {
highlight( $('#filetable tbody tr:first-child') );
} else {
var newItem = ( param=="next" ? highlightedItem.next() : highlightedItem.prev() );
if( newItem.is( 'tr' ) ) {
highlight( newItem );
}
}
}
};
/**
* Checks if an element is within the viewport
*
* @param object el - element object
*/
this.isElementInViewport = function (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)
);
}
/**
* Generates a GUID
*/
this.generateGuid = function() {
var result, i, j;
result = '';
for(j=0; j<20; j++) {
i = Math.floor(Math.random()*16).toString(16).toUpperCase();
result = result + i;
}
return result;
};
/**
* Logs a message if debug mode is on
*
* @param string m - message text
*/
this.log = function( m ) {
if( self.config.debug ) {
console.log( "IFM (debug): " + m );
}
};
/**
* Encodes a string for use within javascript
*
* @param string s - encoding string
*/
this.JSEncode = function(s) {
return s.replace(/'/g, '\\x27').replace(/"/g, '\\x22');
};
/**
* Handles the javascript pop states
*
* @param object event - event object
*/
this.historyPopstateHandler = function(event) {
var dir = "";
if( event.state && event.state.dir ) dir = event.state.dir;
self.changeDirectory( dir, { pushState: false, absolute: true } );
};
/**
* Handles keystrokes
*
* @param object e - event object
*/
this.handleKeystrokes = function( e ) {
// bind 'del' key
if( $(e.target).closest('input')[0] || $(e.target).closest('textarea')[0] ) {
return;
}
switch( e.key ) {
case 'Delete':
if( self.config.delete ) {
if( $('#filetable tr.selectedItem').length > 0 ) {
e.preventDefault();
self.showMultiDeleteDialog();
} else {
var item = $('.highlightedItem');
if( item.length )
self.showDeleteFileDialog( item.data( 'filename' ) );
}
}
break;
case 'e':
if( self.config.edit ) {
var item = $('.highlightedItem');
if( item.length && ! item.hasClass( 'isDir' ) ) {
e.preventDefault();
var action = item.data( 'eaction' );
switch( action ) {
case 'extract':
self.showExtractFileDialog( item.data( 'filename' ) );
break;
case 'edit':
self.editFile( item.data( 'filename' ) );
}
}
}
break;
case 'g':
e.preventDefault();
$('#currentDir').focus();
break;
case 'r':
e.preventDefault();
self.refreshFileTable();
break;
case 'u':
if( self.config.upload ) {
e.preventDefault();
self.showUploadFileDialog();
}
break;
case 'o':
if( self.config.remoteupload ) {
e.preventDefault();
self.showRemoteUploadDialog();
}
break;
case 'a':
if( self.config.ajaxrequest ) {
e.preventDefault();
self.showAjaxRequestDialog();
}
break;
case 'F':
if( self.config.createfile ) {
e.preventDefault();
self.showFileDialog();
}
break;
case 'D':
if( self.config.createdir ) {
e.preventDefault();
self.showCreateDirDialog();
}
break;
case 'h':
case 'ArrowLeft':
e.preventDefault();
self.changeDirectory( '..' );
break;
case 'l':
case 'ArrowRight':
e.preventDefault();
var item = $('.highlightedItem');
if( item.hasClass('isDir') )
self.changeDirectory( item.data( 'filename' ) );
break;
case 'j':
case 'ArrowDown':
e.preventDefault();
self.highlightItem('next');
break;
case 'k':
case 'ArrowUp':
e.preventDefault();
self.highlightItem('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
case 'Enter':
if( $(':focus').is( '.clickable-row td:first-child a:first-child' ) ) {
var trParent = $(':focus').parent().parent();
if( e.key == 'Enter' && trParent.hasClass( 'isDir' ) ) {
e.preventDefault();
e.stopPropagation();
self.changeDirectory( trParent.data( 'filename' ) );
} else if( e.key == ' ' && ! trParent.is( ':first-child' ) ) {
e.preventDefault();
e.stopPropagation();
var item = $('.highlightedItem');
if( item.is( 'tr' ) )
item.toggleClass( 'selectedItem' );
}
}
break;
}
}
/**
* Initializes the application
*/
this.initLoadConfig = function() {
$.ajax({
url: self.api,
type: "POST",
data: {
api: "getConfig"
},
dataType: "json",
success: function(d) {
self.config = d;
self.log( "configuration loaded" );
self.initLoadTemplates();
},
error: function() {
throw new Error( "IFM: could not load configuration" );
}
});
};
this.initLoadTemplates = function() {
// load the templates from the backend
$.ajax({
url: self.api,
type: "POST",
data: {
api: "getTemplates"
},
dataType: "json",
success: function(d) {
self.templates = d;
self.log( "templates loaded" );
self.initApplication();
},
error: function() {
throw new Error( "IFM: could not load templates" );
}
});
};
this.initApplication = function() {
self.rootElement.html(
Mustache.render(
self.templates.app,
{
showpath: "/",
config: self.config,
ftbuttons: function(){
return ( self.config.edit || self.config.rename || self.config.delete || self.config.zipnload || self.config.extract );
}
}
)
);
// bind static buttons
$("#refresh").click(function(){
self.refreshFileTable();
});
$("#createFile").click(function(){
self.showFileDialog();
});
$("#createDir").click(function(){
self.showCreateDirDialog();
});
$("#upload").click(function(){
self.showUploadFileDialog();
});
$('#currentDir').on( 'keypress', function (event) {
if( event.keyCode == 13 ) {
event.preventDefault();
self.changeDirectory( $(this).val(), { absolute: true } );
}
});
$('#buttonRemoteUpload').on( 'click', function() {
self.showRemoteUploadDialog();
return false;
});
$('#buttonAjaxRequest').on( 'click', function() {
self.showAjaxRequestDialog();
return false;
});
// handle keystrokes
$(document).on( 'keydown', self.handleKeystrokes );
// handle history manipulation
window.onpopstate = self.historyPopstateHandler;
// load initial file table
if( window.location.hash ) {
self.changeDirectory( window.location.hash.substring( 1 ) );
} else {
this.refreshFileTable();
}
};
this.init = function( id ) {
self.rootElement = $('#'+id);
this.initLoadConfig();
};
}